|
|
1.1 ! root 1: # include <ingres.h> ! 2: # include <tree.h> ! 3: # include <symbol.h> ! 4: # include <pv.h> ! 5: # include "globs.h" ! 6: # include <sccs.h> ! 7: # include <errors.h> ! 8: ! 9: SCCSID(@(#)byeval.c 8.3 12/18/85) ! 10: ! 11: /* ! 12: ** BYEVAL - process aggregate function ! 13: ** ! 14: ** Byeval is passed the root of the original query ! 15: ** tree and the root of the aggregate function to ! 16: ** be processed. ! 17: ** ! 18: ** It first creates a temporary relation which will ! 19: ** hold the aggregate result. The format of the relation ! 20: ** is: ! 21: ** _SYSxxxxxaa(count, by-dom1, ... , by-domn, ag1, ... , agm) ! 22: ** ! 23: ** The relation is moved into the range table and will become ! 24: ** a part of the query. ! 25: ** ! 26: ** If there are any occurences of the variables ! 27: ** from the by-domains, anywhere in the original query tree, ! 28: ** the aggregate relation is linked on all by-domains in the ! 29: ** original query tree. ! 30: ** ! 31: ** If the aggregate is unique, multivariable, or has a ! 32: ** qualification, then special processing is done. ! 33: ** ! 34: ** If the aggregate is qualified then the by-domains are ! 35: ** projected into the result relation. This guarantees that ! 36: ** every value of the by-domains will be represented in the ! 37: ** aggregate result. ! 38: ** ! 39: ** If the aggregate is unique or multivariable, then another ! 40: ** temporary relation is created and the values which will be ! 41: ** aggregated; along with the by-domains, are retrieved into ! 42: ** the temporary relation. ! 43: ** ! 44: ** If unique, then duplicates are removed from the temporary relation. ! 45: ** ! 46: ** Next the result relation for the aggregate is modified ! 47: ** to hash in order to speed up the processing of the aggregate ! 48: ** and guarantee that there are no duplicates in the bylist. ! 49: ** ! 50: ** The aggregate is then run, and if a temporary relation was ! 51: ** created (eg. unique or multivar aggregate) then it is destroyed. ! 52: ** ! 53: ** Trace Flags: ! 54: ** 42 ! 55: */ ! 56: ! 57: ! 58: QTREE * ! 59: byeval(root, aghead, agvar) ! 60: QTREE *root; /* root of orig query */ ! 61: QTREE *aghead; /* root of ag fcn sub-tree */ ! 62: int agvar; /* variable number assigned to this aggregate */ ! 63: { ! 64: ! 65: register QTREE *q, *ag, *resdom; ! 66: QTREE *r; ! 67: int temp_relnum, i, filled; ! 68: QTREE *lnodv[MAXDOM+2], *save_node[MAXDOM+2]; ! 69: int agbuf[1+AGBUFSIZ/sizeof(int)]; ! 70: char nums[2]; ! 71: int relnum; ! 72: QTREE *byhead, **alnp; ! 73: int bydoms, bymap, primeag, srcmap; ! 74: extern int derror(); ! 75: extern QTREE *makroot(), *makavar(), *makresdom(), *copytree(); ! 76: extern char *rnum_convert(); ! 77: ! 78: # ifdef xDTR1 ! 79: if (tTf(42, -1)) ! 80: printf("BYEVAL\n"); ! 81: # endif ! 82: ! 83: ag = aghead; ! 84: byhead = ag->left; ! 85: ! 86: /* first create the aggregate result relation */ ! 87: /* params for create */ ! 88: ! 89: initp(); /* init globals for setp */ ! 90: setp(PV_STR,"0"); /* initial relstat field */ ! 91: relnum = rnum_alloc(); ! 92: setp(PV_STR,rnum_convert(relnum)); ! 93: setp(PV_STR,"count"); /* domain 1 - count field per BY value */ ! 94: setp(PV_STR,"i4"); /* format of count field */ ! 95: ! 96: i = bydoms = lnode(byhead->left, lnodv, 0); ! 97: lnodv[i] = 0; ! 98: alnp = &lnodv[++i]; ! 99: i = lnode(byhead->right, lnodv, i); ! 100: lnodv[i] = 0; ! 101: ! 102: domnam(lnodv, "by"); /* BY list domains */ ! 103: domnam(alnp, "ag"); /* aggregate value domains */ ! 104: ! 105: call_dbu(mdCREATE, FALSE); ! 106: ! 107: De.de_rangev[agvar].relnum = relnum; ! 108: # ifdef xDTR1 ! 109: if (tTf(42, 7)) ! 110: printf("agvar=%d,rel=%s\n", agvar, rnum_convert(relnum)); ! 111: # endif ! 112: ! 113: bymap = varfind(byhead->left, (QTREE *)NULL); ! 114: ! 115: /* ! 116: ** Find all variables in the tree in which you are nested. ! 117: ** Do not look at any other aggregates in the tree. Just in ! 118: ** case the root is an aggregate, explicitly look at its ! 119: ** two descendents. ! 120: */ ! 121: srcmap = varfind(root->left, ag) | varfind(root->right, ag); ! 122: # ifdef xDTR1 ! 123: if (tTf(42, 8)) ! 124: printf("bymap=%o,srcmap=%o\n", bymap, srcmap); ! 125: # endif ! 126: ! 127: if (bymap & srcmap) ! 128: modqual(root, lnodv, srcmap, agvar); ! 129: ! 130: /* if aggregate is unique or there is a qualification ! 131: ** or aggregate is multi-var, then special processing is done */ ! 132: ! 133: temp_relnum = NORESULT; ! 134: filled = FALSE; ! 135: primeag = prime(byhead->right); ! 136: if (ag->right->sym.type != QLEND || ag->sym.value.sym_root.tvarc > 1 || primeag) ! 137: { ! 138: /* init a buffer for new tree components */ ! 139: initbuf((char *)agbuf, AGBUFSIZ, AGBUFFULL, derror); ! 140: ! 141: /* make a root for a new tree */ ! 142: q = makroot((char *)agbuf); ! 143: ! 144: /* ! 145: ** Create a RESDOM for each by-domain in the original ! 146: ** aggregate. Rather than using the existing by-domain ! 147: ** function, a copy is used instead. This is necessary ! 148: ** since that subtree might be needed later (if modqual()) ! 149: ** decided to use it. Decomp does not restore the trees ! 150: ** it uses and thus the by-domains might be altered. ! 151: */ ! 152: for (i = 0; r = lnodv[i]; i++) ! 153: { ! 154: resdom = makresdom((char *)agbuf, r); ! 155: resdom->sym.value.sym_resdom.resno = i + 2; ! 156: resdom->right = copytree(r->right, (char *)agbuf); ! 157: resdom->left = q->left; ! 158: q->left = resdom; ! 159: } ! 160: mapvar(q, 0); /* make maps on root */ ! 161: # ifdef xDTR1 ! 162: if (tTf(42, 2)) ! 163: { ! 164: printf("byedomains\n"); ! 165: treepr(q); ! 166: } ! 167: # endif ! 168: ! 169: /* if agg is qualified, project by-domains into result */ ! 170: if (ag->right->sym.type != QLEND) ! 171: { ! 172: filled = TRUE; ! 173: i = De.de_sourcevar; /* save value */ ! 174: decomp(q, mdRETR, relnum); ! 175: De.de_sourcevar = i; /* restore value */ ! 176: } ! 177: ! 178: /* if agg is prime or multivar, compute into temp rel */ ! 179: if (ag->sym.value.sym_root.tvarc > 1 || primeag) ! 180: { ! 181: q->right = ag->right; /* give q the qualification */ ! 182: ag->right = De.de_qle; /* remove qualification from ag */ ! 183: ! 184: /* put aop resdoms on tree */ ! 185: for (i = bydoms + 1; r = lnodv[i]; i++) ! 186: { ! 187: resdom = makresdom((char *)agbuf, r); ! 188: resdom->right = r->right; ! 189: resdom->left = q->left; ! 190: q->left = resdom; ! 191: ! 192: /* make aop refer to temp relation */ ! 193: r->right = makavar(resdom, FREEVAR, i); ! 194: } ! 195: ! 196: /* assign result domain numbers */ ! 197: for (resdom = q->left; resdom->sym.type != TREE; resdom = resdom->left) ! 198: resdom->sym.value.sym_resdom.resno = --i; ! 199: ! 200: /* ! 201: ** change by-list in agg to reference new source rel. ! 202: ** Save the old bylist to be restored at the end of ! 203: ** this aggregate. ! 204: */ ! 205: for (i = 0; resdom = lnodv[i]; i++) ! 206: { ! 207: save_node[i] = resdom->right; ! 208: resdom->right = makavar(resdom, FREEVAR, i + 1); ! 209: } ! 210: ! 211: mapvar(q, 0); ! 212: # ifdef xDTR1 ! 213: if (tTf(42, 3)) ! 214: { ! 215: printf("new ag src\n"); ! 216: treepr(q); ! 217: } ! 218: # endif ! 219: ! 220: /* create temp relation */ ! 221: temp_relnum = mak_t_rel(q, "a", -1); ! 222: decomp(q, mdRETR, temp_relnum); ! 223: De.de_rangev[FREEVAR].relnum = temp_relnum; ! 224: De.de_sourcevar = FREEVAR; ! 225: if (primeag) ! 226: removedups(FREEVAR); ! 227: # ifdef xDTR1 ! 228: if (tTf(42, 4)) ! 229: { ! 230: printf("new agg\n"); ! 231: treepr(ag); ! 232: } ! 233: # endif ! 234: } ! 235: } ! 236: ! 237: /* set up parameters for modify to hash */ ! 238: initp(); ! 239: setp(PV_STR, rnum_convert(relnum)); ! 240: setp(PV_STR, "hash"); /* modify the empty rel to hash */ ! 241: setp(PV_STR, "num"); /* code to indicate numeric domain names */ ! 242: nums[1] = '\0'; ! 243: for (i = 0; i < bydoms; i++) ! 244: { ! 245: nums[0] = i + 2; ! 246: setp(PV_STR, nums); ! 247: } ! 248: setp(PV_STR, ""); ! 249: ! 250: /* set up fill factor information */ ! 251: setp(PV_STR,"minpages"); ! 252: if (filled) ! 253: { ! 254: setp(PV_STR,"1"); ! 255: setp(PV_STR,"fillfactor"); ! 256: setp(PV_STR,"100"); ! 257: } ! 258: else ! 259: { ! 260: setp(PV_STR,"10"); ! 261: } ! 262: specclose(relnum); ! 263: call_dbu(mdMODIFY, FALSE); ! 264: ! 265: ! 266: De.de_newq = 1; ! 267: De.de_newr = TRUE; ! 268: call_ovqp(ag, mdRETR, relnum); ! 269: ! 270: De.de_newq = 0; ! 271: /* if temp relation was used, destroy it */ ! 272: if (temp_relnum != NORESULT) ! 273: { ! 274: for (i = 0; resdom = lnodv[i]; i++) ! 275: resdom->right = save_node[i]; ! 276: dstr_rel(temp_relnum); ! 277: } ! 278: } ! 279: ! 280: ! 281: ! 282: ! 283: modqual(root, lnodv, srcmap, agvar) ! 284: QTREE *root; ! 285: QTREE *lnodv[]; ! 286: int srcmap; ! 287: int agvar; ! 288: { ! 289: register QTREE *and_eq, *afcn; ! 290: register int i; ! 291: extern QTREE *copytree(); ! 292: extern char *need(); ! 293: register int len; ! 294: ! 295: # ifdef xDTR1 ! 296: if (tTf(42, 12)) ! 297: printf("modqual %o\n", srcmap); ! 298: # endif ! 299: ! 300: for (i = 0; afcn = lnodv[i]; i++) ! 301: { ! 302: /* `AND' node */ ! 303: len = sizeof (struct rootnode) - sizeof (short); ! 304: and_eq = (QTREE *) need(De.de_qbuf, QT_HDR_SIZ + len); ! 305: and_eq->sym.type = AND; ! 306: and_eq->sym.len = len; ! 307: and_eq->sym.value.sym_root.tvarc = 0; ! 308: and_eq->sym.value.sym_root.lvarc = 0; ! 309: and_eq->sym.value.sym_root.lvarm = 0; ! 310: and_eq->sym.value.sym_root.rvarm = 0; ! 311: and_eq->right = root->right; ! 312: root->right = and_eq; ! 313: ! 314: /* `EQ' node */ ! 315: len = sizeof (struct opnode); ! 316: and_eq->left = (QTREE *) need(De.de_qbuf, QT_HDR_SIZ + len); ! 317: and_eq = and_eq->left; ! 318: and_eq->sym.type = BOP; ! 319: and_eq->sym.len = len; ! 320: and_eq->sym.value.sym_op.opno = opEQ; ! 321: ! 322: /* bydomain opEQ var */ ! 323: and_eq->right = copytree(afcn->right, De.de_qbuf); /* a-fcn (in Source) specifying BY domain */ ! 324: and_eq->left = makavar(afcn, agvar, i+2); /* VAR ref BY domain */ ! 325: } ! 326: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.