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()
26 void *AggTableImpl::getBindFldAddr(const char *name
)
33 DbRetVal
AggTableImpl::bindFld(const char *name
, void *val
)
37 DbRetVal
AggTableImpl::bindFld(const char *fldname
, AggType aggType
, void *val
)
39 FieldInfo
*info
= new FieldInfo();
40 tableHdl
->getFieldInfo(fldname
, info
);
41 AggFldDef
*def
= new AggFldDef();
42 strcpy(def
->fldName
, fldname
);
43 def
->type
= info
->type
;
44 def
->length
= info
->length
;
48 def
->alreadyBinded
= false;
49 ListIterator iter
= fldList
.getIterator();
51 //If it is already binded, then use the same buffer which is binded.
52 //this code is to handle statements which have more aggregates on same field
53 while (iter
.hasElement())
55 elem
= (AggFldDef
*) iter
.nextElement();
56 if (strcmp(elem
->fldName
, fldname
)==0)
58 def
->bindBuf
= elem
->bindBuf
;
59 def
->alreadyBinded
= true;
65 def
->bindBuf
= AllDataType::alloc(def
->type
, def
->length
);
66 tableHdl
->bindFld(fldname
, def
->bindBuf
);
72 DbRetVal
AggTableImpl::setGroup(const char *fldname
, void *val
)
74 FieldInfo
*info
= new FieldInfo();
75 tableHdl
->getFieldInfo(fldname
, info
);
76 strcpy(groupFld
.fldName
, fldname
);
77 groupFld
.type
= info
->type
;
78 groupFld
.length
= info
->length
;
79 groupFld
.appBuf
= val
;
80 groupFld
.bindBuf
= AllDataType::alloc(info
->type
, info
->length
);
81 tableHdl
->bindFld(fldname
, groupFld
.bindBuf
);
86 DbRetVal
AggTableImpl::execute()
88 ListIterator iter
= fldList
.getIterator();
91 aggNodeSize
= AllDataType::size(groupFld
.type
, groupFld
.length
);
94 while (iter
.hasElement())
96 def
= (AggFldDef
*) iter
.nextElement();
97 aggNodeSize
= aggNodeSize
+ AllDataType::size(def
->type
, def
->length
);
98 if (def
->atype
== AGG_AVG
) aggNodeSize
= aggNodeSize
+ sizeof(int);//for count
104 while((tuple
= tableHdl
->fetch()) != NULL
)
106 char *buffer
= (char*)insertOrGet();
109 offset
= AllDataType::size(groupFld
.type
, groupFld
.length
);
112 while (iter
.hasElement())
114 def
= (AggFldDef
*) iter
.nextElement();
118 bool result
= AllDataType::compareVal(buffer
+offset
,
119 def
->bindBuf
, OpGreaterThan
, def
->type
, def
->length
);
121 AllDataType::copyVal(buffer
+offset
, def
->bindBuf
,
122 def
->type
, def
->length
);
126 bool result
= AllDataType::compareVal(buffer
+offset
,
127 def
->bindBuf
, OpLessThan
, def
->type
, def
->length
);
129 AllDataType::copyVal(buffer
+offset
, def
->bindBuf
,
130 def
->type
, def
->length
);
134 AllDataType::addVal(buffer
+offset
, def
->bindBuf
, def
->type
);
138 AllDataType::addVal(buffer
+offset
, def
->bindBuf
, def
->type
);
139 (*(int*)(buffer
+offset
+ AllDataType::size(def
->type
, def
->length
)))++;
140 offset
= offset
+sizeof(int); //->count
144 (*(int*)(buffer
+offset
))++;
147 offset
= offset
+ AllDataType::size(def
->type
, def
->length
);
150 aggNodeIter
= aggNodes
.getIterator();
153 while (iter
.hasElement()) {
154 def
= (AggFldDef
*) iter
.nextElement();
156 offset
= AllDataType::size(groupFld
.type
, groupFld
.length
);
162 while (aggNodeIter
.hasElement()) {
163 element
= (char*)aggNodeIter
.nextElement();
164 AllDataType::divVal(element
+offset
,
165 *(int*)(element
+offset
+AllDataType::size(def
->type
, def
->length
)),
168 offset
= offset
+sizeof(int);
171 offset
= offset
+ AllDataType::size(def
->type
, def
->length
);
177 void* AggTableImpl::insertOrGet()
179 ListIterator aiter
= aggNodes
.getIterator();
181 while (aiter
.hasElement()) {
182 element
= (char*)aiter
.nextElement();
184 if (!isGroupSet()) return element
;
185 if (AllDataType::compareVal(element
, groupFld
.bindBuf
, OpEquals
,
186 groupFld
.type
, groupFld
.length
))
191 element
= (char*)malloc(aggNodeSize
);
192 ListIterator iter
= fldList
.getIterator();
196 AllDataType::copyVal(element
, groupFld
.bindBuf
, groupFld
.type
,
198 offset
= element
+ AllDataType::size(groupFld
.type
, groupFld
.length
);
203 while (iter
.hasElement())
205 def
= (AggFldDef
*) iter
.nextElement();
207 case AGG_MIN
: { *(int*)(offset
)=INT_MAX
; break; }
208 case AGG_MAX
: { *(int*)(offset
)=INT_MIN
; break; }
209 case AGG_SUM
: { *(int*)(offset
)=0; break; }
212 *(int*)(offset
+AllDataType::size(def
->type
, def
->length
))=0; //count
213 offset
= offset
+ sizeof(int);
216 case AGG_COUNT
: { *(int*)(offset
)=0; break; }
218 offset
= offset
+ AllDataType::size(def
->type
, def
->length
);
220 aggNodes
.append(element
);
224 void* AggTableImpl::fetch()
226 if(aggNodeIter
.hasElement())
228 void *elem
= aggNodeIter
.nextElement();
229 copyValuesToBindBuffer(elem
);
236 void* AggTableImpl::fetch(DbRetVal
&rv
)
242 void* AggTableImpl::fetchNoBind()
244 if(aggNodeIter
.hasElement())
246 void *elem
= aggNodeIter
.nextElement();
253 void* AggTableImpl::fetchNoBind(DbRetVal
&rv
)
256 return fetchNoBind();
259 DbRetVal
AggTableImpl::copyValuesToBindBuffer(void *elem
)
261 char *element
= (char*)elem
;
262 //Iterate through the bind list and copy the value here
263 ListIterator fIter
= fldList
.getIterator();
265 AllDataType::copyVal(groupFld
.appBuf
, elem
, groupFld
.type
, groupFld
.length
);
266 char *colPtr
= (char*) elem
+ AllDataType::size(groupFld
.type
, groupFld
.length
);
267 while (fIter
.hasElement())
269 def
= (AggFldDef
*) fIter
.nextElement();
270 if (NULL
!= def
->appBuf
) {
271 AllDataType::copyVal(def
->appBuf
, colPtr
, def
->type
, def
->length
);
273 colPtr
= colPtr
+ os::align(AllDataType::size(def
->type
, def
->length
));
274 if(def
->atype
== AGG_AVG
) colPtr
= colPtr
+ sizeof(int);
279 long AggTableImpl::numTuples()
281 return aggNodes
.size();
283 void AggTableImpl::closeScan()
286 ListIterator aiter
= aggNodes
.getIterator();
288 while (aiter
.hasElement()) {
289 element
= (char*)aiter
.nextElement();
295 DbRetVal
AggTableImpl::close()
297 //free memory allocated. make sure that field buffers are freed only once.
298 //for stmts which has more than one agg on same field needs to be handled safely
299 free(groupFld
.bindBuf
);
300 ListIterator iter
= fldList
.getIterator();
302 while (iter
.hasElement())
304 elem
= (AggFldDef
*) iter
.nextElement();
305 if(!elem
->alreadyBinded
) free(elem
->bindBuf
);