fix for trie index
[csql.git] / src / storage / OrderTableImpl.cxx
blob580be3215a9179a539323474974b055946c85a2f
1 /***************************************************************************
2 * Copyright (C) 2007 by www.databasecache.com *
3 * Contact: praba_tuty@databasecache.com *
4 * *
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. *
9 * *
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. *
14 * *
15 ***************************************************************************/
16 #include<Debug.h>
17 #include<Table.h>
18 #include<TableImpl.h>
19 #include<OrderTableImpl.h>
20 #include<PredicateImpl.h>
21 #include<Parser.h>
22 OrderTableImpl::OrderTableImpl()
24 tableHdl = NULL;
25 curTuple = NULL;
26 sortTree.setDistinct(false);
27 nullValues = 0;
28 orderBySize =0;
29 projSize =0;
30 orderBindBuf= NULL;
31 orderBuffer = NULL;
32 isPlanCreated=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
38 closeScan();
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);
46 delete elem;
48 fldOrderByList.reset();
50 if (tableHdl != NULL) tableHdl->close();
51 tableHdl = NULL;
52 if (orderBuffer) ::free(orderBuffer);
54 void *OrderTableImpl::getBindFldAddr(const char *name)
56 printError(ErrBadCall, "OrderTableImpl getBindFldAdddr not implemented\n");
57 return NULL;
60 DbRetVal OrderTableImpl::bindFld(const char *name, void *val, bool dummy)
62 printError(ErrBadCall, "OrderTableImpl bindFld not implemented\n");
63 return ErrBadCall;
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();
79 FieldValue *elem;
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;
91 break;
94 if (!orderFld->bindBuf)
96 orderFld->bindBuf = AllDataType::alloc(orderFld->type, orderFld->length);
97 rv = tableHdl->bindFld(fldname, orderFld->bindBuf);
98 if (rv != OK) {
99 delete info;
100 ::free(orderFld->bindBuf);
101 delete orderFld;
102 return rv;
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);
116 delete info;
117 return OK;
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();
128 if(firstIter) {
129 firstIter= false;
130 isDescending = oFldDef->isDesc;
131 continue;
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);
143 //set orderby size
144 orderBySize = computeOrderBySize();
145 sortTree.setKeySize(orderBySize + sizeof(int));
147 //set proj size
148 projSize = 0;
149 ListIterator iter = fldProjList.getIterator();
150 FieldValue *fValue;
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();
169 return;
171 DbRetVal OrderTableImpl::execute()
173 nullValues = 0;
174 tableHdl->execute();
175 if (!isPlanCreated) {
176 checkAndSetSortAlgorithm();
177 setNullableForProj();
178 if (sortTree.getDistinct())
180 orderBuffer = (char*)malloc(orderBySize + sizeof(int));
182 isPlanCreated=true;
184 void *tuple = NULL;
185 while ((tuple = tableHdl->fetch()) != NULL)
187 if (sortTree.getDistinct()) insertDistinct(); else insert();
189 sortIter = sortTree.getListIterator();
190 return OK;
192 int OrderTableImpl::computeOrderBySize()
194 ListIterator oiter = fldOrderByList.getIterator();
195 OrderByFldDef *oFldDef = NULL;
196 int nodeOffset =0;
197 while (oiter.hasElement())
199 oFldDef = (OrderByFldDef*) oiter.nextElement();
200 nodeOffset = nodeOffset + oFldDef->length;
202 return nodeOffset;
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;
211 int nodeOffset =0;
212 int i=0;
213 while ((oFldDef = (OrderByFldDef*) oiter.nextElement()) != NULL)
215 if (oFldDef->isNull && tableHdl->isFldNull(oFldDef->fldName))
216 SETBIT(orderNullValues, i);
217 else
218 AllDataType::copyVal(elem+nodeOffset, oFldDef->bindBuf,
219 oFldDef->type, oFldDef->length);
220 nodeOffset = nodeOffset + oFldDef->length;
221 i++;
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));
233 nullValues = 0;
234 i=0;
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);
243 else
244 AllDataType::copyVal(element+nodeOffset, fValue->value,
245 fValue->type, fValue->length);
246 nodeOffset = nodeOffset + fValue->length;
247 i++;
249 AllDataType::copyVal(ptrToCopyNullValues, &nullValues, typeLongLong,
250 sizeof(nullValues));
251 DbRetVal rv = sortTree.insertDataNode(element);
252 return rv;
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);
262 //copy values
263 int nodeOffset =0;
264 ListIterator oiter = fldOrderByList.getIterator();
265 OrderByFldDef *oFldDef = NULL;
266 int orderNullValues =0;
267 int i=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);
273 else
274 AllDataType::copyVal(element+nodeOffset, oFldDef->bindBuf,
275 oFldDef->type, oFldDef->length);
276 nodeOffset = nodeOffset + oFldDef->length;
277 i++;
279 AllDataType::copyVal(element+nodeOffset, &orderNullValues, typeInt,
280 sizeof(orderNullValues));
281 nodeOffset = nodeOffset+ sizeof(orderNullValues);
282 nullValues = 0;
283 i=0;
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);
293 else
294 AllDataType::copyVal(element+nodeOffset, fValue->value,
295 fValue->type, fValue->length);
296 nodeOffset = nodeOffset + fValue->length;
297 i++;
299 AllDataType::copyVal(ptrToCopyNullValues, &nullValues, typeLongLong,
300 sizeof(nullValues));
301 DbRetVal rv = sortTree.insertDataNode(element);
302 if (rv == ErrUnique) ::free (element);
303 return OK;
305 void* OrderTableImpl::fetch()
307 void *elem = sortIter.nextElement();
308 if (NULL == elem) return NULL;
309 copyValuesToBindBuffer(elem);
310 return elem;
313 void* OrderTableImpl::fetch(DbRetVal &rv)
315 rv = OK;
316 return fetch();
319 void* OrderTableImpl::fetchNoBind()
321 void *elem = sortIter.nextElement();
322 if (NULL == elem) return NULL;
323 copyValuesToBindBuffer(elem);
324 return elem;
327 void* OrderTableImpl::fetchNoBind(DbRetVal &rv)
329 rv = OK;
330 return fetchNoBind();
332 DbRetVal OrderTableImpl::setOrderByList(List oList)
334 ListIterator fIter = oList.getIterator();
335 FieldValue *def;
336 while (fIter.hasElement())
338 def = (FieldValue*) fIter.nextElement();
339 setOrderBy(def->fldName);
341 return OK;
343 DbRetVal OrderTableImpl::copyValuesToBindBuffer(void *elem)
345 //Iterate through the bind list and copy the value here
346 ListIterator fIter = fldProjList.getIterator();
347 FieldValue *def;
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;
360 return OK;
362 void OrderTableImpl::setNullableForProj()
364 ListIterator fIter = fldProjList.getIterator();
365 FieldValue *def;
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;
378 delete info;
379 return;
381 bool OrderTableImpl::isFldNull(const char *fldName)
383 int pos = 0;
384 ListIterator fIter = fldProjList.getIterator();
385 FieldValue *def;
386 while (fIter.hasElement())
388 def = (FieldValue*) fIter.nextElement();
389 if (strcmp(fldName, def->fldName) == 0) {
390 break;
392 pos++;
394 return isFldNull(pos);
396 bool OrderTableImpl::isFldNull(int projPos)
398 if (BITSET(nullValues, projPos)) return true;
399 return false;
402 long OrderTableImpl::numTuples()
404 return tableHdl->numTuples();
406 DbRetVal OrderTableImpl::closeScan()
408 sortIter.reset();
409 ListIterator iter = sortTree.getListIterator();
410 void *elem= NULL;
411 while(iter.hasElement()) {
412 elem = iter.nextElement();
413 free(elem);
415 sortTree.removeAll();
416 if (tableHdl) tableHdl->closeScan();
417 return OK;
420 DbRetVal OrderTableImpl::close()
422 nullValues = 0;
423 closeScan();
424 delete this;
425 return OK;
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,
440 fldDef->fldName);
441 else
442 printf("%s <FieldName> %s ASC </FieldName>\n", spaceBuf,
443 fldDef->fldName);
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);
450 return;