This commit is contained in:
Oliver Lehmann 1989-04-17 09:32:53 +00:00
parent 86f59923cd
commit 801ae802cb
2 changed files with 617 additions and 0 deletions

View File

@ -0,0 +1,133 @@
# include "gen.h"
# include "../h/dbs.h"
# include "../h/tree.h"
# include "../h/symbol.h"
struct proctemplate
{
char *proc_name;
int proc_code;
char proc_exec;
char proc_func;
};
static struct proctemplate Proc_template[] =
{
"copy", (int) mdCOPY, 0, 0,
"create", (int) mdCREATE, 0, 0,
"destroy", (int) mdDESTROY, 0, 0,
"display", (int) mdDISPLAY, 0, 0,
"help", (int) mdHELP, 0, 0,
"index", (int) mdINDEX, 0, 0,
"modify", (int) mdMODIFY, 0, 0,
"print", (int) mdPRINT, 0, 0,
"save", (int) mdSAVE, 0, 0,
"update", (int) mdUPDATE, 0, 0,
"resetrel", (int) mdRESETREL, 0, 0,
"remqm", (int) mdREMQM, 0, 0,
(char *) 0
};
init_proctab(proc, my_id)
char *proc;
char my_id;
/*
** Initialize from the run time process table
**
** Each entry in the proctable is seached for in the
** runtime process table. If an entry isn't found it
** is considered a AAsyserr. If an entry is found the
** first one which has an exec_id of "my_id" is taken.
** Otherwise, the very first entry given will be used.
*/
{
register struct proctemplate *pt;
register char *p;
register char *name;
char *found;
int i;
# ifdef xZTR1
AAtTfp(0, 0, "INIT_PTAB:\n");
# endif
for (pt = Proc_template; name = pt->proc_name; pt++)
{
i = AAlength(name);
p = proc;
found = (char *) 0;
while (*p)
{
if (AAbequal(p, name, i))
{
/* found a match. skip past the colon */
while (*p++ != ':')
continue;
/* look for an alias in this dbu */
found = p;
do
{
if (*p == my_id)
{
found = p;
break; /* found one */
}
p++;
p++;
} while (*p++ == ',');
# ifdef xZTR1
AAtTfp(0, 1, "%s: %.2s\n", name, found);
# endif
pt->proc_exec = *found++;
pt->proc_func = *found;
break;
}
/* skip to next */
while (*p++ != '\n')
continue;
}
if (!found)
AAsyserr(11017, name);
}
}
get_proctab(code, exec, func)
int code;
char *exec;
char *func;
/*
** Find the correct exec & func for a given code
*/
{
register struct proctemplate *p;
register int i;
i = code;
for (p = Proc_template; p->proc_name; p++)
{
if (i == p->proc_code)
{
/* found entry */
*exec = p->proc_exec;
*func = p->proc_func;
return;
}
}
/* entry not there */
AAsyserr(11018, i);
}

View File

