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<OrderTableImpl.h>
20 #include<PredicateImpl.h>
22 OrderTableImpl::OrderTableImpl()
26 sortTree
.setDistinct(false);
34 OrderTableImpl::~OrderTableImpl()
36 //free memory allocated. make sure that field buffers are freed only once.
37 //for stmts which has more than one agg on same field needs to be handled safely
40 ListIterator oiter
= fldOrderByList
.getIterator();
41 OrderByFldDef
*elem
= NULL
;
42 while (oiter
.hasElement())
44 elem
= (OrderByFldDef
*) oiter
.nextElement();
45 if(!elem
->alreadyBinded
) free(elem
->bindBuf
);
48 fldOrderByList
.reset();
50 if (tableHdl
!= NULL
) tableHdl
->close();
52 if (orderBuffer
) ::free(orderBuffer
);
54 void *OrderTableImpl::getBindFldAddr(const char *name
)
56 printError(ErrBadCall
, "OrderTableImpl getBindFldAdddr not implemented\n");
60 DbRetVal
OrderTableImpl::bindFld(const char *name
, void *val
, bool dummy
)
62 printError(ErrBadCall
, "OrderTableImpl bindFld not implemented\n");
65 DbRetVal
OrderTableImpl::setOrderBy(const char *fldname
, bool isDesc
)
67 FieldInfo
*info
= new FieldInfo();
68 DbRetVal rv
= tableHdl
->getFieldInfo(fldname
, info
);
69 if (OK
!=rv
) { delete info
; return rv
; }
70 OrderByFldDef
*orderFld
=new OrderByFldDef();
71 strcpy(orderFld
->fldName
, fldname
);
72 orderFld
->type
= info
->type
;
73 //orderFld->length = info->length;
74 orderFld
->length
= AllDataType::size(info
->type
, info
->length
);
75 orderFld
->bindBuf
= NULL
;
76 orderFld
->isDesc
= isDesc
;
78 ListIterator iter
= fldProjList
.getIterator();
81 while (iter
.hasElement())
83 elem
= (FieldValue
*) iter
.nextElement();
84 if ((NULL
!= tableHdl
->getName() &&
85 NULL
!= strstr(elem
->fldName
, fldname
) ||
86 NULL
!= strstr(fldname
, elem
->fldName
)) ||
87 strcmp(elem
->fldName
, fldname
)==0)
89 orderFld
->bindBuf
= elem
->value
;
90 orderFld
->alreadyBinded
= true;
94 if (!orderFld
->bindBuf
)
96 orderFld
->bindBuf
= AllDataType::alloc(orderFld
->type
, orderFld
->length
);
97 rv
= tableHdl
->bindFld(fldname
, orderFld
->bindBuf
);
100 ::free(orderFld
->bindBuf
);
106 //if underlying tablehandle is TableImpl, then set isNull
107 orderFld
->isNull
= true;
108 if (info
->isNull
) orderFld
->isNull
= false;
109 if (info
->isPrimary
|| info
->isDefault
|| info
->isAutoIncrement
) {
110 orderFld
->isNull
= true;
112 if (NULL
== tableHdl
->getName()) orderFld
->isNull
=false;
115 fldOrderByList
.append(orderFld
);
119 OrderByType
OrderTableImpl::getOrderType()
121 ListIterator oiter
= fldOrderByList
.getIterator();
122 OrderByFldDef
*oFldDef
= NULL
;
123 bool isDescending
= false;
124 bool firstIter
= true;
125 while (oiter
.hasElement())
127 oFldDef
= (OrderByFldDef
*) oiter
.nextElement();
130 isDescending
= oFldDef
->isDesc
;
133 if (oFldDef
->isDesc
!= isDescending
) { isDescending
= false; break; }
135 if(isDescending
) return Desc
; else return Asc
;
138 void OrderTableImpl::checkAndSetSortAlgorithm()
140 if (sortTree
.getDistinct()) sortTree
.setFullOrderBy();
141 sortTree
.setOrderByList(fldOrderByList
);
144 orderBySize
= computeOrderBySize();
145 sortTree
.setKeySize(orderBySize
+ sizeof(int));
149 ListIterator iter
= fldProjList
.getIterator();
151 while (iter
.hasElement())
153 fValue
= (FieldValue
*) iter
.nextElement();
154 projSize
= projSize
+ fValue
->length
;
156 OrderByFldDef
*ordFld
=NULL
;
157 bool optGrpIntNoNull
= false;
158 if (orderBySize
== sizeof(int))
160 ListIterator iter
= fldOrderByList
.getIterator();
161 ordFld
= (OrderByFldDef
*)iter
.nextElement();
162 if (!ordFld
->isNull
&& ordFld
->type
== typeInt
)
164 optGrpIntNoNull
=true;
165 orderBindBuf
= ordFld
->bindBuf
;
166 sortTree
.setOrdIntNoNull();
171 DbRetVal
OrderTableImpl::execute()
175 if (!isPlanCreated
) {
176 checkAndSetSortAlgorithm();
177 setNullableForProj();
178 if (sortTree
.getDistinct())
180 orderBuffer
= (char*)malloc(orderBySize
+ sizeof(int));
185 while ((tuple
= tableHdl
->fetch()) != NULL
)
187 if (sortTree
.getDistinct()) insertDistinct(); else insert();
189 sortIter
= sortTree
.getListIterator();
192 int OrderTableImpl::computeOrderBySize()
194 ListIterator oiter
= fldOrderByList
.getIterator();
195 OrderByFldDef
*oFldDef
= NULL
;
197 while (oiter
.hasElement())
199 oFldDef
= (OrderByFldDef
*) oiter
.nextElement();
200 nodeOffset
= nodeOffset
+ oFldDef
->length
;
204 DbRetVal
OrderTableImpl::insertDistinct()
206 char *elem
= orderBuffer
;
207 memset(orderBuffer
, 0, orderBySize
+ sizeof(int));
208 ListIterator oiter
= fldOrderByList
.getIterator();
209 OrderByFldDef
*oFldDef
= NULL
;
210 int orderNullValues
=0;
213 while ((oFldDef
= (OrderByFldDef
*) oiter
.nextElement()) != NULL
)
215 if (oFldDef
->isNull
&& tableHdl
->isFldNull(oFldDef
->fldName
))
216 SETBIT(orderNullValues
, i
);
218 AllDataType::copyVal(elem
+nodeOffset
, oFldDef
->bindBuf
,
219 oFldDef
->type
, oFldDef
->length
);
220 nodeOffset
= nodeOffset
+ oFldDef
->length
;
223 AllDataType::copyVal(elem
+nodeOffset
, &orderNullValues
, typeInt
,
224 sizeof(orderNullValues
));
225 if (sortTree
.find(elem
)) return OK
;
226 nodeOffset
= nodeOffset
+ sizeof(orderNullValues
);
228 int nodeSize
= orderBySize
+ projSize
;
229 nodeSize
= nodeSize
+ sizeof(int);//to store order by field null values
230 nodeSize
= nodeSize
+ sizeof(nullValues
);//to store proj field null values
231 char *element
= (char*)malloc(nodeSize
);
232 memcpy(element
, elem
, orderBySize
+ sizeof(int));
235 ListIterator iter
= fldProjList
.getIterator();
236 FieldValue
*fValue
= NULL
;
237 void* ptrToCopyNullValues
= element
+nodeOffset
;
238 nodeOffset
= nodeOffset
+ sizeof(nullValues
);
239 while ((fValue
= (FieldValue
*) iter
.nextElement()) != NULL
)
241 if (fValue
->isNullable
&& tableHdl
->isFldNull(fValue
->fldName
))
242 SETBIT(nullValues
, i
);
244 AllDataType::copyVal(element
+nodeOffset
, fValue
->value
,
245 fValue
->type
, fValue
->length
);
246 nodeOffset
= nodeOffset
+ fValue
->length
;
249 AllDataType::copyVal(ptrToCopyNullValues
, &nullValues
, typeLongLong
,
251 DbRetVal rv
= sortTree
.insertDataNode(element
);
255 DbRetVal
OrderTableImpl::insert()
257 //compute size of projection
258 int nodeSize
= orderBySize
+ projSize
;
259 nodeSize
= nodeSize
+ sizeof(int);//to store order by field null values
260 nodeSize
= nodeSize
+ sizeof(nullValues
);//to store proj field null values
261 char *element
= (char*)malloc(nodeSize
);
264 ListIterator oiter
= fldOrderByList
.getIterator();
265 OrderByFldDef
*oFldDef
= NULL
;
266 int orderNullValues
=0;
268 while ((oFldDef
= (OrderByFldDef
*) oiter
.nextElement()) != NULL
)
270 //oFldDef = (OrderByFldDef*) oiter.nextElement();
271 if (oFldDef
->isNull
&& tableHdl
->isFldNull(oFldDef
->fldName
))
272 SETBIT(orderNullValues
, i
);
274 AllDataType::copyVal(element
+nodeOffset
, oFldDef
->bindBuf
,
275 oFldDef
->type
, oFldDef
->length
);
276 nodeOffset
= nodeOffset
+ oFldDef
->length
;
279 AllDataType::copyVal(element
+nodeOffset
, &orderNullValues
, typeInt
,
280 sizeof(orderNullValues
));
281 nodeOffset
= nodeOffset
+ sizeof(orderNullValues
);
284 ListIterator iter
= fldProjList
.getIterator();
285 FieldValue
*fValue
= NULL
;
286 void* ptrToCopyNullValues
= element
+nodeOffset
;
287 nodeOffset
= nodeOffset
+ sizeof(nullValues
);
288 while ((fValue
= (FieldValue
*) iter
.nextElement()) != NULL
)
290 //fValue = (FieldValue*) iter.nextElement();
291 if (fValue
->isNullable
&& tableHdl
->isFldNull(fValue
->fldName
))
292 SETBIT(nullValues
, i
);
294 AllDataType::copyVal(element
+nodeOffset
, fValue
->value
,
295 fValue
->type
, fValue
->length
);
296 nodeOffset
= nodeOffset
+ fValue
->length
;
299 AllDataType::copyVal(ptrToCopyNullValues
, &nullValues
, typeLongLong
,
301 DbRetVal rv
= sortTree
.insertDataNode(element
);
302 if (rv
== ErrUnique
) ::free (element
);
305 void* OrderTableImpl::fetch()
307 void *elem
= sortIter
.nextElement();
308 if (NULL
== elem
) return NULL
;
309 copyValuesToBindBuffer(elem
);
313 void* OrderTableImpl::fetch(DbRetVal
&rv
)
319 void* OrderTableImpl::fetchNoBind()
321 void *elem
= sortIter
.nextElement();
322 if (NULL
== elem
) return NULL
;
323 copyValuesToBindBuffer(elem
);
327 void* OrderTableImpl::fetchNoBind(DbRetVal
&rv
)
330 return fetchNoBind();
332 DbRetVal
OrderTableImpl::setOrderByList(List oList
)
334 ListIterator fIter
= oList
.getIterator();
336 while (fIter
.hasElement())
338 def
= (FieldValue
*) fIter
.nextElement();
339 setOrderBy(def
->fldName
);
343 DbRetVal
OrderTableImpl::copyValuesToBindBuffer(void *elem
)
345 //Iterate through the bind list and copy the value here
346 ListIterator fIter
= fldProjList
.getIterator();
348 char *colPtr
= (char*) elem
+ orderBySize
;
349 colPtr
= colPtr
+ sizeof(int);
350 nullValues
= *(long long*) colPtr
;
351 colPtr
= colPtr
+ sizeof (nullValues
);
352 while (fIter
.hasElement())
354 def
= (FieldValue
*) fIter
.nextElement();
355 if (NULL
!= def
->value
) {
356 AllDataType::copyVal(def
->value
, colPtr
, def
->type
, def
->length
);
357 colPtr
= colPtr
+ def
->length
;
362 void OrderTableImpl::setNullableForProj()
364 ListIterator fIter
= fldProjList
.getIterator();
366 FieldInfo
*info
= new FieldInfo();
367 while (fIter
.hasElement())
369 def
= (FieldValue
*) fIter
.nextElement();
370 tableHdl
->getFieldInfo(def
->fldName
, info
);
371 def
->isNullable
= true;
372 if (info
->isNull
|| info
->isPrimary
||
373 info
->isDefault
|| info
->isAutoIncrement
) {
374 def
->isNullable
= false;
376 if (NULL
== tableHdl
->getName()) def
->isNullable
=true;
381 bool OrderTableImpl::isFldNull(const char *fldName
)
384 ListIterator fIter
= fldProjList
.getIterator();
386 while (fIter
.hasElement())
388 def
= (FieldValue
*) fIter
.nextElement();
389 if (strcmp(fldName
, def
->fldName
) == 0) {
394 return isFldNull(pos
);
396 bool OrderTableImpl::isFldNull(int projPos
)
398 if (BITSET(nullValues
, projPos
)) return true;
402 long OrderTableImpl::numTuples()
404 return tableHdl
->numTuples();
406 DbRetVal
OrderTableImpl::closeScan()
409 ListIterator iter
= sortTree
.getListIterator();
411 while(iter
.hasElement()) {
412 elem
= iter
.nextElement();
415 sortTree
.removeAll();
416 if (tableHdl
) tableHdl
->closeScan();
420 DbRetVal
OrderTableImpl::close()
427 void OrderTableImpl::printPlan(int space
)
429 char spaceBuf
[IDENTIFIER_LENGTH
];
430 memset(spaceBuf
, 32, IDENTIFIER_LENGTH
);
431 spaceBuf
[space
] = '\0';
432 printf("%s <SORT-NODE>\n", spaceBuf
);
433 printf("%s <ORDER-BY>\n", spaceBuf
);
434 ListIterator giter
= fldOrderByList
.getIterator();
435 OrderByFldDef
*fldDef
=NULL
;
436 while ((fldDef
= (OrderByFldDef
*)giter
.nextElement()) != NULL
)
438 if (fldDef
->isDesc
) \
439 printf("%s <FieldName> %s DESC </FieldName>\n", spaceBuf
,
442 printf("%s <FieldName> %s ASC </FieldName>\n", spaceBuf
,
445 printf("%s </ORDER-BY>\n", spaceBuf
);
446 if (sortTree
.getDistinct())
447 printf("%s <DISTINCT> true </DISTINCT>\n", spaceBuf
);
448 printf("%s </SORT-NODE>\n", spaceBuf
);
449 if (tableHdl
) tableHdl
->printPlan(space
+2);