1: # include "../ingres.h" 2: # include "../tree.h" 3: # include "../symbol.h" 4: # include "decomp.h" 5: 6: /* 7: ** DECOMP1.C 8: ** 9: ** contains routines associated with setting up 10: ** detachable 1-variable sub-queries. 11: ** ptrs to these sq's are kept in the 12: ** array 'sqlist' declared in the main decomp routine. 13: ** 14: */ 15: 16: pull_sq(tree1, sqlist, locrang, sqrange, buf) 17: struct querytree *tree1; 18: struct querytree *sqlist[]; 19: int locrang[]; 20: int sqrange[]; 21: char *buf; 22: { 23: register struct querytree *q, *tree, *r; 24: struct querytree *s; 25: int anysq, j, badvar; 26: extern struct querytree *makroot(); 27: 28: tree = tree1; 29: 30: # ifdef xDTR1 31: if (tTf(10, 0)) 32: printf("PULL_SQ:tree=%l\n", tree); 33: # endif 34: 35: anysq = 0; 36: for (j = 0; j < MAXRANGE; j++) 37: sqlist[j] = 0; 38: 39: if (((struct qt_root *)tree)->tvarc == 1) 40: return; 41: 42: /* detach all one variable clauses except: 43: ** if the target list is one variable and 44: ** that variable is disjoint from the other 45: ** variables, then don't pull it. 46: ** 47: ** It will be more efficient to process it 48: ** all at once in decompy 49: */ 50: 51: badvar = 0; 52: if (((struct qt_root *)tree)->lvarc == 1) 53: { 54: badvar = ((struct qt_root *)tree)->lvarm; /* get bit position of var */ 55: 56: /* look for a two variable clause involving badvar */ 57: for (r = tree->right; r->sym.type != QLEND; r = r->right) 58: { 59: if (((struct qt_root *)r)->lvarc > 1 && (((struct qt_root *)r)->lvarm & badvar)) 60: { 61: badvar = 0; 62: break; 63: } 64: } 65: } 66: # ifdef xDTR1 67: if (tTf(10, 2)) 68: printf("Detachable clauses: (badvar=%o)\n", badvar); 69: # endif 70: for (r=tree; r->right->sym.type!=QLEND; ) 71: { 72: # ifdef xDTR1 73: if (tTf(10, 3)) 74: writenod(r); 75: # endif 76: q = r; 77: r = r->right; 78: if (((struct qt_root *)r)->lvarc == 1) 79: { 80: j = bitpos(((struct qt_root *)r)->lvarm); 81: # ifdef xDTR1 82: if (tTf(10, 4)) 83: { 84: printf("\nvar=%d,", j); 85: printree(r->left, "clause"); 86: } 87: # endif 88: if (((struct qt_root *)r)->lvarm == badvar) 89: { 90: # ifdef xDTR1 91: if (tTf(10, 5)) 92: printf("not detaching \n"); 93: # endif 94: continue; 95: } 96: anysq++; 97: 98: if (!sqlist[j]) /* MAKE ROOT NODE FOR SUBQUERY */ 99: sqlist[j] = makroot(buf); 100: s = sqlist[j]; 101: 102: /* MODIFY MAIN QUERY */ 103: 104: q->right = r->right; 105: 106: /* MODIFY `AND` NODE OF DETACHED CLAUSE */ 107: 108: r->right = s->right; 109: ((struct qt_root *)r)->rvarm = ((struct qt_root *)s)->rvarm; 110: ((struct qt_root *)r)->tvarc = 1; 111: 112: /* ADD CLAUSE TO SUB-QUERY */ 113: 114: s->right = r; 115: ((struct qt_root *)s)->rvarm = ((struct qt_root *)r)->lvarm; 116: ((struct qt_root *)s)->tvarc = 1; 117: 118: # ifdef xDTR1 119: if (tTf(10, 6)) 120: printree(s, "SQ"); 121: # endif 122: 123: r = q; 124: } 125: } 126: 127: /* NOW SET UP TARGET LIST FOR EACH SUBQUERY IN SQLIST */ 128: 129: # ifdef xDTR1 130: if (tTf(10, 7)) 131: printf("# sq clauses=%d\n", anysq); 132: # endif 133: if (anysq) 134: { 135: # ifdef xDTR1 136: if (tTf(10, 8)) 137: printf("Dfind--\n"); 138: # endif 139: dfind(tree, buf, sqlist); 140: mapvar(tree, 1); 141: 142: /* create the result relations */ 143: for (j = 0; j < MAXRANGE; j++) 144: { 145: if (q = sqlist[j]) 146: { 147: if (q->left->sym.type != TREE) 148: { 149: savrang(locrang, j); 150: sqrange[j] = mak_t_rel(q, "d", -1); 151: } 152: else 153: sqrange[j] = NORESULT; 154: } 155: } 156: } 157: } 158: 159: dfind(tree1, buf, sqlist) 160: struct querytree *tree1; 161: char *buf; 162: struct querytree *sqlist[]; 163: { 164: register int varno; 165: register struct querytree *tree, *sq; 166: extern struct querytree *ckvar(); 167: 168: tree = tree1; 169: if (!tree) 170: return; 171: # ifdef xDTR1 172: if (tTf(10, 9)) 173: writenod(tree); 174: # endif 175: if (tree->sym.type == VAR) 176: { 177: tree = ckvar(tree); 178: varno = ((struct qt_var *)tree)->varno; 179: if (sq = sqlist[varno]) 180: maktl(tree, buf, sq, varno); 181: return; 182: } 183: 184: /* IF CURRENT NODE NOT A `VAR` WITH SQ, RECURSE THRU REST OF TREE */ 185: 186: dfind(tree->left, buf, sqlist); 187: dfind(tree->right, buf, sqlist); 188: return; 189: } 190: 191: 192: maktl(node, buf, sq1, varno) 193: struct querytree *node; 194: char *buf; 195: struct querytree *sq1; 196: int varno; 197: { 198: register struct querytree *resdom, *tree, *sq; 199: int domno, map; 200: extern struct querytree *makresdom(), *copytree(); 201: 202: sq = sq1; 203: domno = ((struct qt_var *)node)->attno; 204: 205: # ifdef xDTR1 206: if (tTf(10, 12)) 207: printf("\tVar=%d,Dom=%d ", varno, domno); 208: # endif 209: /* CHECK IF NODE ALREADY CREATED FOR THIS DOMAIN */ 210: 211: for (tree = sq->left; tree->sym.type != TREE; tree = tree->left) 212: if (((struct qt_var *)tree->right)->attno == domno) 213: { 214: # ifdef xDTR1 215: if (tTf(10, 13)) 216: printf("Domain found\n"); 217: # endif 218: return; 219: } 220: 221: /* create a new resdom for domain */ 222: 223: resdom = makresdom(buf, node); 224: *resdom->sym.value = sq->left->sym.type == TREE? 1: 225: *sq->left->sym.value + 1; 226: /* resdom->right is a copy of the var node in order to 227: ** protect against tempvar() changing the var node. 228: */ 229: resdom->left = sq->left; 230: resdom->right = copytree(node, buf); 231: 232: 233: /* update ROOT node if necessary */ 234: 235: sq->left = resdom; 236: map = 1 << varno; 237: if (!(((struct qt_root *)sq)->lvarm & map)) 238: { 239: /* var not currently in tl */ 240: ((struct qt_root *)sq)->lvarm |= map; 241: ((struct qt_root *)sq)->lvarc++; 242: 243: /* if var is not in qualification then update total count */ 244: if (!(((struct qt_root *)sq)->rvarm & map)) 245: ((struct qt_root *)sq)->tvarc++; 246: # ifdef xDTR1 247: if (tTf(10, 15)) 248: { 249: printf("new root "); 250: writenod(sq); 251: } 252: # endif 253: } 254: 255: # ifdef xDTR1 256: if (tTf(10, 14)) 257: { 258: printf("new dom "); 259: writenod(resdom); 260: } 261: # endif 262: return; 263: }