code reorg
[csql.git] / src / storage / OrderTableImpl.cxx
blobb379b445d400b619d6450c16177e48d96fc96271
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;
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
39 closeScan();
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);
47 delete elem;
49 fldOrderByList.reset();
51 if (tableHdl != NULL) tableHdl->close();
52 tableHdl = NULL;
53 if (orderBuffer) ::free(orderBuffer);
56 void *OrderTableImpl::getBindFldAddr(const char *name)
58 printError(ErrBadCall, "OrderTableImpl getBindFldAdddr not implemented\n");
59 return NULL;
62 DbRetVal OrderTableImpl::bindFld(const char *name, void *val, bool dummy)
64 printError(ErrBadCall, "OrderTableImpl bindFld not implemented\n");
65 return ErrBadCall;
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();
82 FieldValue *elem;
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;
94 break;
97 if (!orderFld->bindBuf)
99 orderFld->bindBuf = AllDataType::alloc(orderFld->type, orderFld->length);
100 rv = tableHdl->bindFld(fldname, orderFld->bindBuf);
101 if (rv != OK) {
102 delete info;
103 ::free(orderFld->bindBuf);
104 delete orderFld;
105 return rv;
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);
119 delete info;
120 return OK;
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();
132 if(firstIter) {
133 firstIter= false;
134 isDescending = oFldDef->isDesc;
135 continue;
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);
147 //set orderby size
148 orderBySize = computeOrderBySize();
149 sortTree.setKeySize(orderBySize + sizeof(int));
151 //set proj size
152 projSize = 0;
153 ListIterator iter = fldProjList.getIterator();
154 FieldValue *fValue;
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();
173 return;
176 DbRetVal OrderTableImpl::execute()
178 nullValues = 0;
179 tableHdl->execute();
180 if (!isPlanCreated) {
181 checkAndSetSortAlgorithm();
182 setNullableForProj();
183 if (sortTree.getDistinct())
185 orderBuffer = (char*)malloc(orderBySize + sizeof(int));
187 isPlanCreated=true;
189 void *tuple = NULL;
190 while ((tuple = tableHdl->fetch()) != NULL)
192 if (sortTree.getDistinct()) insertDistinct(); else insert();
194 sortIter = sortTree.getListIterator();
195 return OK;
198 int OrderTableImpl::computeOrderBySize()
200 ListIterator oiter = fldOrderByList.getIterator();
201 OrderByFldDef *oFldDef = NULL;
202 int nodeOffset =0;
203 while (oiter.hasElement())
205 oFldDef = (OrderByFldDef*) oiter.nextElement();
206 nodeOffset = nodeOffset + oFldDef->length;
208 return nodeOffset;
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;
218 int nodeOffset =0;
219 int i=0;
220 while ((oFldDef = (OrderByFldDef*) oiter.nextElement()) != NULL)
222 if (oFldDef->isNull && tableHdl->isFldNull(oFldDef->fldName))
223 SETBIT(orderNullValues, i);
224 else
225 AllDataType::copyVal(elem+nodeOffset, oFldDef->bindBuf,
226 oFldDef->type, oFldDef->length);
227 nodeOffset = nodeOffset + oFldDef->length;
228 i++;
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));
240 nullValues = 0;
241 i=0;
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);
250 else
251 AllDataType::copyVal(element+nodeOffset, fValue->value,
252 fValue->type, fValue->length);
253 nodeOffset = nodeOffset + fValue->length;
254 i++;
256 AllDataType::copyVal(ptrToCopyNullValues, &nullValues, typeLongLong,
257 sizeof(nullValues));
258 DbRetVal rv = sortTree.insertDataNode(element);
259 return rv;
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);
269 //copy values
270 int nodeOffset =0;
271 ListIterator oiter = fldOrderByList.getIterator();
272 OrderByFldDef *oFldDef = NULL;
273 int orderNullValues =0;
274 int i=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);
280 else
281 AllDataType::copyVal(element+nodeOffset, oFldDef->bindBuf,
282 oFldDef->type, oFldDef->length);
283 nodeOffset = nodeOffset + oFldDef->length;
284 i++;
286 AllDataType::copyVal(element+nodeOffset, &orderNullValues, typeInt,
287 sizeof(orderNullValues));
288 nodeOffset = nodeOffset+ sizeof(orderNullValues);
289 nullValues = 0;
290 i=0;
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);
300 else
301 AllDataType::copyVal(element+nodeOffset, fValue->value,
302 fValue->type, fValue->length);
303 nodeOffset = nodeOffset + fValue->length;
304 i++;
306 AllDataType::copyVal(ptrToCopyNullValues, &nullValues, typeLongLong,
307 sizeof(nullValues));
308 DbRetVal rv = sortTree.insertDataNode(element);
309 if (rv == ErrUnique) ::free (element);
310 return OK;
313 void* OrderTableImpl::fetch()
315 void *elem = sortIter.nextElement();
316 if (NULL == elem) return NULL;
317 copyValuesToBindBuffer(elem);
318 return elem;
322 void* OrderTableImpl::fetch(DbRetVal &rv)
324 rv = OK;
325 return fetch();
328 void* OrderTableImpl::fetchNoBind()
330 void *elem = sortIter.nextElement();
331 if (NULL == elem) return NULL;
332 copyValuesToBindBuffer(elem);
333 return elem;
336 void* OrderTableImpl::fetchNoBind(DbRetVal &rv)
338 rv = OK;
339 return fetchNoBind();
342 DbRetVal OrderTableImpl::setOrderByList(List oList)
344 ListIterator fIter = oList.getIterator();
345 FieldValue *def;
346 while (fIter.hasElement())
348 def = (FieldValue*) fIter.nextElement();
349 setOrderBy(def->fldName);
351 return OK;
354 DbRetVal OrderTableImpl::copyValuesToBindBuffer(void *elem)
356 //Iterate through the bind list and copy the value here
357 ListIterator fIter = fldProjList.getIterator();
358 FieldValue *def;
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;
371 return OK;
374 void OrderTableImpl::setNullableForProj()
376 ListIterator fIter = fldProjList.getIterator();
377 FieldValue *def;
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;
390 delete info;
391 return;
394 bool OrderTableImpl::isFldNull(const char *fldName)
396 int pos = 0;
397 ListIterator fIter = fldProjList.getIterator();
398 FieldValue *def;
399 while (fIter.hasElement())
401 def = (FieldValue*) fIter.nextElement();
402 if (strcmp(fldName, def->fldName) == 0) {
403 break;
405 pos++;
407 return isFldNull(pos);
410 bool OrderTableImpl::isFldNull(int projPos)
412 if (BITSET(nullValues, projPos)) return true;
413 return false;
416 long OrderTableImpl::numTuples()
418 return tableHdl->numTuples();
421 DbRetVal OrderTableImpl::closeScan()
423 sortIter.reset();
424 ListIterator iter = sortTree.getListIterator();
425 void *elem= NULL;
426 while(iter.hasElement()) {
427 elem = iter.nextElement();
428 free(elem);
430 sortTree.removeAll();
431 if (tableHdl) tableHdl->closeScan();
432 return OK;
435 DbRetVal OrderTableImpl::close()
437 nullValues = 0;
438 closeScan();
439 delete this;
440 return OK;
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,
456 fldDef->fldName);
457 else
458 printf("%s <FieldName> %s ASC </FieldName>\n", spaceBuf,
459 fldDef->fldName);
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);
466 return;