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: }

Defined functions

byeval defined in line 9; used 2 times
modqual defined in line 283; used 1 times
Last modified: 1986-04-17
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1298
Valid CSS Valid XHTML 1.0 Strict