Memory Leak Fixes
[csql.git] / src / sql / SelStatement.cxx
blobcfd93132efd3c179512da42425bd79aa1145444a
1 /***************************************************************************
2 * Copyright (C) 2007 by Prabakaran Thirumalai *
3 * praba_tuty@yahoo.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 <os.h>
17 #include <Statement.h>
18 #include <TableImpl.h>
19 #include <OrderTableImpl.h>
21 SelStatement::SelStatement()
23 parsedData = NULL;
24 dbMgr = NULL;
25 table = NULL;
26 params = NULL;
27 paramValues = NULL;
28 totalParams = 0;
29 bindFields = NULL;
30 bindFieldValues = NULL;
31 totalFields = 0;
32 isPointReturned = false;
33 handleAggWithTbl=false;
34 numRecords = 0;
35 isOffsetReached = false;
36 isRecLimitReached = false;
37 isExplain=false;
38 isJoin=false;
41 SelStatement::~SelStatement()
43 close();
44 if (table) { table->close(); table = NULL; }
45 if (totalParams) {
46 free(params);
47 params = NULL;
48 free(paramValues);
49 paramValues = NULL;
51 if (totalFields)
53 free(bindFields);
54 bindFields = NULL;
55 free(bindFieldValues);
56 bindFieldValues = NULL;
60 DbRetVal SelStatement::getParamFldInfo(int paramNo, FieldInfo *&info)
62 if (paramNo <=0 || paramNo > totalParams) return ErrBadArg;
63 ConditionValue *cValue = (ConditionValue*) params [paramNo-1];
64 if (NULL == cValue)
66 printError(ErrSysFatal, "condition value is null. Should never happen");
67 return ErrSysFatal;
69 table->getFieldNameAlone(cValue->fName,info->fldName);
70 info->type = cValue->type;
71 info->length = cValue->length;
72 info->isNull = cValue->isNullable;
73 return OK;
75 DbRetVal SelStatement::execute(int &rowsAffected)
77 DbRetVal rv = OK;
78 //copy param values to binded buffer
79 ConditionValue *value;
80 for (int i = 0; i < totalParams; i ++)
82 value = (ConditionValue*) params[i];
83 if (paramValues[i] == NULL)
85 continue;
86 //printError(ErrBadCall, "param values not set");
87 //return ErrBadCall;
89 AllDataType::copyVal(value->value, paramValues[i], value->type, value->length);
91 //table->printPlan(0);
92 //printf("Execute Called\n");
93 rv = table->execute();
94 numRecords = 0;
95 isOffsetReached = false;
96 isRecLimitReached = false;
98 if (isExplain) table->printPlan(0);
99 return rv;
102 DbRetVal SelStatement::setParam(int paramNo, void *value)
104 if (paramNo <=0 || paramNo > totalParams) return ErrBadArg;
105 if (NULL == value) return ErrBadArg;
106 paramValues[paramNo -1] = (char*) value;
107 return OK;
110 DbRetVal SelStatement::setShortParam(int paramNo, short value)
112 if (paramNo <=0 || paramNo > totalParams) return ErrBadArg;
113 ConditionValue *cValue = (ConditionValue*) params [paramNo-1];
114 if (NULL == cValue)
116 printError(ErrSysFatal, "field value is null. Should never happen");
117 return ErrSysFatal;
119 *(short*)cValue->value = value;
120 return OK;
123 DbRetVal SelStatement::setIntParam(int paramNo, int value)
125 if (paramNo <=0 || paramNo > totalParams) return ErrBadArg;
126 ConditionValue *cValue = (ConditionValue*) params [paramNo-1];
127 if (NULL == cValue)
129 printError(ErrSysFatal, "condition value is null. Should never happen");
130 return ErrSysFatal;
132 *(int*)cValue->value = value;
133 return OK;
135 DbRetVal SelStatement::setLongParam(int paramNo, long value)
137 if (paramNo <=0 || paramNo > totalParams) return ErrBadArg;
138 ConditionValue *cValue = (ConditionValue*) params [paramNo-1];
139 if (NULL == cValue)
141 printError(ErrSysFatal, "condition value is null. Should never happen");
142 return ErrSysFatal;
144 *(long*)cValue->value = value;
145 return OK;
148 DbRetVal SelStatement::setLongLongParam(int paramNo, long long value)
150 if (paramNo <=0 || paramNo > totalParams) return ErrBadArg;
151 ConditionValue *cValue = (ConditionValue*) params [paramNo-1];
152 if (NULL == cValue)
154 printError(ErrSysFatal, "condition value is null. Should never happen");
155 return ErrSysFatal;
157 *(long long*)cValue->value = value;
158 return OK;
160 DbRetVal SelStatement::setByteIntParam(int paramNo, ByteInt value)
162 if (paramNo <=0 || paramNo > totalParams) return ErrBadArg;
163 ConditionValue *cValue = (ConditionValue*) params [paramNo-1];
164 if (NULL == cValue)
166 printError(ErrSysFatal, "condition value is null. Should never happen");
167 return ErrSysFatal;
169 *(ByteInt*)cValue->value = value;
170 return OK;
172 DbRetVal SelStatement::setFloatParam(int paramNo, float value)
174 if (paramNo <=0 || paramNo > totalParams) return ErrBadArg;
175 ConditionValue *cValue = (ConditionValue*) params [paramNo-1];
176 if (NULL == cValue)
178 printError(ErrSysFatal, "condition value is null. Should never happen");
179 return ErrSysFatal;
181 *(float*)cValue->value = value;
182 return OK;
184 DbRetVal SelStatement::setDoubleParam(int paramNo, double value)
186 if (paramNo <=0 || paramNo > totalParams) return ErrBadArg;
187 ConditionValue *cValue = (ConditionValue*) params [paramNo-1];
188 if (NULL == cValue)
190 printError(ErrSysFatal, "condition value is null. Should never happen");
191 return ErrSysFatal;
193 *(double*)cValue->value = value;
194 return OK;
196 DbRetVal SelStatement::setStringParam(int paramNo, char *value)
198 if (paramNo <=0 || paramNo > totalParams) return ErrBadArg;
199 ConditionValue *cValue = (ConditionValue*) params [paramNo-1];
200 if (NULL == cValue)
202 printError(ErrSysFatal, "condition value is null. Should never happen");
203 return ErrSysFatal;
205 strcpy((char*)cValue->value, value);
206 return OK;
208 DbRetVal SelStatement::setDateParam(int paramNo, Date value)
210 if (paramNo <=0 || paramNo > totalParams) return ErrBadArg;
211 ConditionValue *cValue = (ConditionValue*) params [paramNo-1];
212 if (NULL == cValue)
214 printError(ErrSysFatal, "condition value is null. Should never happen");
215 return ErrSysFatal;
217 *(Date*)cValue->value = value;
218 return OK;
220 DbRetVal SelStatement::setTimeParam(int paramNo, Time value)
222 if (paramNo <=0 || paramNo > totalParams) return ErrBadArg;
223 ConditionValue *cValue = (ConditionValue*) params [paramNo-1];
224 if (NULL == cValue)
226 printError(ErrSysFatal, "condition value is null. Should never happen");
227 return ErrSysFatal;
229 *(Time*)cValue->value = value;
230 return OK;
232 DbRetVal SelStatement::setTimeStampParam(int paramNo, TimeStamp value)
234 if (paramNo <=0 || paramNo > totalParams) return ErrBadArg;
235 ConditionValue *cValue = (ConditionValue*) params [paramNo-1];
236 if (NULL == cValue)
238 printError(ErrSysFatal, "condition value is null. Should never happen");
239 return ErrSysFatal;
241 *(TimeStamp*)cValue->value = value;
242 return OK;
245 DbRetVal SelStatement::setBinaryParam(int paramNo, void *value, int length)
247 if (paramNo <=0 || paramNo > totalParams) return ErrBadArg;
248 ConditionValue *cValue = (ConditionValue*) params [paramNo-1];
249 if (NULL == cValue)
251 printError(ErrSysFatal, "condition value is null. Should never happen");
252 return ErrSysFatal;
254 AllDataType::convertToBinary(cValue->value,value,typeString,cValue->length);
255 return OK;
258 DbRetVal SelStatement::setBindField(int colNo, void *value)
260 if (colNo <=0) return ErrBadArg;
261 //TODO: check the upper limit
262 //if (colNo > table->getFieldNameList().size()) return ErrBadArg;
263 if (NULL == value) return ErrBadArg;
264 bindFieldValues[colNo -1] = (char*) value;
265 return OK;
267 bool SelStatement::isTableAlreadyPresent(char *tblName, char *aliasName)
269 ListIterator titer = parsedData->getTableNameList().getIterator();
270 int count =0;
271 while (titer.hasElement())
273 TableName *t = (TableName*)titer.nextElement();
274 if (strcmp(t->tblName, tblName) ==0 &&
275 strcmp(t->aliasName, aliasName) ==0) count++;
277 if (count == 1) return false;
278 return true;
280 DbRetVal SelStatement::openTables()
282 if (dbMgr == NULL) return ErrNoConnection;
283 JoinTableImpl *jHdl = NULL;
284 Table *tHdl = NULL, *prevHdl = NULL;
285 isJoin = false;
286 //check whether all the table exists
287 ListIterator titer = parsedData->getTableNameList().getIterator();
288 ListIterator jiter = parsedData->getJoinTypeList().getIterator();
289 while (titer.hasElement())
291 TableName *t = (TableName*)titer.nextElement();
292 parsedData->setTableName(t->tblName);
293 if (isTableAlreadyPresent(t->tblName, t->aliasName)) {
294 printError(ErrSyntaxError,
295 "Referencing same table again %s", t->tblName);
296 if (prevHdl) delete prevHdl;
297 return ErrSyntaxError;
299 tHdl = dbMgr->openTable(t->tblName);
300 if ( NULL == tHdl )
302 printError(ErrNotExists,
303 "Unable to open the table:Table not exists");
304 if (prevHdl) delete prevHdl;
305 return ErrNotExists;
307 TableImpl *tImpl= (TableImpl*) tHdl;
308 tImpl->setAliasName(t->aliasName);
309 if (NULL != prevHdl)
311 isJoin = true;
312 jHdl = new JoinTableImpl();
313 jHdl->setTable(prevHdl, tHdl);
314 JoinTypeNode *node = (JoinTypeNode*) jiter.nextElement();
315 if (node == NULL) {
316 printError(ErrSyntaxError,
317 "Join Type and number of tables do not match");
318 delete jHdl;
319 return ErrSyntaxError;
321 jHdl->setJoinType(node->jType);
322 prevHdl = jHdl;
323 continue;
325 prevHdl = tHdl;
328 if (isJoin) table = jHdl; else table = tHdl;
329 return OK;
331 DbRetVal SelStatement::resolve()
333 DbRetVal rv = openTables();
334 if (rv != OK) return rv;
335 //get the fieldname list and validate field names
336 ListIterator iter = parsedData->getFieldNameList().getIterator();
337 FieldName *name = NULL;
338 FieldInfo *fInfo = new FieldInfo();
339 List bindFldList;
340 bool isSingleTableNoGrp = false;
341 if(parsedData->getTableNameList().size() == 1 &&
342 parsedData->getGroupFieldNameList().size() == 0)
344 isSingleTableNoGrp = true;
346 AggTableImpl *aggTable = NULL;
347 while (iter.hasElement())
349 name = (FieldName*)iter.nextElement();
350 if (NULL == name)
352 dbMgr->closeTable(table);
353 table = NULL;
354 delete fInfo;
355 printError(ErrSysFatal, "Should never happen. Field Name list has NULL");
356 return ErrSysFatal;
358 bool isBindFld=false;
359 if ('*' == name->fldName[0] && name->aType == AGG_UNKNOWN)
361 rv = resolveStar();
362 if (rv != OK)
364 dbMgr->closeTable(table);
365 table = NULL;
366 delete fInfo;
367 return rv;
369 if (parsedData->getGroupFieldNameList().size()!= 0
370 && !isSingleTableNoGrp)
372 if (!aggTable)
373 aggTable = new AggTableImpl();
374 aggTable->setTable(table);
376 //as soon as it encounters *, it breaks the loop negleting other field names
377 //as they all are deleted during resolveStar method.
378 break;
379 }else {
380 if ('*' == name->fldName[0] && name->aType != AGG_COUNT) {return ErrSyntaxError;}
381 rv = table->getFieldInfo(name->fldName, fInfo);
382 if (ErrNotFound == rv || ErrNotExists == rv)
384 if (aggTable) { delete aggTable; aggTable = NULL; }
385 else dbMgr->closeTable(table);
386 table = NULL;
387 delete fInfo;
388 printError(ErrSyntaxError, "Field %s does not exist in table",
389 name->fldName);
390 return ErrSyntaxError;
392 FieldValue *newVal = new FieldValue();
393 strcpy(newVal->fldName,name->fldName);
394 newVal->parsedString = NULL;
395 newVal->paramNo = 0;
396 newVal->aType = name->aType;
397 newVal->isInResSet = true;
398 newVal->offset = fInfo->offset;
399 newVal->isPrimary = fInfo->isPrimary;
400 newVal->isUnique = fInfo->isUnique;
401 newVal->isAutoIncrement = fInfo->isAutoIncrement;
402 newVal->isDefault = fInfo->isDefault;
403 if (newVal->isDefault)
404 strcpy(newVal->defValBuf, fInfo->defaultValueBuf);
405 else newVal->defValBuf[0] ='\0';
406 if (name->aType == AGG_COUNT) {
407 newVal->type = typeInt;
408 newVal->length = sizeof(int);
410 else if (name->aType == AGG_AVG) {
411 newVal->type = typeDouble;
412 newVal->length = sizeof(double);
413 if (!AllDataType::isValidFieldForAvg(fInfo->type)) {
414 printError(ErrBadArg, "Illegal operation for field %s",
415 fInfo->fldName);
416 dbMgr->closeTable(table);
417 if (aggTable) { delete aggTable; aggTable = NULL; }
418 table = NULL;
419 delete fInfo;
420 return ErrBadArg;
423 else {
424 newVal->type = fInfo->type;
425 newVal->length = fInfo->length;
427 newVal->isNullable = fInfo->isNull;
428 FieldName *bFldName=NULL;
429 ListIterator it = bindFldList.getIterator();
430 while (it.hasElement())
432 bFldName = (FieldName*)it.nextElement();
433 if(0==strcmp(bFldName->fldName,name->fldName) &&
434 name->aType == AGG_UNKNOWN)
436 newVal->value=table->getBindFldAddr(name->fldName);
437 newVal->isAllocVal=false;
438 isBindFld=true;
439 break;
442 if (!isBindFld) {
443 if ( name->aType == AGG_UNKNOWN ||
444 (name->aType != AGG_COUNT &&
445 name->aType != AGG_AVG) ) {
446 if(newVal->type == typeBinary)
447 newVal->value = AllDataType::alloc(fInfo->type,
448 2 * fInfo->length);
449 else newVal->value = AllDataType::alloc(fInfo->type,
450 fInfo->length);
451 } else {
452 if (name->aType == AGG_AVG) {
453 newVal->value = AllDataType::alloc(typeDouble,
454 sizeof(double));
455 memset(newVal->value, 0, sizeof(double));
457 else if (name->aType == AGG_COUNT) {
458 newVal->value = AllDataType::alloc(typeInt,
459 sizeof(int));
460 memset(newVal->value, 0, sizeof(int));
464 newVal->isAllocVal=true;
466 if (name->aType ==AGG_UNKNOWN &&
467 parsedData->getGroupFieldNameList().size()== 0) {
468 rv = table->bindFld(name->fldName, newVal->value);
469 if (OK !=rv) {
470 if (newVal->isAllocVal) free(newVal->value);
471 delete newVal;
472 delete fInfo;
473 return rv;
476 else if (!isSingleTableNoGrp)
478 if (!aggTable) {
479 aggTable = new AggTableImpl();
480 aggTable->setTable(table);
482 rv = aggTable->bindFld(name->fldName, name->aType, newVal->value);
483 if (OK !=rv) {
484 if (newVal->isAllocVal) free(newVal->value);
485 delete newVal; delete fInfo; delete aggTable;
486 aggTable = NULL; table = NULL;
487 return rv;
490 if (name->aType !=AGG_UNKNOWN && isSingleTableNoGrp)
491 handleAggWithTbl= true;
492 parsedData->insertFieldValue(newVal);
494 if (!isBindFld) bindFldList.append(name);
496 bindFldList.reset();
498 //Check if the having list is present in projection list or not.
499 //If not present bind here not to be printed in fetchAndPrint later.
500 ListIterator hiter = parsedData->getHavingFieldNameList().getIterator();
501 while (hiter.hasElement()) {
502 FieldName *fnm = (FieldName *) hiter.nextElement();
503 rv = table->getFieldInfo(fnm->fldName, fInfo);
504 if (!isInProjectionList(fnm->fldName, fnm->aType)) {
505 FieldValue *newVal = new FieldValue();
506 strcpy(newVal->fldName,fnm->fldName);
507 newVal->parsedString = NULL;
508 newVal->paramNo = 0;
509 newVal->aType = fnm->aType;
510 newVal->isInResSet = false;
511 newVal->isNullable = fInfo->isNull;
512 newVal->offset = fInfo->offset;
513 newVal->isPrimary = fInfo->isPrimary;
514 newVal->isUnique = fInfo->isUnique;
515 newVal->isAutoIncrement = fInfo->isAutoIncrement;
516 if (fnm->aType == AGG_AVG) {
517 newVal->value = AllDataType::alloc(typeDouble, sizeof(double));
518 memset(newVal->value, 0, sizeof(double));
519 } else if (fnm->aType == AGG_COUNT) {
520 newVal->value = AllDataType::alloc(typeInt, sizeof(int));
521 memset(newVal->value, 0, sizeof(int));
522 } else {
523 newVal->value = AllDataType::alloc(fInfo->type, fInfo->length);
524 memset(newVal->value, 0, fInfo->length);
526 newVal->isAllocVal = true;
527 parsedData->insertFieldValue(newVal);
528 aggTable->bindFld(fnm->fldName, fnm->aType, newVal->value);
532 rv = setBindFieldAndValues();
533 if (rv != OK)
535 delete fInfo;
536 if (aggTable) { delete aggTable; aggTable = NULL; }
537 else dbMgr->closeTable(table);
538 table = NULL;
539 return rv;
542 table->setCondition(parsedData->getCondition());
544 rv = resolveForCondition();
545 if (rv != OK)
547 delete fInfo;
548 //TODO::free memory allocated for params
549 if (aggTable) { delete aggTable; aggTable = NULL; }
550 else {
551 table->setCondition(NULL);
552 dbMgr->closeTable(table);
554 table = NULL;
555 return rv;
557 rv = resolveGroupFld(aggTable);
558 if (rv != OK)
560 delete fInfo;
561 //TODO::free memory allocated for params
562 if (aggTable) { delete aggTable; aggTable = NULL; }
563 else if (table)
565 table->setCondition(NULL);
566 dbMgr->closeTable(table);
568 table = NULL;
569 return rv;
572 rv = resolveOrderByFld();
573 if (rv != OK)
575 delete fInfo;
576 delete table;
577 table = NULL;
578 return rv;
580 rv = resolveDistinct();
581 delete fInfo;
582 if(parsedData->getExplain()) isExplain = true;
583 return rv;
585 DbRetVal SelStatement::resolveDistinct()
587 if (!parsedData->getDistinct()) {
588 return OK;
590 OrderTableImpl *orderTable = new OrderTableImpl();
591 orderTable->setTable(table);
592 orderTable->setProjList(parsedData->getFieldValueList());
593 orderTable->setOrderByList(parsedData->getFieldValueList());
594 orderTable->setDistinct();
595 table = orderTable;
596 handleAggWithTbl= false;
597 return OK;
601 DbRetVal SelStatement::resolveOrderByFld()
603 if (0 == parsedData->getOrderFieldNameList().size()) {
604 return OK;
606 OrderTableImpl *orderTable = new OrderTableImpl();
607 orderTable->setTable(table);
608 orderTable->setProjList(parsedData->getFieldValueList());
609 ListIterator giter = parsedData->getOrderFieldNameList().getIterator();
610 FieldName *name = NULL;
611 DbRetVal rv = OK;
612 FieldInfo *fInfo = new FieldInfo();
613 while (giter.hasElement())
615 name = (FieldName*)giter.nextElement();
616 rv = table->getFieldInfo(name->fldName, fInfo);
617 if (ErrNotFound == rv || ErrNotExists == rv)
619 delete fInfo;
620 printError(ErrSyntaxError, "Field %s does not exist in table",
621 name->fldName);
622 return ErrSyntaxError;
624 /*FieldValue *newVal = new FieldValue();
625 strcpy(newVal->fldName,name->fldName);
626 newVal->parsedString = NULL;
627 newVal->paramNo = 0;
628 newVal->type = fInfo->type;
629 newVal->isNullable = fInfo->isNull;
630 newVal->length = fInfo->length;
631 if (newVal->type == typeBinary)
632 newVal->value = AllDataType::alloc(fInfo->type, 2 * fInfo->length);
633 else newVal->value = AllDataType::alloc(fInfo->type, fInfo->length);
634 newVal->isAllocVal=true;
635 parsedData->insertFieldValue(newVal);
637 if (name->aType == AGG_UNKNOWN) orderTable->setOrderBy(name->fldName);
638 else orderTable->setOrderBy(name->fldName, true); //descending
640 delete fInfo;
641 table = orderTable;
642 handleAggWithTbl= false;
643 return OK;
646 DbRetVal SelStatement::resolveGroupFld(AggTableImpl *aggTable)
648 if (!aggTable) return OK;
650 //check whether all non aggregate projections are from group list
651 ListIterator iter = parsedData->getFieldNameList().getIterator();
652 ListIterator giter = parsedData->getGroupFieldNameList().getIterator();
653 FieldName *name = NULL;
654 while (iter.hasElement())
656 name = (FieldName*) iter.nextElement();
657 if (name->aType == AGG_UNKNOWN && !isGroupFld(name->fldName) ) {
658 printError(ErrSyntaxError, "Non aggregate projection contains non group field: %s", name->fldName);
659 return ErrSyntaxError;
663 DbRetVal rv = OK;
664 FieldInfo *fInfo = new FieldInfo();
665 while (giter.hasElement())
667 name = (FieldName*)giter.nextElement();
668 rv = table->getFieldInfo(name->fldName, fInfo);
669 if (ErrNotFound == rv || ErrNotExists == rv)
671 delete fInfo;
672 printError(ErrSyntaxError, "Field %s does not exist in table",
673 name->fldName);
674 return ErrSyntaxError;
676 FieldValue *newVal = new FieldValue();
677 strcpy(newVal->fldName,name->fldName);
678 newVal->parsedString = NULL;
679 newVal->paramNo = 0;
680 newVal->type = fInfo->type;
681 newVal->isNullable = fInfo->isNull;
682 newVal->length = fInfo->length;
683 newVal->offset = fInfo->offset;
684 newVal->isPrimary = fInfo->isPrimary;
685 newVal->isUnique = fInfo->isUnique;
686 newVal->isAutoIncrement = fInfo->isAutoIncrement;
687 if (newVal->type == typeBinary)
688 newVal->value = AllDataType::alloc(fInfo->type, 2 * fInfo->length);
689 else newVal->value = AllDataType::alloc(fInfo->type, fInfo->length);
690 newVal->isAllocVal=true;
691 parsedData->insertFieldValue(newVal);
692 aggTable->setGroup(name->fldName, newVal->value);
694 delete fInfo;
695 aggTable->setCondition(parsedData->getHavingCondition());
696 /*if (giter.hasElement())
698 printError(ErrSyntaxError, "Only one field allowed in group\n");
699 return ErrSyntaxError;
701 table = aggTable;
702 return OK;
705 DbRetVal SelStatement::resolveStar()
707 DbRetVal rv = OK;
708 parsedData->clearFieldNameList();
709 FieldValue *newVal = NULL;
710 List fNameList = table->getFieldNameList();
711 ListIterator fNameIter = fNameList.getIterator();
712 //fNameList.resetIter(); //do not remove this.
713 FieldInfo *fInfo = new FieldInfo();
714 for (int i = 0; i < fNameList.size() ; i++)
716 char *fName = ((Identifier*)(fNameIter.nextElement()))->name;
717 rv = table->getFieldInfo(fName, fInfo);
718 if (ErrNotFound == rv || ErrNotExists == rv)
720 delete fInfo;
721 fNameList.reset();
722 printError(ErrSysFatal, "Should never happen.");
723 return ErrSysFatal;
725 newVal = new FieldValue();
726 strcpy(newVal->fldName,fName);
727 newVal->parsedString = NULL;
728 newVal->paramNo = 0;
729 newVal->type = fInfo->type;
730 newVal->length = fInfo->length;
731 newVal->offset = fInfo->offset;
732 newVal->isPrimary = fInfo->isPrimary;
733 newVal->isUnique = fInfo->isUnique;
734 newVal->isAutoIncrement = fInfo->isAutoIncrement;
736 // for binary datatype input buffer size should be 2 times the length
737 if(newVal->type == typeBinary)
738 newVal->value = AllDataType::alloc(fInfo->type, 2 * fInfo->length);
739 else newVal->value = AllDataType::alloc(fInfo->type, fInfo->length);
740 newVal->isAllocVal=true;
741 newVal->isInResSet = true;
742 parsedData->insertFieldValue(newVal);
743 parsedData->insertField(fName);
744 rv = table->bindFld(fName, newVal->value);
745 if (rv != OK) {
746 delete fInfo;
747 return rv;
750 fNameIter.reset();
751 while (fNameIter.hasElement())
752 delete (Identifier *) fNameIter.nextElement();
753 fNameList.reset();
754 delete fInfo;
755 return OK;
758 DbRetVal SelStatement::setBindFieldAndValues()
760 totalFields = parsedData->getFieldNameList().size();
761 bindFields = (FieldValue**) malloc ( totalFields * sizeof(FieldValue*));
762 bindFieldValues = (char**) malloc( totalFields * sizeof(char*));
763 memset(bindFields, 0, totalFields * sizeof(FieldValue*));
764 memset(bindFieldValues, 0, totalFields * sizeof(char*));
765 ListIterator valIter = parsedData->getFieldValueList().getIterator();
766 int colNo =0;
767 FieldValue *value = NULL;
768 //The second condition colNo < totalFields is important for projection list
769 //might not contain the binded having field.
770 while(valIter.hasElement() && colNo < totalFields)
772 value = (FieldValue*) valIter.nextElement();
773 if (value == NULL)
775 free(bindFields); bindFields = NULL;
776 free(bindFieldValues); bindFieldValues = NULL;
777 printError(ErrSysFatal, "Should never happen. value NULL after iteration");
778 return ErrSysFatal;
780 bindFields[colNo++] = value;
782 return OK;
786 DbRetVal SelStatement::resolveForCondition()
788 //get the fieldname list and validate field names
789 ListIterator iter = parsedData->getConditionValueList().getIterator();
791 ConditionValue *value;
792 FieldInfo *fInfo = new FieldInfo();
793 int paramPos =1;
794 DbRetVal rv = OK;
795 while (iter.hasElement())
797 value = (ConditionValue*) iter.nextElement();
798 if (NULL == value)
800 delete fInfo;
801 printError(ErrSysFatal, "Should never happen.");
802 return ErrSysFatal;
804 rv = table->getFieldInfo(value->fName, fInfo);
805 if (ErrNotFound == rv || ErrNotExists == rv)
807 delete fInfo;
808 printError(ErrSyntaxError, "Field %s does not exist in table",
809 value->fName);
810 return ErrSyntaxError;
812 if (value->aType == AGG_AVG) {
813 value->type = typeDouble;
814 value->length = sizeof(double);
815 } else if (value->aType == AGG_COUNT) {
816 value->type = typeInt;
817 value->length = sizeof(int);
818 } else {
819 value->type = fInfo->type;
820 value->length = fInfo->length;
822 value->isNullable = fInfo->isNull;
823 value->value = AllDataType::alloc(value->type, value->length);
824 //table->bindFld(name->fldName, value->value);
825 if(value->paramNo ==1) continue;//For Predecate t1.f1=t2.f1
826 if (value->parsedString == NULL)
828 delete fInfo;
829 printError(ErrSyntaxError, "Condition value should not be NULL");
830 return ErrSyntaxError;
832 if (value->parsedString[0] == '?')
834 //if(!value->opLike) // checks if 'LIKE' operator is used
835 value->paramNo = paramPos++;
837 if (!value->paramNo) {
838 // for valid Integer
839 if((value->type == typeInt) || (value->type==typeShort) || (value->type==typeByteInt) || (value->type==typeLongLong) || (value->type==typeLong)){
840 int len=strlen(value->parsedString);
841 for(int n=0;n<len;n++){
842 int p=value->parsedString[n];
843 if(!(p>=48 && p<=57 || p==45))
844 return ErrBadArg;
848 // Here for binary dataType it is not strcpy'd bcos internally memcmp is done for predicates like f2 = 'abcd' where f2 is binary
849 AllDataType::strToValue(value->value, value->parsedString, value->type, value->length);
852 delete fInfo;
853 totalParams = paramPos -1;
854 if (0 == totalParams) return OK;
855 params = (void**) malloc ( totalParams * sizeof(FieldValue*));
856 paramValues = (char**) malloc( totalParams * sizeof(char*));
857 memset(params, 0, totalParams * sizeof(FieldValue*));
858 memset(paramValues, 0, totalParams * sizeof(char*));
859 iter.reset();
860 while(iter.hasElement())
862 value = (ConditionValue*) iter.nextElement();
863 if (value == NULL)
865 free(params); params = NULL;
866 free(paramValues); paramValues = NULL;
867 printError(ErrSysFatal, "Should never happen. value NULL after iteration");
868 return ErrSysFatal;
870 params[value->paramNo -1 ] = value;
872 return OK;
874 bool SelStatement::isGroupFld(char *fieldName)
876 ListIterator giter = parsedData->getGroupFieldNameList().getIterator();
877 FieldName *name = NULL;
878 while (giter.hasElement())
880 name = (FieldName*) giter.nextElement();
881 if (0 == strcmp(name->fldName, fieldName)) return true;
883 return false;
886 void* SelStatement::handleSingleTableAggWithoutGroup()
888 if (isPointReturned) return NULL;
889 TableImpl *tblImpl = (TableImpl*)table;
890 ListIterator iter = parsedData->getFieldNameList().getIterator();
891 int i=0;
892 DbRetVal rv = OK;
893 FieldName *name;
894 FieldValue *fVal = NULL;
895 bool noRec = false;
896 while (iter.hasElement())
898 name = (FieldName*) iter.nextElement();
899 fVal = bindFields[i];
901 rv = tblImpl->fetchAgg(name->fldName, name->aType, fVal->value, noRec);
902 if (OK != rv) return NULL;
903 i++;
904 tblImpl->closeScan();
905 tblImpl->execute();
907 isPointReturned = true;
908 if(noRec && name->aType != AGG_COUNT) return NULL;
909 return fVal;
911 void* SelStatement::fetch()
913 void *tuple = NULL;
914 if(handleAggWithTbl)
916 tuple = handleSingleTableAggWithoutGroup();
917 if (NULL == tuple) return NULL;
918 }else {
919 if (isOffsetReached) {
920 if (!isRecLimitReached) {
921 tuple = table->fetch();
922 if (NULL != tuple) numRecords++;
923 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
926 else {
927 int recordOffset =0;
928 while(recordOffset <= parsedData->getOffset()) {
929 tuple = table->fetch();
930 if (NULL == tuple) break;
931 recordOffset++;
933 isOffsetReached = true;
934 if (NULL != tuple) numRecords++;
935 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
938 if (NULL == tuple) return NULL;
940 //copy values to binded buffer
941 FieldValue *value;
942 for (int i = 0; i < totalFields; i++)
944 value = bindFields[i];
945 if (bindFieldValues[i] == NULL)
947 printError(ErrBadCall, "Fields are not binded properly. Should never happen");
948 return NULL;
950 AllDataType::copyVal(bindFieldValues[i], value->value, value->type, value->length);
952 return tuple;
955 void* SelStatement::fetch(DbRetVal &rv)
957 void *tuple = NULL;
958 if(handleAggWithTbl)
960 tuple = handleSingleTableAggWithoutGroup();
961 if (NULL == tuple) return NULL;
962 }else {
963 if (isOffsetReached) {
964 if (!isRecLimitReached) {
965 tuple = table->fetch(rv);
966 if (NULL != tuple) numRecords++;
967 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
969 } else {
970 int recordOffset =0;
971 while(recordOffset <= parsedData->getOffset()) {
972 tuple = table->fetch(rv);
973 if (NULL == tuple) break;
974 recordOffset++;
976 isOffsetReached = true;
977 if (NULL != tuple) numRecords++;
978 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
981 if (NULL == tuple) return NULL;
982 //copy values to binded buffer
983 FieldValue *value;
984 for (int i = 0; i < totalFields; i++)
986 value = bindFields[i];
987 if (bindFieldValues[i] == NULL)
989 printError(ErrBadCall, "Fields are not binded properly. Should never happen %d", i);
990 return NULL;
992 AllDataType::copyVal(bindFieldValues[i], value->value, value->type, value->length);
994 return tuple;
997 DbRetVal SelStatement::close()
999 isPointReturned = false;
1000 if (table) return table->closeScan();
1001 else return OK;
1004 void* SelStatement::getParamValuePtr( int pos )
1006 ConditionValue *p = (ConditionValue*) params [pos-1];
1007 return ( (void*) p->value );
1010 char* SelStatement::getFieldName ( int pos )
1012 //TODO::if not yet prepared return error
1013 //TODO::check the upper limit for projpos
1014 ListIterator iter = parsedData->getFieldNameList().getIterator();
1015 int position = 1;
1016 while (iter.hasElement())
1018 FieldName *name = (FieldName*) iter.nextElement();
1019 if (position == pos) {
1020 if (NULL == name)
1022 printError(ErrSysFatal, "Should never happen. Field Name list has NULL");
1023 return (char*) 0;
1025 return name->fldName;
1027 position++;
1029 return (char*) 0;
1032 DataType SelStatement::getFieldType( int pos )
1034 FieldValue *v = bindFields[pos];
1035 return ( (DataType) v->type );
1038 int SelStatement::getFieldLength( int pos )
1040 FieldValue *v = bindFields[pos];
1041 return ( (int) v->type );
1044 void* SelStatement::fetchAndPrint(bool SQL)
1046 void *tuple = NULL;
1047 if(handleAggWithTbl)
1049 tuple = handleSingleTableAggWithoutGroup();
1050 }else {
1051 if (isOffsetReached) {
1052 if (!isRecLimitReached) {
1053 tuple = table->fetch();
1054 if (NULL != tuple) numRecords++;
1055 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
1058 else {
1059 int recordOffset =0;
1060 while(recordOffset <= parsedData->getOffset()) {
1061 tuple = table->fetch();
1062 if (NULL == tuple) break;
1063 recordOffset++;
1065 isOffsetReached = true;
1066 if (NULL != tuple) numRecords++;
1067 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
1070 if (NULL == tuple) return NULL;
1071 FieldValue *value;
1072 bool nullValueSet;
1073 char stmt[128];
1074 if (SQL) {
1075 sprintf(stmt, "INSERT INTO %s VALUES(", table->getName());
1076 printf("%s", stmt);
1078 for (int i = 0; i < totalFields; i++)
1080 value = bindFields[i];
1081 if (!value->isInResSet) continue;
1082 nullValueSet = table->isFldNull(value->fldName);
1083 if (nullValueSet) {
1084 if (SQL) {
1085 if (i==0)
1086 printf("NULL");
1087 else
1088 printf(", NULL");
1090 else if (value->aType != AGG_COUNT) printf("NULL\t");
1091 else printf("0\t");
1093 else {
1094 if (SQL) {
1095 switch(value->type)
1097 case typeString:
1098 case typeBinary:
1099 case typeDate:
1100 case typeTime:
1101 case typeTimeStamp:
1103 if (i==0)
1104 printf(" '");
1105 else
1106 printf(", '");
1107 break;
1109 default:
1111 if (i!=0)
1112 printf(",");
1116 AllDataType::printVal(value->value, value->type, value->length);
1117 if (SQL) {
1118 switch(value->type)
1120 case typeString:
1121 case typeBinary:
1122 case typeDate:
1123 case typeTime:
1124 case typeTimeStamp:
1125 printf("'");
1127 } else printf("\t");
1130 if (SQL) printf(");\n");
1131 return tuple;
1134 void* SelStatement::next()
1136 if(handleAggWithTbl)
1138 return handleSingleTableAggWithoutGroup();
1140 return( table->fetch() );
1144 void* SelStatement::getFieldValuePtr( int pos )
1146 FieldValue *v = bindFields[pos];
1147 return ( (void*) v->value );
1150 void* SelStatement::getFieldValuePtr( char *name )
1152 FieldValue *value;
1153 char fName[IDENTIFIER_LENGTH];
1154 for (int i = 0; i < totalFields; i++)
1156 value = bindFields[i];
1157 table->getFieldNameAlone(value->fldName,fName);
1158 if (strcmp(fName,name)==0)
1160 return ( (void*) value->value );
1164 return NULL;
1166 void SelStatement::getProjFieldType(int *data)
1168 FieldValue *value;
1169 for (int i = 0; i < totalFields; i++)
1171 value = bindFields[i];
1172 data[i+1] = value->type;
1176 int SelStatement::noOfProjFields()
1178 return totalFields;
1181 DbRetVal SelStatement::getProjFldInfo (int projpos, FieldInfo *&fInfo)
1184 DbRetVal rv = OK;
1185 //TODO::if not yet prepared return error
1186 //TODO::check the upper limit for projpos
1187 if (projpos < 0 || projpos >totalFields) return ErrBadArg;
1188 FieldValue *value = bindFields[projpos-1];
1189 fInfo->type = value->type;
1190 fInfo->length= value->length;
1191 fInfo->isNull = value->isNullable;
1192 fInfo->aType = value->aType;
1193 fInfo->offset = value->offset;
1194 fInfo->isPrimary = value->isPrimary;
1195 fInfo->isUnique = value->isUnique;
1196 fInfo->isAutoIncrement= value->isAutoIncrement;
1197 fInfo->isDefault = value->isDefault;
1198 if (fInfo->aType == AGG_UNKNOWN) {
1199 strcpy(fInfo->fldName, value->fldName);
1200 if (fInfo->isDefault) strcpy(fInfo->defaultValueBuf, value->defValBuf);
1201 return OK;
1203 switch(fInfo->aType)
1205 case AGG_COUNT:
1206 sprintf(fInfo->fldName, "COUNT(%s)", value->fldName);
1207 fInfo->type = typeInt;
1208 fInfo->length = sizeof(int);
1209 break;
1210 case AGG_MIN:
1211 sprintf(fInfo->fldName, "MIN(%s)", value->fldName);
1212 break;
1213 case AGG_MAX:
1214 sprintf(fInfo->fldName, "MAX(%s)", value->fldName);
1215 break;
1216 case AGG_SUM:
1217 sprintf(fInfo->fldName, "SUM(%s)", value->fldName);
1218 break;
1219 case AGG_AVG:
1220 sprintf(fInfo->fldName, "AVG(%s)", value->fldName);
1221 fInfo->type = typeDouble;
1222 fInfo->length = sizeof(double);
1223 break;
1224 default:
1225 strcpy(fInfo->fldName, value->fldName);
1226 break;
1228 return rv;
1230 int SelStatement::getFldPos(char *name)
1232 return table->getFldPos(name);
1235 bool SelStatement::isInProjectionList(char *name, AggType aType)
1237 ListIterator iter = parsedData->getFieldNameList().getIterator();
1238 FieldName *fldName = NULL;
1239 while (iter.hasElement()) {
1240 fldName = (FieldName*) iter.nextElement();
1241 if ((strcmp(fldName->fldName, name)==0) && fldName->aType == aType) {
1242 return true;
1245 return false;