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