|
|
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(@(#)reduction.c 7.1 2/5/81) ! 9: ! 10: /* ! 11: ** Reduction -- This file contains routines related to the ! 12: ** reduction algorithm. The routines are all called by ! 13: ** decision(). ! 14: ** ! 15: ** Included are: ! 16: ** ! 17: ** algorithm -- groups clauses according to common variables ! 18: ** ! 19: ** buildlist -- build linked list of clauses from a query tree ! 20: ** ! 21: ** construct -- build query trees from link lists of clauses ! 22: ** ! 23: ** order -- order a linked list of clauses into the prefered ! 24: ** execution sequence ! 25: */ ! 26: /* ! 27: ** Algorithm - determine whether query is connected or not ! 28: ** ! 29: ** Algorithm takes a linked list of query components ! 30: ** and groups them according to the variables involved ! 31: ** in each component. If the query is fully interconnected ! 32: ** then algorithm returns TRUE else it returns FALSE. ! 33: ** ! 34: ** By definition a constant clause (one involving zero variables) ! 35: ** is considered to use all variables. Without this rule, ! 36: ** a query with a null target list would always break into ! 37: ** two pieces. ! 38: ** ! 39: ** Whether a query is fully connected is independent ! 40: ** of whether there are any one variable components ! 41: ** or not. This includes the target list. After applying ! 42: ** the algorithm, a scan is made to see how many multi-var ! 43: ** components are present. If there are two or more multi-var ! 44: ** components then the query is disconnected. ! 45: ** ! 46: ** Trace Flags: ! 47: ** 38 ! 48: */ ! 49: ! 50: algorithm(clist, varmap) ! 51: struct complist *clist; ! 52: int varmap; ! 53: { ! 54: register struct complist *chead, *cnext; ! 55: register int var; ! 56: int vmap; ! 57: struct complist *cprev, *cl; ! 58: ! 59: vmap = varmap; ! 60: for (var = 1; vmap; var <<= 1) ! 61: { ! 62: if ((vmap & var) == 0) ! 63: continue; ! 64: vmap &= ~var; /* remove var */ ! 65: ! 66: /* done if query is already a single piece */ ! 67: if (clist->nextcomp == 0) ! 68: break; ! 69: ! 70: /* find first component using variable var */ ! 71: for (chead = clist; chead; chead = chead->nextcomp) ! 72: { ! 73: if (chead->bitmap == 0 || (chead->bitmap & var)) ! 74: { ! 75: /* this component uses variable var */ ! 76: ! 77: cprev = chead; ! 78: ! 79: /* look for other components using variable var */ ! 80: for (cnext = chead->nextcomp; cnext; cnext = cnext->nextcomp) ! 81: { ! 82: if (cnext->bitmap == 0 || (cnext->bitmap & var)) ! 83: { ! 84: ! 85: /* ! 86: ** Found a component. Remove it from "next" ! 87: ** link and put it with head piece ! 88: */ ! 89: ! 90: /* remove piece */ ! 91: cprev->nextcomp = cnext->nextcomp; ! 92: ! 93: /* fix up bit map */ ! 94: chead->bitmap |= cnext->bitmap; ! 95: ! 96: /* find end of head component */ ! 97: for (cl = chead; cl->linkcomp; cl = cl->linkcomp); ! 98: ! 99: /* connect with head piece */ ! 100: cl->linkcomp = cnext; ! 101: } ! 102: else ! 103: cprev = cnext; ! 104: } ! 105: } ! 106: } ! 107: } ! 108: ! 109: /* return whether connected or not connected */ ! 110: for (var =0, chead = clist; chead; chead = chead->nextcomp) ! 111: if (bitcnt(chead->bitmap) > 1) ! 112: var++; /* this component involves 2 or more vars */ ! 113: ! 114: return (var < 2); /* return TRUE if zero or one component multi-var */ ! 115: } ! 116: /* ! 117: ** Buildlist -- Build a component list from a query tree. ! 118: ** ! 119: ** Each ROOT and AND node is treated as a separate component ! 120: ** and a linked list is built connecting them. The ROOT node ! 121: ** MUST be the first element. This list will later be manipulated ! 122: ** by algorithm() to determine the structure of the query. ! 123: ** ! 124: ** Returns: ! 125: ** Head of the list ! 126: */ ! 127: ! 128: struct complist * ! 129: buildlist(root1, buf) ! 130: QTREE *root1; ! 131: char *buf; ! 132: { ! 133: register struct complist *head, *next; ! 134: register QTREE *root; ! 135: struct complist *ret; ! 136: extern char *need(); ! 137: ! 138: ret = (struct complist *) need(buf, 0); ! 139: head = 0; ! 140: ! 141: for (root = root1; root->sym.type != QLEND; root = root->right) ! 142: { ! 143: next = (struct complist *) need(buf, sizeof (*next)); ! 144: next->clause = root; ! 145: next->nextcomp = next->linkcomp = 0; ! 146: next->bitmap = root->sym.value.sym_root.lvarm; ! 147: ! 148: if (head) ! 149: head->nextcomp = next; ! 150: head = next; ! 151: } ! 152: return (ret); ! 153: } ! 154: /* ! 155: ** Construct -- construct a tree from a list component ! 156: ** ! 157: ** Construct takes a list head and builds a querytree ! 158: ** from the components in the list. If the head component ! 159: ** is the ROOT of the original query, then ! 160: ** the original ROOT node is reused. ! 161: ** ! 162: */ ! 163: ! 164: QTREE * ! 165: construct(root, listhead, buf) ! 166: QTREE *root; ! 167: struct complist *listhead; ! 168: char *buf; ! 169: { ! 170: register QTREE *ret, *q; ! 171: register struct complist *clist; ! 172: extern QTREE *makroot(); ! 173: ! 174: clist = listhead; ! 175: ! 176: /* determine ROOT of tree */ ! 177: if (root == clist->clause) ! 178: { ! 179: q = root; ! 180: clist = clist->linkcomp; ! 181: } ! 182: else ! 183: { ! 184: q = makroot(buf); ! 185: } ! 186: ret = q; ! 187: for (; clist; clist = clist->linkcomp) ! 188: { ! 189: q->right = clist->clause; ! 190: q = q->right; ! 191: } ! 192: ! 193: q->right = De.de_qle; ! 194: ! 195: mapvar(ret, 1); ! 196: # ifdef xDTR1 ! 197: if (tTf(38, 0)) ! 198: { ! 199: printf("Construct\n"); ! 200: treepr(ret); ! 201: } ! 202: # endif ! 203: return (ret); ! 204: } ! 205: /* ! 206: ** Order -- order a link list set of query components. ! 207: ** ! 208: ** Takes a list of components and orders them: ! 209: ** first - disjoint components ! 210: ** second - reduction pieces ! 211: ** last - the original target list piece ! 212: ** ! 213: ** Return: ! 214: ** new head of list ! 215: */ ! 216: ! 217: struct complist * ! 218: order(clist, ovlapvar) ! 219: struct complist *clist; ! 220: int ovlapvar; ! 221: { ! 222: register struct complist *cl, *joint, *disjoint; ! 223: struct complist *xd, *xj, *tlpiece, *ret; ! 224: QTREE *tmp; ! 225: int map; ! 226: ! 227: tlpiece = clist; /* target list piece always first */ ! 228: disjoint = joint = 0; ! 229: map = ovlapvar >= 0 ? 1 << ovlapvar : 0; ! 230: ! 231: /* examine each irreducible component for disjointness */ ! 232: for (cl = tlpiece->nextcomp; cl; cl = cl->nextcomp) ! 233: { ! 234: if (cl->bitmap & map) ! 235: { ! 236: /* joint piece */ ! 237: if (joint == 0) ! 238: { ! 239: joint = cl; ! 240: xj = cl; ! 241: } ! 242: else ! 243: { ! 244: joint->nextcomp = cl; ! 245: joint = cl; ! 246: } ! 247: } ! 248: else ! 249: { ! 250: /* disjoint piece */ ! 251: if (disjoint == 0) ! 252: { ! 253: disjoint = cl; ! 254: xd = cl; ! 255: } ! 256: else ! 257: { ! 258: disjoint->nextcomp = cl; ! 259: disjoint = cl; ! 260: } ! 261: } ! 262: ! 263: } ! 264: /* we now have all disjoint, joint and tl pieces */ ! 265: /* order them in order (1) xd, (2) xj, (3) tlpiece */ ! 266: ! 267: ret = tlpiece; ! 268: tlpiece->nextcomp = 0; ! 269: ! 270: if (joint) ! 271: { ! 272: ret = xj; ! 273: joint->nextcomp = tlpiece; ! 274: if ((tlpiece->bitmap & (~map)) == 0) ! 275: { ! 276: /* ! 277: ** This is the special case of the target list ! 278: ** being one (or zero) variable and that variable ! 279: ** is the overlap variable. If left as is, the ! 280: ** reduction will take one step more than is ! 281: ** necessary. The target list piece is combined ! 282: ** with the last joint piece and processed together. ! 283: ** ! 284: ** An example of when this will happen is: ! 285: ** ret(p.a) : p.b = s.b ^ p.c = y.c ! 286: ** ! 287: ** Reduction would split this up into ! 288: ** (1) ret (p.a,p.b) : p.c = y.c ! 289: ** (2) ret (p.a) : p.b = s.b ! 290: ** (3) ret (p.a) ! 291: ** ! 292: ** Here we are allowing pieces (2) & (3) to be done together ! 293: */ ! 294: ! 295: for (cl = joint; cl->linkcomp; cl = cl->linkcomp); ! 296: ! 297: cl->linkcomp = tlpiece; ! 298: joint->nextcomp = 0; ! 299: ! 300: /* switch tl clause to top of complist */ ! 301: tmp = joint->clause; ! 302: joint->clause = tlpiece->clause; ! 303: tlpiece->clause = tmp; ! 304: } ! 305: } ! 306: ! 307: if (disjoint) ! 308: { ! 309: ret = xd; ! 310: disjoint->nextcomp = joint ? xj : tlpiece; ! 311: } ! 312: ! 313: return (ret); ! 314: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.