1 /***************************************************************************
2 * Copyright (C) 2007 by www.databasecache.com *
3 * Contact: praba_tuty@databasecache.com *
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. *
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. *
15 ***************************************************************************/
19 #include<AggTableImpl.h>
20 AggTableImpl::AggTableImpl()
23 AggTableImpl::~AggTableImpl()
27 void *AggTableImpl::getBindFldAddr(const char *name
)
29 printError(ErrBadCall
, "AggTableImpl getBindFldAdddr not implemented\n");
35 DbRetVal
AggTableImpl::bindFld(const char *name
, void *val
)
37 printError(ErrBadCall
, "AggTableImpl bindFld not implemented\n");
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
;
51 def
->alreadyBinded
= false;
52 ListIterator iter
= fldList
.getIterator();
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;
68 def
->bindBuf
= AllDataType::alloc(def
->type
, def
->length
);
69 tableHdl
->bindFld(fldname
, def
->bindBuf
);
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
);
89 DbRetVal
AggTableImpl::execute()
91 ListIterator iter
= fldList
.getIterator();
94 aggNodeSize
= groupFld
.length
;
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
112 while((tuple
= tableHdl
->fetch()) != NULL
)
114 char *buffer
= (char*)insertOrGet();
117 offset
= groupFld
.length
;
120 while (iter
.hasElement())
122 def
= (AggFldDef
*) iter
.nextElement();
126 bool result
= AllDataType::compareVal(buffer
+offset
,
127 def
->bindBuf
, OpGreaterThanEquals
, def
->type
, def
->length
);
129 AllDataType::copyVal(buffer
+offset
, def
->bindBuf
,
130 def
->type
, def
->length
);
134 bool result
= AllDataType::compareVal(buffer
+offset
,
135 def
->bindBuf
, OpLessThanEquals
, def
->type
, def
->length
);
137 AllDataType::copyVal(buffer
+offset
, def
->bindBuf
,
138 def
->type
, def
->length
);
142 AllDataType::addVal(buffer
+offset
, def
->bindBuf
, def
->type
);
146 AllDataType::addVal(buffer
+offset
, def
->bindBuf
, def
->type
);
147 (*(int*)(buffer
+offset
+ def
->length
))++;
148 offset
= offset
+sizeof(int); //->count
152 (*(int*)(buffer
+offset
))++;
153 if ((*(int*)(buffer
+offset
)) % 1000000 ==0)
154 printf("PRABA:%d\n", (*(int*)(buffer
+offset
)));
158 AllDataType::copyVal(buffer
+offset
, groupFld
.bindBuf
,
159 groupFld
.type
, groupFld
.length
);
163 offset
= offset
+ def
->length
;
166 aggNodeIter
= aggNodes
.getIterator();
169 while (iter
.hasElement()) {
170 def
= (AggFldDef
*) iter
.nextElement();
172 offset
= groupFld
.length
;
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
;
189 tableHdl
->closeScan();
192 void* AggTableImpl::insertOrGet()
196 ListIterator aiter
= aggNodes
.getIterator();
197 if (aiter
.hasElement())
198 return aiter
.nextElement();
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))
217 element
= (char*)malloc(aggNodeSize
);
218 ListIterator iter
= fldList
.getIterator();
222 AllDataType::copyVal(element
, groupFld
.bindBuf
, groupFld
.type
,
224 offset
= element
+ groupFld
.length
;
229 while (iter
.hasElement())
231 def
= (AggFldDef
*) iter
.nextElement();
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; }
238 *(int*)(offset
+ def
->length
)=0; //count
239 offset
= offset
+ sizeof(int);
242 case AGG_COUNT
: { *(int*)(offset
)=0; break; }
244 offset
= offset
+ def
->length
;
246 aggNodes
.append(element
);
247 aggNodeMap
.insert(element
);
251 void* AggTableImpl::fetch()
253 if(aggNodeIter
.hasElement())
255 void *elem
= aggNodeIter
.nextElement();
256 copyValuesToBindBuffer(elem
);
263 void* AggTableImpl::fetch(DbRetVal
&rv
)
269 void* AggTableImpl::fetchNoBind()
271 if(aggNodeIter
.hasElement())
273 void *elem
= aggNodeIter
.nextElement();
280 void* AggTableImpl::fetchNoBind(DbRetVal
&rv
)
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();
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);
306 long AggTableImpl::numTuples()
308 return aggNodes
.size();
310 DbRetVal
AggTableImpl::closeScan()
313 ListIterator aiter
= aggNodes
.getIterator();
315 while (aiter
.hasElement()) {
316 element
= (char*)aiter
.nextElement();
320 aggNodeMap
.removeAll();
321 if(tableHdl
) 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
329 free(groupFld
.bindBuf
);
330 groupFld
.bindBuf
= NULL
;
331 ListIterator iter
= fldList
.getIterator();
333 while (iter
.hasElement())
335 elem
= (AggFldDef
*) iter
.nextElement();
336 if(!elem
->alreadyBinded
) free(elem
->bindBuf
);
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
];
354 bucket
[hashVal
] = newNode
;
357 while(node
->next
!= NULL
) ;
358 node
->next
= newNode
;
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
)
369 HashMapNode
*node
= (HashMapNode
*) bucket
[hashVal
];
370 while(node
!= NULL
) {
371 if ( (*(int*) node
->elem
) == (*(int*)element
)) return node
->elem
;
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
) {