# include # include # include # include # include "globs.h" # include SCCSID(@(#)pull_sq.c 8.1 12/31/84) /* ** DECOMP1.C ** ** contains routines associated with setting up ** detachable 1-variable sub-queries. ** ptrs to these sq's are kept in the ** array 'sqlist' declared in the main decomp routine. ** ** Trace Flags: ** 34 */ pull_sq(tree1, sqlist, locrang, sqrange, buf) QTREE *tree1; QTREE *sqlist[]; int locrang[]; int sqrange[]; char *buf; { register QTREE *q, *tree, *r; QTREE *s; int anysq, j, badvar; extern QTREE *makroot(); tree = tree1; # ifdef xDTR1 if (tTf(34, 0)) printf("PULL_SQ:tree=%x\n", tree); # endif anysq = 0; for (j = 0; j < MAXRANGE; j++) sqlist[j] = 0; if (tree->sym.value.sym_root.tvarc == 1) return; /* detach all one variable clauses except: ** if the target list is one variable and ** that variable is disjoint from the other ** variables, then don't pull it. ** ** It will be more efficient to process it ** all at once in decompy */ badvar = 0; if (tree->sym.value.sym_root.lvarc == 1) { badvar = tree->sym.value.sym_root.lvarm; /* get bit position of var */ /* look for a two variable clause involving badvar */ for (r = tree->right; r->sym.type != QLEND; r = r->right) { if (r->sym.value.sym_root.lvarc > 1 && (r->sym.value.sym_root.lvarm & badvar)) { badvar = 0; break; } } } # ifdef xDTR1 if (tTf(34, 2)) printf("Detachable clauses: (badvar=%o)\n", badvar); # endif for (r=tree; r->right->sym.type!=QLEND; ) { # ifdef xDTR1 if (tTf(34, 3)) nodepr(r); # endif q = r; r = r->right; if (r->sym.value.sym_root.lvarc == 1) { j = bitpos(r->sym.value.sym_root.lvarm); # ifdef xDTR1 if (tTf(34, 4)) { printf("\nvar=%d, clause\n", j); treepr(r->left); } # endif if (r->sym.value.sym_root.lvarm == badvar) { # ifdef xDTR1 if (tTf(34, 5)) printf("not detaching \n"); # endif continue; } anysq++; if (!sqlist[j]) /* MAKE ROOT NODE FOR SUBQUERY */ sqlist[j] = makroot(buf); s = sqlist[j]; /* MODIFY MAIN QUERY */ q->right = r->right; /* MODIFY `AND` NODE OF DETACHED CLAUSE */ r->right = s->right; r->sym.value.sym_root.rvarm = s->sym.value.sym_root.rvarm; r->sym.value.sym_root.tvarc = 1; /* ADD CLAUSE TO SUB-QUERY */ s->right = r; s->sym.value.sym_root.rvarm = r->sym.value.sym_root.lvarm; s->sym.value.sym_root.tvarc = 1; # ifdef xDTR1 if (tTf(34, 6)) { printf("SQ\n"); treepr(s); } # endif r = q; } } /* NOW SET UP TARGET LIST FOR EACH SUBQUERY IN SQLIST */ # ifdef xDTR1 if (tTf(34, 7)) printf("# sq clauses=%d\n", anysq); # endif if (anysq) { # ifdef xDTR1 if (tTf(34, 8)) printf("Dfind--\n"); # endif dfind(tree, buf, sqlist); mapvar(tree, 1); /* create the result relations */ for (j = 0; j < MAXRANGE; j++) { if (q = sqlist[j]) { if (q->left->sym.type != TREE) { savrang(locrang, j); sqrange[j] = mak_t_rel(q, "d", -1); } else sqrange[j] = NORESULT; } } } } /* ** DFIND */ dfind(tree, buf, sqlist) register QTREE *tree; char *buf; QTREE *sqlist[]; { register char varno; register QTREE *sq; extern QTREE *ckvar(); if (tree == NULL) return; # ifdef xDTR1 if (tTf(34, 9)) nodepr(tree); # endif if (tree->sym.type == VAR) { tree = ckvar(tree); varno = tree->sym.value.sym_var.varno; if (sq = sqlist[varno]) maktl(tree, buf, sq, varno); return; } /* IF CURRENT NODE NOT A `VAR` WITH SQ, RECURSE THRU REST OF TREE */ dfind(tree->left, buf, sqlist); dfind(tree->right, buf, sqlist); return; } /* ** MAKTL */ maktl(node, buf, sq1, varno) QTREE *node; char *buf; QTREE *sq1; int varno; { register QTREE *resdom, *tree, *sq; int domno, map; extern QTREE *makresdom(); extern QTREE *copytree(); sq = sq1; domno = node->sym.value.sym_var.attno; # ifdef xDTR1 if (tTf(34, 12)) printf("\tVar=%d,Dom=%d ", varno, domno); # endif /* CHECK IF NODE ALREADY CREATED FOR THIS DOMAIN */ for (tree = sq->left; tree->sym.type != TREE; tree = tree->left) if (tree->right->sym.value.sym_var.attno == domno) { # ifdef xDTR1 if (tTf(34, 13)) printf("Domain found\n"); # endif return; } /* create a new resdom for domain */ resdom = makresdom(buf, node); resdom->sym.value.sym_resdom.resno = sq->left->sym.type == TREE? 1: sq->left->sym.value.sym_resdom.resno + 1; /* resdom->right is a copy of the var node in order to ** protect against tempvar() changing the var node. */ resdom->left = sq->left; resdom->right = copytree(node, buf); /* update ROOT node if necessary */ sq->left = resdom; map = 1 << varno; if (!(sq->sym.value.sym_root.lvarm & map)) { /* var not currently in tl */ sq->sym.value.sym_root.lvarm |= map; sq->sym.value.sym_root.lvarc++; /* if var is not in qualification then update total count */ if (!(sq->sym.value.sym_root.rvarm & map)) sq->sym.value.sym_root.tvarc++; # ifdef xDTR1 if (tTf(34, 15)) { printf("new root "); nodepr(sq); } # endif } # ifdef xDTR1 if (tTf(34, 14)) { printf("new dom "); nodepr(resdom); } # endif return; }