# include # include # include # include # include "globs.h" # include # include SCCSID(@(#)decomp.c 8.3 12/18/85) /* ** DECOMP -- Process a query given a query tree and range table. ** ** Decomp processes any arbitrary query by converting it into ** a sequence of "one variable queries"; eg. queries involving ** at most one source relation. This file and decision.c contain ** the principle decision making routines. ** ** Decomp() is called with a pointer to a query tree, the mode ** of the query (retrieve, append, etc.), and the internal name ** of the result relation (if any). The routines included are: ** ** Decomp -- Opens the source relations and decides whether the ** query is multi-variable or single/zero variable. ** ** Decompx -- Takes a multivariable query, removes and executes any ** one-var restrictions and passes the remaining query ** to decompz (if one/zero variable) or decision(). ** ** Decompy -- Performs "tuple substitution" on a multi-var query, ** does any new one-var restrictions and passes the ** remaining query to decompz (if one/zero variable) ** or decision(). ** ** Decompz -- Executes a one/zero variable query by calling call_ovqp(). */ /* ** Process query by calling either decompx for multivar ** or decompz for 0 or 1 var query. Decomp() must guarantee ** that the range table is the same upon exiting as it was ** when entered. Newquery() and endquery() perform that function. ** ** Trace Flags: ** 30 */ decomp(q, qmode, result_num) QTREE *q; int qmode; int result_num; { register QTREE *root; register int vc, i; int locrange[MAXRANGE]; root = q; vc = root->sym.value.sym_root.tvarc; # ifdef xDTR1 if (tTf(30, 0)) printf("DECOMP: %d-var query, result_num=%d\n", vc, result_num); if (tTf(30, 1)) { printf("DECOMP\n"); treepr(root); } # endif openrs(root); if (vc > 1) { newquery(locrange); i = decompx(root, qmode, result_num); endquery(locrange, FALSE); /* don't reopen previous range */ } else { De.de_newq = 1; De.de_sourcevar = -1; i = decompz(root, qmode, result_num); } /* ** remove the range variables that the view subsystem ** might have placed in. */ clrrange(); return (i); } /* ** Decompx -- Initialize for multi-variable query. ** All one-variable subqueries are run. ** If the remaining query is still multi-var ** then decision() is called; else decompz() ** is called. The range table is restored ** after the query is complete. ** The tempvars from the exec_sq() are left on the ** tree since it is presumed that the tree will be discarded ** anyway. ** ** Trace Flags: ** 31 */ decompx(root, qmode, result_num) QTREE *root; int qmode; int result_num; { register int i, vc; int disj; int sqbuf[1+SQSIZ/sizeof(int)]; QTREE *sqlist[MAXRANGE]; int locrang[MAXRANGE], sqrange[MAXRANGE]; extern int derror(); vc = root->sym.value.sym_root.tvarc; initbuf((char *)sqbuf, SQSIZ, SQBUFFULL, derror); pull_sq(root, sqlist, locrang, sqrange, (char *)sqbuf); if ((i = exec_sq(sqlist, sqrange, &disj)) != -1) { undo_sq(sqlist, locrang, sqrange, i, i, FALSE); return (FALSE); } vc -= disj; tempvar(root, sqlist, (char *)sqbuf); if (pull_const(root, (char *)sqbuf) == 0) return (FALSE); if (vc <= 1) { De.de_sourcevar = -1; De.de_newq = 1; return (decompz(root, qmode, result_num)); } i = decision(root, qmode, result_num, (char *)sqbuf); undo_sq(sqlist, locrang, sqrange, MAXRANGE, MAXRANGE, FALSE); return (i); } /* ** Decompy -- decompose a multi-variable query by tuple substitution. ** First a variable is selected ** for substitution. Then for each tuple in the ** selected variable, all one variable restrictions ** are done (exec_sq) and the remaining query is ** solved by calling either decompz() or recursively ** decision(). ** ** The original tree and range table are guaranteed to ** be the same on entry and exit (modulo the effects of ** reformat()). ** ** Trace Flags: ** 32 */ decompy(q, qmode, result_num, sqbuf) QTREE *q; int qmode; int result_num; char *sqbuf; { register QTREE *root; register int j, vc; DESC *d; QTREE *newroot; int constl, sqcnt, var, srcvar, maxsqcnt; int disj, tc, qtrue; TID tid, hitid; char *tuple; QTREE *sqlist[MAXRANGE]; int sqmark, sqmark1; int locrang[MAXRANGE], sqrange[MAXRANGE]; extern DESC *readopen(); extern char *need(), *rangename(); extern QTREE *copy_ands(); root = q; vc = root->sym.value.sym_root.tvarc; # ifdef xDTR1 if (tTf(32, -1)) printf("DECOMPY:%x,vc=%d\n", root, vc); # endif sqmark = markbuf(sqbuf); constl = !root->sym.value.sym_root.lvarc; qtrue = FALSE; if ((var = selectv(root)) < 0) return (qtrue); d = readopen(var); /* gets full descriptor for setvar & get */ tuple = need(sqbuf, d->reldum.relwid); setvar(root, var, &tid, tuple); pull_sq(root, sqlist, locrang, sqrange, sqbuf); tempvar(root, sqlist, sqbuf); reformat(var, sqlist, locrang, sqbuf, root); vc--; # ifdef xDTR2 if (tTf(32, 0)) { printf("DECOMPY: &tup=%x, ", tuple); printdesc(d); } # endif xDTR2 /* HERE FOR MULTI-VAR SUBSTITUTION */ sqmark1 = markbuf(sqbuf); De.de_newq = 1; tc = 0; sqcnt = maxsqcnt = 0; srcvar = -1; De.de_sourcevar = -1; find(readopen(var), NOKEY, &tid, &hitid); while (!(j=get(readopen(var), &tid, &hitid, tuple, NXTTUP))) { # ifdef xDTR1 if (tTf(32, 2)) { printf("Subst:"); printup(readopen(var), tuple); } # endif tc++; if (vc > 1) { reset_sq(sqlist, locrang, sqcnt); if ((sqcnt = exec_sq(sqlist, sqrange, &disj)) != -1) continue; maxsqcnt = sqcnt; vc -= disj; if (vc <= 1) { De.de_sourcevar = srcvar; qtrue |= decompz(root, qmode, result_num); srcvar = De.de_sourcevar; } else { freebuf(sqbuf, sqmark1); newroot = copy_ands(root, sqbuf); qtrue |= decision(newroot, qmode, result_num, sqbuf); } vc += disj; } else qtrue |= decompz(root, qmode, result_num); /* check for early termination on constant Target list */ if (constl && qtrue) break; } if (j < 0) syserr("decompy: bad get %d on %.12s", j, readopen(var)->reldum.relid); /* undo the effect of pulling the sub queries */ origvar(root, sqlist); undo_sq(sqlist, locrang, sqrange, sqcnt, maxsqcnt, TRUE); /* undo the setvar on the main tree and all subtrees */ clearvar(root, var); for (j = 0; j < MAXRANGE; j++) clearvar(sqlist[j], var); /* return any used buffer space */ freebuf(sqbuf, sqmark); # ifdef xDTR1 if (tTf(32, 2)) printf("tc[%.12s]=%d,qtrue=%d\n", rangename(var), tc, qtrue); # endif return (qtrue); } /* ** Decompz processes a one variable query ** by calling call_ovqp(). ** ** Trace Flags: ** 33 */ decompz(q, qmode, result_num) QTREE *q; int qmode; int result_num; { register QTREE *root; register int qualfound; root = q; if (root->sym.value.sym_root.tvarc) { if (De.de_sourcevar < 0) { if ((De.de_sourcevar = selectv(root)) < 0) return (FALSE); } } else { De.de_sourcevar = -1; } qualfound = call_ovqp(root, qmode, result_num); De.de_newq = 0; return (qualfound); }