You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
490 lines
14 KiB
490 lines
14 KiB
3 years ago
|
/*
|
||
|
* $Id: qgen.c,v 1.3 2005/10/28 02:54:35 jms Exp $
|
||
|
*
|
||
|
* Revision History
|
||
|
* ===================
|
||
|
* $Log: qgen.c,v $
|
||
|
* Revision 1.3 2005/10/28 02:54:35 jms
|
||
|
* add release.h changes
|
||
|
*
|
||
|
* Revision 1.2 2005/01/03 20:08:59 jms
|
||
|
* change line terminations
|
||
|
*
|
||
|
* Revision 1.1.1.1 2004/11/24 23:31:47 jms
|
||
|
* re-establish external server
|
||
|
*
|
||
|
* Revision 1.1.1.1 2003/04/03 18:54:21 jms
|
||
|
* recreation after CVS crash
|
||
|
*
|
||
|
* Revision 1.1.1.1 2003/04/03 18:54:21 jms
|
||
|
* initial checkin
|
||
|
*
|
||
|
*
|
||
|
*/
|
||
|
/*
|
||
|
* qgen.c -- routines to convert query templates to executable query
|
||
|
* text for TPC-H and TPC-R
|
||
|
*/
|
||
|
#define DECLARER
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#if (defined(_POSIX_)||!defined(WIN32))
|
||
|
#include <unistd.h>
|
||
|
#else
|
||
|
#include "process.h"
|
||
|
#endif /* WIN32 */
|
||
|
#include <ctype.h>
|
||
|
#include <time.h>
|
||
|
#include "config.h"
|
||
|
#include "dss.h"
|
||
|
#include "tpcd.h"
|
||
|
#include "permute.h"
|
||
|
#include "release.h"
|
||
|
|
||
|
|
||
|
#define LINE_SIZE 512
|
||
|
|
||
|
/*
|
||
|
* Function Protoypes
|
||
|
*/
|
||
|
void varsub PROTO((int qnum, int vnum, int flags));
|
||
|
int strip_comments PROTO((char *line));
|
||
|
void usage PROTO((void));
|
||
|
int process_options PROTO((int cnt, char **args));
|
||
|
int setup PROTO((void));
|
||
|
void qsub PROTO((char *qtag, int flags));
|
||
|
|
||
|
|
||
|
|
||
|
extern char *optarg;
|
||
|
extern int optind;
|
||
|
char **mk_ascdate(void);
|
||
|
extern seed_t Seed[];
|
||
|
|
||
|
char **asc_date;
|
||
|
int snum = -1;
|
||
|
char *prog;
|
||
|
tdef tdefs = { NULL };
|
||
|
long rndm;
|
||
|
double flt_scale;
|
||
|
distribution q13a, q13b;
|
||
|
int qnum;
|
||
|
char *db_name = NULL;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* FUNCTION strip_comments(line)
|
||
|
*
|
||
|
* remove all comments from 'line'; recognizes both {} and -- comments
|
||
|
*/
|
||
|
int
|
||
|
strip_comments(char *line)
|
||
|
{
|
||
|
static int in_comment = 0;
|
||
|
char *cp1, *cp2;
|
||
|
|
||
|
cp1 = line;
|
||
|
|
||
|
while (1) /* traverse the entire string */
|
||
|
{
|
||
|
if (in_comment)
|
||
|
{
|
||
|
if ((cp2 = strchr(cp1, '}')) != NULL) /* comment ends */
|
||
|
{
|
||
|
strcpy(cp1, cp2 + 1);
|
||
|
in_comment = 0;
|
||
|
continue;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*cp1 = '\0';
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else /* not in_comment */
|
||
|
{
|
||
|
if ((cp2 = strchr(cp1, '-')) != NULL)
|
||
|
{
|
||
|
if (*(cp2 + 1) == '-') /* found a '--' comment */
|
||
|
{
|
||
|
*cp2 = '\0';
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if ((cp2 = strchr(cp1, '{')) != NULL) /* comment starts */
|
||
|
{
|
||
|
in_comment = 1;
|
||
|
*cp2 = ' ';
|
||
|
continue;
|
||
|
}
|
||
|
else break;
|
||
|
}
|
||
|
}
|
||
|
return(0);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* FUNCTION qsub(char *qtag, int flags)
|
||
|
*
|
||
|
* based on the settings of flags, and the template file $QDIR/qtag.sql
|
||
|
* make the following substitutions to turn a query template into EQT
|
||
|
*
|
||
|
* String Converted to Based on
|
||
|
* ====== ============ ===========
|
||
|
* first line database <db_name>; -n from command line
|
||
|
* second line set explain on; -x from command line
|
||
|
* :<number> parameter <number>
|
||
|
* :k set number
|
||
|
* :o output to outpath/qnum.snum
|
||
|
* -o from command line, SET_OUTPUT
|
||
|
* :s stream number
|
||
|
* :b BEGIN WORK; -a from command line, START_TRAN
|
||
|
* :e COMMIT WORK; -a from command line, END_TRAN
|
||
|
* :q query number
|
||
|
* :n<number> sets rowcount to be returned
|
||
|
*/
|
||
|
void
|
||
|
qsub(char *qtag, int flags)
|
||
|
{
|
||
|
static char *line = NULL,
|
||
|
*qpath = NULL;
|
||
|
FILE *qfp;
|
||
|
char *cptr,
|
||
|
*mark,
|
||
|
*qroot = NULL;
|
||
|
|
||
|
qnum = atoi(qtag);
|
||
|
if (line == NULL)
|
||
|
{
|
||
|
line = malloc(BUFSIZ);
|
||
|
qpath = malloc(BUFSIZ);
|
||
|
MALLOC_CHECK(line);
|
||
|
MALLOC_CHECK(qpath);
|
||
|
}
|
||
|
|
||
|
qroot = env_config(QDIR_TAG, QDIR_DFLT);
|
||
|
sprintf(qpath, "%s%c%s.sql",
|
||
|
qroot, PATH_SEP, qtag);
|
||
|
qfp = fopen(qpath, "r");
|
||
|
OPEN_CHECK(qfp, qpath);
|
||
|
|
||
|
rowcnt = rowcnt_dflt[qnum];
|
||
|
varsub(qnum, 0, flags); /* set the variables */
|
||
|
if (flags & DFLT_NUM)
|
||
|
fprintf(ofp, SET_ROWCOUNT, rowcnt);
|
||
|
while (fgets(line, BUFSIZ, qfp) != NULL)
|
||
|
{
|
||
|
if (!(flags & COMMENT))
|
||
|
strip_comments(line);
|
||
|
mark = line;
|
||
|
while ((cptr = strchr(mark, VTAG)) != NULL)
|
||
|
{
|
||
|
*cptr = '\0';
|
||
|
cptr++;
|
||
|
fprintf(ofp,"%s", mark);
|
||
|
switch(*cptr)
|
||
|
{
|
||
|
case 'b':
|
||
|
case 'B':
|
||
|
if (!(flags & ANSI))
|
||
|
fprintf(ofp,"%s\n", START_TRAN);
|
||
|
cptr++;
|
||
|
break;
|
||
|
case 'c':
|
||
|
case 'C':
|
||
|
if (flags & DBASE)
|
||
|
fprintf(ofp, SET_DBASE, db_name);
|
||
|
cptr++;
|
||
|
break;
|
||
|
case 'e':
|
||
|
case 'E':
|
||
|
if (!(flags & ANSI))
|
||
|
fprintf(ofp,"%s\n", END_TRAN);
|
||
|
cptr++;
|
||
|
break;
|
||
|
case 'n':
|
||
|
case 'N':
|
||
|
if (!(flags & DFLT_NUM))
|
||
|
{
|
||
|
rowcnt=atoi(++cptr);
|
||
|
while (isdigit(*cptr) || *cptr == ' ') cptr++;
|
||
|
fprintf(ofp, SET_ROWCOUNT, rowcnt);
|
||
|
}
|
||
|
continue;
|
||
|
case 'o':
|
||
|
case 'O':
|
||
|
if (flags & OUTPUT)
|
||
|
fprintf(ofp,"%s '%s/%s.%d'", SET_OUTPUT, osuff,
|
||
|
qtag, (snum < 0)?0:snum);
|
||
|
cptr++;
|
||
|
break;
|
||
|
case 'q':
|
||
|
case 'Q':
|
||
|
fprintf(ofp,"%s", qtag);
|
||
|
cptr++;
|
||
|
break;
|
||
|
case 's':
|
||
|
case 'S':
|
||
|
fprintf(ofp,"%d", (snum < 0)?0:snum);
|
||
|
cptr++;
|
||
|
break;
|
||
|
case 'X':
|
||
|
case 'x':
|
||
|
if (flags & EXPLAIN)
|
||
|
fprintf(ofp, "%s\n", GEN_QUERY_PLAN);
|
||
|
cptr++;
|
||
|
break;
|
||
|
case '1':
|
||
|
case '2':
|
||
|
case '3':
|
||
|
case '4':
|
||
|
case '5':
|
||
|
case '6':
|
||
|
case '7':
|
||
|
case '8':
|
||
|
case '9':
|
||
|
varsub(qnum, atoi(cptr), flags & DFLT);
|
||
|
while (isdigit(*++cptr));
|
||
|
break;
|
||
|
default:
|
||
|
fprintf(stderr, "-- unknown flag '%c%c' ignored\n",
|
||
|
VTAG, *cptr);
|
||
|
cptr++;
|
||
|
break;
|
||
|
}
|
||
|
mark=cptr;
|
||
|
}
|
||
|
fprintf(ofp,"%s", mark);
|
||
|
}
|
||
|
fclose(qfp);
|
||
|
fflush(stdout);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
usage(void)
|
||
|
{
|
||
|
printf("%s Parameter Substitution (v. %d.%d.%d build %d)\n",
|
||
|
NAME, VERSION,RELEASE,
|
||
|
PATCH,BUILD);
|
||
|
printf("Copyright %s %s\n", TPC, C_DATES);
|
||
|
printf("USAGE: %s <options> [ queries ]\n", prog);
|
||
|
printf("Options:\n");
|
||
|
printf("\t-a\t\t-- use ANSI semantics.\n");
|
||
|
printf("\t-b <str>\t-- load distributions from <str>\n");
|
||
|
printf("\t-c\t\t-- retain comments found in template.\n");
|
||
|
printf("\t-d\t\t-- use default substitution values.\n");
|
||
|
printf("\t-h\t\t-- print this usage summary.\n");
|
||
|
printf("\t-i <str>\t-- use the contents of file <str> to begin a query.\n");
|
||
|
printf("\t-l <str>\t-- log parameters to <str>.\n");
|
||
|
printf("\t-n <str>\t-- connect to database <str>.\n");
|
||
|
printf("\t-N\t\t-- use default rowcounts and ignore :n directive.\n");
|
||
|
printf("\t-o <str>\t-- set the output file base path to <str>.\n");
|
||
|
printf("\t-p <n>\t\t-- use the query permutation for stream <n>\n");
|
||
|
printf("\t-r <n>\t\t-- seed the random number generator with <n>\n");
|
||
|
printf("\t-s <n>\t\t-- base substitutions on an SF of <n>\n");
|
||
|
printf("\t-v\t\t-- verbose.\n");
|
||
|
printf("\t-t <str>\t-- use the contents of file <str> to complete a query\n");
|
||
|
printf("\t-x\t\t-- enable SET EXPLAIN in each query.\n");
|
||
|
}
|
||
|
|
||
|
int
|
||
|
process_options(int cnt, char **args)
|
||
|
{
|
||
|
int flag;
|
||
|
|
||
|
while((flag = getopt(cnt, args, "ab:cdhi:n:Nl:o:p:r:s:t:vx")) != -1)
|
||
|
switch(flag)
|
||
|
{
|
||
|
case 'a': /* use ANSI semantics */
|
||
|
flags |= ANSI;
|
||
|
break;
|
||
|
case 'b': /* load distributions from named file */
|
||
|
d_path = (char *)malloc((int)strlen(optarg) + 1);
|
||
|
MALLOC_CHECK(d_path);
|
||
|
strcpy(d_path, optarg);
|
||
|
break;
|
||
|
case 'c': /* retain comments in EQT */
|
||
|
flags |= COMMENT;
|
||
|
break;
|
||
|
case 'd': /* use default substitution values */
|
||
|
flags |= DFLT;
|
||
|
break;
|
||
|
case 'h': /* just generate the usage summary */
|
||
|
usage();
|
||
|
exit(0);
|
||
|
break;
|
||
|
case 'i': /* set stream initialization file name */
|
||
|
ifile = malloc((int)strlen(optarg) + 1);
|
||
|
MALLOC_CHECK(ifile);
|
||
|
strcpy(ifile, optarg);
|
||
|
flags |= INIT;
|
||
|
break;
|
||
|
case 'l': /* log parameter usages */
|
||
|
lfile = malloc((int)strlen(optarg) + 1);
|
||
|
MALLOC_CHECK(lfile);
|
||
|
strcpy(lfile, optarg);
|
||
|
flags |= LOG;
|
||
|
break;
|
||
|
case 'N': /* use default rowcounts */
|
||
|
flags |= DFLT_NUM;
|
||
|
break;
|
||
|
case 'n': /* set database name */
|
||
|
db_name = malloc((int)strlen(optarg) + 1);
|
||
|
MALLOC_CHECK(db_name);
|
||
|
strcpy(db_name, optarg);
|
||
|
flags |= DBASE;
|
||
|
break;
|
||
|
case 'o': /* set the output path */
|
||
|
osuff = malloc((int)strlen(optarg) + 1);
|
||
|
MALLOC_CHECK(osuff);
|
||
|
strcpy(osuff, optarg);
|
||
|
flags |=OUTPUT;
|
||
|
break;
|
||
|
case 'p': /* permutation for a given stream */
|
||
|
snum = atoi(optarg);
|
||
|
break;
|
||
|
case 'r': /* set random number seed for parameter gen */
|
||
|
flags |= SEED;
|
||
|
rndm = atol(optarg);
|
||
|
break;
|
||
|
case 's': /* scale of data set to run against */
|
||
|
flt_scale = atof(optarg);
|
||
|
if (scale > MAX_SCALE)
|
||
|
fprintf(stderr, "%s %5.0f %s\n%s\n",
|
||
|
"WARNING: Support for scale factors >",
|
||
|
MAX_SCALE,
|
||
|
"GB is still in development.",
|
||
|
"Data set integrity is not guaranteed.\n");
|
||
|
break;
|
||
|
case 't': /* set termination file name */
|
||
|
tfile = malloc((int)strlen(optarg) + 1);
|
||
|
MALLOC_CHECK(tfile);
|
||
|
strcpy(tfile, optarg);
|
||
|
flags |= TERMINATE;
|
||
|
break;
|
||
|
case 'v': /* verbose */
|
||
|
flags |= VERBOSE;
|
||
|
break;
|
||
|
case 'x': /* set explain in the queries */
|
||
|
flags |= EXPLAIN;
|
||
|
break;
|
||
|
default:
|
||
|
printf("unknown option '%s' ignored\n", args[optind]);
|
||
|
usage();
|
||
|
exit(1);
|
||
|
break;
|
||
|
}
|
||
|
return(0);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
setup(void)
|
||
|
{
|
||
|
asc_date = mk_ascdate();
|
||
|
read_dist(env_config(DIST_TAG, DIST_DFLT), "p_cntr", &p_cntr_set);
|
||
|
read_dist(env_config(DIST_TAG, DIST_DFLT), "colors", &colors);
|
||
|
read_dist(env_config(DIST_TAG, DIST_DFLT), "p_types", &p_types_set);
|
||
|
read_dist(env_config(DIST_TAG, DIST_DFLT), "nations", &nations);
|
||
|
read_dist(env_config(DIST_TAG, DIST_DFLT), "nations2", &nations2);
|
||
|
read_dist(env_config(DIST_TAG, DIST_DFLT), "regions", ®ions);
|
||
|
read_dist(env_config(DIST_TAG, DIST_DFLT), "o_oprio",
|
||
|
&o_priority_set);
|
||
|
read_dist(env_config(DIST_TAG, DIST_DFLT), "instruct",
|
||
|
&l_instruct_set);
|
||
|
read_dist(env_config(DIST_TAG, DIST_DFLT), "smode", &l_smode_set);
|
||
|
read_dist(env_config(DIST_TAG, DIST_DFLT), "category",
|
||
|
&l_category_set);
|
||
|
read_dist(env_config(DIST_TAG, DIST_DFLT), "rflag", &l_rflag_set);
|
||
|
read_dist(env_config(DIST_TAG, DIST_DFLT), "msegmnt", &c_mseg_set);
|
||
|
read_dist(env_config(DIST_TAG, DIST_DFLT), "Q13a", &q13a);
|
||
|
read_dist(env_config(DIST_TAG, DIST_DFLT), "Q13b", &q13b);
|
||
|
|
||
|
return(0);
|
||
|
}
|
||
|
|
||
|
|
||
|
int main(int ac, char **av)
|
||
|
{
|
||
|
int i;
|
||
|
FILE *ifp;
|
||
|
char line[LINE_SIZE];
|
||
|
|
||
|
prog = av[0];
|
||
|
flt_scale = (double)1.0;
|
||
|
flags = 0;
|
||
|
d_path = NULL;
|
||
|
process_options(ac, av);
|
||
|
if (flags & VERBOSE)
|
||
|
fprintf(ofp,
|
||
|
"-- TPC %s Parameter Substitution (Version %d.%d.%d build %d)\n",
|
||
|
NAME, VERSION, RELEASE, PATCH, BUILD);
|
||
|
|
||
|
setup();
|
||
|
|
||
|
if (!(flags & DFLT)) /* perturb the RNG */
|
||
|
{
|
||
|
if (!(flags & SEED))
|
||
|
rndm = (long)((unsigned)time(NULL));
|
||
|
if (rndm < 0)
|
||
|
rndm += 2147483647;
|
||
|
Seed[0].value = rndm;
|
||
|
for (i=1; i <= QUERIES_PER_SET; i++)
|
||
|
{
|
||
|
Seed[0].value = NextRand(Seed[0].value);
|
||
|
Seed[i].value = Seed[0].value;
|
||
|
}
|
||
|
printf("-- using %ld as a seed to the RNG\n", rndm);
|
||
|
}
|
||
|
else
|
||
|
printf("-- using default substitutions\n");
|
||
|
|
||
|
if (flags & INIT) /* init stream with ifile */
|
||
|
{
|
||
|
ifp = fopen(ifile, "r");
|
||
|
OPEN_CHECK(ifp, ifile);
|
||
|
while (fgets(line, LINE_SIZE, ifp) != NULL)
|
||
|
fprintf(stdout, "%s", line);
|
||
|
}
|
||
|
|
||
|
if (snum >= 0)
|
||
|
if (optind < ac)
|
||
|
for (i=optind; i < ac; i++)
|
||
|
{
|
||
|
char qname[10];
|
||
|
sprintf(qname, "%d", SEQUENCE(snum, atoi(av[i])));
|
||
|
qsub(qname, flags);
|
||
|
}
|
||
|
else
|
||
|
for (i=1; i <= QUERIES_PER_SET; i++)
|
||
|
{
|
||
|
char qname[10];
|
||
|
sprintf(qname, "%d", SEQUENCE(snum, i));
|
||
|
qsub(qname, flags);
|
||
|
}
|
||
|
else
|
||
|
if (optind < ac)
|
||
|
for (i=optind; i < ac; i++)
|
||
|
qsub(av[i], flags);
|
||
|
else
|
||
|
for (i=1; i <= QUERIES_PER_SET; i++)
|
||
|
{
|
||
|
char qname[10];
|
||
|
sprintf(qname, "%d", i);
|
||
|
qsub(qname, flags);
|
||
|
}
|
||
|
|
||
|
if (flags & TERMINATE) /* terminate stream with tfile */
|
||
|
{
|
||
|
ifp = fopen(tfile, "r");
|
||
|
if (ifp == NULL)
|
||
|
OPEN_CHECK(ifp, tfile);
|
||
|
while (fgets(line, LINE_SIZE, ifp) != NULL)
|
||
|
fprintf(stdout, "%s", line);
|
||
|
}
|
||
|
|
||
|
return(0);
|
||
|
}
|
||
|
|