Fixing bugs in aggregate and join
[csql.git] / src / storage / AggTableImpl.cxx
blobaee53b9127ddbf17194eaaaa8122011fc288fbfa
1 /***************************************************************************
2 * Copyright (C) 2007 by www.databasecache.com *
3 * Contact: praba_tuty@databasecache.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 ***************************************************************************/
16 #include<Debug.h>
17 #include<Table.h>
18 #include<TableImpl.h>
19 #include<AggTableImpl.h>
20 AggTableImpl::AggTableImpl()
23 AggTableImpl::~AggTableImpl()
25 close();
27 void *AggTableImpl::getBindFldAddr(const char *name)
29 printError(ErrBadCall, "AggTableImpl getBindFldAdddr not implemented\n");
30 return NULL;
35 DbRetVal AggTableImpl::bindFld(const char *name, void *val)
37 printError(ErrBadCall, "AggTableImpl bindFld not implemented\n");
38 return ErrBadCall;
40 DbRetVal AggTableImpl::bindFld(const char *fldname, AggType aggType, void *val)
42 FieldInfo *info = new FieldInfo();
43 tableHdl->getFieldInfo(fldname, info);
44 AggFldDef *def = new AggFldDef();
45 strcpy(def->fldName, fldname);
46 def->type = info->type;
47 def->length= info->length;
48 def->appBuf = val;
49 def->atype=aggType;
50 def->bindBuf = NULL;
51 def->alreadyBinded = false;
52 ListIterator iter = fldList.getIterator();
53 AggFldDef *elem;
54 //If it is already binded, then use the same buffer which is binded.
55 //this code is to handle statements which have more aggregates on same field
56 while (iter.hasElement())
58 elem = (AggFldDef*) iter.nextElement();
59 if (strcmp(elem->fldName, fldname)==0)
61 def->bindBuf = elem->bindBuf;
62 def->alreadyBinded = true;
63 break;
66 if (!def->bindBuf)
68 def->bindBuf = AllDataType::alloc(def->type, def->length);
69 tableHdl->bindFld(fldname, def->bindBuf);
71 fldList.append(def);
72 delete info;
73 return OK;
75 DbRetVal AggTableImpl::setGroup(const char *fldname, void *val)
77 FieldInfo *info = new FieldInfo();
78 tableHdl->getFieldInfo(fldname, info);
79 strcpy(groupFld.fldName, fldname);
80 groupFld.type = info->type;
81 groupFld.length = info->length;
82 groupFld.appBuf = val;
83 groupFld.bindBuf = AllDataType::alloc(info->type, info->length);
84 tableHdl->bindFld(fldname, groupFld.bindBuf);
85 delete info;
86 return OK;
89 DbRetVal AggTableImpl::execute()
91 ListIterator iter = fldList.getIterator();
92 AggFldDef *def;
93 if (isGroupSet())
94 aggNodeSize = AllDataType::size(groupFld.type, groupFld.length);
95 else
96 aggNodeSize = 0;
97 while (iter.hasElement())
99 def = (AggFldDef*) iter.nextElement();
100 aggNodeSize = aggNodeSize + AllDataType::size(def->type, def->length);
101 if (def->atype == AGG_AVG) aggNodeSize = aggNodeSize + sizeof(int);//for count
103 void *tuple = NULL;
104 int offset=0;
105 tableHdl->execute();
106 aggNodes.reset();
107 while((tuple = tableHdl->fetch()) != NULL)
109 char *buffer = (char*)insertOrGet();
110 iter.reset();
111 if (isGroupSet())
112 offset = AllDataType::size(groupFld.type, groupFld.length);
113 else
114 offset = 0;
115 while (iter.hasElement())
117 def = (AggFldDef*) iter.nextElement();
118 switch(def->atype)
120 case AGG_MIN: {
121 bool result = AllDataType::compareVal(buffer+offset,
122 def->bindBuf, OpGreaterThan, def->type, def->length);
123 if (result)
124 AllDataType::copyVal(buffer+offset, def->bindBuf,
125 def->type, def->length);
126 break;
128 case AGG_MAX: {
129 bool result = AllDataType::compareVal(buffer+offset,
130 def->bindBuf, OpLessThan, def->type, def->length);
131 if (result)
132 AllDataType::copyVal(buffer+offset, def->bindBuf,
133 def->type, def->length);
134 break;
136 case AGG_SUM: {
137 AllDataType::addVal(buffer+offset, def->bindBuf, def->type);
138 break;
140 case AGG_AVG: {
141 AllDataType::addVal(buffer+offset, def->bindBuf, def->type);
142 (*(int*)(buffer+offset + AllDataType::size(def->type, def->length)))++;
143 offset = offset +sizeof(int); //->count
144 break;
146 case AGG_COUNT:
147 (*(int*)(buffer+offset))++;
148 if ((*(int*)(buffer+offset)) % 1000000 ==0)
149 printf("PRABA:%d\n", (*(int*)(buffer+offset)));
150 break;
152 offset = offset + AllDataType::size(def->type, def->length);
155 aggNodeIter = aggNodes.getIterator();
156 iter.reset();
157 char *element;
158 while (iter.hasElement()) {
159 def = (AggFldDef*) iter.nextElement();
160 if (isGroupSet())
161 offset = AllDataType::size(groupFld.type, groupFld.length);
162 else
163 offset = 0;
164 switch(def->atype)
166 case AGG_AVG: {
167 while (aggNodeIter.hasElement()) {
168 element = (char*)aggNodeIter.nextElement();
169 AllDataType::divVal(element+offset,
170 *(int*)(element+offset+AllDataType::size(def->type, def->length)),
171 def->type);
173 offset = offset +sizeof(int);
176 offset = offset + AllDataType::size(def->type, def->length);
178 aggNodeIter.reset();
179 tableHdl->close();
180 return OK;
182 void* AggTableImpl::insertOrGet()
184 ListIterator aiter = aggNodes.getIterator();
185 char *element;
186 while (aiter.hasElement()) {
187 element = (char*)aiter.nextElement();
189 if (!isGroupSet()) return element;
190 if (AllDataType::compareVal(element, groupFld.bindBuf, OpEquals,
191 groupFld.type, groupFld.length))
193 return element;
196 element = (char*)malloc(aggNodeSize);
197 ListIterator iter = fldList.getIterator();
198 AggFldDef *def;
199 char *offset;
200 if (isGroupSet()) {
201 AllDataType::copyVal(element, groupFld.bindBuf, groupFld.type,
202 groupFld.length);
203 offset = element + AllDataType::size(groupFld.type, groupFld.length);
205 else
206 offset = element;
208 while (iter.hasElement())
210 def = (AggFldDef*) iter.nextElement();
211 switch(def->atype) {
212 case AGG_MIN: { *(int*)(offset)=INT_MAX; break; }
213 case AGG_MAX: { *(int*)(offset)=INT_MIN; break; }
214 case AGG_SUM: { *(int*)(offset)=0; break; }
215 case AGG_AVG: {
216 *(int*)(offset)=0;
217 *(int*)(offset+AllDataType::size(def->type, def->length))=0; //count
218 offset = offset+ sizeof(int);
219 break;
221 case AGG_COUNT: { *(int*)(offset)=0; break; }
223 offset = offset + AllDataType::size(def->type, def->length);
225 aggNodes.append(element);
226 return element;
229 void* AggTableImpl::fetch()
231 if(aggNodeIter.hasElement())
233 void *elem = aggNodeIter.nextElement();
234 copyValuesToBindBuffer(elem);
235 return elem;
237 else
238 return NULL;
241 void* AggTableImpl::fetch(DbRetVal &rv)
243 rv = OK;
244 return fetch();
247 void* AggTableImpl::fetchNoBind()
249 if(aggNodeIter.hasElement())
251 void *elem = aggNodeIter.nextElement();
252 return elem;
254 else
255 return NULL;
258 void* AggTableImpl::fetchNoBind(DbRetVal &rv)
260 rv = OK;
261 return fetchNoBind();
264 DbRetVal AggTableImpl::copyValuesToBindBuffer(void *elem)
266 char *element = (char*)elem;
267 //Iterate through the bind list and copy the value here
268 ListIterator fIter = fldList.getIterator();
269 AggFldDef *def;
270 AllDataType::copyVal(groupFld.appBuf, elem, groupFld.type, groupFld.length);
271 char *colPtr = (char*) elem + AllDataType::size(groupFld.type, groupFld.length);
272 while (fIter.hasElement())
274 def = (AggFldDef*) fIter.nextElement();
275 if (NULL != def->appBuf) {
276 AllDataType::copyVal(def->appBuf, colPtr, def->type, def->length);
278 colPtr = colPtr + os::align(AllDataType::size(def->type, def->length));
279 if(def->atype == AGG_AVG) colPtr = colPtr + sizeof(int);
281 return OK;
284 long AggTableImpl::numTuples()
286 return aggNodes.size();
288 DbRetVal AggTableImpl::closeScan()
290 aggNodeIter.reset();
291 ListIterator aiter = aggNodes.getIterator();
292 char *element;
293 while (aiter.hasElement()) {
294 element = (char*)aiter.nextElement();
295 free(element);
297 aggNodes.reset();
298 tableHdl->closeScan();
301 DbRetVal AggTableImpl::close()
303 //free memory allocated. make sure that field buffers are freed only once.
304 //for stmts which has more than one agg on same field needs to be handled safely
305 closeScan();
306 free(groupFld.bindBuf);
307 groupFld.bindBuf= NULL;
308 ListIterator iter = fldList.getIterator();
309 AggFldDef *elem;
310 while (iter.hasElement())
312 elem = (AggFldDef*) iter.nextElement();
313 //if(!elem->alreadyBinded) free(elem->bindBuf);
314 //TEMPHACK:PRABA::to avoid cordump in odbcBench
316 fldList.reset();
317 return OK;