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.
 
 
 
 
 
 

489 lines
14 KiB

/*
* $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", &regions);
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);
}