1: # include "../pipes.h" 2: # include "../ingres.h" 3: # include "../tree.h" 4: # include "../symbol.h" 5: # include "decomp.h" 6: 7: /* 8: ** DECOMP -- Process a query given a query tree and range table. 9: ** 10: ** Decomp processes any arbitrary query by converting it into 11: ** a sequence of "one variable queries"; eg. queries involving 12: ** at most one source relation. This file and decision.c contain 13: ** the principle decision making routines. 14: ** 15: ** Decomp() is called with a pointer to a query tree, the mode 16: ** of the query (retrieve, append, etc.), and the internal name 17: ** of the result relation (if any). The routines included are: 18: ** 19: ** Decomp -- Opens the source relations and decides whether the 20: ** query is multi-variable or single/zero variable. 21: ** 22: ** Decompx -- Takes a multivariable query, removes and executes any 23: ** one-var restrictions and passes the remaining query 24: ** to decompz (if one/zero variable) or decision(). 25: ** 26: ** Decompy -- Performs "tuple substitution" on a multi-var query, 27: ** does any new one-var restrictions and passes the 28: ** remaining query to decompz (if one/zero variable) 29: ** or decision(). 30: ** 31: ** Decompz -- Executes a one/zero variable query by calling call_ovqp(). 32: */ 33: 34: decomp(q, qmode, result_num) 35: struct querytree *q; 36: int qmode; 37: int result_num; 38: 39: /* 40: ** Process query by calling either decompx for multivar 41: ** or decompz for 0 or 1 var query. Decomp() must guarantee 42: ** that the range table is the same upon exiting as it was 43: ** when entered. Newquery() and endquery() perform that function. 44: */ 45: 46: { 47: register struct querytree *root; 48: register int vc, i; 49: int locrange[MAXRANGE]; 50: 51: root = q; 52: vc = ((struct qt_root *)root)->tvarc; 53: # ifdef xDTR1 54: if (tTf(9, 0)) 55: printf("DECOMP: %d-var query, result_num=%d\n", vc, result_num); 56: if (tTf(9, 1)) 57: printree(root, "DECOMP"); 58: # endif 59: 60: openrs(root); 61: 62: if (vc > 1) 63: { 64: newquery(locrange); 65: i = decompx(root, qmode, result_num); 66: endquery(locrange, FALSE); /* don't reopen previous range */ 67: } 68: else 69: { 70: Newq = 1; 71: Sourcevar = -1; 72: i = decompz(root, qmode, result_num); 73: } 74: return (i); 75: } 76: 77: 78: decompx(root, qmode, result_num) 79: struct querytree *root; 80: int qmode; 81: int result_num; 82: 83: /* 84: ** Decompx -- Initialize for multi-variable query. 85: ** All one-variable subqueries are run. 86: ** If the remaining query is still multi-var 87: ** then decision() is called; else decompz() 88: ** is called. The range table is restored 89: ** after the query is complete. 90: ** The tempvars from the exec_sq() are left on the 91: ** tree since it is presumed that the tree will be discarded 92: ** anyway. 93: */ 94: 95: { 96: register int i, vc; 97: int disj; 98: char sqbuf[SQSIZ]; 99: struct querytree *sqlist[MAXRANGE]; 100: int locrang[MAXRANGE], sqrange[MAXRANGE]; 101: extern int derror(); 102: 103: vc = ((struct qt_root *)root)->tvarc; 104: initbuf(sqbuf, SQSIZ, SQBUFFULL, &derror); 105: pull_sq(root, sqlist, locrang, sqrange, sqbuf); 106: if ((i = exec_sq(sqlist, sqrange, &disj)) != -1) 107: { 108: undo_sq(sqlist, locrang, sqrange, i, i, FALSE); 109: return (FALSE); 110: } 111: vc -= disj; 112: tempvar(root, sqlist, sqbuf); 113: if (pull_const(root, sqbuf) == 0) 114: return (FALSE); 115: if (vc <= 1) 116: { 117: Sourcevar = -1; 118: Newq = 1; 119: return (decompz(root, qmode, result_num)); 120: } 121: i = decision(root, qmode, result_num, sqbuf); 122: undo_sq(sqlist, locrang, sqrange, MAXRANGE, MAXRANGE, FALSE); 123: return (i); 124: } 125: 126: 127: decompy(q, qmode, result_num, sqbuf) 128: struct querytree *q; 129: int qmode; 130: int result_num; 131: char *sqbuf; 132: 133: /* 134: ** Decompy -- decompose a multi-variable query by tuple substitution. 135: ** First a variable is selected 136: ** for substitution. Then for each tuple in the 137: ** selected variable, all one variable restrictions 138: ** are done (exec_sq) and the remaining query is 139: ** solved by calling either decompz() or recursively 140: ** decision(). 141: ** 142: ** The original tree and range table are guaranteed to 143: ** be the same on entry and exit (modulo the effects of 144: ** reformat()). 145: */ 146: 147: { 148: register struct querytree *root; 149: register int j, vc; 150: struct descriptor *descript; 151: struct querytree *newroot; 152: int constl, sqcnt, var, srcvar, maxsqcnt; 153: int disj, tc, qtrue; 154: long tid, hitid; 155: char *tuple; 156: struct querytree *sqlist[MAXRANGE], *need(), *copy_ands(); 157: int sqmark, sqmark1; 158: int locrang[MAXRANGE], sqrange[MAXRANGE]; 159: extern struct descriptor *readopen(); 160: 161: root = q; 162: vc = ((struct qt_root *)root)->tvarc; 163: 164: # ifdef xDTR1 165: if (tTf(9, -1)) 166: printf("DECOMPY:%l,vc=%d\n", root, vc); 167: # endif 168: 169: sqmark = markbuf(sqbuf); 170: constl = !((struct qt_root *)root)->lvarc; 171: qtrue = FALSE; 172: 173: if ((var = selectv(root)) < 0) 174: return (qtrue); 175: descript = readopen(var); /* gets full descriptor for setvar & get */ 176: tuple = (char *) need(sqbuf, descript->relwid); 177: setvar(root, var, &tid, tuple); 178: pull_sq(root, sqlist, locrang, sqrange, sqbuf); 179: tempvar(root, sqlist, sqbuf); 180: reformat(var, sqlist, locrang, sqbuf, root); 181: vc--; 182: 183: /* HERE FOR MULTI-VAR SUBSTITUTION */ 184: sqmark1 = markbuf(sqbuf); 185: Newq = 1; 186: tc = 0; 187: sqcnt = maxsqcnt = 0; 188: srcvar = -1; 189: Sourcevar = -1; 190: find(readopen(var), NOKEY, &tid, &hitid); 191: while (!(j=get(readopen(var), &tid, &hitid, tuple, NXTTUP))) 192: { 193: # ifdef xDTR1 194: if (tTf(9, 2)) 195: { 196: printf("Subst:"); 197: printup(readopen(var), tuple); 198: } 199: # endif 200: tc++; 201: if (vc > 1) 202: { 203: reset_sq(sqlist, locrang, sqcnt); 204: if ((sqcnt = exec_sq(sqlist, sqrange, &disj)) != -1) 205: continue; 206: 207: maxsqcnt = sqcnt; 208: vc -= disj; 209: if (vc <= 1) 210: { 211: Sourcevar = srcvar; 212: qtrue |= decompz(root, qmode, result_num); 213: srcvar = Sourcevar; 214: } 215: else 216: { 217: freebuf(sqbuf, sqmark1); 218: newroot = copy_ands(root, sqbuf); 219: qtrue |= decision(newroot, qmode, result_num, sqbuf); 220: } 221: vc += disj; 222: } 223: else 224: qtrue |= decompz(root, qmode, result_num); 225: 226: /* check for early termination on constant Target list */ 227: if (constl && qtrue) 228: break; 229: } 230: if (j < 0) 231: syserr("decompy: bad get %d on %.12s", j, readopen(var)->relid); 232: 233: /* undo the effect of pulling the sub queries */ 234: origvar(root, sqlist); 235: undo_sq(sqlist, locrang, sqrange, sqcnt, maxsqcnt, TRUE); 236: 237: /* undo the setvar on the main tree and all subtrees */ 238: clearvar(root, var); 239: for (j = 0; j < MAXRANGE; j++) 240: clearvar(sqlist[j], var); 241: 242: /* return any used buffer space */ 243: freebuf(sqbuf, sqmark); 244: 245: # ifdef xDTR1 246: if (tTf(9, 2)) 247: printf("tc[%.12s]=%d,qtrue=%d\n", rangename(var), tc, qtrue); 248: # endif 249: 250: return (qtrue); 251: } 252: 253: 254: 255: decompz(q, qmode, result_num) 256: struct querytree *q; 257: int qmode; 258: int result_num; 259: 260: /* 261: ** Decompz processes a one variable query 262: ** by calling call_ovqp(). 263: */ 264: 265: { 266: register struct querytree *root; 267: register int qualfound; 268: 269: root = q; 270: if (((struct qt_root *)root)->tvarc) 271: { 272: if (Sourcevar < 0) 273: { 274: if ((Sourcevar = selectv(root)) < 0) 275: return (FALSE); 276: } 277: } 278: else 279: { 280: Sourcevar = -1; 281: } 282: 283: qualfound = call_ovqp(root, qmode, result_num); 284: Newq = 0; 285: return (qualfound); 286: }