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