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);
35 OrderTableImpl::~OrderTableImpl()
37 //free memory allocated. make sure that field buffers are freed only once.
38 //for stmts which has more than one agg on same field needs to be handled safely
41 ListIterator oiter
= fldOrderByList
.getIterator();
42 OrderByFldDef
*elem
= NULL
;
43 while (oiter
.hasElement())
45 elem
= (OrderByFldDef
*) oiter
.nextElement();
46 if(!elem
->alreadyBinded
) free(elem
->bindBuf
);
49 fldOrderByList
.reset();
51 if (tableHdl
!= NULL
) tableHdl
->close();
53 if (orderBuffer
) ::free(orderBuffer
);
56 void *OrderTableImpl::getBindFldAddr(const char *name
)
58 printError(ErrBadCall
, "OrderTableImpl getBindFldAdddr not implemented\n");
62 DbRetVal
OrderTableImpl::bindFld(const char *name
, void *val
, bool dummy
)
64 printError(ErrBadCall
, "OrderTableImpl bindFld not implemented\n");
68 DbRetVal
OrderTableImpl::setOrderBy(const char *fldname
, bool isDesc
)
70 FieldInfo
*info
= new FieldInfo();
71 DbRetVal rv
= tableHdl
->getFieldInfo(fldname
, info
);
72 if (OK
!=rv
) { delete info
; return rv
; }
73 OrderByFldDef
*orderFld
=new OrderByFldDef();
74 strcpy(orderFld
->fldName
, fldname
);
75 orderFld
->type
= info
->type
;
76 //orderFld->length = info->length;
77 orderFld
->length
= AllDataType::size(info
->type
, info
->length
);
78 orderFld
->bindBuf
= NULL
;
79 orderFld
->isDesc
= isDesc
;
81 ListIterator iter
= fldProjList
.getIterator();
84 while (iter
.hasElement())
86 elem
= (FieldValue
*) iter
.nextElement();
87 if ((NULL
!= tableHdl
->getName() &&
88 NULL
!= strstr(elem
->fldName
, fldname
) ||
89 NULL
!= strstr(fldname
, elem
->fldName
)) ||
90 strcmp(elem
->fldName
, fldname
)==0)
92 orderFld
->bindBuf
= elem
->value
;
93 orderFld
->alreadyBinded
= true;
97 if (!orderFld
->bindBuf
)
99 orderFld
->bindBuf
= AllDataType::alloc(orderFld
->type
, orderFld
->length
);
100 rv
= tableHdl
->bindFld(fldname
, orderFld
->bindBuf
);
103 ::free(orderFld
->bindBuf
);
109 //if underlying tablehandle is TableImpl, then set isNull
110 orderFld
->isNull
= true;
111 if (info
->isNull
) orderFld
->isNull
= false;
112 if (info
->isPrimary
|| info
->isDefault
|| info
->isAutoIncrement
) {
113 orderFld
->isNull
= true;
115 if (NULL
== tableHdl
->getName()) orderFld
->isNull
=false;
118 fldOrderByList
.append(orderFld
);
123 OrderByType
OrderTableImpl::getOrderType()
125 ListIterator oiter
= fldOrderByList
.getIterator();
126 OrderByFldDef
*oFldDef
= NULL
;
127 bool isDescending
= false;
128 bool firstIter
= true;
129 while (oiter
.hasElement())
131 oFldDef
= (OrderByFldDef
*) oiter
.nextElement();
134 isDescending
= oFldDef
->isDesc
;
137 if (oFldDef
->isDesc
!= isDescending
) { isDescending
= false; break; }
139 if(isDescending
) return Desc
; else return Asc
;
142 void OrderTableImpl::checkAndSetSortAlgorithm()
144 if (sortTree
.getDistinct()) sortTree
.setFullOrderBy();
145 sortTree
.setOrderByList(fldOrderByList
);
148 orderBySize
= computeOrderBySize();
149 sortTree
.setKeySize(orderBySize
+ sizeof(int));
153 ListIterator iter
= fldProjList
.getIterator();
155 while (iter
.hasElement())
157 fValue
= (FieldValue
*) iter
.nextElement();
158 projSize
= projSize
+ fValue
->length
;
160 OrderByFldDef
*ordFld
=NULL
;
161 bool optGrpIntNoNull
= false;
162 if (orderBySize
== sizeof(int))
164 ListIterator iter
= fldOrderByList
.getIterator();
165 ordFld
= (OrderByFldDef
*)iter
.nextElement();
166 if (!ordFld
->isNull
&& ordFld
->type
== typeInt
)
168 optGrpIntNoNull
=true;
169 orderBindBuf
= ordFld
->bindBuf
;
170 sortTree
.setOrdIntNoNull();
176 DbRetVal
OrderTableImpl::execute()
180 if (!isPlanCreated
) {
181 checkAndSetSortAlgorithm();
182 setNullableForProj();
183 if (sortTree
.getDistinct())
185 orderBuffer
= (char*)malloc(orderBySize
+ sizeof(int));
190 while ((tuple
= tableHdl
->fetch()) != NULL
)
192 if (sortTree
.getDistinct()) insertDistinct(); else insert();
194 sortIter
= sortTree
.getListIterator();
198 int OrderTableImpl::computeOrderBySize()
200 ListIterator oiter
= fldOrderByList
.getIterator();
201 OrderByFldDef
*oFldDef
= NULL
;
203 while (oiter
.hasElement())
205 oFldDef
= (OrderByFldDef
*) oiter
.nextElement();
206 nodeOffset
= nodeOffset
+ oFldDef
->length
;
211 DbRetVal
OrderTableImpl::insertDistinct()
213 char *elem
= orderBuffer
;
214 memset(orderBuffer
, 0, orderBySize
+ sizeof(int));
215 ListIterator oiter
= fldOrderByList
.getIterator();
216 OrderByFldDef
*oFldDef
= NULL
;
217 int orderNullValues
=0;
220 while ((oFldDef
= (OrderByFldDef
*) oiter
.nextElement()) != NULL
)
222 if (oFldDef
->isNull
&& tableHdl
->isFldNull(oFldDef
->fldName
))
223 SETBIT(orderNullValues
, i
);
225 AllDataType::copyVal(elem
+nodeOffset
, oFldDef
->bindBuf
,
226 oFldDef
->type
, oFldDef
->length
);
227 nodeOffset
= nodeOffset
+ oFldDef
->length
;
230 AllDataType::copyVal(elem
+nodeOffset
, &orderNullValues
, typeInt
,
231 sizeof(orderNullValues
));
232 if (sortTree
.find(elem
)) return OK
;
233 nodeOffset
= nodeOffset
+ sizeof(orderNullValues
);
235 int nodeSize
= orderBySize
+ projSize
;
236 nodeSize
= nodeSize
+ sizeof(int);//to store order by field null values
237 nodeSize
= nodeSize
+ sizeof(nullValues
);//to store proj field null values
238 char *element
= (char*)malloc(nodeSize
);
239 memcpy(element
, elem
, orderBySize
+ sizeof(int));
242 ListIterator iter
= fldProjList
.getIterator();
243 FieldValue
*fValue
= NULL
;
244 void* ptrToCopyNullValues
= element
+nodeOffset
;
245 nodeOffset
= nodeOffset
+ sizeof(nullValues
);
246 while ((fValue
= (FieldValue
*) iter
.nextElement()) != NULL
)
248 if (fValue
->isNullable
&& tableHdl
->isFldNull(fValue
->fldName
))
249 SETBIT(nullValues
, i
);
251 AllDataType::copyVal(element
+nodeOffset
, fValue
->value
,
252 fValue
->type
, fValue
->length
);
253 nodeOffset
= nodeOffset
+ fValue
->length
;
256 AllDataType::copyVal(ptrToCopyNullValues
, &nullValues
, typeLongLong
,
258 DbRetVal rv
= sortTree
.insertDataNode(element
);
262 DbRetVal
OrderTableImpl::insert()
264 //compute size of projection
265 int nodeSize
= orderBySize
+ projSize
;
266 nodeSize
= nodeSize
+ sizeof(int);//to store order by field null values
267 nodeSize
= nodeSize
+ sizeof(nullValues
);//to store proj field null values
268 char *element
= (char*)malloc(nodeSize
);
271 ListIterator oiter
= fldOrderByList
.getIterator();
272 OrderByFldDef
*oFldDef
= NULL
;
273 int orderNullValues
=0;
275 while ((oFldDef
= (OrderByFldDef
*) oiter
.nextElement()) != NULL
)
277 //oFldDef = (OrderByFldDef*) oiter.nextElement();
278 if (oFldDef
->isNull
&& tableHdl
->isFldNull(oFldDef
->fldName
))
279 SETBIT(orderNullValues
, i
);
281 AllDataType::copyVal(element
+nodeOffset
, oFldDef
->bindBuf
,
282 oFldDef
->type
, oFldDef
->length
);
283 nodeOffset
= nodeOffset
+ oFldDef
->length
;
286 AllDataType::copyVal(element
+nodeOffset
, &orderNullValues
, typeInt
,
287 sizeof(orderNullValues
));
288 nodeOffset
= nodeOffset
+ sizeof(orderNullValues
);
291 ListIterator iter
= fldProjList
.getIterator();
292 FieldValue
*fValue
= NULL
;
293 void* ptrToCopyNullValues
= element
+nodeOffset
;
294 nodeOffset
= nodeOffset
+ sizeof(nullValues
);
295 while ((fValue
= (FieldValue
*) iter
.nextElement()) != NULL
)
297 //fValue = (FieldValue*) iter.nextElement();
298 if (fValue
->isNullable
&& tableHdl
->isFldNull(fValue
->fldName
))
299 SETBIT(nullValues
, i
);
301 AllDataType::copyVal(element
+nodeOffset
, fValue
->value
,
302 fValue
->type
, fValue
->length
);
303 nodeOffset
= nodeOffset
+ fValue
->length
;
306 AllDataType::copyVal(ptrToCopyNullValues
, &nullValues
, typeLongLong
,
308 DbRetVal rv
= sortTree
.insertDataNode(element
);
309 if (rv
== ErrUnique
) ::free (element
);
313 void* OrderTableImpl::fetch()
315 void *elem
= sortIter
.nextElement();
316 if (NULL
== elem
) return NULL
;
317 copyValuesToBindBuffer(elem
);
322 void* OrderTableImpl::fetch(DbRetVal
&rv
)
328 void* OrderTableImpl::fetchNoBind()
330 void *elem
= sortIter
.nextElement();
331 if (NULL
== elem
) return NULL
;
332 copyValuesToBindBuffer(elem
);
336 void* OrderTableImpl::fetchNoBind(DbRetVal
&rv
)
339 return fetchNoBind();
342 DbRetVal
OrderTableImpl::setOrderByList(List oList
)
344 ListIterator fIter
= oList
.getIterator();
346 while (fIter
.hasElement())
348 def
= (FieldValue
*) fIter
.nextElement();
349 setOrderBy(def
->fldName
);
354 DbRetVal
OrderTableImpl::copyValuesToBindBuffer(void *elem
)
356 //Iterate through the bind list and copy the value here
357 ListIterator fIter
= fldProjList
.getIterator();
359 char *colPtr
= (char*) elem
+ orderBySize
;
360 colPtr
= colPtr
+ sizeof(int);
361 nullValues
= *(long long*) colPtr
;
362 colPtr
= colPtr
+ sizeof (nullValues
);
363 while (fIter
.hasElement())
365 def
= (FieldValue
*) fIter
.nextElement();
366 if (NULL
!= def
->value
) {
367 AllDataType::copyVal(def
->value
, colPtr
, def
->type
, def
->length
);
368 colPtr
= colPtr
+ def
->length
;
374 void OrderTableImpl::setNullableForProj()
376 ListIterator fIter
= fldProjList
.getIterator();
378 FieldInfo
*info
= new FieldInfo();
379 while (fIter
.hasElement())
381 def
= (FieldValue
*) fIter
.nextElement();
382 tableHdl
->getFieldInfo(def
->fldName
, info
);
383 def
->isNullable
= true;
384 if (info
->isNull
|| info
->isPrimary
||
385 info
->isDefault
|| info
->isAutoIncrement
) {
386 def
->isNullable
= false;
388 if (NULL
== tableHdl
->getName()) def
->isNullable
=true;
394 bool OrderTableImpl::isFldNull(const char *fldName
)
397 ListIterator fIter
= fldProjList
.getIterator();
399 while (fIter
.hasElement())
401 def
= (FieldValue
*) fIter
.nextElement();
402 if (strcmp(fldName
, def
->fldName
) == 0) {
407 return isFldNull(pos
);
410 bool OrderTableImpl::isFldNull(int projPos
)
412 if (BITSET(nullValues
, projPos
)) return true;
416 long OrderTableImpl::numTuples()
418 return tableHdl
->numTuples();
421 DbRetVal
OrderTableImpl::closeScan()
424 ListIterator iter
= sortTree
.getListIterator();
426 while(iter
.hasElement()) {
427 elem
= iter
.nextElement();
430 sortTree
.removeAll();
431 if (tableHdl
) tableHdl
->closeScan();
435 DbRetVal
OrderTableImpl::close()
443 void OrderTableImpl::printPlan(int space
)
445 char spaceBuf
[IDENTIFIER_LENGTH
];
446 memset(spaceBuf
, 32, IDENTIFIER_LENGTH
);
447 spaceBuf
[space
] = '\0';
448 printf("%s <SORT-NODE>\n", spaceBuf
);
449 printf("%s <ORDER-BY>\n", spaceBuf
);
450 ListIterator giter
= fldOrderByList
.getIterator();
451 OrderByFldDef
*fldDef
=NULL
;
452 while ((fldDef
= (OrderByFldDef
*)giter
.nextElement()) != NULL
)
454 if (fldDef
->isDesc
) \
455 printf("%s <FieldName> %s DESC </FieldName>\n", spaceBuf
,
458 printf("%s <FieldName> %s ASC </FieldName>\n", spaceBuf
,
461 printf("%s </ORDER-BY>\n", spaceBuf
);
462 if (sortTree
.getDistinct())
463 printf("%s <DISTINCT> true </DISTINCT>\n", spaceBuf
);
464 printf("%s </SORT-NODE>\n", spaceBuf
);
465 if (tableHdl
) tableHdl
->printPlan(space
+2);