1: # include   "../pipes.h"
   2: # include   "../ingres.h"
   3: # include   "../aux.h"
   4: # include   "../unix.h"
   5: # include   "../tree.h"
   6: # include   "../symbol.h"
   7: # include   "decomp.h"
   8: 
   9: 
  10: /*
  11: ** CALL_OVQP -- Routines which interface to the One Variable Query Processor.
  12: **
  13: **	This file contains the routines associated with sending queries
  14: **	and receiving results from OVQP. The interface to these routines is
  15: **	still messy. Call_ovqp is given the query, mode, and result relation
  16: **	as parameters and gets the source relation, and two flags
  17: **	(Newq, Newr) as globals. The routines include:
  18: **
  19: **	Call_ovqp -- Sends a One-var query to ovqp, flushes the pipe,
  20: **			and reads result from ovqp.
  21: **
  22: **	Endovqp    -- Informs ovqp that the query is over. Helps to synchronize
  23: **			the batch file (if any).
  24: **
  25: **	Pipesym    -- Writes a token symbol to ovqp.
  26: */
  27: 
  28: struct pipfrmt Outpipe, Inpipe;
  29: struct retcode  Retcode;    /* return code structure */
  30: 
  31: 
  32: 
  33: call_ovqp(qtree, mode, resultnum)
  34: struct querytree    *qtree;
  35: int         mode;
  36: int         resultnum;
  37: 
  38: /*
  39: ** Call_ovqp -- send query down pipe to ovqp and flush pipe.
  40: **	Inputs are:
  41: **		mode		retrieve, append, etc.
  42: **		resultnum	result relation id
  43: **		qtree		the query
  44: **		Sourcevar	(global) if >= 0 then source var
  45: **		Newq		send NEWQ symbol
  46: **		Newr		send NEWR symbol
  47: */
  48: 
  49: {
  50:     register struct querytree   *tree;
  51:     register int            i;
  52:     char                *rangename();
  53:     struct retcode          ret;
  54:     struct symbol           s;
  55:     int             j;
  56: 
  57:     tree = qtree;
  58: #	ifdef xDTR1
  59:     if (tTf(8, -1))
  60:     {
  61:         if (tTf(8, 0))
  62:             printf("CALL_OVQP-\n");
  63:         if (tTf(8, 1))
  64:         {
  65:             if (Newq)
  66:                 printree(tree, "new query to ovqp");
  67:             else
  68:                 printf("query same as previous\n");
  69:         }
  70:         if (tTf(8, 2))
  71:         {
  72:             printf("Sourcevar=%d\t", Sourcevar);
  73:             if (Sourcevar >= 0)
  74:                 printf("relid=%s\t", rangename(Sourcevar));
  75:             if (resultnum >= 0)
  76:                 printf("Resultname=%s", rnum_convert(resultnum));
  77:             if (((struct qt_root *) tree)->rootuser)
  78:                 printf(", userquery");
  79:             printf("\n");
  80:         }
  81:     }
  82: #	endif
  83: 
  84: 
  85: 
  86:     /*  header information needed by OVQP for each query  */
  87:     wrpipe(P_PRIME, &Outpipe, EXEC_OVQP, 0, 0);
  88:     pipesym(QMODE, 1, mode);
  89: 
  90:     if (Newq)
  91:         pipesym(CHANGESTRAT, 0);
  92: 
  93:     if (Newr)
  94:     {
  95:         pipesym(REOPENRES, 0);
  96:         Newr = FALSE;
  97:     }
  98: 
  99:     if (Sourcevar >= 0)
 100:     {
 101:         s.type = SOURCEID;
 102:         s.len = MAXNAME;
 103:         wrpipe(P_NORM, &Outpipe, W_ovqp, &s, 2);
 104:         wrpipe(P_NORM, &Outpipe, W_ovqp, rangename(Sourcevar), MAXNAME);
 105:     }
 106: 
 107:     if (resultnum >= 0)
 108:     {
 109:         s.type = RESULTID;
 110:         s.len = MAXNAME;
 111:         wrpipe(P_NORM, &Outpipe, W_ovqp, &s, 2);
 112:         wrpipe(P_NORM, &Outpipe, W_ovqp, rnum_convert(resultnum), MAXNAME);
 113:     }
 114: 
 115:     /*	this symbol, USERQRY, should be sent last because OVQP
 116: 	 *	requires the query mode and result relation when it
 117: 	 *	encounters USERQRY.
 118: 	 */
 119: 
 120:     if (((struct qt_root *) tree)->rootuser)
 121:     {
 122:         pipesym(USERQRY, 0);
 123:     }
 124: 
 125:     /*  now write the query list itself  */
 126: 
 127:     pipesym(TREE, 0);
 128: 
 129:     if (tree->sym.type == AGHEAD)
 130:     {
 131:         pipesym(AGHEAD, 0);
 132:         if (tree->left->sym.type == BYHEAD)
 133:         {
 134:             mklist(tree->left->right);
 135:             pipesym(BYHEAD, 0);
 136:             mklist(tree->left->left);
 137:         }
 138:         else
 139:             mklist(tree->left);
 140:     }
 141:     else
 142:         mklist(tree->left);
 143: 
 144:     pipesym(ROOT, 0);
 145:     mklist(tree->right);
 146:     pipesym(QLEND, 0);
 147: 
 148:     /* now flush the query to ovqp */
 149:     wrpipe(P_FLUSH, &Outpipe, W_ovqp);
 150: 
 151:     /*
 152: 	** Read the result of the query from ovqp. A Retcode
 153: 	** struct is expected.
 154: 	** The possble values of Retcode.rt_status are:
 155: 	**	EMPTY     -- no tuples satisfied
 156: 	**	NONEMPTY  -- at least one tuple satisfied
 157: 	**	error num -- ovqp user error
 158: 	*/
 159: 
 160: 
 161:     rdpipe(P_PRIME, &Inpipe);
 162:     if (rdpipe(P_NORM, &Inpipe, R_ovqp, &ret, sizeof (ret)) != sizeof (ret))
 163:         syserr("readresult: read error on R_ovqp");
 164:     j = ret.rc_status;
 165:     switch (j)
 166:     {
 167:       case EMPTY:
 168:         i = FALSE;
 169:         break;
 170: 
 171:       case NONEMPTY:
 172:         i = TRUE;
 173:         if (((struct qt_root *) tree)->rootuser)
 174:             Retcode.rc_tupcount = ret.rc_tupcount;
 175:         break;
 176: 
 177:       default:
 178:         derror(j);
 179: 
 180:     }
 181:     return (i);
 182: }
 183: 
 184: 
 185: 
 186: readagg_result(result)
 187: struct querytree    *result[];
 188: 
 189: /*
 190: ** Readagg_result -- read results from ovqp from a simple aggregate.
 191: */
 192: 
 193: {
 194:     register struct querytree   **r, *aop;
 195:     register int            vallen;
 196:     int             i;
 197: 
 198:     r = result;
 199:     while (aop = *r++)
 200:     {
 201:         vallen = aop->sym.len & I1MASK;
 202:         if (rdpipe(P_NORM, &Inpipe, R_ovqp, &aop->sym, 2) != 2)
 203:             syserr("ageval:rd err (1)");
 204:         if (vallen != (aop->sym.len & I1MASK))
 205:             syserr("ageval:len %d,%d", vallen, aop->sym.len);
 206:         if ((i = rdpipe(P_NORM, &Inpipe, R_ovqp, aop->sym.value, vallen)) != vallen)
 207:             syserr("ageval:rd err %d,%d", i, vallen);
 208: #		ifdef xDTR1
 209:         if (tTf(8, 3))
 210:             writenod(aop);
 211: #		endif
 212:     }
 213: }
 214: 
 215: 
 216: 
 217: 
 218: endovqp(ack)
 219: int ack;
 220: 
 221: /*
 222: ** Endovqp -- Inform ovqp that processing is complete. "Ack" indicates
 223: **	whether to wait for an acknowledgement from ovqp. The overall
 224: **	mode of the query is sent followed by an EXIT command.
 225: **
 226: **	Ovqp decides whether to use batch update or not. If ack == ACK
 227: **	then endovqp will read a RETVAL symbol from ovqp and return
 228: **	a token which specifies whether to call the update processor or not.
 229: */
 230: 
 231: {
 232:     register int        done, j;
 233:     struct retcode      ret;
 234:     extern int      Qry_mode;
 235:     extern struct descriptor Inddes;
 236: 
 237:     if (ack != RUBACK)
 238:     {
 239:         wrpipe(P_PRIME, &Outpipe, EXEC_OVQP, 0, 0);
 240: 
 241:         /* send mode of the query */
 242:         pipesym(QMODE, 1, Qry_mode);
 243: 
 244:         /* send exit code */
 245:         pipesym(EXIT, 1, ack);
 246: 
 247:         wrpipe(P_END, &Outpipe, W_ovqp);
 248:     }
 249: 
 250:     j = NOUPDATE;
 251:     if (ack == ACK)
 252:     {
 253:         /* read acknowledgement from ovqp */
 254:         rdpipe(P_PRIME, &Inpipe);
 255:         if (rdpipe(P_NORM, &Inpipe, R_ovqp, &ret, sizeof (ret)) != sizeof (ret))
 256:             syserr("endovqp no retcode");
 257: 
 258:         j = ret.rc_status;
 259:         if (j != UPDATE && j != NOUPDATE)
 260:             syserr("endovqp:%d", j);
 261: 
 262:         rdpipe(P_SYNC, &Inpipe, R_ovqp);
 263:     }
 264: 
 265:     cleanrel(&Inddes);  /* could be closecatalog(FALSE) except for
 266: 				** text space limitations */
 267:     return (j);
 268: }
 269: 
 270: 
 271: 
 272: 
 273: 
 274: 
 275: pipesym(token, length, val)
 276: int token;
 277: int length;
 278: int val;
 279: {
 280:     register struct symbol  *s;
 281:     char            temp[4];
 282:     register int        i;
 283: 
 284:     s = (struct symbol *) temp;
 285:     i = length;
 286: 
 287:     s->type = token;
 288:     if (s->len = i)
 289:         s->value[0] = val;
 290: 
 291:     wrpipe(P_NORM, &Outpipe, W_ovqp, s, i + 2);
 292: }
 293: 
 294: ovqpnod(node)
 295: struct querytree    *node;
 296: {
 297: 
 298:     register int            typ;
 299:     register struct querytree   *q;
 300:     register struct symbol      *s;
 301:     int             i;
 302:     char                temp[4];
 303:     struct querytree        *ckvar();
 304: 
 305:     q = node;
 306:     s = (struct symbol *) temp;
 307: 
 308:     typ = q->sym.type;
 309:     s->type = typ;
 310: 
 311:     switch (typ)
 312:     {
 313:       case VAR:
 314:         q = ckvar(q);
 315: 
 316:         /*  check to see if this variable has been substituted for.
 317: 		**  if so, pass the constant value to OVQP		      */
 318: 
 319:         if (((struct qt_var *)q)->valptr)
 320:         {
 321:             s->type = ((struct qt_var *)q)->frmt;
 322:             s->len = ((struct qt_var *)q)->frml;
 323:             wrpipe(P_NORM, &Outpipe, W_ovqp, s, 2);
 324:             wrpipe(P_NORM, &Outpipe, W_ovqp, ((struct qt_var *)q)->valptr, s->len & 0377);
 325:             return;
 326:         }
 327:         else
 328:         {
 329:             /* double check that variable is sourcevar */
 330:             if (((struct qt_var *)q)->varno != Sourcevar)
 331:                 syserr("mklist:src=%d,var=%d", Sourcevar, ((struct qt_var *)q)->varno);
 332:             s->len = 1;
 333:             s->value[0] = ((struct qt_var *)q)->attno;
 334:             break;
 335:         }
 336: 
 337:       case TREE:
 338:         return;
 339: 
 340:       case AND:
 341:       case OR:
 342:         s->len = 0;
 343:         break;
 344: 
 345:       case BOP:
 346:       case RESDOM:
 347:       case UOP:
 348:         s->len = 1;
 349:         s->value[0] = *(q->sym.value);
 350:         break;
 351: 
 352:       default:
 353:         i = (q->sym.len & 0377) + 2;
 354:         wrpipe(P_NORM, &Outpipe, W_ovqp, &q->sym, i);
 355:         return;
 356:     }
 357: 
 358:     wrpipe(P_NORM, &Outpipe, W_ovqp, s, s->len + 2);
 359: }
 360: 
 361: /*
 362: **	Use "inpcloser()" for closing relations. See
 363: **	desc_close in openrs.c for details.
 364: */
 365: extern int  inpcloser();
 366: int     (*Des_closefunc)()  = inpcloser;
 367: 
 368: 
 369: init_decomp()
 370: {
 371:     /* this is a null routine called from main() */
 372: }
 373: 
 374: 
 375: startdecomp()
 376: {
 377:     /* called at the start of each user query */
 378:     Retcode.rc_tupcount = 0;
 379:     initrange();
 380:     rnum_init();
 381: }
 382: 
 383: 
 384: /*
 385: ** Files_avail -- returns how many file descriptors are available
 386: **	for decomposition. For decomp running by itself the fixed
 387: **	overhead for files is:
 388: **
 389: **		4 -- pipes
 390: **		1 -- relation relation
 391: **		1 -- attribute relation
 392: **		1 -- indexes relation
 393: **		1 -- standard output
 394: **		1 -- concurrency
 395: */
 396: 
 397: files_avail(mode)
 398: int mode;
 399: {
 400:     return (MAXFILES - 9);
 401: }

Defined functions

files_avail defined in line 397; used 1 times
init_decomp defined in line 369; used 1 times
ovqpnod defined in line 294; used 2 times
pipesym defined in line 275; used 11 times
readagg_result defined in line 186; used 1 times
startdecomp defined in line 375; used 1 times

Defined variables

Inpipe defined in line 28; used 7 times
Outpipe defined in line 28; used 13 times
Retcode defined in line 29; used 2 times
Last modified: 1995-03-04
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3886
Valid CSS Valid XHTML 1.0 Strict