statement caching modifications and cache stmt display
[csql.git] / src / sql / SelStatement.cxx
blob6ffade5fbdad735cfbef5041bee4fffe18e52cb5
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';
407 if (name->aType == AGG_COUNT) {
408 newVal->type = typeInt;
409 newVal->length = sizeof(int);
411 else if (name->aType == AGG_AVG) {
412 newVal->type = typeDouble;
413 newVal->length = sizeof(double);
414 if (!AllDataType::isValidFieldForAvg(fInfo->type)) {
415 printError(ErrBadArg, "Illegal operation for field %s",
416 fInfo->fldName);
417 dbMgr->closeTable(table);
418 if (aggTable) { delete aggTable; aggTable = NULL; }
419 table = NULL;
420 delete fInfo;
421 return ErrBadArg;
424 else {
425 newVal->type = fInfo->type;
426 newVal->length = fInfo->length;
428 newVal->isNullable = fInfo->isNull;
429 FieldName *bFldName=NULL;
430 ListIterator it = bindFldList.getIterator();
431 while (it.hasElement())
433 bFldName = (FieldName*)it.nextElement();
434 if(0==strcmp(bFldName->fldName,name->fldName) &&
435 name->aType == AGG_UNKNOWN)
437 newVal->value=table->getBindFldAddr(name->fldName);
438 newVal->isAllocVal=false;
439 isBindFld=true;
440 break;
443 if (!isBindFld) {
444 if ( name->aType == AGG_UNKNOWN ||
445 (name->aType != AGG_COUNT &&
446 name->aType != AGG_AVG) ) {
447 if(newVal->type == typeBinary)
448 newVal->value = AllDataType::alloc(fInfo->type,
449 2 * fInfo->length);
450 else newVal->value = AllDataType::alloc(fInfo->type,
451 fInfo->length);
452 } else {
453 if (name->aType == AGG_AVG) {
454 newVal->value = AllDataType::alloc(typeDouble,
455 sizeof(double));
456 memset(newVal->value, 0, sizeof(double));
458 else if (name->aType == AGG_COUNT) {
459 newVal->value = AllDataType::alloc(typeInt,
460 sizeof(int));
461 memset(newVal->value, 0, sizeof(int));
465 newVal->isAllocVal=true;
467 if (name->aType ==AGG_UNKNOWN &&
468 parsedData->getGroupFieldNameList().size()== 0) {
469 rv = table->bindFld(name->fldName, newVal->value);
470 if (OK !=rv) {
471 if (newVal->isAllocVal) free(newVal->value);
472 delete newVal;
473 delete fInfo;
474 return rv;
477 else if (!isSingleTableNoGrp)
479 if (!aggTable) {
480 aggTable = new AggTableImpl();
481 aggTable->setTable(table);
483 rv = aggTable->bindFld(name->fldName, name->aType, newVal->value);
484 if (OK !=rv) {
485 if (newVal->isAllocVal) free(newVal->value);
486 delete newVal; delete fInfo; delete aggTable;
487 aggTable = NULL; table = NULL;
488 return rv;
491 if (name->aType !=AGG_UNKNOWN && isSingleTableNoGrp)
492 handleAggWithTbl= true;
493 parsedData->insertFieldValue(newVal);
495 if (!isBindFld) bindFldList.append(name);
497 bindFldList.reset();
499 //Check if the having list is present in projection list or not.
500 //If not present bind here not to be printed in fetchAndPrint later.
501 ListIterator hiter = parsedData->getHavingFieldNameList().getIterator();
502 while (hiter.hasElement()) {
503 FieldName *fnm = (FieldName *) hiter.nextElement();
504 rv = table->getFieldInfo(fnm->fldName, fInfo);
505 if (!isInProjectionList(fnm->fldName, fnm->aType)) {
506 FieldValue *newVal = new FieldValue();
507 strcpy(newVal->fldName,fnm->fldName);
508 newVal->parsedString = NULL;
509 newVal->paramNo = 0;
510 newVal->aType = fnm->aType;
511 newVal->isInResSet = false;
512 newVal->isNullable = fInfo->isNull;
513 newVal->offset = fInfo->offset;
514 newVal->isPrimary = fInfo->isPrimary;
515 newVal->isUnique = fInfo->isUnique;
516 newVal->isAutoIncrement = fInfo->isAutoIncrement;
517 if (fnm->aType == AGG_AVG) {
518 newVal->value = AllDataType::alloc(typeDouble, sizeof(double));
519 memset(newVal->value, 0, sizeof(double));
520 } else if (fnm->aType == AGG_COUNT) {
521 newVal->value = AllDataType::alloc(typeInt, sizeof(int));
522 memset(newVal->value, 0, sizeof(int));
523 } else {
524 newVal->value = AllDataType::alloc(fInfo->type, fInfo->length);
525 memset(newVal->value, 0, fInfo->length);
527 newVal->isAllocVal = true;
528 parsedData->insertFieldValue(newVal);
529 aggTable->bindFld(fnm->fldName, fnm->aType, newVal->value);
533 rv = setBindFieldAndValues();
534 if (rv != OK)
536 delete fInfo;
537 if (aggTable) { delete aggTable; aggTable = NULL; }
538 else dbMgr->closeTable(table);
539 table = NULL;
540 return rv;
543 table->setCondition(parsedData->getCondition());
545 rv = resolveForCondition();
546 if (rv != OK)
548 delete fInfo;
549 //TODO::free memory allocated for params
550 if (aggTable) { delete aggTable; aggTable = NULL; }
551 else {
552 table->setCondition(NULL);
553 dbMgr->closeTable(table);
555 table = NULL;
556 return rv;
558 if (NULL == parsedData->getCondition()) parsedData->setCacheWorthy(false);
559 rv = resolveGroupFld(aggTable);
560 if (rv != OK)
562 delete fInfo;
563 //TODO::free memory allocated for params
564 if (aggTable) { delete aggTable; aggTable = NULL; }
565 else if (table)
567 table->setCondition(NULL);
568 dbMgr->closeTable(table);
570 table = NULL;
571 return rv;
574 rv = resolveOrderByFld();
575 if (rv != OK)
577 delete fInfo;
578 delete table;
579 table = NULL;
580 return rv;
582 rv = resolveDistinct();
583 delete fInfo;
584 if(parsedData->getExplain()) isExplain = true;
585 return rv;
587 DbRetVal SelStatement::resolveDistinct()
589 if (!parsedData->getDistinct()) {
590 return OK;
592 OrderTableImpl *orderTable = new OrderTableImpl();
593 orderTable->setTable(table);
594 orderTable->setProjList(parsedData->getFieldValueList());
595 orderTable->setOrderByList(parsedData->getFieldValueList());
596 orderTable->setDistinct();
597 table = orderTable;
598 handleAggWithTbl= false;
599 return OK;
603 DbRetVal SelStatement::resolveOrderByFld()
605 if (0 == parsedData->getOrderFieldNameList().size()) {
606 return OK;
608 OrderTableImpl *orderTable = new OrderTableImpl();
609 orderTable->setTable(table);
610 orderTable->setProjList(parsedData->getFieldValueList());
611 ListIterator giter = parsedData->getOrderFieldNameList().getIterator();
612 FieldName *name = NULL;
613 DbRetVal rv = OK;
614 FieldInfo *fInfo = new FieldInfo();
615 while (giter.hasElement())
617 name = (FieldName*)giter.nextElement();
618 rv = table->getFieldInfo(name->fldName, fInfo);
619 if (ErrNotFound == rv || ErrNotExists == rv)
621 delete fInfo;
622 printError(ErrSyntaxError, "Field %s does not exist in table",
623 name->fldName);
624 return ErrSyntaxError;
626 /*FieldValue *newVal = new FieldValue();
627 strcpy(newVal->fldName,name->fldName);
628 newVal->parsedString = NULL;
629 newVal->paramNo = 0;
630 newVal->type = fInfo->type;
631 newVal->isNullable = fInfo->isNull;
632 newVal->length = fInfo->length;
633 if (newVal->type == typeBinary)
634 newVal->value = AllDataType::alloc(fInfo->type, 2 * fInfo->length);
635 else newVal->value = AllDataType::alloc(fInfo->type, fInfo->length);
636 newVal->isAllocVal=true;
637 parsedData->insertFieldValue(newVal);
639 if (name->aType == AGG_UNKNOWN) orderTable->setOrderBy(name->fldName);
640 else orderTable->setOrderBy(name->fldName, true); //descending
642 delete fInfo;
643 table = orderTable;
644 handleAggWithTbl= false;
645 return OK;
648 DbRetVal SelStatement::resolveGroupFld(AggTableImpl *aggTable)
650 if (!aggTable) return OK;
652 //check whether all non aggregate projections are from group list
653 ListIterator iter = parsedData->getFieldNameList().getIterator();
654 ListIterator giter = parsedData->getGroupFieldNameList().getIterator();
655 FieldName *name = NULL;
656 while (iter.hasElement())
658 name = (FieldName*) iter.nextElement();
659 if (name->aType == AGG_UNKNOWN && !isGroupFld(name->fldName) ) {
660 printError(ErrSyntaxError, "Non aggregate projection contains non group field: %s", name->fldName);
661 return ErrSyntaxError;
665 DbRetVal rv = OK;
666 FieldInfo *fInfo = new FieldInfo();
667 while (giter.hasElement())
669 name = (FieldName*)giter.nextElement();
670 rv = table->getFieldInfo(name->fldName, fInfo);
671 if (ErrNotFound == rv || ErrNotExists == rv)
673 delete fInfo;
674 printError(ErrSyntaxError, "Field %s does not exist in table",
675 name->fldName);
676 return ErrSyntaxError;
678 FieldValue *newVal = new FieldValue();
679 strcpy(newVal->fldName,name->fldName);
680 newVal->parsedString = NULL;
681 newVal->paramNo = 0;
682 newVal->type = fInfo->type;
683 newVal->isNullable = fInfo->isNull;
684 newVal->length = fInfo->length;
685 newVal->offset = fInfo->offset;
686 newVal->isPrimary = fInfo->isPrimary;
687 newVal->isUnique = fInfo->isUnique;
688 newVal->isAutoIncrement = fInfo->isAutoIncrement;
689 if (newVal->type == typeBinary)
690 newVal->value = AllDataType::alloc(fInfo->type, 2 * fInfo->length);
691 else newVal->value = AllDataType::alloc(fInfo->type, fInfo->length);
692 newVal->isAllocVal=true;
693 parsedData->insertFieldValue(newVal);
694 aggTable->setGroup(name->fldName, newVal->value);
696 delete fInfo;
697 aggTable->setCondition(parsedData->getHavingCondition());
698 /*if (giter.hasElement())
700 printError(ErrSyntaxError, "Only one field allowed in group\n");
701 return ErrSyntaxError;
703 table = aggTable;
704 return OK;
707 DbRetVal SelStatement::resolveStar()
709 DbRetVal rv = OK;
710 parsedData->clearFieldNameList();
711 FieldValue *newVal = NULL;
712 List fNameList = table->getFieldNameList();
713 ListIterator fNameIter = fNameList.getIterator();
714 //fNameList.resetIter(); //do not remove this.
715 FieldInfo *fInfo = new FieldInfo();
716 for (int i = 0; i < fNameList.size() ; i++)
718 char *fName = ((Identifier*)(fNameIter.nextElement()))->name;
719 rv = table->getFieldInfo(fName, fInfo);
720 if (ErrNotFound == rv || ErrNotExists == rv)
722 delete fInfo;
723 fNameList.reset();
724 printError(ErrSysFatal, "Should never happen.");
725 return ErrSysFatal;
727 newVal = new FieldValue();
728 strcpy(newVal->fldName,fName);
729 newVal->parsedString = NULL;
730 newVal->paramNo = 0;
731 newVal->type = fInfo->type;
732 newVal->length = fInfo->length;
733 newVal->offset = fInfo->offset;
734 newVal->isPrimary = fInfo->isPrimary;
735 newVal->isUnique = fInfo->isUnique;
736 newVal->isAutoIncrement = fInfo->isAutoIncrement;
738 // for binary datatype input buffer size should be 2 times the length
739 if(newVal->type == typeBinary)
740 newVal->value = AllDataType::alloc(fInfo->type, 2 * fInfo->length);
741 else newVal->value = AllDataType::alloc(fInfo->type, fInfo->length);
742 newVal->isAllocVal=true;
743 newVal->isInResSet = true;
744 parsedData->insertFieldValue(newVal);
745 parsedData->insertField(fName);
746 rv = table->bindFld(fName, newVal->value);
747 if (rv != OK) {
748 delete fInfo;
749 return rv;
752 fNameIter.reset();
753 while (fNameIter.hasElement())
754 delete (Identifier *) fNameIter.nextElement();
755 fNameList.reset();
756 delete fInfo;
757 return OK;
760 DbRetVal SelStatement::setBindFieldAndValues()
762 totalFields = parsedData->getFieldNameList().size();
763 bindFields = (FieldValue**) malloc ( totalFields * sizeof(FieldValue*));
764 bindFieldValues = (char**) malloc( totalFields * sizeof(char*));
765 memset(bindFields, 0, totalFields * sizeof(FieldValue*));
766 memset(bindFieldValues, 0, totalFields * sizeof(char*));
767 ListIterator valIter = parsedData->getFieldValueList().getIterator();
768 int colNo =0;
769 FieldValue *value = NULL;
770 //The second condition colNo < totalFields is important for projection list
771 //might not contain the binded having field.
772 while(valIter.hasElement() && colNo < totalFields)
774 value = (FieldValue*) valIter.nextElement();
775 if (value == NULL)
777 free(bindFields); bindFields = NULL;
778 free(bindFieldValues); bindFieldValues = NULL;
779 printError(ErrSysFatal, "Should never happen. value NULL after iteration");
780 return ErrSysFatal;
782 bindFields[colNo++] = value;
784 return OK;
788 DbRetVal SelStatement::resolveForCondition()
790 //get the fieldname list and validate field names
791 ListIterator iter = parsedData->getConditionValueList().getIterator();
793 ConditionValue *value;
794 FieldInfo *fInfo = new FieldInfo();
795 int paramPos =1;
796 DbRetVal rv = OK;
797 while (iter.hasElement())
799 value = (ConditionValue*) iter.nextElement();
800 if (NULL == value)
802 delete fInfo;
803 printError(ErrSysFatal, "Should never happen.");
804 return ErrSysFatal;
806 if(!value->isFunctionInvolve){
807 rv = table->getFieldInfo(value->fName, fInfo);
808 if (ErrNotFound == rv || ErrNotExists == rv)
810 delete fInfo;
811 printError(ErrSyntaxError, "Field %s does not exist in table",
812 value->fName);
813 return ErrSyntaxError;
815 if (value->aType == AGG_AVG) {
816 value->type = typeDouble;
817 value->length = sizeof(double);
818 } else if (value->aType == AGG_COUNT) {
819 value->type = typeInt;
820 value->length = sizeof(int);
821 } else {
822 value->type = fInfo->type;
823 value->length = fInfo->length;
825 value->isNullable = fInfo->isNull;
826 }else{
827 value->type = AllDataType::getCsqlTypeFromFunctionTypeForComparision(parsedData->getFunctionType());
829 value->value = AllDataType::alloc(value->type, value->length);
830 //table->bindFld(name->fldName, value->value);
831 if(value->paramNo ==1) continue;//For Predecate t1.f1=t2.f1
832 if (value->parsedString == NULL)
834 delete fInfo;
835 printError(ErrSyntaxError, "Condition value should not be NULL");
836 return ErrSyntaxError;
838 if (value->parsedString[0] == '?')
840 //if(!value->opLike) // checks if 'LIKE' operator is used
841 value->paramNo = paramPos++;
843 if (!value->paramNo) {
844 // for valid Integer
845 if (value->type == typeDate || value->type == typeTime ||
846 value->type == typeTimeStamp)
847 parsedData->setCacheWorthy(false);
848 if((value->type == typeInt) || (value->type==typeShort) ||
849 (value->type==typeByteInt) || (value->type==typeLongLong) ||
850 (value->type==typeLong)) {
851 int len=strlen(value->parsedString);
852 for(int n=0;n<len;n++){
853 int p=value->parsedString[n];
854 if(!(p>=48 && p<=57 || p==45)) return ErrBadArg;
858 // Here for binary dataType it is not strcpy'd bcos internally memcmp is done for predicates like f2 = 'abcd' where f2 is binary
859 AllDataType::strToValue(value->value, value->parsedString, value->type, value->length);
862 delete fInfo;
863 totalParams = paramPos -1;
864 if (0 == totalParams) return OK;
865 params = (void**) malloc ( totalParams * sizeof(FieldValue*));
866 paramValues = (char**) malloc( totalParams * sizeof(char*));
867 memset(params, 0, totalParams * sizeof(FieldValue*));
868 memset(paramValues, 0, totalParams * sizeof(char*));
869 iter.reset();
870 while(iter.hasElement())
872 value = (ConditionValue*) iter.nextElement();
873 if (value == NULL)
875 free(params); params = NULL;
876 free(paramValues); paramValues = NULL;
877 printError(ErrSysFatal, "Should never happen. value NULL after iteration");
878 return ErrSysFatal;
880 if (value->paramNo) params[value->paramNo - 1] = value;
882 return OK;
884 bool SelStatement::isGroupFld(char *fieldName)
886 ListIterator giter = parsedData->getGroupFieldNameList().getIterator();
887 FieldName *name = NULL;
888 while (giter.hasElement())
890 name = (FieldName*) giter.nextElement();
891 if (0 == strcmp(name->fldName, fieldName)) return true;
893 return false;
896 void* SelStatement::handleSingleTableAggWithoutGroup()
898 if (isPointReturned) return NULL;
899 TableImpl *tblImpl = (TableImpl*)table;
900 ListIterator iter = parsedData->getFieldNameList().getIterator();
901 int i=0;
902 DbRetVal rv = OK;
903 FieldName *name;
904 FieldValue *fVal = NULL;
905 bool noRec = false;
906 while (iter.hasElement())
908 name = (FieldName*) iter.nextElement();
909 fVal = bindFields[i];
911 rv = tblImpl->fetchAgg(name->fldName, name->aType, fVal->value, noRec);
912 if (OK != rv) return NULL;
913 i++;
914 tblImpl->closeScan();
915 tblImpl->execute();
917 isPointReturned = true;
918 if(noRec && name->aType != AGG_COUNT) return NULL;
919 return fVal;
921 void* SelStatement::fetch()
923 void *tuple = NULL;
924 if(handleAggWithTbl)
926 tuple = handleSingleTableAggWithoutGroup();
927 if (NULL == tuple) return NULL;
928 }else {
929 if (isOffsetReached) {
930 if (!isRecLimitReached) {
931 tuple = table->fetch();
932 if (NULL != tuple) numRecords++;
933 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
936 else {
937 int recordOffset =0;
938 while(recordOffset <= parsedData->getOffset()) {
939 tuple = table->fetch();
940 if (NULL == tuple) break;
941 recordOffset++;
943 isOffsetReached = true;
944 if (NULL != tuple) numRecords++;
945 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
948 if (NULL == tuple) return NULL;
950 //copy values to binded buffer
951 FieldValue *value;
952 for (int i = 0; i < totalFields; i++)
954 value = bindFields[i];
955 if (bindFieldValues[i] == NULL)
957 printError(ErrBadCall, "Fields are not binded properly. Should never happen");
958 return NULL;
960 AllDataType::copyVal(bindFieldValues[i], value->value, value->type, value->length);
962 return tuple;
965 void* SelStatement::fetch(DbRetVal &rv)
967 void *tuple = NULL;
968 if(handleAggWithTbl)
970 tuple = handleSingleTableAggWithoutGroup();
971 if (NULL == tuple) return NULL;
972 }else {
973 if (isOffsetReached) {
974 if (!isRecLimitReached) {
975 tuple = table->fetch(rv);
976 if (NULL != tuple) numRecords++;
977 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
979 } else {
980 int recordOffset =0;
981 while(recordOffset <= parsedData->getOffset()) {
982 tuple = table->fetch(rv);
983 if (NULL == tuple) break;
984 recordOffset++;
986 isOffsetReached = true;
987 if (NULL != tuple) numRecords++;
988 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
991 if (NULL == tuple) return NULL;
992 //copy values to binded buffer
993 FieldValue *value;
994 for (int i = 0; i < totalFields; i++)
996 value = bindFields[i];
997 if (bindFieldValues[i] == NULL)
999 printError(ErrBadCall, "Fields are not binded properly. Should never happen %d", i);
1000 return NULL;
1002 AllDataType::copyVal(bindFieldValues[i], value->value, value->type, value->length);
1004 return tuple;
1007 DbRetVal SelStatement::close()
1009 isPointReturned = false;
1010 if (table) return table->closeScan();
1011 else return OK;
1014 void* SelStatement::getParamValuePtr( int pos )
1016 ConditionValue *p = (ConditionValue*) params [pos-1];
1017 return ( (void*) p->value );
1020 char* SelStatement::getFieldName ( int pos )
1022 //TODO::if not yet prepared return error
1023 //TODO::check the upper limit for projpos
1024 ListIterator iter = parsedData->getFieldNameList().getIterator();
1025 int position = 1;
1026 while (iter.hasElement())
1028 FieldName *name = (FieldName*) iter.nextElement();
1029 if (position == pos) {
1030 if (NULL == name)
1032 printError(ErrSysFatal, "Should never happen. Field Name list has NULL");
1033 return (char*) 0;
1035 return name->fldName;
1037 position++;
1039 return (char*) 0;
1042 DataType SelStatement::getFieldType( int pos )
1044 FieldValue *v = bindFields[pos];
1045 return ( (DataType) v->type );
1048 int SelStatement::getFieldLength( int pos )
1050 FieldValue *v = bindFields[pos];
1051 return ( (int) v->type );
1054 void* SelStatement::fetchAndPrint(bool SQL)
1056 void *tuple = NULL;
1057 if(handleAggWithTbl)
1059 tuple = handleSingleTableAggWithoutGroup();
1060 }else {
1061 if (isOffsetReached) {
1062 if (!isRecLimitReached) {
1063 tuple = table->fetch();
1064 if (NULL != tuple) numRecords++;
1065 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
1068 else {
1069 int recordOffset =0;
1070 while(recordOffset <= parsedData->getOffset()) {
1071 tuple = table->fetch();
1072 if (NULL == tuple) break;
1073 recordOffset++;
1075 isOffsetReached = true;
1076 if (NULL != tuple) numRecords++;
1077 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
1080 if (NULL == tuple) return NULL;
1081 FieldValue *value;
1082 bool nullValueSet;
1083 char stmt[128];
1084 if (SQL) {
1085 sprintf(stmt, "INSERT INTO %s VALUES(", table->getName());
1086 printf("%s", stmt);
1088 for (int i = 0; i < totalFields; i++)
1090 value = bindFields[i];
1091 if (!value->isInResSet) continue;
1092 nullValueSet = table->isFldNull(value->fldName);
1093 if (nullValueSet) {
1094 if (SQL) {
1095 if (i==0)
1096 printf("NULL");
1097 else
1098 printf(", NULL");
1100 else if (value->aType != AGG_COUNT) printf("NULL\t");
1101 else printf("0\t");
1103 else {
1104 if (SQL) {
1105 switch(value->type)
1107 case typeString:
1108 case typeVarchar:
1109 case typeBinary:
1110 case typeDate:
1111 case typeTime:
1112 case typeTimeStamp:
1114 if (i==0)
1115 printf(" '");
1116 else
1117 printf(", '");
1118 break;
1120 default:
1122 if (i!=0)
1123 printf(",");
1127 AllDataType::printVal(value->value, value->type, value->length);
1128 if (SQL) {
1129 switch(value->type)
1131 case typeString:
1132 case typeVarchar:
1133 case typeBinary:
1134 case typeDate:
1135 case typeTime:
1136 case typeTimeStamp:
1137 printf("'");
1139 } else printf("\t");
1142 if (SQL) printf(");\n");
1143 return tuple;
1146 void* SelStatement::next()
1148 if(handleAggWithTbl)
1150 return handleSingleTableAggWithoutGroup();
1152 return( table->fetch() );
1156 void* SelStatement::getFieldValuePtr( int pos )
1158 FieldValue *v = bindFields[pos];
1159 return ( (void*) v->value );
1162 void* SelStatement::getFieldValuePtr( char *name )
1164 FieldValue *value;
1165 char fName[IDENTIFIER_LENGTH];
1166 for (int i = 0; i < totalFields; i++)
1168 value = bindFields[i];
1169 table->getFieldNameAlone(value->fldName,fName);
1170 if (strcmp(fName,name)==0)
1172 return ( (void*) value->value );
1176 return NULL;
1178 void SelStatement::getProjFieldType(int *data)
1180 FieldValue *value;
1181 for (int i = 0; i < totalFields; i++)
1183 value = bindFields[i];
1184 data[i+1] = value->type;
1188 int SelStatement::noOfProjFields()
1190 return totalFields;
1193 DbRetVal SelStatement::getProjFldInfo (int projpos, FieldInfo *&fInfo)
1196 DbRetVal rv = OK;
1197 //TODO::if not yet prepared return error
1198 //TODO::check the upper limit for projpos
1199 if (projpos < 0 || projpos >totalFields) return ErrBadArg;
1200 FieldValue *value = bindFields[projpos-1];
1201 fInfo->type = value->type;
1202 fInfo->length= value->length;
1203 fInfo->isNull = value->isNullable;
1204 fInfo->aType = value->aType;
1205 fInfo->offset = value->offset;
1206 fInfo->isPrimary = value->isPrimary;
1207 fInfo->isUnique = value->isUnique;
1208 fInfo->isAutoIncrement= value->isAutoIncrement;
1209 fInfo->isDefault = value->isDefault;
1210 if (fInfo->aType == AGG_UNKNOWN) {
1211 strcpy(fInfo->fldName, value->fldName);
1212 if (fInfo->isDefault) strcpy(fInfo->defaultValueBuf, value->defValBuf);
1213 return OK;
1215 switch(fInfo->aType)
1217 case AGG_COUNT:
1218 sprintf(fInfo->fldName, "COUNT(%s)", value->fldName);
1219 fInfo->type = typeInt;
1220 fInfo->length = sizeof(int);
1221 break;
1222 case AGG_MIN:
1223 sprintf(fInfo->fldName, "MIN(%s)", value->fldName);
1224 break;
1225 case AGG_MAX:
1226 sprintf(fInfo->fldName, "MAX(%s)", value->fldName);
1227 break;
1228 case AGG_SUM:
1229 sprintf(fInfo->fldName, "SUM(%s)", value->fldName);
1230 break;
1231 case AGG_AVG:
1232 sprintf(fInfo->fldName, "AVG(%s)", value->fldName);
1233 fInfo->type = typeDouble;
1234 fInfo->length = sizeof(double);
1235 break;
1236 default:
1237 strcpy(fInfo->fldName, value->fldName);
1238 break;
1240 return rv;
1242 int SelStatement::getFldPos(char *name)
1244 return table->getFldPos(name);
1247 bool SelStatement::isInProjectionList(char *name, AggType aType)
1249 ListIterator iter = parsedData->getFieldNameList().getIterator();
1250 FieldName *fldName = NULL;
1251 while (iter.hasElement()) {
1252 fldName = (FieldName*) iter.nextElement();
1253 if ((strcmp(fldName->fldName, name)==0) && fldName->aType == aType) {
1254 return true;
1257 return false;