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: }

Defined functions

adjust defined in line 357; used 2 times
mvands defined in line 419; used 3 times
nnorm defined in line 228; used 6 times
norm defined in line 90; used 11 times
norml defined in line 7; used 5 times
notpush defined in line 275; used 6 times
travers defined in line 200; used 4 times
treedup defined in line 388; used 5 times
Last modified: 1986-04-17
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1304
Valid CSS Valid XHTML 1.0 Strict