performance fixes for JDBC wisc benchmark
[csql.git] / src / storage / AggTableImpl.cxx
blob76d25d0ed3e1c4235e4ef998d38d1f6f63a23b89
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 = groupFld.length;
95 else
96 aggNodeSize = 0;
97 while (iter.hasElement())
99 def = (AggFldDef*) iter.nextElement();
100 if (def->atype != AGG_UNKNOWN &&
101 0 == strcmp(def->fldName, groupFld.fldName))
103 def->atype = AGG_UNKNOWN;
105 aggNodeSize = aggNodeSize + def->length;
106 if (def->atype == AGG_AVG) aggNodeSize = aggNodeSize + sizeof(int);//for count
108 void *tuple = NULL;
109 int offset=0;
110 tableHdl->execute();
111 aggNodes.reset();
112 while((tuple = tableHdl->fetch()) != NULL)
114 char *buffer = (char*)insertOrGet();
115 iter.reset();
116 if (isGroupSet())
117 offset = groupFld.length;
118 else
119 offset = 0;
120 while (iter.hasElement())
122 def = (AggFldDef*) iter.nextElement();
123 switch(def->atype)
125 case AGG_MIN: {
126 bool result = AllDataType::compareVal(buffer+offset,
127 def->bindBuf, OpGreaterThan, def->type, def->length);
128 if (result)
129 AllDataType::copyVal(buffer+offset, def->bindBuf,
130 def->type, def->length);
131 break;
133 case AGG_MAX: {
134 bool result = AllDataType::compareVal(buffer+offset,
135 def->bindBuf, OpLessThan, def->type, def->length);
136 if (result)
137 AllDataType::copyVal(buffer+offset, def->bindBuf,
138 def->type, def->length);
139 break;
141 case AGG_SUM: {
142 AllDataType::addVal(buffer+offset, def->bindBuf, def->type);
143 break;
145 case AGG_AVG: {
146 AllDataType::addVal(buffer+offset, def->bindBuf, def->type);
147 (*(int*)(buffer+offset + def->length))++;
148 offset = offset +sizeof(int); //->count
149 break;
151 case AGG_COUNT:
152 (*(int*)(buffer+offset))++;
153 if ((*(int*)(buffer+offset)) % 1000000 ==0)
154 printf("PRABA:%d\n", (*(int*)(buffer+offset)));
155 break;
156 case AGG_UNKNOWN:
158 AllDataType::copyVal(buffer+offset, groupFld.bindBuf,
159 groupFld.type, groupFld.length);
160 break;
163 offset = offset + def->length;
166 aggNodeIter = aggNodes.getIterator();
167 iter.reset();
168 char *element;
169 while (iter.hasElement()) {
170 def = (AggFldDef*) iter.nextElement();
171 if (isGroupSet())
172 offset = groupFld.length;
173 else
174 offset = 0;
175 switch(def->atype)
177 case AGG_AVG: {
178 while (aggNodeIter.hasElement()) {
179 element = (char*)aggNodeIter.nextElement();
180 AllDataType::divVal(element+offset,
181 *(int*)(element+offset+ def->length), def->type);
183 offset = offset +sizeof(int);
186 offset = offset + def->length;
188 aggNodeIter.reset();
189 tableHdl->close();
190 return OK;
192 void* AggTableImpl::insertOrGet()
194 char *element;
195 if (!isGroupSet()) {
196 ListIterator aiter = aggNodes.getIterator();
197 if (aiter.hasElement())
198 return aiter.nextElement();
199 } else {
200 //TODO::perf opt for no group
201 //TODO::if group not set, use another class variable
202 element = (char*) aggNodeMap.find(groupFld.bindBuf);
203 if (element) return element;
206 /*ListIterator aiter = aggNodes.getIterator();
207 while (aiter.hasElement()) {
208 element = (char*)aiter.nextElement();
210 if (!isGroupSet()) return element;
211 if (AllDataType::compareVal(element, groupFld.bindBuf, OpEquals,
212 groupFld.type, groupFld.length))
214 return element;
217 element = (char*)malloc(aggNodeSize);
218 ListIterator iter = fldList.getIterator();
219 AggFldDef *def;
220 char *offset;
221 if (isGroupSet()) {
222 AllDataType::copyVal(element, groupFld.bindBuf, groupFld.type,
223 groupFld.length);
224 offset = element + groupFld.length;
226 else
227 offset = element;
229 while (iter.hasElement())
231 def = (AggFldDef*) iter.nextElement();
232 switch(def->atype) {
233 case AGG_MIN: { *(int*)(offset)=INT_MAX; break; }
234 case AGG_MAX: { *(int*)(offset)=INT_MIN; break; }
235 case AGG_SUM: { *(int*)(offset)=0; break; }
236 case AGG_AVG: {
237 *(int*)(offset)=0;
238 *(int*)(offset+ def->length)=0; //count
239 offset = offset+ sizeof(int);
240 break;
242 case AGG_COUNT: { *(int*)(offset)=0; break; }
244 offset = offset + def->length;
246 aggNodes.append(element);
247 aggNodeMap.insert(element);
248 return element;
251 void* AggTableImpl::fetch()
253 if(aggNodeIter.hasElement())
255 void *elem = aggNodeIter.nextElement();
256 copyValuesToBindBuffer(elem);
257 return elem;
259 else
260 return NULL;
263 void* AggTableImpl::fetch(DbRetVal &rv)
265 rv = OK;
266 return fetch();
269 void* AggTableImpl::fetchNoBind()
271 if(aggNodeIter.hasElement())
273 void *elem = aggNodeIter.nextElement();
274 return elem;
276 else
277 return NULL;
280 void* AggTableImpl::fetchNoBind(DbRetVal &rv)
282 rv = OK;
283 return fetchNoBind();
286 DbRetVal AggTableImpl::copyValuesToBindBuffer(void *elem)
288 char *element = (char*)elem;
289 //Iterate through the bind list and copy the value here
290 ListIterator fIter = fldList.getIterator();
291 AggFldDef *def;
292 AllDataType::copyVal(groupFld.appBuf, elem, groupFld.type, groupFld.length);
293 char *colPtr = (char*) elem + groupFld.length;
294 while (fIter.hasElement())
296 def = (AggFldDef*) fIter.nextElement();
297 if (NULL != def->appBuf) {
298 AllDataType::copyVal(def->appBuf, colPtr, def->type, def->length);
300 colPtr = colPtr + def->length;
301 if(def->atype == AGG_AVG) colPtr = colPtr + sizeof(int);
303 return OK;
306 long AggTableImpl::numTuples()
308 return aggNodes.size();
310 DbRetVal AggTableImpl::closeScan()
312 aggNodeIter.reset();
313 ListIterator aiter = aggNodes.getIterator();
314 char *element;
315 while (aiter.hasElement()) {
316 element = (char*)aiter.nextElement();
317 free(element);
319 aggNodes.reset();
320 aggNodeMap.removeAll();
321 tableHdl->closeScan();
324 DbRetVal AggTableImpl::close()
326 //free memory allocated. make sure that field buffers are freed only once.
327 //for stmts which has more than one agg on same field needs to be handled safely
328 closeScan();
329 free(groupFld.bindBuf);
330 groupFld.bindBuf= NULL;
331 ListIterator iter = fldList.getIterator();
332 AggFldDef *elem;
333 while (iter.hasElement())
335 elem = (AggFldDef*) iter.nextElement();
336 if(!elem->alreadyBinded) free(elem->bindBuf);
337 delete elem;
339 fldList.reset();
340 return OK;
343 //------------------------------------------------------
344 DbRetVal HashMap::insert(void *element)
346 HashMapNode *newNode = new HashMapNode();
347 newNode->elem = element;
348 newNode->next = NULL;
349 int hashVal = (*(int*) element) % bucketSize;
350 //printf("Hash val is %d\n", hashVal);
351 HashMapNode *node = (HashMapNode*) bucket[hashVal];
352 if (NULL == node)
354 bucket[hashVal] = newNode;
355 return OK;
357 while(node->next != NULL) ;
358 node->next = newNode;
359 return OK;
361 void* HashMap::find(void *element)
363 int hashVal = (*(int*) element) % bucketSize;
364 //printf("Hash val is %d\n", hashVal);
365 if (bucket[hashVal] == NULL)
367 return NULL;
369 HashMapNode *node = (HashMapNode*) bucket[hashVal];
370 while(node != NULL) {
371 if ( (*(int*) node->elem) == (*(int*)element)) return node->elem;
372 node = node->next;
374 return NULL;
376 void HashMap::removeAll()
378 for (int i=0; i <bucketSize; i++) {
379 HashMapNode *node =(HashMapNode*) (bucket[i]);
380 HashMapNode *prev = NULL;
381 while(node != NULL) {
382 prev = node;
383 node = node->next;
384 delete prev;
386 bucket[i]=NULL;
388 return;