Bug fix: explain plan followed by simple select display the query plan
[csql.git] / src / sql / SelStatement.cxx
blob3586f26fcb04050db8f055041a5d13fc938ec05d
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 isMixPrjList = false;
341 bool isAggFld = false;
342 bool isNotAggFld = false;
343 bool isSingleTableNoGrp = false;
344 bool isGroupFld = false;
345 if(parsedData->getTableNameList().size() == 1 &&
346 parsedData->getGroupFieldNameList().size() == 0)
348 isSingleTableNoGrp = true;
350 AggTableImpl *aggTable = NULL;
351 while (iter.hasElement())
353 name = (FieldName*)iter.nextElement();
354 if (NULL == name)
356 dbMgr->closeTable(table);
357 table = NULL;
358 delete fInfo;
359 printError(ErrSysFatal, "Should never happen. Field Name list has NULL");
360 return ErrSysFatal;
362 bool isBindFld=false;
363 if ('*' == name->fldName[0] && name->aType == AGG_UNKNOWN)
365 rv = resolveStar();
366 if (rv != OK)
368 dbMgr->closeTable(table);
369 table = NULL;
370 delete fInfo;
371 return rv;
373 if (parsedData->getGroupFieldNameList().size()!= 0
374 && !isSingleTableNoGrp)
376 if (!aggTable)
377 aggTable = new AggTableImpl();
378 aggTable->setTable(table);
380 //as soon as it encounters *, it breaks the loop negleting other field names
381 //as they all are deleted during resolveStar method.
382 break;
383 } else {
384 if ('*' == name->fldName[0] && name->aType != AGG_COUNT) {
385 return ErrSyntaxError;
387 rv = table->getFieldInfo(name->fldName, fInfo);
388 if (ErrNotFound == rv || ErrNotExists == rv)
390 if (aggTable) { delete aggTable; aggTable = NULL; }
391 else dbMgr->closeTable(table);
392 table = NULL;
393 delete fInfo;
394 printError(ErrSyntaxError, "Field %s does not exist in table",
395 name->fldName);
396 return ErrSyntaxError;
398 FieldValue *newVal = new FieldValue();
399 strcpy(newVal->fldName,name->fldName);
400 newVal->parsedString = NULL;
401 newVal->paramNo = 0;
402 newVal->aType = name->aType;
403 if (!isMixPrjList) {
404 if (newVal->aType != AGG_UNKNOWN) isAggFld = true;
405 else isNotAggFld = true;
406 if (isAggFld && isNotAggFld) isMixPrjList = true;
408 newVal->isInResSet = true;
409 newVal->offset = fInfo->offset;
410 newVal->isPrimary = fInfo->isPrimary;
411 newVal->isUnique = fInfo->isUnique;
412 newVal->isAutoIncrement = fInfo->isAutoIncrement;
413 newVal->isDefault = fInfo->isDefault;
414 if (newVal->isDefault)
415 strcpy(newVal->defValBuf, fInfo->defaultValueBuf);
416 else newVal->defValBuf[0]='\0';
418 if (name->aType == AGG_COUNT) {
419 newVal->type = typeInt;
420 newVal->length = sizeof(int);
422 else if (name->aType == AGG_AVG) {
423 newVal->type = typeDouble;
424 newVal->length = sizeof(double);
425 if (!AllDataType::isValidFieldForAvg(fInfo->type)) {
426 printError(ErrBadArg, "Illegal operation for field %s",
427 fInfo->fldName);
428 dbMgr->closeTable(table);
429 if (aggTable) { delete aggTable; aggTable = NULL; }
430 table = NULL;
431 delete fInfo;
432 return ErrBadArg;
435 else {
436 newVal->type = fInfo->type;
437 newVal->length = fInfo->length;
439 newVal->isNullable = fInfo->isNull;
440 FieldName *bFldName=NULL;
441 ListIterator it = bindFldList.getIterator();
442 while (it.hasElement())
444 bFldName = (FieldName*)it.nextElement();
445 if(0==strcmp(bFldName->fldName,name->fldName) &&
446 name->aType == AGG_UNKNOWN)
448 newVal->value=table->getBindFldAddr(name->fldName);
449 newVal->isAllocVal=false;
450 isBindFld=true;
451 break;
454 if (!isBindFld) {
455 if ( name->aType == AGG_UNKNOWN ||
456 (name->aType != AGG_COUNT &&
457 name->aType != AGG_AVG) ) {
458 if(newVal->type == typeBinary)
459 newVal->value = AllDataType::alloc(fInfo->type,
460 2 * fInfo->length);
461 else newVal->value = AllDataType::alloc(fInfo->type,
462 fInfo->length);
463 } else {
464 if (name->aType == AGG_AVG) {
465 newVal->value = AllDataType::alloc(typeDouble,
466 sizeof(double));
467 memset(newVal->value, 0, sizeof(double));
469 else if (name->aType == AGG_COUNT) {
470 newVal->value = AllDataType::alloc(typeInt,
471 sizeof(int));
472 memset(newVal->value, 0, sizeof(int));
476 newVal->isAllocVal=true;
478 if (name->aType ==AGG_UNKNOWN &&
479 parsedData->getGroupFieldNameList().size()== 0) {
480 rv = table->bindFld(name->fldName, newVal->value);
481 if (OK !=rv) {
482 if (newVal->isAllocVal) free(newVal->value);
483 delete newVal;
484 delete fInfo;
485 return rv;
488 else if (!isSingleTableNoGrp)
490 if (!aggTable) {
491 aggTable = new AggTableImpl();
492 aggTable->setTable(table);
494 rv = aggTable->bindFld(name->fldName, name->aType, newVal->value);
495 if (OK !=rv) {
496 if (newVal->isAllocVal) free(newVal->value);
497 delete newVal; delete fInfo; delete aggTable;
498 aggTable = NULL; table = NULL;
499 return rv;
502 if (name->aType !=AGG_UNKNOWN && isSingleTableNoGrp)
503 handleAggWithTbl= true;
504 parsedData->insertFieldValue(newVal);
506 if (!isBindFld) bindFldList.append(name);
508 bindFldList.reset();
510 //Check if the having list is present in projection list or not.
511 //If not present bind here not to be printed in fetchAndPrint later.
512 ListIterator hiter = parsedData->getHavingFieldNameList().getIterator();
513 while (hiter.hasElement()) {
514 FieldName *fnm = (FieldName *) hiter.nextElement();
515 rv = table->getFieldInfo(fnm->fldName, fInfo);
516 if (!isInProjectionList(fnm->fldName, fnm->aType)) {
517 FieldValue *newVal = new FieldValue();
518 strcpy(newVal->fldName,fnm->fldName);
519 newVal->parsedString = NULL;
520 newVal->paramNo = 0;
521 newVal->aType = fnm->aType;
522 newVal->isInResSet = false;
523 newVal->isNullable = fInfo->isNull;
524 newVal->offset = fInfo->offset;
525 newVal->isPrimary = fInfo->isPrimary;
526 newVal->isUnique = fInfo->isUnique;
527 newVal->isAutoIncrement = fInfo->isAutoIncrement;
528 if (fnm->aType == AGG_AVG) {
529 newVal->value = AllDataType::alloc(typeDouble, sizeof(double));
530 memset(newVal->value, 0, sizeof(double));
531 } else if (fnm->aType == AGG_COUNT) {
532 newVal->value = AllDataType::alloc(typeInt, sizeof(int));
533 memset(newVal->value, 0, sizeof(int));
534 } else {
535 newVal->value = AllDataType::alloc(fInfo->type, fInfo->length);
536 memset(newVal->value, 0, fInfo->length);
538 newVal->isAllocVal = true;
539 parsedData->insertFieldValue(newVal);
540 aggTable->bindFld(fnm->fldName, fnm->aType, newVal->value);
544 rv = setBindFieldAndValues();
545 if (rv != OK)
547 delete fInfo;
548 if (aggTable) { delete aggTable; aggTable = NULL; }
549 else dbMgr->closeTable(table);
550 table = NULL;
551 return rv;
554 table->setCondition(parsedData->getCondition());
556 rv = resolveForCondition();
557 if (rv != OK)
559 delete fInfo;
560 //TODO::free memory allocated for params
561 if (aggTable) { delete aggTable; aggTable = NULL; }
562 else {
563 table->setCondition(NULL);
564 dbMgr->closeTable(table);
566 table = NULL;
567 return rv;
569 if (NULL == parsedData->getCondition()) parsedData->setCacheWorthy(false);
570 rv = resolveGroupFld(aggTable, isGroupFld);
571 if (rv != OK)
573 delete fInfo;
574 //TODO::free memory allocated for params
575 if (aggTable) { delete aggTable; aggTable = NULL; }
576 else if (table)
578 table->setCondition(NULL);
579 dbMgr->closeTable(table);
581 table = NULL;
582 return rv;
584 if (isMixPrjList && ! isGroupFld) {
585 printError(ErrSyntax, "Group By Field required.");
586 delete fInfo;
587 if (aggTable) { delete aggTable; aggTable = NULL; }
588 else if (table)
590 table->setCondition(NULL);
591 dbMgr->closeTable(table);
593 table = NULL;
594 return ErrSyntax;
597 rv = resolveOrderByFld();
598 if (rv != OK)
600 delete fInfo;
601 delete table;
602 table = NULL;
603 return rv;
605 rv = resolveDistinct();
606 delete fInfo;
607 if(parsedData->getExplain()) isExplain = true;
608 else
609 isExplain= false;
610 return rv;
612 DbRetVal SelStatement::resolveDistinct()
614 if (!parsedData->getDistinct()) {
615 return OK;
617 OrderTableImpl *orderTable = new OrderTableImpl();
618 orderTable->setTable(table);
619 orderTable->setProjList(parsedData->getFieldValueList());
620 orderTable->setOrderByList(parsedData->getFieldValueList());
621 orderTable->setDistinct();
622 table = orderTable;
623 handleAggWithTbl= false;
624 return OK;
628 DbRetVal SelStatement::resolveOrderByFld()
630 if (0 == parsedData->getOrderFieldNameList().size()) {
631 return OK;
633 OrderTableImpl *orderTable = new OrderTableImpl();
634 orderTable->setTable(table);
635 orderTable->setProjList(parsedData->getFieldValueList());
636 ListIterator giter = parsedData->getOrderFieldNameList().getIterator();
637 FieldName *name = NULL;
638 DbRetVal rv = OK;
639 FieldInfo *fInfo = new FieldInfo();
640 while (giter.hasElement())
642 name = (FieldName*)giter.nextElement();
643 rv = table->getFieldInfo(name->fldName, fInfo);
644 if (ErrNotFound == rv || ErrNotExists == rv)
646 delete fInfo;
647 printError(ErrSyntaxError, "Field %s does not exist in table",
648 name->fldName);
649 return ErrSyntaxError;
651 /*FieldValue *newVal = new FieldValue();
652 strcpy(newVal->fldName,name->fldName);
653 newVal->parsedString = NULL;
654 newVal->paramNo = 0;
655 newVal->type = fInfo->type;
656 newVal->isNullable = fInfo->isNull;
657 newVal->length = fInfo->length;
658 if (newVal->type == typeBinary)
659 newVal->value = AllDataType::alloc(fInfo->type, 2 * fInfo->length);
660 else newVal->value = AllDataType::alloc(fInfo->type, fInfo->length);
661 newVal->isAllocVal=true;
662 parsedData->insertFieldValue(newVal);
664 if (name->aType == AGG_UNKNOWN) orderTable->setOrderBy(name->fldName);
665 else orderTable->setOrderBy(name->fldName, true); //descending
667 delete fInfo;
668 table = orderTable;
669 handleAggWithTbl= false;
670 return OK;
673 DbRetVal SelStatement::resolveGroupFld(AggTableImpl *aggTable, bool &isGrpFld)
675 if (!aggTable) return OK;
677 //check whether all non aggregate projections are from group list
678 ListIterator iter = parsedData->getFieldNameList().getIterator();
679 ListIterator giter = parsedData->getGroupFieldNameList().getIterator();
680 FieldName *name = NULL;
681 while (iter.hasElement())
683 name = (FieldName*) iter.nextElement();
684 if (name->aType == AGG_UNKNOWN && !isGroupFld(name->fldName) ) {
685 printError(ErrSyntaxError,
686 "Non aggregate projection contains non group field: %s",
687 name->fldName);
688 return ErrSyntaxError;
692 DbRetVal rv = OK;
693 FieldInfo *fInfo = new FieldInfo();
694 while (giter.hasElement())
696 name = (FieldName*)giter.nextElement();
697 rv = table->getFieldInfo(name->fldName, fInfo);
698 if (ErrNotFound == rv || ErrNotExists == rv)
700 delete fInfo;
701 printError(ErrSyntaxError, "Field %s does not exist in table",
702 name->fldName);
703 return ErrSyntaxError;
705 FieldValue *newVal = new FieldValue();
706 strcpy(newVal->fldName,name->fldName);
707 newVal->parsedString = NULL;
708 newVal->paramNo = 0;
709 newVal->type = fInfo->type;
710 newVal->isNullable = fInfo->isNull;
711 newVal->length = fInfo->length;
712 newVal->offset = fInfo->offset;
713 newVal->isPrimary = fInfo->isPrimary;
714 newVal->isUnique = fInfo->isUnique;
715 newVal->isAutoIncrement = fInfo->isAutoIncrement;
716 if (newVal->type == typeBinary)
717 newVal->value = AllDataType::alloc(fInfo->type, 2 * fInfo->length);
718 else newVal->value = AllDataType::alloc(fInfo->type, fInfo->length);
719 newVal->isAllocVal=true;
720 parsedData->insertFieldValue(newVal);
721 aggTable->setGroup(name->fldName, newVal->value);
723 delete fInfo;
724 aggTable->setCondition(parsedData->getHavingCondition());
725 /*if (giter.hasElement())
727 printError(ErrSyntaxError, "Only one field allowed in group\n");
728 return ErrSyntaxError;
730 table = aggTable;
731 isGrpFld = true;
732 return OK;
735 DbRetVal SelStatement::resolveStar()
737 DbRetVal rv = OK;
738 parsedData->clearFieldNameList();
739 FieldValue *newVal = NULL;
740 List fNameList = table->getFieldNameList();
741 ListIterator fNameIter = fNameList.getIterator();
742 //fNameList.resetIter(); //do not remove this.
743 FieldInfo *fInfo = new FieldInfo();
744 for (int i = 0; i < fNameList.size() ; i++)
746 char *fName = ((Identifier*)(fNameIter.nextElement()))->name;
747 rv = table->getFieldInfo(fName, fInfo);
748 if (ErrNotFound == rv || ErrNotExists == rv)
750 delete fInfo;
751 fNameList.reset();
752 printError(ErrSysFatal, "Should never happen.");
753 return ErrSysFatal;
755 newVal = new FieldValue();
756 strcpy(newVal->fldName,fName);
757 newVal->parsedString = NULL;
758 newVal->paramNo = 0;
759 newVal->type = fInfo->type;
760 newVal->length = fInfo->length;
761 newVal->offset = fInfo->offset;
762 newVal->isPrimary = fInfo->isPrimary;
763 newVal->isUnique = fInfo->isUnique;
764 newVal->isAutoIncrement = fInfo->isAutoIncrement;
766 // for binary datatype input buffer size should be 2 times the length
767 if(newVal->type == typeBinary)
768 newVal->value = AllDataType::alloc(fInfo->type, 2 * fInfo->length);
769 else newVal->value = AllDataType::alloc(fInfo->type, fInfo->length);
770 newVal->isAllocVal=true;
771 newVal->isInResSet = true;
772 parsedData->insertFieldValue(newVal);
773 parsedData->insertField(fName);
774 rv = table->bindFld(fName, newVal->value);
775 if (rv != OK) {
776 delete fInfo;
777 return rv;
780 fNameIter.reset();
781 while (fNameIter.hasElement())
782 delete (Identifier *) fNameIter.nextElement();
783 fNameList.reset();
784 delete fInfo;
785 return OK;
788 DbRetVal SelStatement::setBindFieldAndValues()
790 totalFields = parsedData->getFieldNameList().size();
791 bindFields = (FieldValue**) malloc ( totalFields * sizeof(FieldValue*));
792 bindFieldValues = (char**) malloc( totalFields * sizeof(char*));
793 memset(bindFields, 0, totalFields * sizeof(FieldValue*));
794 memset(bindFieldValues, 0, totalFields * sizeof(char*));
795 ListIterator valIter = parsedData->getFieldValueList().getIterator();
796 int colNo =0;
797 FieldValue *value = NULL;
798 //The second condition colNo < totalFields is important for projection list
799 //might not contain the binded having field.
800 while(valIter.hasElement() && colNo < totalFields)
802 value = (FieldValue*) valIter.nextElement();
803 if (value == NULL)
805 free(bindFields); bindFields = NULL;
806 free(bindFieldValues); bindFieldValues = NULL;
807 printError(ErrSysFatal, "Should never happen. value NULL after iteration");
808 return ErrSysFatal;
810 bindFields[colNo++] = value;
812 return OK;
816 DbRetVal SelStatement::resolveForCondition()
818 //get the fieldname list and validate field names
819 ListIterator iter = parsedData->getConditionValueList().getIterator();
821 ConditionValue *value;
822 FieldInfo *fInfo = new FieldInfo();
823 int paramPos =1;
824 DbRetVal rv = OK;
825 while (iter.hasElement())
827 value = (ConditionValue*) iter.nextElement();
828 if (NULL == value)
830 delete fInfo;
831 printError(ErrSysFatal, "Should never happen.");
832 return ErrSysFatal;
834 if(!value->isFunctionInvolve){
835 rv = table->getFieldInfo(value->fName, fInfo);
836 if (ErrNotFound == rv || ErrNotExists == rv)
838 delete fInfo;
839 printError(ErrSyntaxError, "Field %s does not exist in table",
840 value->fName);
841 return ErrSyntaxError;
843 if (value->aType == AGG_AVG) {
844 value->type = typeDouble;
845 value->length = sizeof(double);
846 } else if (value->aType == AGG_COUNT) {
847 value->type = typeInt;
848 value->length = sizeof(int);
849 } else {
850 value->type = fInfo->type;
851 value->length = fInfo->length;
853 value->isNullable = fInfo->isNull;
854 }else{
855 value->type = AllDataType::getCsqlTypeFromFunctionTypeForComparision(parsedData->getFunctionType());
857 value->value = AllDataType::alloc(value->type, value->length);
858 //table->bindFld(name->fldName, value->value);
859 if(value->paramNo ==1) continue;//For Predecate t1.f1=t2.f1
860 if (value->parsedString == NULL)
862 delete fInfo;
863 printError(ErrSyntaxError, "Condition value should not be NULL");
864 return ErrSyntaxError;
866 if (value->parsedString[0] == '?')
868 value->paramNo = paramPos++;
870 if (!value->paramNo) {
871 // for valid Integer
872 if (value->type == typeDate || value->type == typeTime ||
873 value->type == typeTimeStamp)
874 parsedData->setCacheWorthy(false);
875 if((value->type == typeInt) || (value->type==typeShort) ||
876 (value->type==typeByteInt) || (value->type==typeLongLong) ||
877 (value->type==typeLong)) {
878 int len=strlen(value->parsedString);
879 for(int n=0;n<len;n++){
880 int p=value->parsedString[n];
881 if(!(p>=48 && p<=57 || p==45)) return ErrBadArg;
885 // Here for binary dataType it is not strcpy'd bcos internally memcmp is done for predicates like f2 = 'abcd' where f2 is binary
886 AllDataType::strToValue(value->value, value->parsedString, value->type, value->length);
889 delete fInfo;
890 totalParams = paramPos -1;
891 if (0 == totalParams) return OK;
892 params = (void**) malloc ( totalParams * sizeof(FieldValue*));
893 paramValues = (char**) malloc( totalParams * sizeof(char*));
894 memset(params, 0, totalParams * sizeof(FieldValue*));
895 memset(paramValues, 0, totalParams * sizeof(char*));
896 iter.reset();
897 while(iter.hasElement())
899 value = (ConditionValue*) iter.nextElement();
900 if (value == NULL)
902 free(params); params = NULL;
903 free(paramValues); paramValues = NULL;
904 printError(ErrSysFatal, "Should never happen. value NULL after iteration");
905 return ErrSysFatal;
907 if (value->paramNo) params[value->paramNo - 1] = value;
909 return OK;
911 bool SelStatement::isGroupFld(char *fieldName)
913 ListIterator giter = parsedData->getGroupFieldNameList().getIterator();
914 FieldName *name = NULL;
915 while (giter.hasElement())
917 name = (FieldName*) giter.nextElement();
918 if (0 == strcmp(name->fldName, fieldName)) return true;
920 return false;
923 void* SelStatement::handleSingleTableAggWithoutGroup()
925 if (isPointReturned) return NULL;
926 TableImpl *tblImpl = (TableImpl*)table;
927 ListIterator iter = parsedData->getFieldNameList().getIterator();
928 int i=0;
929 DbRetVal rv = OK;
930 FieldName *name;
931 FieldValue *fVal = NULL;
932 bool noRec = false;
933 while (iter.hasElement())
935 name = (FieldName*) iter.nextElement();
936 fVal = bindFields[i];
938 rv = tblImpl->fetchAgg(name->fldName, name->aType, fVal->value, noRec);
939 if (OK != rv) return NULL;
940 i++;
941 tblImpl->closeScan();
942 tblImpl->execute();
944 isPointReturned = true;
945 if(noRec && name->aType != AGG_COUNT) return NULL;
946 return fVal;
948 void* SelStatement::fetch()
950 void *tuple = NULL;
951 if(handleAggWithTbl)
953 tuple = handleSingleTableAggWithoutGroup();
954 if (NULL == tuple) return NULL;
955 }else {
956 if (isOffsetReached) {
957 if (!isRecLimitReached) {
958 tuple = table->fetch();
959 if (NULL != tuple) numRecords++;
960 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
963 else {
964 int recordOffset =0;
965 while(recordOffset <= parsedData->getOffset()) {
966 tuple = table->fetch();
967 if (NULL == tuple) break;
968 recordOffset++;
970 isOffsetReached = true;
971 if (NULL != tuple) numRecords++;
972 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
975 if (NULL == tuple) return NULL;
977 //copy values to binded buffer
978 FieldValue *value;
979 for (int i = 0; i < totalFields; i++)
981 value = bindFields[i];
982 if (bindFieldValues[i] == NULL)
984 printError(ErrBadCall, "Fields are not binded properly. Should never happen");
985 return NULL;
987 AllDataType::copyVal(bindFieldValues[i], value->value, value->type, value->length);
989 return tuple;
992 void* SelStatement::fetch(DbRetVal &rv)
994 void *tuple = NULL;
995 if(handleAggWithTbl)
997 tuple = handleSingleTableAggWithoutGroup();
998 if (NULL == tuple) return NULL;
999 }else {
1000 if (isOffsetReached) {
1001 if (!isRecLimitReached) {
1002 tuple = table->fetch(rv);
1003 if (NULL != tuple) numRecords++;
1004 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
1006 } else {
1007 int recordOffset =0;
1008 while(recordOffset <= parsedData->getOffset()) {
1009 tuple = table->fetch(rv);
1010 if (NULL == tuple) break;
1011 recordOffset++;
1013 isOffsetReached = true;
1014 if (NULL != tuple) numRecords++;
1015 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
1018 if (NULL == tuple) return NULL;
1019 //copy values to binded buffer
1020 FieldValue *value;
1021 for (int i = 0; i < totalFields; i++)
1023 value = bindFields[i];
1024 if (bindFieldValues[i] == NULL)
1026 printError(ErrBadCall, "Fields are not binded properly. Should never happen %d", i);
1027 return NULL;
1029 AllDataType::copyVal(bindFieldValues[i], value->value, value->type, value->length);
1031 return tuple;
1034 DbRetVal SelStatement::close()
1036 isPointReturned = false;
1037 isExplain = false;
1038 if (table) return table->closeScan();
1039 else return OK;
1042 void* SelStatement::getParamValuePtr( int pos )
1044 ConditionValue *p = (ConditionValue*) params [pos-1];
1045 return ( (void*) p->value );
1048 char* SelStatement::getFieldName ( int pos )
1050 //TODO::if not yet prepared return error
1051 //TODO::check the upper limit for projpos
1052 ListIterator iter = parsedData->getFieldNameList().getIterator();
1053 int position = 1;
1054 while (iter.hasElement())
1056 FieldName *name = (FieldName*) iter.nextElement();
1057 if (position == pos) {
1058 if (NULL == name)
1060 printError(ErrSysFatal, "Should never happen. Field Name list has NULL");
1061 return (char*) 0;
1063 return name->fldName;
1065 position++;
1067 return (char*) 0;
1070 DataType SelStatement::getFieldType( int pos )
1072 FieldValue *v = bindFields[pos];
1073 return ( (DataType) v->type );
1076 int SelStatement::getFieldLength( int pos )
1078 FieldValue *v = bindFields[pos];
1079 return ( (int) v->type );
1082 void* SelStatement::fetchAndPrint(bool SQL)
1084 void *tuple = NULL;
1085 if(handleAggWithTbl)
1087 tuple = handleSingleTableAggWithoutGroup();
1088 }else {
1089 if (isOffsetReached) {
1090 if (!isRecLimitReached) {
1091 tuple = table->fetch();
1092 if (NULL != tuple) numRecords++;
1093 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
1096 else {
1097 int recordOffset =0;
1098 while(recordOffset <= parsedData->getOffset()) {
1099 tuple = table->fetch();
1100 if (NULL == tuple) break;
1101 recordOffset++;
1103 isOffsetReached = true;
1104 if (NULL != tuple) numRecords++;
1105 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
1108 if (NULL == tuple) return NULL;
1109 FieldValue *value;
1110 bool nullValueSet;
1111 char stmt[128];
1112 if (SQL) {
1113 sprintf(stmt, "INSERT INTO %s VALUES(", table->getName());
1114 printf("%s", stmt);
1116 for (int i = 0; i < totalFields; i++)
1118 value = bindFields[i];
1119 if (!value->isInResSet) continue;
1120 nullValueSet = table->isFldNull(value->fldName);
1121 if (nullValueSet) {
1122 if (SQL) {
1123 if (i==0)
1124 printf("NULL");
1125 else
1126 printf(", NULL");
1128 else if (value->aType != AGG_COUNT) printf("NULL\t");
1129 else printf("0\t");
1131 else {
1132 if (SQL) {
1133 switch(value->type)
1135 case typeString:
1136 case typeVarchar:
1137 case typeBinary:
1138 case typeDate:
1139 case typeTime:
1140 case typeTimeStamp:
1142 if (i==0)
1143 printf(" '");
1144 else
1145 printf(", '");
1146 break;
1148 default:
1150 if (i!=0)
1151 printf(",");
1155 AllDataType::printVal(value->value, value->type, value->length);
1156 if (SQL) {
1157 switch(value->type)
1159 case typeString:
1160 case typeVarchar:
1161 case typeBinary:
1162 case typeDate:
1163 case typeTime:
1164 case typeTimeStamp:
1165 printf("'");
1167 } else printf("\t");
1170 if (SQL) printf(");\n");
1171 return tuple;
1174 void* SelStatement::next()
1176 if(handleAggWithTbl)
1178 return handleSingleTableAggWithoutGroup();
1180 return( table->fetch() );
1184 void* SelStatement::getFieldValuePtr( int pos )
1186 FieldValue *v = bindFields[pos];
1187 return ( (void*) v->value );
1190 void* SelStatement::getFieldValuePtr( char *name )
1192 FieldValue *value;
1193 char fName[IDENTIFIER_LENGTH];
1194 for (int i = 0; i < totalFields; i++)
1196 value = bindFields[i];
1197 table->getFieldNameAlone(value->fldName,fName);
1198 if (strcmp(fName,name)==0)
1200 return ( (void*) value->value );
1204 return NULL;
1206 void SelStatement::getProjFieldType(int *data)
1208 FieldValue *value;
1209 for (int i = 0; i < totalFields; i++)
1211 value = bindFields[i];
1212 data[i+1] = value->type;
1216 int SelStatement::noOfProjFields()
1218 return totalFields;
1221 DbRetVal SelStatement::getProjFldInfo (int projpos, FieldInfo *&fInfo)
1224 DbRetVal rv = OK;
1225 //TODO::if not yet prepared return error
1226 //TODO::check the upper limit for projpos
1227 if (projpos < 0 || projpos >totalFields) return ErrBadArg;
1228 FieldValue *value = bindFields[projpos-1];
1229 fInfo->type = value->type;
1230 fInfo->length= value->length;
1231 fInfo->isNull = value->isNullable;
1232 fInfo->aType = value->aType;
1233 fInfo->offset = value->offset;
1234 fInfo->isPrimary = value->isPrimary;
1235 fInfo->isUnique = value->isUnique;
1236 fInfo->isAutoIncrement= value->isAutoIncrement;
1237 fInfo->isDefault = value->isDefault;
1238 if (fInfo->aType == AGG_UNKNOWN) {
1239 strcpy(fInfo->fldName, value->fldName);
1240 if (fInfo->isDefault) strcpy(fInfo->defaultValueBuf, value->defValBuf);
1241 return OK;
1243 switch(fInfo->aType)
1245 case AGG_COUNT:
1246 sprintf(fInfo->fldName, "COUNT(%s)", value->fldName);
1247 fInfo->type = typeInt;
1248 fInfo->length = sizeof(int);
1249 break;
1250 case AGG_MIN:
1251 sprintf(fInfo->fldName, "MIN(%s)", value->fldName);
1252 break;
1253 case AGG_MAX:
1254 sprintf(fInfo->fldName, "MAX(%s)", value->fldName);
1255 break;
1256 case AGG_SUM:
1257 sprintf(fInfo->fldName, "SUM(%s)", value->fldName);
1258 break;
1259 case AGG_AVG:
1260 sprintf(fInfo->fldName, "AVG(%s)", value->fldName);
1261 fInfo->type = typeDouble;
1262 fInfo->length = sizeof(double);
1263 break;
1264 default:
1265 strcpy(fInfo->fldName, value->fldName);
1266 break;
1268 return rv;
1270 int SelStatement::getFldPos(char *name)
1272 return table->getFldPos(name);
1275 bool SelStatement::isInProjectionList(char *name, AggType aType)
1277 ListIterator iter = parsedData->getFieldNameList().getIterator();
1278 FieldName *fldName = NULL;
1279 while (iter.hasElement()) {
1280 fldName = (FieldName*) iter.nextElement();
1281 if ((strcmp(fldName->fldName, name)==0) && fldName->aType == aType) {
1282 return true;
1285 return false;