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