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