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

Defined functions

byeval defined in line 51; used 1 times
modqual defined in line 266; used 1 times
Last modified: 1995-04-14
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3047
Valid CSS Valid XHTML 1.0 Strict