@ -0,0 +1,484 @@
# include <stdio.h>
# include "gen.h"
# include "../h/dbs.h"
# include "../h/aux.h"
# include "../h/symbol.h"
# include "../h/tree.h"
# include "../h/pipes.h"
# include "decomp.h"
/*
** DECISION -- This file contains code related to deciding how to
** process the remaining query. The main routine is decision()
** and the other routines are called only by decision. The routine
** in this file include:
**
** Decision -- Decides how to process a query.
**
** Fixtl -- Determines the target list for each component.
**
** Fixresult -- Determines the result relation for the next query
**
** Fixrange -- Adjust the range table after a query
**
** Fixovlap -- Fixes trees in cases where reduction is used
**
** Rmovlap -- Restores trees in cases where reduction was used.
**
** Listcomp -- Debugging routine.
*/
decision(root, qmode, result_num, buf)
QTREE *root;
int qmode;
int result_num;
char *buf;
/*
** Decision is given a subquery and decides how to process it.
** The choices are:
** Disjoint pieces -- The original query had disjoint components.
** Do each component separately.
** Reduction -- The query is joined by a single variable.
** Reduce the query on that joining variable
** and do each component separately.
** Substitution -- The query is neither disjoint nor reducible.
** Process by tuple substitution.
**
** Notice that decision() is recursive and will call itself on each
** subcomponent it decides to do. Decision calls various support
** routines in the file "reduction.c".
*/
{
register QTREE **qp;
register struct complist *clist;
register int ovlapvar;
register struct complist *cp;
int i;
int onepiece;
int qtrue;
int map;
int mark;
int mark1;
int cand_map;
register QTREE *tree;
register QTREE *newtree;
QTREE *qlist[MAXRANGE];
int newqmode;
int ovlaprelnum;
int newr;
int locrange[MAXRANGE];
extern struct complist *buildlist();
extern struct complist *order();
extern QTREE *copy_ands();
extern QTREE *construct();
# ifdef xDTR1
AAtTfp(15, -1, "DECISION root=0%o,vc=%d,res=%d\n",
root, ((ROOT_NODE *) root)->tvarc, result_num);
# endif
mark = markbuf(buf);
if (((ROOT_NODE *) root)->tvarc < 3)
{
/* setup to do as one single piece */
onepiece = TRUE;
}
else
{
/* break the query apart if possible */
/* build component list */
clist = buildlist(root, buf);
# ifdef xDTR1
if (AAtTf(15, 2))
listcomp(clist, "Original Comp");
# endif
/* is query completely connected or disjoint */
map = ((ROOT_NODE *) root)->lvarm | ((ROOT_NODE *) root)->rvarm;
onepiece = algorithm(clist, map);
# ifdef xDTR1
AAtTfp(15, 1, "Orig query %s\n", onepiece ? "connected" : "disjoint");
# endif
/* assume there is no joining variable */
ovlapvar = -1;
if (onepiece)
{
/*
** Try to reduce a single connected piece.
** In turn each variable will be logically
** removed from the query and a test will
** be made to see if the query is still
** connected.
*/
cand_map = map;
for (i = 1; cand_map; i <<= 1)
{
if ((cand_map & i) == 0)
continue;
cand_map &= ~i;
freebuf(buf, mark);
clist = buildlist(root, buf);
if (algorithm(clist, map & ~i) == 0)
{
ovlapvar = bitpos(i);
ovlaprelnum = Rangev[ovlapvar].relnum;
onepiece = FALSE;
break;
}
}
# ifdef xDTR1
if (AAtTf(15, 1))
{
if (ovlapvar < 0)
printf("Query not reducible\n");
else
{
printf("Query Reducible on %d\n", ovlapvar);
if (AAtTf(15, 3))
listcomp(clist, "After reduct");
}
}
# endif
}
/*
** If query is more than one piece, build trees
** for each piece.
*/
if (!onepiece)
{
/* order pieces */
clist = order(clist, ovlapvar);
# ifdef xDTR1
if (AAtTf(15, 4))
listcomp(clist, "After ordering");
# endif
cp = clist;
qp = qlist;
do
{
*qp++ = construct(root, cp, buf);
} while (cp = cp->nextcomp);
*qp++ = 0;
}
}
/*
** The query is now either the one original piece or
** is in multiple pieces. The information in clist
** is no longer needed and now the ordered pieces
** will be processed.
*/
if (onepiece)
{
freebuf(buf, mark);
qtrue = decompy(root, qmode, result_num, buf);
}
else
{
/* the query is in pieces. prepare to process */
newquery(locrange); /* save state of range table */
/* determine the target list for each piece of the query */
for (qp = qlist; tree = *qp++; )
fixtl(tree, qp, ovlapvar, buf);
/* adjust refs to ovlapvar since domain #'s could have changed */
fixovlap(qlist, ovlapvar, buf);
/* now process each component */
mark1 = markbuf(buf);
for (qp = qlist; tree = *qp++; )
{
# ifdef xDTR1
if (AAtTf(15, 6))
printree(tree, "Next piece");
# endif
/* determine result relation name */
newr = fixresult(root, tree, &newqmode, qmode, result_num);
/*
** Run the query. If reduction is being
** performed, the actual tree given to
** the decision routine must be a copy
** to protect from the recursive call changing
** the tree. Any work done at this level,
** must be to the original tree
*/
newtree = tree;
if (ovlapvar != -1)
{
freebuf(buf, mark1);
newtree = copy_ands(tree, buf);
}
qtrue = decision(newtree, newqmode, newr, buf);
/* fix up the range table */
fixrange(root, tree, ovlapvar, ovlaprelnum, newr);
/* if last piece was false then done */
if (!qtrue)
break;
}
/* restore the trees */
rmovlap(qlist, ovlapvar);
/* restore range table back to original */
endquery(locrange, TRUE); /* reopen previous range */
/* return any buffer space used */
freebuf(buf, mark);
}
/* all done with query */
return (qtrue);
}
fixresult(root, tree1, newmode, origmode, resnum)
QTREE *root;
QTREE *tree1;
int *newmode;
int origmode;
int resnum;
/*
** Fixresult -- Determine result relation for 'tree' query.
** If 'tree' is the original target list piece then use the
** original relation and mode.
** If 'tree' is a reduction piece then create a temporary relation
** for it.
** If 'tree' is a disjoint piece then there is no target list nor
** result relation.
**
** Return:
** result relation number
** Side Effects:
** *newmode is set to the query mode of the next piece
*/
{
register QTREE *tree;
register int newresult;
tree = tree1;
*newmode = (int) mdRETR;
if (tree->left->sym.type != TREE)
{
if (tree != root)
{
/* make new result for reduction step */
newresult = mak_t_rel(tree, "r", -1);
}
else
{
/* final piece with original result and mode */
newresult = resnum;
*newmode = origmode;
}
}
else
newresult = NORESULT;
return (newresult);
}
fixrange(root, tree, ovlapvar, reductnum, newrelnum)
QTREE *root;
QTREE *tree;
int ovlapvar;
int reductnum;
int newrelnum;
/*
** Update range table after a reduction has been processed.
** Only the intermiediate reductions will affect the range
** table. The last piece does not.
*/
{
register int old;
register int i;
if (root != tree)
{
/* this is an intermediate piece */
i = ovlapvar;
if (newrelnum >= 0)
{
old = new_range(i, newrelnum);
if (old != reductnum)
dstr_rel(old);
openr1(i);
}
}
}
fixovlap(qlist, ovlapvar, buf)
QTREE *qlist[];
int ovlapvar;
char *buf;
/*
** Fixovlap -- Adjust subsequent trees which reference the reduction var
**
** If the first query in list redefines the reduction variable
** (if any) then each subsequent query which references the
** reduction variable is adjusted.
** Since there may be multiple pieces,
** subsequence redefinitions are done without
** reallocating buffer space.
**
*/
{
register QTREE **qp;
register QTREE *piece;
register QTREE **qp1;
register QTREE *next;
register int ovmap;
ovmap = 1 << ovlapvar;
/* for each piece, if it redefines ovlapvar, then fix up rest */
for (qp = qlist; piece = *qp++; )
{
if (((ROOT_NODE *) piece)->lvarm & ovmap)
{
for (qp1 = qp; next = *qp1++; )
{
if ((((ROOT_NODE *) next)->lvarm | ((ROOT_NODE *) next)->rvarm) & ovmap)
{
tempvar(next, mksqlist(piece, ovlapvar), buf);
buf = (char *) 0; /* do not allocate on subsequent refs */
}
}
}
}
}
rmovlap(qlist, ovlapvar)
QTREE *qlist[];
int ovlapvar;
/*
** Rmovlap -- Restore query trees back to their original state.
**
** Rmovlap undoes the effect of fixovlap(). Any references
** to the reduction variable which were adjusted are now
** reverted back to the original reference. Note that the
** first piece is not effected by fixovlap.
*/
{
register QTREE **qp;
register QTREE *tree;
if (1 << ovlapvar)
{
/* for each piece, remove any tempvars */
for (qp = &qlist[1]; tree = *qp++; )
origvar(tree, mksqlist(tree, ovlapvar));
}
}
fixtl(tree1, qp1, ovlapvar, buf)
QTREE *tree1;
QTREE *qp1[];
int ovlapvar;
char *buf;
/*
** Fixtl -- Determine what the target list of each tree should be.
**
** Fixtl takes each query which references the reduction variable
** and looks for references to that variable in subsequent queries.
** Dfind will build a target list which includes every domain
** which will later be referenced.
*/
{
register QTREE *tree;
register QTREE **qp;
register QTREE *next;
register int var;
register int map;
tree = tree1;
var = ovlapvar;
map = 1 << var;
/*
** if the last tree referenced the overlap variable then
** try to fix next tree
*/
if (((ROOT_NODE *) tree)->rvarm & map)
{
qp = qp1;
while (next = *qp++)
{
if ((((ROOT_NODE *) next)->lvarm | ((ROOT_NODE *) next)->rvarm) & map)
dfind(next, buf, mksqlist(tree, var));
}
}
}
# ifdef xDTR1
listcomp(list, mesg)
struct complist *list;
char *mesg;
/*
** This is strictly a debuggin routine used for
** printing component lists.
*/
{
register struct complist *c;
register struct complist *cl;
register int i;
if (AAtTfp(15, 14, "%s\n", mesg))
{
i = -1;
for (cl = list; cl; cl = cl->nextcomp)
{
i++;
printf("Component %d:map=0%o\n", i, cl->bitmap);
for (c = cl; c; c = c->linkcomp)
{
printf("0%o, ", c->clause);
if (AAtTf(15, 15))
{
printree(c->clause->left, "");
writenod(c->clause);
}
}
putchar('\n');
}
}
}
# endif