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