|
|
1.1 root 1: # include <ingres.h>
2: # include <aux.h>
3: # include <opsys.h>
4: # include <access.h>
5: # include <tree.h>
6: # include <symbol.h>
7: # include "globs.h"
8: # include <sccs.h>
9:
10: SCCSID(@(#)call_ovqp.c 7.1 2/5/81)
11:
12:
13: /*
14: ** CALL_OVQP -- Routines which interface to the One Variable Query Processor.
15: **
16: ** This file contains the routines associated with sending queries
17: ** and receiving results from OVQP. The interface to these routines is
18: ** still messy. Call_ovqp is given the query, mode, and result relation
19: ** as parameters and gets the source relation, and two flags
20: ** (De.de_newq, De.de_newr) as globals. The routines include:
21: **
22: ** Call_ovqp -- Sends a One-var query to ovqp and flushes the pipe.
23: **
24: ** Readresult -- Reads the result from a one-var query.
25: **
26: ** Endovqp -- Informs ovqp that the query is over. Helps to synchronize
27: ** the batch file (if any).
28: **
29: ** Trace Flags:
30: ** 61
31: */
32: /*
33: ** Call_ovqp -- send query down pipe to ovqp and flush pipe.
34: ** Inputs are:
35: ** mode retrieve, append, etc.
36: ** resultnum result relation id
37: ** tree the query
38: ** De.de_sourcevar (global) if >= 0 then source var
39: ** De.de_newq send NEWQ symbol
40: ** De.de_newr send NEWR symbol
41: */
42:
43: call_ovqp(tree, mode, resultnum)
44: register QTREE *tree;
45: int mode;
46: int resultnum;
47: {
48: register int i;
49: char *rangename();
50: extern int derror();
51: extern bool Batchupd;
52: extern DESC Inddes;
53: char ovqpbuf[LBUFSIZE];
54: DESC *readopen();
55: extern DESC *specopen();
56: extern char *rnum_convert();
57:
58: # ifdef xOTM
59: if (tTf(90, 1))
60: timtrace(7, 0);
61: # endif
62:
63: # ifdef xDTR1
64: if (tTf(61, -1))
65: {
66: if (tTf(61, 0))
67: printf("CALL_OVQP-\n");
68: if (tTf(61, 1))
69: {
70: if (De.de_newq)
71: {
72: printf("new query to ovqp\n");
73: treepr(tree);
74: }
75: else
76: printf("query same as previous\n");
77: }
78: if (tTf(61, 2))
79: {
80: printf("De.de_sourcevar=%d\t", De.de_sourcevar);
81: if (De.de_sourcevar >= 0)
82: printf("relid=%s\t", rangename(De.de_sourcevar));
83: if (resultnum >= 0)
84: printf("De.ov_resultname=%s", rnum_convert(resultnum));
85: if (tree->sym.value.sym_root.rootuser)
86: printf(", userqry");
87: printf("\n");
88: }
89: }
90: # endif
91:
92:
93:
94: /* assign mode of this query */
95: De.de_qmode = mode;
96:
97: if (De.de_newr)
98: {
99: De.de_newr = FALSE;
100: }
101:
102: if (resultnum >= 0)
103: {
104: De.ov_result = specopen(resultnum);
105: }
106: else
107: De.ov_result = NULL;
108:
109: if (De.de_sourcevar >= 0)
110: De.ov_source = readopen(De.de_sourcevar);
111: else
112: De.ov_source = NULL;
113:
114: /* assume this will be direct update */
115: De.ov_userqry = De.de_buflag = FALSE;
116:
117: if (tree->sym.value.sym_root.rootuser)
118: {
119: De.ov_userqry = TRUE;
120: /* handle batch file */
121: if (De.ov_result && De.de_qmode != mdRETR)
122: {
123: if (Batchupd || De.ov_result->reldum.relindxd > 0)
124: {
125: if (De.ov_bopen == 0)
126: {
127: if (De.ov_result->reldum.relindxd > 0)
128: opencatalog("indexes", 0);
129: if (i = openbatch(De.ov_result, &Inddes, De.de_qmode))
130: syserr("call_ovqp:opn batch %d", i);
131: De.ov_bopen = TRUE;
132: }
133: De.de_buflag = TRUE;
134: }
135: }
136: }
137:
138: /* now write the query list itself */
139: if (De.de_newq)
140: {
141: De.ov_ovqpbuf = ovqpbuf;
142: initbuf(De.ov_ovqpbuf, LBUFSIZE, LISTFULL, derror);
143: De.de_qvptr = 0;
144: De.ov_alist = De.ov_bylist = De.ov_qlist = De.ov_tlist = NULL;
145: De.ov_targvc = tree->sym.value.sym_root.lvarc;
146: De.ov_qualvc = bitcnt(tree->sym.value.sym_root.rvarm);
147: De.ov_agcount = 0;
148:
149: if (tree->sym.type == AGHEAD)
150: {
151: De.ov_alist = &De.de_qvect[0];
152: if (tree->left->sym.type == BYHEAD)
153: {
154: mklist(tree->left->right);
155: ovqpnod(tree->left); /* BYHEAD node */
156: De.ov_bylist = &De.de_qvect[De.de_qvptr];
157: mklist(tree->left->left);
158: }
159: else
160: mklist(tree->left);
161: }
162: else
163: {
164: if (tree->left->sym.type != TREE)
165: {
166: De.ov_tlist = &De.de_qvect[0];
167: mklist(tree->left);
168: }
169: }
170:
171: /* now for the qualification */
172: ovqpnod(tree); /* ROOT node */
173:
174: if (tree->right->sym.type != QLEND)
175: {
176: De.ov_qlist = &De.de_qvect[De.de_qvptr];
177: mklist(tree->right);
178: }
179: ovqpnod(De.de_qle); /* QLEND node */
180: }
181:
182: /* Now call ovqp */
183: if (strategy())
184: {
185:
186: # ifdef xOTM
187: if (tTf(90, 2))
188: timtrace(9, 0);
189: # endif
190:
191: i = scan(); /* scan the relation */
192:
193: # ifdef xOTM
194: if (tTf(90, 2))
195: timtrace(10, 0);
196: # endif
197:
198: }
199: else
200: i = EMPTY;
201:
202: # ifdef xOTM
203: if (tTf(90, 1))
204: timtrace(8, 0);
205: # endif
206:
207:
208: /* return result of query */
209: return (i == NONEMPTY); /* TRUE if tuple satisfied */
210: }
211: /*
212: ** Endovqp -- Inform ovqp that processing is complete. "Ack" indicates
213: ** whether to wait for an acknowledgement from ovqp. The overall
214: ** mode of the query is sent followed by an EXIT command.
215: **
216: ** Ovqp decides whether to use batch update or not. If ack == ACK
217: ** then endovqp will read a RETVAL symbol from ovqp and return
218: ** a token which specifies whether to call the update processor or not.
219: */
220:
221: endovqp(ack)
222: int ack;
223: {
224: register int i;
225:
226: if (ack != RUBACK)
227: {
228: if (Equel && De.de_qry_mode == mdRETTERM)
229: equeleol(EXIT); /* signal end of retrieve to equel process */
230: }
231:
232: i = NOUPDATE;
233:
234: if (ack == ACK)
235: {
236: if (De.ov_bopen)
237: {
238: closebatch();
239: De.ov_bopen = FALSE;
240: i = UPDATE;
241: }
242: }
243: else
244: {
245: if (De.ov_bopen)
246: {
247: rmbatch();
248: De.ov_bopen = FALSE;
249: }
250: }
251:
252: closecatalog(FALSE);
253:
254: return (i);
255: }
256: /*
257: ** Add node q to ovqp's list
258: */
259:
260: ovqpnod(q)
261: register QTREE *q;
262: {
263: register SYMBOL *s;
264: extern QTREE *ckvar();
265: extern char *need();
266: register int i;
267:
268: s = &q->sym;
269:
270: /* VAR nodes must be specially processed */
271: if (s->type == VAR)
272: {
273: /* locate currently active VAR */
274: q = ckvar(q);
275:
276: /* Allocate an ovqp var node for the VAR */
277: s = (SYMBOL *) need(De.ov_ovqpbuf, SYM_HDR_SIZ + sizeof s->value.sym_var);
278: s->len = sizeof s->value.sym_var;
279: s->value.sym_var.attno = q->sym.value.sym_var.attno;
280: s->value.sym_var.varfrmt = q->sym.value.sym_var.varfrmt;
281: s->value.sym_var.varfrml = q->sym.value.sym_var.varfrml;
282:
283: /* If VAR has been substituted for, get value */
284: if (q->sym.value.sym_var.valptr)
285: {
286: /* This is a substituted variable */
287: if (q->sym.value.sym_var.varno == De.de_sourcevar)
288: syserr("ovqpnod:bd sub %d,%d", q->sym.value.sym_var.varno, De.de_sourcevar);
289:
290: s->type = S_VAR;
291: s->value.sym_var.valptr = q->sym.value.sym_var.valptr;
292: }
293: else
294: {
295: /* Var for one variable query */
296: if (q->sym.value.sym_var.varno != De.de_sourcevar)
297: syserr("ovqpnod:src var %d,%d", q->sym.value.sym_var.varno, De.de_sourcevar);
298: s->type = VAR;
299: i = q->sym.value.sym_var.attno;
300: if (i != 0)
301: s->value.sym_var.valptr = (ANYTYPE *) (De.ov_intup + De.ov_source->reloff[i]);
302: else
303: s->value.sym_var.valptr = (ANYTYPE *) &De.ov_intid;
304: }
305: }
306: if (s->type == AOP)
307: De.ov_agcount++;
308:
309: /* add symbol to list */
310: if (De.de_qvptr > MAXNODES - 1)
311: ov_err(NODOVFLOW);
312: De.de_qvect[De.de_qvptr++] = s;
313: }
314: /*
315: ** READAGG_RESULT
316: */
317:
318: readagg_result(result)
319: QTREE *result[];
320: {
321: register QTREE **r, *aop;
322: register int i;
323:
324: De.ov_tend = De.ov_outtup;
325: r = result;
326:
327: while (aop = *r++)
328: {
329: i = aop->sym.len & I1MASK;
330:
331: if (aop->sym.type == CHAR)
332: pad(De.ov_tend, i);
333:
334: bmove(De.ov_tend, (char *)&aop->sym.value, i);
335:
336: De.ov_tend += i;
337: # ifdef xDTR1
338: if (tTf(61, 3))
339: nodepr(aop);
340: # endif
341: }
342: }
343:
344:
345: ov_err(code)
346: int code;
347: {
348: derror(code);
349: }
350:
351:
352: DESC *
353: openindex(name)
354: char *name;
355: {
356: register DESC *d;
357: register int varno;
358: DESC *readopen();
359:
360: varno = SECINDVAR;
361: De.de_rangev[varno].relnum = rnum_assign(name);
362: d = readopen(varno);
363: return (d);
364: }
365: /*
366: ** Use "closer()" for closing relations. See
367: ** desc_close in openrs.c for details.
368: */
369: extern int closer();
370: int (*Des_closefunc)() = closer;
371:
372: init_decomp()
373: {
374: static struct accbuf xtrabufs[12];
375:
376: set_so_buf();
377: acc_addbuf(xtrabufs, 12);
378: }
379:
380:
381: startdecomp()
382: {
383: /* called at the start of each user query */
384: initrange();
385: rnum_init();
386: startovqp();
387: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.