1: # include "../ingres.h" 2: # include "../aux.h" 3: # include "../symbol.h" 4: # include "../tree.h" 5: # include "../pipes.h" 6: # include "ovqp.h" 7: 8: /* 9: ** getqry is called to read a logical query 10: ** from decomp. The query always comes is a 11: ** standard sequence: 12: ** 13: ** Query info 14: ** ie. source, result, mode etc. 15: ** 16: ** TREE 17: ** 18: ** optional target list 19: ** 20: ** optional AGHEAD 21: ** 22: ** optional BYLIST for AG 23: ** 24: ** ROOT 25: ** 26: ** optional qualification list 27: ** 28: ** QLEND 29: ** 30: ** return 0 if query received 31: ** return ACK or NOACK if query processing done 32: */ 33: 34: extern struct pipfrmt Inpipe, Outpipe; 35: struct descriptor Reldesc, Srcdesc, Inddes; 36: 37: 38: getqry() 39: { 40: register struct symbol *sym; 41: extern int Batchupd; 42: register int i; 43: register int qb_mark; 44: extern ov_err(); 45: extern char *Ovqpbuf; 46: char *rdsym(); 47: struct symbol **sym_ad(); 48: 49: /* initialize query buffer, and prepare for priming it later 50: * in this routine 51: */ 52: 53: initbuf(Ovqpbuf, LBUFSIZE, LISTFULL, ov_err); 54: qb_mark = markbuf(Ovqpbuf); 55: wrpipe(P_PRIME, &Outpipe, EXEC_DECOMP, 0, 0); 56: 57: Source = Result = 0; /* assume no source or result relations */ 58: Userqry = Buflag = Newq = FALSE; /* assume batch not needed */ 59: /* read in initial info about query */ 60: 61: while ((sym = (struct symbol *) rdsym())->type != TREE) /* process until TREE */ 62: { 63: switch (sym->type) 64: { 65: case SOURCEID: 66: Source = &Srcdesc; 67: openrel(&Srcdesc, sym->value, 0); 68: break; 69: 70: case RESULTID: 71: Result = &Reldesc; 72: openrel(&Reldesc, sym->value, 1); 73: break; 74: 75: case USERQRY: 76: Userqry = TRUE; 77: /* if this is an update, consider using batch */ 78: if (Result && (Ov_qmode != mdRETR)) 79: { 80: /* if the batchupd flag is set or the rel has a secondary index */ 81: /* batch the updates */ 82: # ifdef xOTR1 83: if (tTf(22, 9)) 84: printf("Batchupd=%d,relindx=%d\n", Batchupd, Result->relindxd); 85: # endif 86: if (Batchupd || Result->relindxd) 87: { 88: /* if the batch hasn't been opened yet, open it */ 89: # ifdef xOTR1 90: if (tTf(22, 10)) 91: printf("USING BATCH\n"); 92: # endif 93: if (!Bopen) 94: { 95: opencatalog("indexes", 0); 96: if (i = openbatch(Result, &Inddes, Ov_qmode)) 97: syserr("getqry:openbatch ret %d", i); 98: Bopen = TRUE; 99: } 100: Buflag = TRUE; 101: } 102: } 103: if (!Result) /* true if this is a retrieve to equel or the terminal */ 104: Retrieve = TRUE; 105: break; 106: 107: case CHANGESTRAT: 108: /* indicates to strategy that a new strategy must be determined */ 109: Newq = TRUE; 110: break; 111: 112: case REOPENRES: 113: /* guarantee that result relation will be opened fresh */ 114: closerel(&Reldesc); 115: break; 116: 117: case QMODE: 118: Ov_qmode = *sym->value & 0377; 119: /* 120: ** A mode of RETINTO comes only at the 121: ** end of a query. It's use is for signaling 122: ** the Retrieve flag for equel. It is 123: ** actually only needed when an equel 124: ** retrieve is made on an empty relation. 125: ** If you don't understand this don't worry. 126: */ 127: if (Ov_qmode == mdRETTERM) 128: { 129: Retrieve = TRUE; 130: /* change the mode just in case */ 131: Ov_qmode = mdRETR; 132: } 133: break; 134: 135: case EXIT: 136: rdpipe(P_SYNC, &Inpipe, R_decomp); /* read the end of pipe */ 137: return (*sym->value & 0377); /* return mode of query end */ 138: 139: default: 140: syserr("getqry:bad sym %d", sym->type); 141: } 142: } 143: 144: /* init the various list head as null */ 145: Tlist = Alist = Bylist = Qlist = 0; 146: Qvpointer = Targvc = Qualvc = 0; 147: 148: /* prime the buffer, 149: * this throws away the header info from above 150: */ 151: freebuf(Ovqpbuf, qb_mark); 152: 153: /* read in (possibly null) target list */ 154: while ((sym = (struct symbol *) rdsym())->type != AGHEAD) /* read until an AGHEAD */ 155: { 156: switch (sym->type) 157: { 158: case ROOT: 159: goto qread; 160: 161: case VAR: 162: /* variable in target list */ 163: Targvc++; 164: putvar(sym, &Srcdesc, Intup); 165: /* fall through for Tlist check */ 166: 167: default: 168: /* the catch all INT, CHAR, etc. */ 169: if (!Tlist) 170: Tlist = sym_ad(); /* top of target list */ 171: break; 172: } 173: } 174: /* next possibility is aggregate */ 175: 176: Agcount = 0; 177: while ((sym = (struct symbol *) rdsym())->type != ROOT) /* process until ROOT */ 178: { 179: switch (sym->type) 180: { 181: case VAR: 182: /* variable in aggregate list */ 183: Targvc++; 184: putvar(sym, &Srcdesc, Intup); 185: /* fall through for Alist check */ 186: 187: default: 188: if (!Alist) 189: Alist = sym_ad(); 190: if (sym->type == AOP) 191: Agcount++; 192: break; 193: 194: case BYHEAD: 195: /* aggregate function */ 196: while ((sym = (struct symbol *) rdsym())->type != ROOT) /* read until ROOT */ 197: { 198: if (!Bylist) 199: Bylist = sym_ad(); 200: if (sym->type == VAR) 201: putvar(sym, &Srcdesc, Intup); 202: } 203: goto qread; 204: } 205: } 206: 207: qread: 208: 209: /* read in the qualification */ 210: while ((sym = (struct symbol *) rdsym())->type != QLEND) /* read until end of qualification */ 211: { 212: if (!Qlist) 213: Qlist = sym_ad(); 214: if (sym->type == VAR) 215: { 216: Qualvc++; 217: putvar(sym, &Srcdesc, Intup); 218: } 219: } 220: return (0); /* successful return */ 221: }