|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.