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