|
|
1.1 ! root 1: # include <ingres.h> ! 2: # include <symbol.h> ! 3: # include <aux.h> ! 4: # include <tree.h> ! 5: # include "globs.h" ! 6: # include <sccs.h> ! 7: ! 8: SCCSID(@(#)decision.c 7.1 2/5/81) ! 9: ! 10: /* ! 11: ** DECISION -- This file contains code related to deciding how to ! 12: ** process the remaining query. The main routine is decision() ! 13: ** and the other routines are called only by decision. The routine ! 14: ** in this file include: ! 15: ** ! 16: ** Decision -- Decides how to process a query. ! 17: ** ! 18: ** Fixtl -- Determines the target list for each component. ! 19: ** ! 20: ** Fixresult -- Determines the result relation for the next query ! 21: ** ! 22: ** Fixrange -- Adjust the range table after a query ! 23: ** ! 24: ** Fixovlap -- Fixes trees in cases where reduction is used ! 25: ** ! 26: ** Rmovlap -- Restores trees in cases where reduction was used. ! 27: ** ! 28: ** Listcomp -- Debugging routine. ! 29: */ ! 30: /* ! 31: ** Decision is given a subquery and decides how to process it. ! 32: ** The choices are: ! 33: ** Disjoint pieces -- The original query had disjoint components. ! 34: ** Do each component separately. ! 35: ** Reduction -- The query is joined by a single variable. ! 36: ** Reduce the query on that joining variable ! 37: ** and do each component separately. ! 38: ** Substitution -- The query is neither disjoint nor reducible. ! 39: ** Process by tuple substitution. ! 40: ** ! 41: ** Notice that decision() is recursive and will call itself on each ! 42: ** subcomponent it decides to do. Decision calls various support ! 43: ** routines in the file "reduction.c". ! 44: */ ! 45: ! 46: decision(root, qmode, result_num, buf) ! 47: QTREE *root; ! 48: int qmode; ! 49: int result_num; ! 50: char *buf; ! 51: { ! 52: register QTREE **qp; ! 53: register struct complist *clist; ! 54: register int ovlapvar; ! 55: struct complist *cp; ! 56: int i, onepiece, qtrue, map; ! 57: int mark, mark1, cand_map; ! 58: QTREE *tree, *newtree; ! 59: QTREE *qlist[MAXRANGE]; ! 60: int newqmode; ! 61: int ovlaprelnum, newr; ! 62: int locrange[MAXRANGE]; ! 63: extern QTREE *copy_ands(); ! 64: extern struct complist *buildlist(), *order(); ! 65: extern QTREE *construct(); ! 66: ! 67: # ifdef xDTR1 ! 68: if (tTf(37, -1)) ! 69: { ! 70: printf("DECISION root=%x,vc=%d,res=%d\n", root, root->sym.value.sym_root.tvarc, result_num); ! 71: } ! 72: # endif ! 73: mark = markbuf(buf); ! 74: if (root->sym.value.sym_root.tvarc < 3) ! 75: { ! 76: /* setup to do as one single piece */ ! 77: onepiece = TRUE; ! 78: } ! 79: else ! 80: { ! 81: /* break the query apart if possible */ ! 82: ! 83: /* build component list */ ! 84: clist = buildlist(root, buf); ! 85: # ifdef xDTR1 ! 86: if (tTf(37, 2)) ! 87: listcomp(clist, "Original Comp"); ! 88: # endif ! 89: ! 90: /* is query completely connected or disjoint */ ! 91: map = root->sym.value.sym_root.lvarm | root->sym.value.sym_root.rvarm; ! 92: onepiece = algorithm(clist, map); ! 93: # ifdef xDTR1 ! 94: if (tTf(37, 1)) ! 95: printf("Orig query %s\n", onepiece ? "connected" : "disjoint"); ! 96: # endif ! 97: /* assume there is no joining variable */ ! 98: ovlapvar = -1; ! 99: ! 100: if (onepiece) ! 101: { ! 102: /* ! 103: ** Try to reduce a single connected piece. ! 104: ** In turn each variable will be logically ! 105: ** removed from the query and a test will ! 106: ** be made to see if the query is still ! 107: ** connected. ! 108: */ ! 109: ! 110: cand_map = map; ! 111: for (i = 1; cand_map; i <<= 1) ! 112: { ! 113: if ((cand_map & i) == 0) ! 114: continue; ! 115: cand_map &= ~i; ! 116: freebuf(buf, mark); ! 117: clist = buildlist(root, buf); ! 118: if (algorithm(clist, map & ~i) == 0) ! 119: { ! 120: ovlapvar = bitpos(i); ! 121: ovlaprelnum = De.de_rangev[ovlapvar].relnum; ! 122: onepiece = FALSE; ! 123: break; ! 124: } ! 125: } ! 126: # ifdef xDTR1 ! 127: if (tTf(37, 1)) ! 128: { ! 129: if (ovlapvar < 0) ! 130: printf("Query not reducible\n"); ! 131: else ! 132: { ! 133: printf("Query Reducible on %d\n", ovlapvar); ! 134: if (tTf(37, 3)) ! 135: listcomp(clist, "After reduct"); ! 136: } ! 137: } ! 138: # endif ! 139: } ! 140: ! 141: /* ! 142: ** If query is more than one piece, build trees ! 143: ** for each piece. ! 144: */ ! 145: ! 146: if (!onepiece) ! 147: { ! 148: /* order pieces */ ! 149: clist = order(clist, ovlapvar); ! 150: # ifdef xDTR1 ! 151: if (tTf(37, 4)) ! 152: listcomp(clist, "After ordering"); ! 153: # endif ! 154: cp = clist; ! 155: qp = qlist; ! 156: do ! 157: { ! 158: *qp++ = construct(root, cp, buf); ! 159: } while (cp = cp->nextcomp); ! 160: *qp++ = 0; ! 161: } ! 162: } ! 163: ! 164: /* ! 165: ** The query is now either the one original piece or ! 166: ** is in multiple pieces. The information in clist ! 167: ** has been thrown away and now the ordered pieces ! 168: ** will be processed. ! 169: */ ! 170: ! 171: if (onepiece) ! 172: { ! 173: freebuf(buf, mark); ! 174: qtrue = decompy(root, qmode, result_num, buf); ! 175: } ! 176: else ! 177: { ! 178: /* the query is in pieces. prepare to process */ ! 179: ! 180: newquery(locrange); /* save state of range table */ ! 181: ! 182: /* determine the target list for each piece of the query */ ! 183: for (qp = qlist; tree = *qp++; ) ! 184: fixtl(tree, qp, ovlapvar, buf); ! 185: ! 186: /* adjust refs to ovlapvar since domain #'s could have changed */ ! 187: fixovlap(qlist, ovlapvar, buf); ! 188: ! 189: ! 190: /* now process each component */ ! 191: mark1 = markbuf(buf); ! 192: for (qp = qlist; tree = *qp++; ) ! 193: { ! 194: ! 195: # ifdef xDTR1 ! 196: if (tTf(37, 6)) ! 197: { ! 198: printf("next piece\n"); ! 199: treepr(tree); ! 200: } ! 201: # endif ! 202: ! 203: /* determine result relation name */ ! 204: newr = fixresult(root, tree, &newqmode, qmode, result_num); ! 205: ! 206: /* ! 207: ** Run the query. If reduction is being ! 208: ** performed, the actual tree given to ! 209: ** the decision routine must be a copy ! 210: ** to protect from the recursive call changing ! 211: ** the tree. Any work done at this level, ! 212: ** must be to the original tree ! 213: */ ! 214: newtree = tree; ! 215: if (ovlapvar != -1) ! 216: { ! 217: freebuf(buf, mark1); ! 218: newtree = copy_ands(tree, buf); ! 219: } ! 220: qtrue = decision(newtree, newqmode, newr, buf); ! 221: ! 222: /* fix up the range table */ ! 223: fixrange(root, tree, ovlapvar, ovlaprelnum, newr); ! 224: ! 225: /* if last piece was false then done */ ! 226: if (!qtrue) ! 227: break; ! 228: ! 229: } ! 230: ! 231: /* restore the trees */ ! 232: rmovlap(qlist, ovlapvar); ! 233: ! 234: /* restore range table back to original */ ! 235: endquery(locrange, TRUE); /* reopen previous range */ ! 236: ! 237: /* return any buffer space used */ ! 238: freebuf(buf, mark); ! 239: } ! 240: ! 241: /* all done with query */ ! 242: return (qtrue); ! 243: } ! 244: /* ! 245: ** Fixresult -- Determine result relation for "tree" query. ! 246: ** If "tree" is the original target list piece then use the ! 247: ** original relation and mode. ! 248: ** If "tree" is a reduction piece then create a temporary relation ! 249: ** for it. ! 250: ** If "tree" is a disjoint piece then there is no target list nor ! 251: ** result relation. ! 252: ** ! 253: ** Return: ! 254: ** result relation number ! 255: ** Side Effects: ! 256: ** *newmode is set to the query mode of the next piece ! 257: */ ! 258: ! 259: fixresult(root, tree1, newmode, origmode, resnum) ! 260: QTREE *root; ! 261: QTREE *tree1; ! 262: int *newmode; ! 263: int origmode; ! 264: int resnum; ! 265: { ! 266: register QTREE *tree; ! 267: register int newresult; ! 268: ! 269: tree = tree1; ! 270: *newmode = mdRETR; ! 271: if (tree->left->sym.type != TREE) ! 272: { ! 273: if (tree != root) ! 274: { ! 275: /* make new result for reduction step */ ! 276: newresult = mak_t_rel(tree, "r", -1); ! 277: } ! 278: else ! 279: { ! 280: /* final piece with original result and mode */ ! 281: newresult = resnum; ! 282: *newmode = origmode; ! 283: } ! 284: } ! 285: else ! 286: newresult = NORESULT; ! 287: return (newresult); ! 288: } ! 289: /* ! 290: ** Update range table after a reduction has been processed. ! 291: ** Only the intermediate reductions will affect the range ! 292: ** table. The last piece does not. ! 293: */ ! 294: ! 295: fixrange(root, tree, ovlapvar, reductnum, newrelnum) ! 296: QTREE *root; ! 297: QTREE *tree; ! 298: int ovlapvar; ! 299: int reductnum; ! 300: int newrelnum; ! 301: { ! 302: register int old; ! 303: register int i; ! 304: extern DESC *openr1(); ! 305: ! 306: if (root != tree) ! 307: { ! 308: /* this is an intermediate piece */ ! 309: i = ovlapvar; ! 310: ! 311: if (newrelnum >= 0) ! 312: { ! 313: old = new_range(i, newrelnum); ! 314: if (old != reductnum) ! 315: dstr_rel(old); ! 316: openr1(i); ! 317: } ! 318: } ! 319: } ! 320: /* ! 321: ** Fixovlap -- Adjust subsequent trees which reference the reduction var ! 322: ** ! 323: ** If the first query in list redefines the reduction variable ! 324: ** (if any) then each subsequent query which references the ! 325: ** reduction variable is adjusted. ! 326: ** Since there may be multiple pieces, ! 327: ** subsequence redefinitions are done without ! 328: ** reallocating buffer space. ! 329: ** ! 330: */ ! 331: ! 332: fixovlap(qlist, ovlapvar, buf) ! 333: QTREE *qlist[]; ! 334: int ovlapvar; ! 335: char *buf; ! 336: { ! 337: register QTREE **qp, *piece, **qp1; ! 338: QTREE *next; ! 339: int ovmap; ! 340: extern QTREE **mksqlist(); ! 341: ! 342: ovmap = 1 << ovlapvar; ! 343: ! 344: /* for each piece, if it redefines ovlapvar, then fix up rest */ ! 345: for (qp = qlist; piece = *qp++; ) ! 346: { ! 347: if (piece->sym.value.sym_root.lvarm & ovmap) ! 348: { ! 349: for (qp1 = qp; next = *qp1++; ) ! 350: { ! 351: if ((next->sym.value.sym_root.lvarm | next->sym.value.sym_root.rvarm) & ovmap) ! 352: { ! 353: tempvar(next, mksqlist(piece, ovlapvar), buf); ! 354: buf = NULL; /* do not allocate on subsequent refs */ ! 355: } ! 356: } ! 357: } ! 358: } ! 359: } ! 360: /* ! 361: ** Rmovlap -- Restore query trees back to their original state. ! 362: ** ! 363: ** Rmovlap undoes the effect of fixovlap(). Any references ! 364: ** to the reduction variable which were adjusted are now ! 365: ** reverted back to the original reference. Note that the ! 366: ** first piece is not effected by fixovlap. ! 367: */ ! 368: ! 369: rmovlap(qlist, ovlapvar) ! 370: QTREE *qlist[]; ! 371: int ovlapvar; ! 372: { ! 373: register QTREE **qp, *tree; ! 374: int ovmap; ! 375: ! 376: if (ovmap = (1 << ovlapvar)) ! 377: { ! 378: /* for each piece, remove any tempvars */ ! 379: for (qp = &qlist[1]; tree = *qp++; ) ! 380: { ! 381: origvar(tree, mksqlist(tree, ovlapvar)); ! 382: } ! 383: } ! 384: } ! 385: /* ! 386: ** Fixtl -- Determine what the target list of each tree should be. ! 387: ** ! 388: ** Fixtl takes each query which references the reduction variable ! 389: ** and looks for references to that variable in subsequent queries. ! 390: ** Dfind will build a target list which includes every domain ! 391: ** which will later be referenced. ! 392: */ ! 393: ! 394: fixtl(tree1, qp1, ovlapvar, buf) ! 395: QTREE *tree1; ! 396: QTREE *qp1[]; ! 397: int ovlapvar; ! 398: char *buf; ! 399: { ! 400: register QTREE *tree, **qp, *next; ! 401: int var, map; ! 402: extern QTREE **mksqlist(); ! 403: ! 404: tree = tree1; ! 405: var = ovlapvar; ! 406: map = 1 << var; ! 407: ! 408: /* ! 409: ** if the last tree referenced the overlap variable then ! 410: ** try to fix next tree ! 411: */ ! 412: if (tree->sym.value.sym_root.rvarm & map) ! 413: { ! 414: qp = qp1; ! 415: while (next = *qp++) ! 416: { ! 417: if ((next->sym.value.sym_root.lvarm | next->sym.value.sym_root.rvarm) & map) ! 418: dfind(next, buf, mksqlist(tree, var)); ! 419: } ! 420: } ! 421: } ! 422: ! 423: ! 424: ! 425: # ifdef xDTR1 ! 426: ! 427: /* ! 428: ** This is strictly a debuggin routine used for ! 429: ** printing component lists. ! 430: */ ! 431: ! 432: listcomp(list, mesg) ! 433: struct complist *list; ! 434: char *mesg; ! 435: { ! 436: register struct complist *c, *cl; ! 437: register int i; ! 438: ! 439: if (tTf(37, 14)) ! 440: { ! 441: printf("%s\n", mesg); ! 442: i = -1; ! 443: ! 444: for (cl = list; cl; cl = cl->nextcomp) ! 445: { ! 446: i++; ! 447: printf("Component %d:map=%o\n", i, cl->bitmap); ! 448: for (c = cl; c; c = c->linkcomp) ! 449: { ! 450: printf("%x, ", c->clause); ! 451: if (tTf(37, 15)) ! 452: { ! 453: treepr(c->clause->left); ! 454: nodepr(c->clause); ! 455: } ! 456: } ! 457: printf("\n"); ! 458: } ! 459: } ! 460: } ! 461: # endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.