|
|
1.1 ! root 1: # include <ingres.h> ! 2: # include <symbol.h> ! 3: # include <tree.h> ! 4: # include "qrymod.h" ! 5: # include <sccs.h> ! 6: # include <errors.h> ! 7: ! 8: SCCSID(@(#)trscan.c 8.2 2/8/85) ! 9: ! 10: /* ! 11: ** AGGCHECK -- check for any aggregate in subtree. ! 12: ** ! 13: ** This routine checks to insure that the view algorithm can ! 14: ** proceed safely by checking for aggregates in the view tree. ! 15: ** ! 16: ** Parameters: ! 17: ** root -- the root of the tree to check. ! 18: ** ! 19: ** Returns: ! 20: ** TRUE -- an aggregate found. ! 21: ** FALSE -- no aggregates in tree. ! 22: ** ! 23: ** Side Effects: ! 24: ** none ! 25: ** ! 26: ** Trace Flags: ! 27: ** none. ! 28: */ ! 29: ! 30: aggcheck(root) ! 31: QTREE *root; ! 32: { ! 33: register QTREE *t; ! 34: ! 35: t = root; ! 36: ! 37: /* check for no pointer */ ! 38: while (t != NULL) ! 39: { ! 40: /* check for this node an AGHEAD */ ! 41: if (t->sym.type == AGHEAD) ! 42: return (TRUE); ! 43: ! 44: /* check left subtree recursively */ ! 45: if (aggcheck(t->left)) ! 46: return (TRUE); ! 47: ! 48: /* check right subtree iteratively */ ! 49: t = t->right; ! 50: } ! 51: ! 52: return (FALSE); ! 53: } ! 54: /* ! 55: ** VFIND -- find definition for attribute in view tree ! 56: ** ! 57: ** The view tree is scanned for a specified RESDOM; a pointer ! 58: ** to the value is returned. ! 59: ** ! 60: ** Parameters: ! 61: ** vn -- the variable number to dig out. ! 62: ** vtree -- a pointer to the target list of the ! 63: ** view definition tree. ! 64: ** ! 65: ** Returns: ! 66: ** a pointer to the substitution value for the specified ! 67: ** 'vn'. ! 68: ** NULL -- if not found. ! 69: ** ! 70: ** Side Effects: ! 71: ** none ! 72: ** ! 73: ** Trace Flags: ! 74: ** none. ! 75: */ ! 76: ! 77: QTREE * ! 78: vfind(vn, vtree) ! 79: int vn; ! 80: QTREE *vtree; ! 81: { ! 82: register int n; ! 83: register QTREE *v; ! 84: ! 85: n = vn; ! 86: ! 87: for (v = vtree; v->sym.type == RESDOM; v = v->left) ! 88: { ! 89: if (v->sym.value.sym_resdom.resno != n) ! 90: continue; ! 91: ! 92: /* found the correct replacement */ ! 93: return (v->right); ! 94: } ! 95: ! 96: if (v->sym.type != TREE) ! 97: syserr("vfind: bad RESDOM node %d", v->sym.type); ! 98: return (NULL); ! 99: } ! 100: /* ! 101: ** QSCAN -- find specified VAR node in subtree ! 102: ** ! 103: ** Intended for finding a variable in a qualification, this ! 104: ** routine just scans a tree recursively looking for a node ! 105: ** with the specified VAR (varno.attno) node. ! 106: ** ! 107: ** Parameters: ! 108: ** root -- the root of the tree to scan. ! 109: ** vn -- the varno to scan for. ! 110: ** an -- the attno to scan for. ! 111: ** ! 112: ** Returns: ! 113: ** A pointer to the first found VAR node which matches. ! 114: ** Scan is prefix. ! 115: ** NULL if not found at all. ! 116: ** ! 117: ** Side Effects: ! 118: ** none ! 119: ** ! 120: ** Trace Flags: ! 121: ** none. ! 122: */ ! 123: ! 124: QTREE * ! 125: qscan(root, vn, an) ! 126: QTREE *root; ! 127: int vn; ! 128: int an; ! 129: { ! 130: register QTREE *t; ! 131: register QTREE *u; ! 132: ! 133: t = root; ! 134: ! 135: /* check for null node */ ! 136: if (t == NULL) ! 137: return (t); ! 138: ! 139: /* check to see if this node qualifies */ ! 140: if (t->sym.type == VAR && t->sym.value.sym_var.varno == vn && t->sym.value.sym_var.attno == an) ! 141: return (t); ! 142: ! 143: /* check other nodes */ ! 144: if ((u = qscan(t->left, vn, an)) != NULL) ! 145: return (u); ! 146: return (qscan(t->right, vn, an)); ! 147: } ! 148: /* ! 149: ** VARSET -- scan tree and set a bit vector of variables ! 150: ** ! 151: ** The return value is a bit vector representing the set of ! 152: ** variables used in that subtree. ! 153: ** ! 154: ** Parameters: ! 155: ** root -- the root of the tree to check. ! 156: ** ! 157: ** Returns: ! 158: ** A bit vector, such that bit zero (on the low order, ! 159: ** right-hand end) means var zero. ! 160: ** ! 161: ** Side Effects: ! 162: ** none ! 163: ** ! 164: ** Trace Flags: ! 165: ** none ! 166: */ ! 167: ! 168: varset(root) ! 169: QTREE *root; ! 170: { ! 171: register QTREE *t; ! 172: register int s; ! 173: ! 174: t = root; ! 175: ! 176: if (t == NULL) ! 177: return (0); ! 178: ! 179: /* scan left and right branches */ ! 180: s = varset(t->left); ! 181: s |= varset(t->right); ! 182: ! 183: /* check out this node */ ! 184: if (t->sym.type == VAR) ! 185: { ! 186: /* or in bit corresponding to this varno */ ! 187: s |= 1 << t->sym.value.sym_var.varno; ! 188: } ! 189: ! 190: return (s); ! 191: } ! 192: /* ! 193: ** SUBSVARS -- scan query tree and replace VAR nodes ! 194: ** ! 195: ** Scans a tree and finds all VAR nodes for this variable. ! 196: ** These nodes are looked up in the translation tree and ! 197: ** replaced by the value found there. If this is for a ! 198: ** view, the corresponding node must exist in the translation ! 199: ** tree, otherwise, a 'zero' node (of a type appropriate based ! 200: ** on the context) is created and inserted. ! 201: ** ! 202: ** This routine is one half of the guts of the whole view ! 203: ** algorithm. ! 204: ** ! 205: ** VAR nodes are detached and replaced with the replacement ! 206: ** as defined by the view. Note that there can never be any ! 207: ** problems here, since VAR nodes are only used in retrieve ! 208: ** contexts. ! 209: ** ! 210: ** It does some extra processing with RESDOM nodes with ! 211: ** resno = 0. These nodes specify a 'tid' domain, and are ! 212: ** included by the parser on REPLACE and DELETE commands ! 213: ** (for some reason decomp wants them). Subsvars will allow ! 214: ** this construct iff the right hand pointer is a VAR node ! 215: ** with attno = 0. In this case it just changes the varno ! 216: ** of the VAR node to be the Qt.qt_resvar number. This is be- ! 217: ** cause the Qt.qt_resvar is the variable number of the one and ! 218: ** only underlying base relation of the view on an update ! 219: ** (which is presumably the only case where this can come ! 220: ** up). Vrscan has already insured that there can only be ! 221: ** a single base relation in this case. ! 222: ** ! 223: ** This whole messy thing is only done with view substitutions. ! 224: ** ! 225: ** Parameters: ! 226: ** proot -- a pointer to the pointer to the root of the ! 227: ** tree to be updated. ! 228: ** vn -- the varno of the view variable. This is the ! 229: ** varno which will be scanned for. ! 230: ** transtree -- a pointer to the left branch (target list) ! 231: ** of the translation tree. ! 232: ** vmode -- mdVIEW if called from view processor, mdAPP ! 233: ** if called from the integrity processor with ! 234: ** an APPEND command, else something else. ! 235: ** Mostly, changes the handling of TID type ! 236: ** nodes, and forces an error on a view if the ! 237: ** VAR node in the scanned tree does not exist ! 238: ** in the vtree. ! 239: ** ! 240: ** Returns: ! 241: ** none ! 242: ** (non-local on error). ! 243: ** ! 244: ** Side Effects: ! 245: ** The tree pointed to by *proot is updated in possibly ! 246: ** very exciting ways. ! 247: ** ! 248: ** Trace Flags: ! 249: ** 32 ! 250: */ ! 251: ! 252: subsvars(proot, vn, transtree, vmode) ! 253: QTREE **proot; ! 254: int vn; ! 255: QTREE *transtree; ! 256: int vmode; ! 257: { ! 258: register QTREE *t; ! 259: register QTREE *v; ! 260: register int i; ! 261: extern QTREE *vfind(); ! 262: extern QTREE *makezero(); ! 263: extern QTREE *treedup(); ! 264: ! 265: t = *proot; ! 266: v = transtree; ! 267: ! 268: # ifdef xQTR3 ! 269: if (tTf(32, 0)) ! 270: printf("subsvars: vn %d root %u transtree %u\n", vn, t, v); ! 271: # endif ! 272: ! 273: if (t == NULL) ! 274: return; ! 275: ! 276: /* check left branch of the tree */ ! 277: subsvars(&t->left, vn, v, vmode); ! 278: ! 279: /* check for special 'tid' RESDOM (used by DEL and REPL) */ ! 280: if (t->sym.type == RESDOM && t->sym.value.sym_resdom.resno == 0) ! 281: { ! 282: /* test for not Qt.qt_resvar, in which case we ignore leaf */ ! 283: if (vn != Qt.qt_resvar) ! 284: return; ! 285: ! 286: /* t->right better be VAR node, attno 0 */ ! 287: t = t->right; ! 288: if (t->sym.type != VAR || t->sym.value.sym_var.attno != 0 || t->sym.value.sym_var.varno != vn) ! 289: syserr("subsvars: RESDOM 0 not VAR 0 %d, %d, %d", ! 290: vn, t->sym.value.sym_var.attno, t->sym.type); ! 291: ! 292: /* change varno to new Qm.qm_newresvar (set by vrscan) */ ! 293: # ifdef xQTR3 ! 294: if (tTf(32, 1)) ! 295: printf("RESDOM 0: Qm.qm_newresvar %d\n", Qm.qm_newresvar); ! 296: # endif ! 297: t->sym.value.sym_var.varno = Qm.qm_newresvar; ! 298: return; ! 299: } ! 300: ! 301: /* scan right branch */ ! 302: subsvars(&t->right, vn, v, vmode); ! 303: ! 304: /* check for interesting node */ ! 305: if (t->sym.type != VAR || t->sym.value.sym_var.varno != vn) ! 306: return; ! 307: ! 308: /* test for special 'tid' attribute case */ ! 309: if (t->sym.value.sym_var.attno == 0 && vmode == mdVIEW) ! 310: { ! 311: qmerror(VIEWTIDS, Qt.qt_qmode, vn, 0); /* views do not have tids */ ! 312: } ! 313: ! 314: /* find var in vtree */ ! 315: v = vfind(t->sym.value.sym_var.attno, v); ! 316: if (v == NULL) ! 317: { ! 318: if (vmode == mdVIEW) ! 319: syserr("subsvars: attno %d", t->sym.value.sym_var.attno); ! 320: else if (vmode == mdAPP) ! 321: v = makezero(); ! 322: } ! 323: else ! 324: v = treedup(v); ! 325: ! 326: /* replace VAR node */ ! 327: if (v != NULL) ! 328: *proot = v; ! 329: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.