|
|
1.1 ! root 1: # include <ingres.h> ! 2: # include <aux.h> ! 3: # include <symbol.h> ! 4: # include <tree.h> ! 5: # include "qrymod.h" ! 6: # include <sccs.h> ! 7: ! 8: SCCSID(@(#)util.c 8.1 12/31/84) ! 9: ! 10: /* ! 11: ** TRIMQLEND -- trim QLEND node off of qualification ! 12: ** ! 13: ** The QLEND node, and possible the AND node preceeding it, ! 14: ** are trimmed off. The result of this routine should be ! 15: ** a very ordinary tree like you might see in some textbook. ! 16: ** ! 17: ** A fast not on the algorithm: the pointer 't' points to the ! 18: ** current node (the one which we are checking for a QLEND). ! 19: ** 's' points to 't's parent, and 'r' points to 's's parent; ! 20: ** 'r' is NULL at the top of the tree. ! 21: ** ! 22: ** This routine works correctly on trees with no QLEND in ! 23: ** the first place, returning the original tree. ! 24: ** ! 25: ** If there is a QLEND, it must be on the far right branch ! 26: ** of the tree, that is, the tree must be INGRES-canonical. ! 27: ** ! 28: ** Parameters: ! 29: ** qual -- the qualification to be trimmed. ! 30: ** ! 31: ** Returns: ! 32: ** A pointer to the new qualification. ! 33: ** NULL if the qualification was null once the ! 34: ** QLEND is stripped. ! 35: ** ! 36: ** Side Effects: ! 37: ** The tree pointed to by 'qual' may be modified. ! 38: ** ! 39: ** Trace Flags: ! 40: ** none ! 41: */ ! 42: ! 43: QTREE * ! 44: trimqlend(qual) ! 45: QTREE *qual; ! 46: { ! 47: register QTREE *t; ! 48: register QTREE *s; ! 49: register QTREE *r; ! 50: ! 51: t = qual; ! 52: ! 53: /* check for the simple null qualification case */ ! 54: if (t == NULL || t->sym.type == QLEND) ! 55: return (NULL); ! 56: ! 57: /* scan tree for QLEND node */ ! 58: for (r = NULL, s = t; (t = t->right) != NULL; r = s, s = t) ! 59: { ! 60: if (t->sym.type == QLEND) ! 61: { ! 62: /* trim of QLEND and AND node */ ! 63: if (r == NULL) ! 64: { ! 65: /* only one AND -- return its operand */ ! 66: return (s->left); ! 67: } ! 68: ! 69: r->right = s->left; ! 70: break; ! 71: } ! 72: } ! 73: ! 74: /* return tree with final AND node and QLEND node pruned */ ! 75: return (qual); ! 76: } ! 77: /* ! 78: ** APPQUAL -- append qualification to tree ! 79: ** ! 80: ** The qualification is conjoined to the qualificaion of the ! 81: ** tree which is passed. ! 82: ** ! 83: ** Parameters: ! 84: ** qual -- a pointer to the qualification to be appended. ! 85: ** root -- a pointer to the tree to be appended to. ! 86: ** ! 87: ** Returns: ! 88: ** none ! 89: ** ! 90: ** Side Effects: ! 91: ** Both 'qual' ad 'root' may be modified. Note that ! 92: ** 'qual' is linked into 'root', and must be ! 93: ** retained. ! 94: ** ! 95: ** Trace Flags: ! 96: ** 13 ! 97: */ ! 98: ! 99: appqual(qual, root) ! 100: QTREE *qual; ! 101: QTREE *root; ! 102: { ! 103: register QTREE *p; ! 104: register QTREE *r; ! 105: ! 106: r = root; ! 107: # ifdef xQTR3 ! 108: if (r == NULL) ! 109: syserr("appqual: NULL root"); ! 110: # endif ! 111: ! 112: /* ! 113: ** Find node before QLEND node ! 114: ** p points the node we are examining, r points to ! 115: ** it's parent. ! 116: */ ! 117: ! 118: while ((p = r->right) != NULL && p->sym.type != QLEND) ! 119: { ! 120: # ifdef xQTR3 ! 121: if (p->sym.type != AND) ! 122: syserr("appqual: node %d", p->sym.type); ! 123: # endif ! 124: r = p; ! 125: } ! 126: ! 127: /* link in qualification */ ! 128: r->right = qual; ! 129: } ! 130: /* ! 131: ** QMERROR -- issue fatal error message and abort query ! 132: ** ! 133: ** This call is almost exactly like 'error' (which is called), ! 134: ** but never returns: the return is done by 'reset'. Also, the ! 135: ** R_up pipe is flushed. ! 136: ** ! 137: ** Parameters: ! 138: ** errno -- the error number. ! 139: ** qmode -- the query mode to pass as $0, -1 if none. ! 140: ** vn -- the varno of the relation name to pass as ! 141: ** $1, -1 if none. ! 142: ** p1 to p5 -- the parameters $2 through $6 ! 143: ** ! 144: ** Returns: ! 145: ** non-local (via reset()) ! 146: ** ! 147: ** Side Effects: ! 148: ** The error message is generated. ! 149: ** ! 150: ** Trace Flags: ! 151: ** none ! 152: */ ! 153: ! 154: char *QmdName[] = ! 155: { ! 156: "[ERROR]", /* 0 = mdRETTERM */ ! 157: "RETRIEVE", /* 1 = mdRETR */ ! 158: "APPEND", /* 2 = mdAPP */ ! 159: "REPLACE", /* 3 = mdREPL */ ! 160: "DELETE", /* 4 = mdDEL */ ! 161: "", /* 5 = mdCOPY */ ! 162: "", /* 6 = mdCREATE */ ! 163: "", /* 7 = mdDESTROY */ ! 164: "", /* 8 = mdHELP */ ! 165: "", /* 9 = mdINDEX */ ! 166: "", /* 10 = mdMODIFY */ ! 167: "", /* 11 = mdPRINT */ ! 168: "", /* 12 = mdRANGE */ ! 169: "", /* 13 = mdSAVE */ ! 170: "DEFINE", /* 14 = mdDEFINE */ ! 171: "RET_UNIQUE", /* 15 = mdRET_UNI */ ! 172: "", /* 16 = mdVIEW */ ! 173: "", /* 17 = mdUPDATE */ ! 174: "", /* 18 = mdRESETREL */ ! 175: "", /* 19 = mdERIC */ ! 176: "", /* 20 = mdNETQRY */ ! 177: "", /* 21 = mdMOVEREL */ ! 178: "", /* 22 = mdPROT */ ! 179: "", /* 23 = mdINTEG */ ! 180: "", /* 24 = mdDCREATE */ ! 181: }; ! 182: ! 183: ! 184: qmerror(errno, qmode, vn, p1, p2, p3, p4, p5, p6) ! 185: int errno; ! 186: int qmode; ! 187: int vn; ! 188: char *p1, *p2, *p3, *p4, *p5, *p6; ! 189: { ! 190: register char *x1; ! 191: register char *x2; ! 192: char xbuf[MAXNAME + 1]; ! 193: register int i; ! 194: extern char *trim_relname(); ! 195: ! 196: /* set up qmode and varno parameters */ ! 197: x1 = x2 = ""; ! 198: i = qmode; ! 199: if (i >= 0) ! 200: x1 = QmdName[i]; ! 201: i = vn; ! 202: if (i >= 0) ! 203: smove(trim_relname(Qt.qt_rangev[i].rngvdesc->reldum.relid), ! 204: x2 = xbuf); ! 205: ! 206: /* issue the error message and exit */ ! 207: error(errno, x1, x2, p1, p2, p3, p4, p5, p6, 0); ! 208: syserr("qmerror"); ! 209: } ! 210: /* ! 211: ** LSETBIT -- set a bit in a domain set ! 212: ** ! 213: ** Parameters: ! 214: ** bitno -- the bit number to set (0 -> 127) ! 215: ** xset -- the set to set it in. ! 216: ** ! 217: ** Returns: ! 218: ** none ! 219: ** ! 220: ** Side Effects: ! 221: ** none ! 222: */ ! 223: ! 224: lsetbit(bitno, xset) ! 225: int bitno; ! 226: int xset[8]; ! 227: { ! 228: register int b; ! 229: register int n; ! 230: register int *x; ! 231: ! 232: x = xset; ! 233: ! 234: b = bitno; ! 235: n = b >> LOG2WORDSIZE; ! 236: b &= WORDSIZE - 1; ! 237: ! 238: x[n] |= 1 << b; ! 239: } ! 240: /* ! 241: ** MERGEVAR -- merge variable numbers to link terms ! 242: ** ! 243: ** One specified variable gets mapped into another, effectively ! 244: ** merging those two variables. This is used for protection ! 245: ** and integrity, since the constraint read from the tree ! 246: ** must coincide with one of the variables in the query tree. ! 247: ** ! 248: ** Parameters: ! 249: ** va -- the variable which will dissappear. ! 250: ** vb -- the variable which 'va' gets mapped into. ! 251: ** root -- the root of the tree to map. ! 252: ** ! 253: ** Returns: ! 254: ** none ! 255: ** ! 256: ** Side Effects: ! 257: ** The tree pointed at by 'root' gets VAR and RESDOM ! 258: ** nodes mapped. ! 259: ** Range table entry for 'va' is deallocated. ! 260: ** The 'Qt.qt_remap' vector gets reset and left in an ! 261: ** undefined state. ! 262: ** ! 263: ** Trace Flags: ! 264: ** 72 ! 265: */ ! 266: ! 267: mergevar(a, b, root) ! 268: register int a; ! 269: register int b; ! 270: QTREE *root; ! 271: { ! 272: register int i; ! 273: ! 274: # ifdef xQTR1 ! 275: if (tTf(72, 0)) ! 276: { ! 277: printf("\nmergevar(%d->%d)", a, b); ! 278: treepr(root, NULL); ! 279: } ! 280: # endif ! 281: ! 282: /* ! 283: ** Insure that 'a' and 'b' are consistant, that is, ! 284: ** that they both are in range, are defined, and range over ! 285: ** the same relation. ! 286: */ ! 287: ! 288: if (a < 0 || b < 0 || a >= MAXVAR + 1 || b >= MAXVAR + 1) ! 289: syserr("mergevar: range %d %d", a, b); ! 290: if (Qt.qt_rangev[a].rngvdesc == NULL || Qt.qt_rangev[b].rngvdesc == NULL) ! 291: syserr("mergevar: undef %d %d", a, b); ! 292: if (!bequal(Qt.qt_rangev[a].rngvdesc->reldum.relid, ! 293: Qt.qt_rangev[b].rngvdesc->reldum.relid, MAXNAME) || ! 294: !bequal(Qt.qt_rangev[a].rngvdesc->reldum.relowner, ! 295: Qt.qt_rangev[b].rngvdesc->reldum.relowner, 2)) ! 296: { ! 297: syserr("mergevar: incon %.14s %.14s", ! 298: Qt.qt_rangev[a].rngvdesc->reldum.relid, ! 299: Qt.qt_rangev[b].rngvdesc->reldum.relid); ! 300: } ! 301: ! 302: /* ! 303: ** To do the actual mapping, we will set up 'Qt.qt_remap' and ! 304: ** call 'mapvars()'. This is because I am too lazy to ! 305: ** do it myself. ! 306: */ ! 307: ! 308: for (i = 0; i < MAXRANGE; i++) ! 309: Qt.qt_remap[i] = i; ! 310: Qt.qt_remap[a] = b; ! 311: mapvars(root); ! 312: ! 313: /* delete a from the range table */ ! 314: declare(a, NULL); ! 315: } ! 316: /* ! 317: ** MAKEZERO -- make a node with value 'zero' ! 318: ** ! 319: ** A node is created with value representing the zero value ! 320: ** for the specified type, that is, 0 for integers, 0.0 for ! 321: ** floats, and the blank string for chars. ! 322: ** ! 323: ** Parameters: ! 324: ** typ -- the node type. ! 325: ** ! 326: ** Returns: ! 327: ** a pointer to the zero node. ! 328: ** ! 329: ** Side Effects: ! 330: ** space is grabbed from Qbuf ! 331: */ ! 332: ! 333: QTREE * ! 334: makezero(typ) ! 335: int typ; ! 336: { ! 337: register int l; ! 338: register QTREE *s; ! 339: int symbuf[(sizeof *s) / sizeof l]; /*word aligned*/ ! 340: extern char *need(); ! 341: ! 342: s = (QTREE *) symbuf; ! 343: s->sym.type = typ; ! 344: ! 345: switch (typ) ! 346: { ! 347: case INT: ! 348: s->sym.len = l = 2; ! 349: s->sym.value.sym_data.i2type = 0; ! 350: break; ! 351: ! 352: case FLOAT: ! 353: s->sym.len = l = 4; ! 354: s->sym.value.sym_data.f4type = 0.0; ! 355: break; ! 356: ! 357: case CHAR: ! 358: s->sym.len = l = 2; ! 359: s->sym.value.sym_data.i2type = ' '; /* (two spaces) */ ! 360: break; ! 361: ! 362: default: ! 363: syserr("makezero: typ %d", typ); ! 364: } ! 365: ! 366: /* duplicate the node into Qbuf */ ! 367: l += 2 + 2 * QT_HDR_SIZ; /* size of type + len + left + right */ ! 368: s = (QTREE *) need(Qbuf, l); ! 369: bmove(symbuf, s, l); ! 370: return (s); ! 371: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.