1: # include "../pipes.h" 2: # include "../ingres.h" 3: # include "../tree.h" 4: # include "../symbol.h" 5: # include "decomp.h" 6: 7: /* 8: ** AGEVAL -- evaluate simple aggregate. 9: ** 10: ** Uses trace flag 5 11: ** 12: ** Ageval is passed the tree of a simple aggregate, 13: ** and an array of space to store the results. The 14: ** amount of space actually allocated is stored in 15: ** (*result)->sym.len 16: ** 17: ** If the aggregate is unique (eg. countu, sumu, avgu) 18: ** or if the aggregate is multi-variable, special 19: ** processing is done. A temporary relation is formed 20: ** with a result domain for each single agg in the tree. 21: ** Decomp is called to retrieve 22: ** the values to be aggregated into that relation. 23: ** 24: ** If the aggregate is unique, then duplicates are 25: ** removed from the temporary relation. 26: ** 27: ** Next the aggregate is run on either the original relation 28: ** or on the temporary relation. 29: ** 30: ** Finally the result is read from OVQP and if a 31: ** temporary relation was used, it is destroyed. 32: ** 33: */ 34: 35: 36: struct querytree *ageval(tree, result) 37: struct querytree *tree; /* root of aggregate */ 38: struct querytree *result[]; /* space for results */ 39: { 40: register struct querytree *aghead, *resdom, *aop; 41: struct querytree *newtree; 42: struct querytree *lnodv[MAXDOM + 2]; 43: char agbuf[AGBUFSIZ]; 44: int temp_relnum, i; 45: extern int derror(); 46: extern struct querytree *makroot(); 47: extern struct querytree *makresdom(); 48: extern struct querytree *makavar(); 49: 50: aghead = tree; 51: aop = aghead->left; 52: temp_relnum = NORESULT; 53: 54: /* if PRIME or multi-var, form aggregate domain in temp relation */ 55: if (prime(aop) || ((struct qt_root *) aghead)->tvarc > 1) 56: { 57: initbuf(agbuf, AGBUFSIZ, AGBUFFULL, &derror); 58: 59: lnodv[lnode(aop, lnodv, 0)] = 0; 60: 61: /* create new tree for retrieve and give it the qualification */ 62: newtree = makroot(agbuf); 63: newtree->right = aghead->right; 64: aghead->right = Qle; 65: 66: /* put a resdom on new tree for each aop in orig tree */ 67: /* make each aop in orig tree reference new relation */ 68: for (i = 0; aop = lnodv[i]; ) 69: { 70: 71: /* create resdom for new tree */ 72: resdom = makresdom(agbuf, aop); 73: ((struct qt_res *) resdom)->resno = ++i; 74: resdom->right = aop->right; 75: 76: /* connect it to newtree */ 77: resdom->left = newtree->left; 78: newtree->left = resdom; 79: 80: /* make orig aop reference new relation */ 81: aop->right = makavar(resdom, FREEVAR, i); 82: } 83: 84: /* make result relation */ 85: temp_relnum = mak_t_rel(newtree, "a", -1); 86: 87: /* prepare for query */ 88: mapvar(newtree, 0); 89: decomp(newtree, mdRETR, temp_relnum); 90: Rangev[FREEVAR].relnum = temp_relnum; 91: Sourcevar = FREEVAR; 92: 93: /* if prime, remove dups */ 94: if (prime(aghead->left)) 95: { 96: /* modify to heapsort */ 97: removedups(FREEVAR); 98: } 99: 100: } 101: 102: Newq = 1; 103: Newr = TRUE; 104: 105: call_ovqp(aghead, mdRETR, NORESULT); /* call ovqp with no result relation */ 106: Newq = 0; 107: 108: /* pick up results */ 109: readagg_result(result); 110: 111: /* if temp relation was created, destroy it */ 112: if (temp_relnum != NORESULT) 113: dstr_rel(temp_relnum); 114: 115: } 116: 117: prime(aop) 118: struct querytree *aop; 119: 120: /* 121: ** Determine if an aggregate contains any 122: ** prime aggregates. Note that there might 123: ** be more than one aggregate. 124: */ 125: 126: { 127: register struct querytree *a; 128: 129: a = aop; 130: do 131: { 132: switch (a->sym.value[0]) 133: { 134: case opCOUNTU: 135: case opSUMU: 136: case opAVGU: 137: return (TRUE); 138: } 139: } while (a = a->left); 140: return (FALSE); 141: } 142: 143: removedups(var) 144: int var; 145: 146: /* 147: ** Remove dups from an unopened relation 148: ** by calling heapsort 149: */ 150: 151: { 152: register char *p; 153: char *rangename(); 154: 155: closer1(var); /* guarantee that relation has been closed */ 156: initp(); 157: p = rangename(var); /* get name of relation */ 158: # ifdef xDTR1 159: if (tTf(5, 1)) 160: printf("removing dups from %s\n", p); 161: # endif 162: setp(p); 163: setp("heapsort"); 164: setp("num"); 165: call_dbu(mdMODIFY, FALSE); 166: }