|
|
1.1 ! root 1: # include <ingres.h> ! 2: # include <aux.h> ! 3: # include <tree.h> ! 4: # include <symbol.h> ! 5: # include <sccs.h> ! 6: ! 7: SCCSID(@(#)norml.c 8.1 12/31/84) ! 8: ! 9: /* ! 10: ** NORML.C -- functions for normalizing tree ! 11: ** ! 12: ** Defines ! 13: ** norml -- main routine ! 14: ** norm ! 15: ** travers ! 16: ** nnorm ! 17: ** notpush ! 18: ** adjust ! 19: ** treedup ! 20: ** mvands ! 21: ** ! 22: ** Trace Flags: ! 23: ** NORMAL.C ~~ 56, 57 ! 24: */ ! 25: ! 26: /* ! 27: ** NORML -- normalizing routine ! 28: ** ! 29: ** this routine passes the qualification clause portion of the query ! 30: ** tree to the routines for depressing nots and for conjunctive ! 31: ** normalization. It also calls a routine to place an and with one ! 32: ** null branch at the rightmost end of the tree. ! 33: ** ! 34: ** Parameters: ! 35: ** ptr -- tree to normalize ! 36: ** ! 37: ** Returns: ! 38: ** nothing ! 39: ** ! 40: ** Trace Flags: ! 41: ** norml ~~ 56.0 ! 42: */ ! 43: ! 44: QTREE * ! 45: norml(ptr) ! 46: QTREE *ptr; ! 47: { ! 48: extern QTREE *nnorm(); ! 49: extern QTREE *travers(); ! 50: extern QTREE *tree(); ! 51: extern char Qbuf[]; ! 52: ! 53: # ifdef xPTR1 ! 54: tTfp(56, 0, "norml(%d)\n", ptr); ! 55: # endif ! 56: ! 57: if (ptr == NULL) ! 58: return (tree(NULL, NULL, QLEND, 0, 0)); ! 59: ! 60: /* push through the 'nots' as far a possible */ ! 61: ptr = nnorm(ptr); ! 62: ! 63: /* make tree into conjunctive normal form */ ! 64: ptr = travers(ptr); ! 65: ! 66: /* terminate the list on the rightmost branch */ ! 67: adjust(&ptr); ! 68: ! 69: /* make 'ands' into a linear list */ ! 70: mvands(ptr); ! 71: ! 72: # ifdef xPTR1 ! 73: tTfp(56, 1, ">>norml(%d)\n", ptr); ! 74: # endif ! 75: ! 76: return (ptr); ! 77: } ! 78: ! 79: ! 80: /* ! 81: ** NORM ! 82: ** this routine takes a tree which has nots only at the lower ends, and ! 83: ** places it into conjunctive normal form by repeatedly applying the ! 84: ** replacement rule: A or (B and C) ==> (A or B) and (A or C) ! 85: ** ! 86: ** Trace Flags: ! 87: ** norm ~~ 56.4 ! 88: */ ! 89: ! 90: QTREE * ! 91: norm(p) ! 92: register QTREE *p; ! 93: { ! 94: register QTREE *lptr; ! 95: register QTREE *rptr; ! 96: extern QTREE *treedup(); ! 97: extern QTREE *tree(); ! 98: ! 99: # ifdef xPTR1 ! 100: tTfp(56, 4, "norm(%d)\n", p); ! 101: # endif ! 102: ! 103: switch (p->sym.type) ! 104: { ! 105: case AND: ! 106: p->left = norm(p->left); ! 107: p->right = norm(p->right); ! 108: break; ! 109: ! 110: case OR: ! 111: if (p->right->sym.type == AND) ! 112: { ! 113: andright: ! 114: /* ! 115: ** combine left subtree with each subtree of the ! 116: ** right subtree ! 117: */ ! 118: /* ! 119: ** use copy first so that the copy is guaranteed to be ! 120: ** the same as the original ! 121: */ ! 122: lptr = tree(treedup(p->left), p->right->left, OR, sizeof(struct rootnode) - 2, 0); ! 123: rptr = tree(p->left, p->right->right, OR, sizeof(struct rootnode) - 2, 0); ! 124: lptr = norm(lptr); ! 125: rptr = norm(rptr); ! 126: /* change node type to AND from OR */ ! 127: p->left = lptr; ! 128: p->right = rptr; ! 129: p->sym.type = AND; /* length is same */ ! 130: break; ! 131: } ! 132: if (p->left->sym.type == AND) ! 133: { ! 134: andleft: ! 135: /* ! 136: ** combine right subtree with each subtree of the ! 137: ** left subtree ! 138: */ ! 139: /* ! 140: ** again, the copy should be used first ! 141: */ ! 142: lptr = tree(p->left->left, treedup(p->right), OR, sizeof(struct rootnode) - 2, 0); ! 143: rptr = tree(p->left->right, p->right, OR, sizeof(struct rootnode) - 2, 0); ! 144: lptr = norm(lptr); ! 145: rptr = norm(rptr); ! 146: /* change node type to AND from OR */ ! 147: p->left = lptr; ! 148: p->right = rptr; ! 149: p->sym.type = AND; ! 150: break; ! 151: } ! 152: /* ! 153: ** when TRAVERS is being used to optomize the normalization ! 154: ** order there should never be (I think) an OR as a child ! 155: ** of the OR in the parent. Since TRAVERS works bottom up ! 156: ** in the tree the second OR level should be gone. ! 157: */ ! 158: if (p->right->sym.type == OR) ! 159: { ! 160: /* skip this (p->sym.type) "or" and normalize the right subtree */ ! 161: p->right = norm(p->right); ! 162: ! 163: /* now re-try the current node */ ! 164: if (p->right->sym.type == AND) ! 165: goto andright; ! 166: break; ! 167: } ! 168: if (p->left->sym.type == OR) ! 169: { ! 170: /* skip this "or" and normalize the left subtree */ ! 171: p->left = norm(p->left); ! 172: ! 173: /* now re-try the current node */ ! 174: if (p->left->sym.type == AND) ! 175: goto andleft; ! 176: break; ! 177: } ! 178: break; ! 179: } ! 180: return (p); ! 181: } ! 182: ! 183: /* ! 184: ** TRAVERS ! 185: ** traverse the tree so that conversion of ORs of ANDs can ! 186: ** take place at the innermost clauses first. IE, normalize ! 187: ** before replication rather than after replication. ! 188: ** ! 189: ** This routine need not be used. The NORM routine will completely ! 190: ** traverse the tree and normalize it but... TRAVERS finds ! 191: ** the lowest subtree to normalize first so that sub-trees can ! 192: ** be normalized before replication, hence reducing the time required ! 193: ** to normalize large trees. It will also make OR-less trees faster ! 194: ** to normalize (since nothing need be done to it). ! 195: ** ! 196: ** Trace Flags: ! 197: ** travers ~~ 56.8 ! 198: */ ! 199: ! 200: QTREE * ! 201: travers(p1) ! 202: QTREE *p1; ! 203: { ! 204: register QTREE *p; ! 205: extern QTREE *norm(); ! 206: ! 207: # ifdef xPTR1 ! 208: tTfp(56, 8, "travers(%d)\n", p1); ! 209: # endif ! 210: ! 211: p = p1; ! 212: if (p->right != NULL) ! 213: p->right = travers(p->right); ! 214: if (p->left != NULL) ! 215: p->left = travers(p->left); ! 216: if (p->sym.type == OR) ! 217: p = norm(p); ! 218: return (p); ! 219: } ! 220: /* ! 221: ** NNORM ! 222: ** this routine depresses nots in the query tree to the lowest possible ! 223: ** nodes. It may also affect arithmetic operators in this procedure ! 224: ** ! 225: ** Trace Flags: ! 226: ** nnorm ~~ 56.12 ! 227: */ ! 228: QTREE * ! 229: nnorm(p1) ! 230: QTREE *p1; ! 231: { ! 232: extern QTREE *notpush(); ! 233: register QTREE *p; ! 234: ! 235: # ifdef xPTR1 ! 236: tTfp(56, 12, "nnorm(%d)\n", p1); ! 237: # endif ! 238: ! 239: p = p1; ! 240: if (p->sym.type == AGHEAD) ! 241: { ! 242: /* ! 243: ** don't need to continue past an AGHEAD ! 244: ** actually, it causes problems if you do ! 245: ** because the qualification on the agg ! 246: ** has already been normalized and the ! 247: ** QLEND needs to stay put ! 248: */ ! 249: return (p); ! 250: } ! 251: if ((p->sym.type == UOP) && (p->sym.value.sym_op.opno == opNOT)) ! 252: { ! 253: /* skip not node */ ! 254: p = p->right; ! 255: p = notpush(p); ! 256: } ! 257: else ! 258: { ! 259: if (p->left != NULL) ! 260: p->left = nnorm(p->left); ! 261: if (p->right != NULL) ! 262: p->right = nnorm(p->right); ! 263: } ! 264: return (p); ! 265: } ! 266: ! 267: /* ! 268: ** NOTPUSH ! 269: ** this routine decides what to do once a not has been found in the ! 270: ** query tree ! 271: ** ! 272: ** Trace Flags: ! 273: ** notpush ~~ 57.0 ! 274: */ ! 275: QTREE * ! 276: notpush(p1) ! 277: QTREE *p1; ! 278: { ! 279: extern QTREE *nnorm(); ! 280: register QTREE *p; ! 281: ! 282: # ifdef xPTR1 ! 283: tTfp(57, 0, "notpush(%d)\n", p1); ! 284: # endif ! 285: ! 286: p = p1; ! 287: switch (p->sym.type) ! 288: { ! 289: case AND: ! 290: p->sym.type = OR; ! 291: p->left = notpush(p->left); ! 292: p->right = notpush(p->right); ! 293: break; ! 294: ! 295: case OR: ! 296: p->sym.type = AND; ! 297: p->left = notpush(p->left); ! 298: p->right = notpush(p->right); ! 299: break; ! 300: ! 301: case BOP: ! 302: switch (p->sym.value.sym_op.opno) ! 303: { ! 304: case opEQ: ! 305: p->sym.value.sym_op.opno = opNE; ! 306: break; ! 307: ! 308: case opNE: ! 309: p->sym.value.sym_op.opno = opEQ; ! 310: break; ! 311: ! 312: case opLT: ! 313: p->sym.value.sym_op.opno = opGE; ! 314: break; ! 315: ! 316: case opGE: ! 317: p->sym.value.sym_op.opno = opLT; ! 318: break; ! 319: ! 320: case opLE: ! 321: p->sym.value.sym_op.opno = opGT; ! 322: break; ! 323: ! 324: case opGT: ! 325: p->sym.value.sym_op.opno = opLE; ! 326: break; ! 327: ! 328: default: ! 329: syserr("strange BOP in notpush '%d'", p->sym.value.sym_op.opno); ! 330: } ! 331: break; ! 332: ! 333: case UOP: ! 334: if (p->sym.value.sym_op.opno == opNOT) ! 335: { ! 336: /* skip not node */ ! 337: p = p->right; ! 338: p = nnorm(p); ! 339: } ! 340: else ! 341: syserr("strange UOP in notpush '%d'", p->sym.value.sym_op.opno); ! 342: break; ! 343: ! 344: default: ! 345: syserr("unrecognizable node type in notpush '%d'", p->sym.type); ! 346: } ! 347: return (p); ! 348: } ! 349: ! 350: /* ! 351: ** ADJUST ! 352: ** terminate qual with an AND and a QLEND at the rightmost branch ! 353: ** ! 354: ** Trace Flags: ! 355: ** adjust ~~ 57.4 ! 356: */ ! 357: adjust(pp) ! 358: QTREE **pp; ! 359: { ! 360: extern QTREE *tree(); ! 361: register QTREE *p; ! 362: ! 363: # ifdef xPTR1 ! 364: tTfp(57, 4, "adjust(%d)\n", pp); ! 365: # endif ! 366: ! 367: p = *pp; ! 368: switch (p->sym.type) ! 369: { ! 370: case AND: ! 371: adjust(&(p->right)); ! 372: break; ! 373: ! 374: case OR: ! 375: default: ! 376: *pp = tree(p, tree(NULL, NULL, QLEND, 0, NULL), AND, sizeof(struct rootnode) - 2, 0); ! 377: break; ! 378: } ! 379: } ! 380: /* ! 381: ** TREEDUP -- ! 382: ** ! 383: ** Trace Flags: ! 384: ** norm ~~ 57.8 ! 385: */ ! 386: ! 387: ! 388: QTREE ! 389: *treedup(p1) ! 390: QTREE *p1; ! 391: { ! 392: register QTREE *np; ! 393: register QTREE *p; ! 394: extern char Qbuf[]; ! 395: extern char *need(); ! 396: ! 397: # ifdef xPTR1 ! 398: tTfp(57, 8, "treedup(%d)\n", p1); ! 399: # endif ! 400: ! 401: if ((p = p1) == NULL) ! 402: return (p); ! 403: ! 404: np = (QTREE *) need(Qbuf, (p->sym.len & I1MASK) + QT_HDR_SIZ); ! 405: ! 406: bmove(p, np, (p->sym.len & I1MASK) + QT_HDR_SIZ); ! 407: ! 408: np->left = treedup(p->left); ! 409: np->right = treedup(p->right); ! 410: return (np); ! 411: } ! 412: ! 413: /* ! 414: ** MVANDS -- pushes all AND's in Qual into linear list ! 415: ** ! 416: ** Trace Flags: ! 417: ** mvands ~~ 57.12 ! 418: */ ! 419: mvands(andp) ! 420: QTREE *andp; ! 421: { ! 422: register QTREE *ap, *lp, *rp; ! 423: ! 424: # ifdef xPTR1 ! 425: tTfp(57, 12, "mvands(%d)\n", andp); ! 426: # endif ! 427: ! 428: ap = andp; ! 429: if (ap->sym.type == QLEND) ! 430: return; ! 431: rp = ap->right; ! 432: lp = ap->left; ! 433: if (lp->sym.type == AND) ! 434: { ! 435: ap->left = lp->right; ! 436: ap->right = lp; ! 437: lp->right = rp; ! 438: mvands(ap); ! 439: } ! 440: else ! 441: mvands(rp); ! 442: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.