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 DbRetVal
AggTableImpl::bindFld(const char *name
, void *val
)
30 DbRetVal
AggTableImpl::bindFld(const char *fldname
, AggType aggType
, void *val
)
32 FieldInfo
*info
= new FieldInfo();
33 tableHdl
->getFieldInfo(fldname
, info
);
34 AggFldDef
*def
= new AggFldDef();
35 strcpy(def
->fldName
, fldname
);
36 def
->type
= info
->type
;
37 def
->length
= info
->length
;
41 def
->alreadyBinded
= false;
42 ListIterator iter
= fldList
.getIterator();
44 //If it is already binded, then use the same buffer which is binded.
45 //this code is to handle statements which have more aggregates on same field
46 while (iter
.hasElement())
48 elem
= (AggFldDef
*) iter
.nextElement();
49 if (strcmp(elem
->fldName
, fldname
)==0)
51 def
->bindBuf
= elem
->bindBuf
;
52 def
->alreadyBinded
= true;
58 def
->bindBuf
= AllDataType::alloc(def
->type
, def
->length
);
59 tableHdl
->bindFld(fldname
, def
->bindBuf
);
65 DbRetVal
AggTableImpl::setGroup(const char *fldname
, void *val
)
67 FieldInfo
*info
= new FieldInfo();
68 tableHdl
->getFieldInfo(fldname
, info
);
69 strcpy(groupFld
.fldName
, fldname
);
70 groupFld
.type
= info
->type
;
71 groupFld
.length
= info
->length
;
72 groupFld
.appBuf
= val
;
73 groupFld
.bindBuf
= AllDataType::alloc(info
->type
, info
->length
);
74 tableHdl
->bindFld(fldname
, groupFld
.bindBuf
);
79 DbRetVal
AggTableImpl::execute()
81 ListIterator iter
= fldList
.getIterator();
84 aggNodeSize
= AllDataType::size(groupFld
.type
, groupFld
.length
);
87 while (iter
.hasElement())
89 def
= (AggFldDef
*) iter
.nextElement();
90 aggNodeSize
= aggNodeSize
+ AllDataType::size(def
->type
, def
->length
);
91 if (def
->atype
== AGG_AVG
) aggNodeSize
= aggNodeSize
+ sizeof(int);//for count
97 while((tuple
= tableHdl
->fetch()) != NULL
)
99 char *buffer
= (char*)insertOrGet();
102 offset
= AllDataType::size(groupFld
.type
, groupFld
.length
);
105 while (iter
.hasElement())
107 def
= (AggFldDef
*) iter
.nextElement();
111 bool result
= AllDataType::compareVal(buffer
+offset
,
112 def
->bindBuf
, OpGreaterThanEquals
, def
->type
, def
->length
);
114 AllDataType::copyVal(buffer
+offset
, def
->bindBuf
,
115 def
->type
, def
->length
);
119 bool result
= AllDataType::compareVal(buffer
+offset
,
120 def
->bindBuf
, OpLessThanEquals
, def
->type
, def
->length
);
122 AllDataType::copyVal(buffer
+offset
, def
->bindBuf
,
123 def
->type
, def
->length
);
127 AllDataType::addVal(buffer
+offset
, def
->bindBuf
, def
->type
);
131 AllDataType::addVal(buffer
+offset
, def
->bindBuf
, def
->type
);
132 (*(int*)(buffer
+offset
+ AllDataType::size(def
->type
, def
->length
)))++;
133 offset
= offset
+sizeof(int); //->count
137 (*(int*)(buffer
+offset
))++;
140 offset
= offset
+ AllDataType::size(def
->type
, def
->length
);
143 aggNodeIter
= aggNodes
.getIterator();
146 while (iter
.hasElement()) {
147 def
= (AggFldDef
*) iter
.nextElement();
149 offset
= AllDataType::size(groupFld
.type
, groupFld
.length
);
155 while (aggNodeIter
.hasElement()) {
156 element
= (char*)aggNodeIter
.nextElement();
157 AllDataType::divVal(element
+offset
,
158 *(int*)(element
+offset
+AllDataType::size(def
->type
, def
->length
)),
161 offset
= offset
+sizeof(int);
164 offset
= offset
+ AllDataType::size(def
->type
, def
->length
);
170 void* AggTableImpl::insertOrGet()
172 ListIterator aiter
= aggNodes
.getIterator();
174 while (aiter
.hasElement()) {
175 element
= (char*)aiter
.nextElement();
177 if (!isGroupSet()) return element
;
178 if (AllDataType::compareVal(element
, groupFld
.bindBuf
, OpEquals
,
179 groupFld
.type
, groupFld
.length
))
184 element
= (char*)malloc(aggNodeSize
);
185 ListIterator iter
= fldList
.getIterator();
189 AllDataType::copyVal(element
, groupFld
.bindBuf
, groupFld
.type
,
191 offset
= element
+ AllDataType::size(groupFld
.type
, groupFld
.length
);
196 while (iter
.hasElement())
198 def
= (AggFldDef
*) iter
.nextElement();
200 case AGG_MIN
: { *(int*)(offset
)=INT_MAX
; break; }
201 case AGG_MAX
: { *(int*)(offset
)=INT_MIN
; break; }
202 case AGG_SUM
: { *(int*)(offset
)=0; break; }
205 *(int*)(offset
+AllDataType::size(def
->type
, def
->length
))=0; //count
206 offset
= offset
+ sizeof(int);
209 case AGG_COUNT
: { *(int*)(offset
)=0; break; }
211 offset
= offset
+ AllDataType::size(def
->type
, def
->length
);
213 aggNodes
.append(element
);
217 void* AggTableImpl::fetch()
219 if(aggNodeIter
.hasElement())
221 void *elem
= aggNodeIter
.nextElement();
222 copyValuesToBindBuffer(elem
);
229 void* AggTableImpl::fetch(DbRetVal
&rv
)
235 void* AggTableImpl::fetchNoBind()
237 if(aggNodeIter
.hasElement())
239 void *elem
= aggNodeIter
.nextElement();
246 void* AggTableImpl::fetchNoBind(DbRetVal
&rv
)
249 return fetchNoBind();
252 DbRetVal
AggTableImpl::copyValuesToBindBuffer(void *elem
)
254 char *element
= (char*)elem
;
255 //Iterate through the bind list and copy the value here
256 ListIterator fIter
= fldList
.getIterator();
258 AllDataType::copyVal(groupFld
.appBuf
, elem
, groupFld
.type
, groupFld
.length
);
259 char *colPtr
= (char*) elem
+ AllDataType::size(groupFld
.type
, groupFld
.length
);
260 while (fIter
.hasElement())
262 def
= (AggFldDef
*) fIter
.nextElement();
263 if (NULL
!= def
->appBuf
) {
264 AllDataType::copyVal(def
->appBuf
, colPtr
, def
->type
, def
->length
);
266 colPtr
= colPtr
+ os::align(AllDataType::size(def
->type
, def
->length
));
267 if(def
->atype
== AGG_AVG
) colPtr
= colPtr
+ sizeof(int);
272 long AggTableImpl::numTuples()
274 return aggNodes
.size();
276 void AggTableImpl::closeScan()
279 ListIterator aiter
= aggNodes
.getIterator();
281 while (aiter
.hasElement()) {
282 element
= (char*)aiter
.nextElement();
288 DbRetVal
AggTableImpl::close()
290 //free memory allocated. make sure that field buffers are freed only once.
291 //for stmts which has more than one agg on same field needs to be handled safely
292 free(groupFld
.bindBuf
);
293 ListIterator iter
= fldList
.getIterator();
295 while (iter
.hasElement())
297 elem
= (AggFldDef
*) iter
.nextElement();
298 if(!elem
->alreadyBinded
) free(elem
->bindBuf
);
310 //-----------------------------------------------------------
312 JoinTableImpl::JoinTableImpl()
316 JoinTableImpl::~JoinTableImpl()
319 void JoinTableImpl::getFieldNameAlone(char *fname
, char *name
) {
320 bool dotFound
= false;
321 char *fullname
= fname
;
322 while(*fullname
!= '\0')
324 if (*fullname
== '.') { dotFound
= true; break; }
327 if (dotFound
) strcpy(name
, ++fullname
); else strcpy(name
, fname
);
330 void JoinTableImpl::getTableNameAlone(char *fname
, char *name
) {
334 if (*name
== '.') { *name
='\0'; break; }
339 DbRetVal
JoinTableImpl::bindFld(const char *fldname
, void *val
)
341 FieldInfo
*info
= new FieldInfo();
342 char tableName
[IDENTIFIER_LENGTH
];
343 char fieldName
[IDENTIFIER_LENGTH
];
344 getTableNameAlone((char*)fldname
, tableName
);
345 getFieldNameAlone((char*)fldname
, fieldName
);
346 printf("%s %s \n", tableName
, fieldName
);
348 ListIterator iter
= projList
.getIterator();
349 JoinProjFieldInfo
*elem
;
350 while (iter
.hasElement())
352 elem
= (JoinProjFieldInfo
*) iter
.nextElement();
353 if (strcmp(elem
->fieldName
, fieldName
)==0 &&
354 strcmp(elem
->tableName
, tableName
) ==0)
356 printError(ErrBadCall
, "Field already binded %s\n", fldname
);
361 JoinProjFieldInfo
*def
= new JoinProjFieldInfo();
362 strcpy(def
->tableName
, tableName
);
363 strcpy(def
->fieldName
, fieldName
);
365 def
->bindBuf
= AllDataType::alloc(def
->type
, def
->length
);
367 if (strcmp(tableName
, leftTableHdl
->getName()) == 0)
369 leftTableHdl
->getFieldInfo(fieldName
, info
);
370 def
->bindBuf
= AllDataType::alloc(info
->type
, info
->length
);
371 leftTableHdl
->bindFld(fieldName
, def
->bindBuf
);
373 }else if (strcmp(tableName
, rightTableHdl
->getName()) == 0)
375 rightTableHdl
->getFieldInfo(fieldName
, info
);
376 def
->bindBuf
= AllDataType::alloc(info
->type
, info
->length
);
377 rightTableHdl
->bindFld(fieldName
, def
->bindBuf
);
380 printError(ErrBadCall
, "TableName is invalid\n");
384 def
->type
= info
->type
;
385 def
->length
= info
->length
;
386 projList
.append(def
);
390 DbRetVal
JoinTableImpl::setJoinCondition(const char *fldname1
,
392 const char *fldname2
)
394 getTableNameAlone((char*)fldname1
, jCondition
.tableName1
);
395 getFieldNameAlone((char*)fldname1
, jCondition
.fieldName1
);
396 getTableNameAlone((char*)fldname2
, jCondition
.tableName2
);
397 getFieldNameAlone((char*)fldname2
, jCondition
.fieldName2
);
399 //check if it is already binded
400 ListIterator iter
= projList
.getIterator();
401 JoinProjFieldInfo
*elem
;
402 jCondition
.alreadyBinded1
= false;
403 jCondition
.alreadyBinded2
= false;
405 while (iter
.hasElement())
407 elem
= (JoinProjFieldInfo
*) iter
.nextElement();
408 if (strcmp(elem
->fieldName
, jCondition
.fieldName1
)==0 &&
409 strcmp(elem
->tableName
, jCondition
.tableName1
) ==0)
411 jCondition
.alreadyBinded1
= true;
412 jCondition
.bindBuf1
= elem
->bindBuf
;
413 jCondition
.type1
= elem
->type
;
414 jCondition
.length1
= elem
->length
;
416 if (strcmp(elem
->fieldName
, jCondition
.fieldName2
)==0 &&
417 strcmp(elem
->tableName
, jCondition
.tableName2
) ==0)
419 jCondition
.alreadyBinded2
= true;
420 jCondition
.bindBuf2
= elem
->bindBuf
;
421 jCondition
.type2
= elem
->type
;
422 jCondition
.length2
= elem
->length
;
426 FieldInfo
*info
= new FieldInfo();
427 if (!jCondition
.alreadyBinded1
) {
428 if (strcmp(jCondition
.tableName1
, leftTableHdl
->getName()) == 0)
430 leftTableHdl
->getFieldInfo(jCondition
.fieldName1
, info
);
431 jCondition
.bindBuf1
= AllDataType::alloc(info
->type
, info
->length
);
432 leftTableHdl
->bindFld(jCondition
.fieldName1
, jCondition
.bindBuf1
);
434 }else if (strcmp(jCondition
.tableName1
, rightTableHdl
->getName()) == 0)
436 rightTableHdl
->getFieldInfo(jCondition
.fieldName1
, info
);
437 jCondition
.bindBuf1
= AllDataType::alloc(info
->type
, info
->length
);
438 rightTableHdl
->bindFld(jCondition
.fieldName1
, jCondition
.bindBuf1
);
441 printError(ErrBadCall
, "TableName is invalid\n");
446 if (!jCondition
.alreadyBinded2
) {
447 if (strcmp(jCondition
.tableName2
, leftTableHdl
->getName()) == 0)
449 leftTableHdl
->getFieldInfo(jCondition
.fieldName2
, info
);
450 jCondition
.bindBuf2
= AllDataType::alloc(info
->type
, info
->length
);
451 leftTableHdl
->bindFld(jCondition
.fieldName2
, jCondition
.bindBuf2
);
453 }else if (strcmp(jCondition
.tableName2
, rightTableHdl
->getName()) == 0)
455 rightTableHdl
->getFieldInfo(jCondition
.fieldName2
, info
);
456 jCondition
.bindBuf2
= AllDataType::alloc(info
->type
, info
->length
);
457 rightTableHdl
->bindFld(jCondition
.fieldName2
, jCondition
.bindBuf2
);
460 printError(ErrBadCall
, "TableName is invalid\n");
469 DbRetVal
JoinTableImpl::execute()
472 leftTableHdl
->execute();
473 rightTableHdl
->execute();
474 leftTableHdl
->fetch();
476 //if join condition is not set then do nl
477 //if it is inner join, hen do nl
478 //nl cannot be done for outer join
482 void* JoinTableImpl::fetch()
486 void *rec
= rightTableHdl
->fetch();
489 rightTableHdl
->close();
490 rightTableHdl
->execute();
491 rec
= rightTableHdl
->fetch();
492 if (rec
== NULL
) return NULL
;
493 rec
= leftTableHdl
->fetch();
494 if (rec
== NULL
) return NULL
;
495 bool result
= evaluate();
496 if (! result
) return fetch();
497 copyValuesToBindBuffer(NULL
);
501 bool result
= evaluate();
502 if (! result
) return fetch();
503 copyValuesToBindBuffer(NULL
);
510 bool JoinTableImpl::evaluate()
512 if (!jCondition
.bindBuf1
|| !jCondition
.bindBuf2
) return true;
513 return AllDataType::compareVal(jCondition
.bindBuf1
, jCondition
.bindBuf2
,
515 jCondition
.type1
, jCondition
.length1
);
517 void* JoinTableImpl::fetch(DbRetVal
&rv
)
523 void* JoinTableImpl::fetchNoBind()
528 void* JoinTableImpl::fetchNoBind(DbRetVal
&rv
)
531 return fetchNoBind();
534 DbRetVal
JoinTableImpl::copyValuesToBindBuffer(void *elem
)
536 //Iterate through the bind list and copy the value here
537 ListIterator fIter
= projList
.getIterator();
538 JoinProjFieldInfo
*def
;
539 while (fIter
.hasElement())
541 def
= (JoinProjFieldInfo
*) fIter
.nextElement();
542 if (NULL
!= def
->appBuf
) {
543 AllDataType::copyVal(def
->appBuf
, def
->bindBuf
, def
->type
, def
->length
);
549 long JoinTableImpl::numTuples()
553 void JoinTableImpl::closeScan()
556 DbRetVal
JoinTableImpl::close()