|
|
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.