statement caching for select statement with no parameter and with predicates. Bu
[csql.git] / src / sql / SelStatement.cxx
blob56a09a2b2c208dfe358653a071e8a6218370033e
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 rv = table->getFieldInfo(value->fName, fInfo);
807 if (ErrNotFound == rv || ErrNotExists == rv)
809 delete fInfo;
810 printError(ErrSyntaxError, "Field %s does not exist in table",
811 value->fName);
812 return ErrSyntaxError;
814 if (value->aType == AGG_AVG) {
815 value->type = typeDouble;
816 value->length = sizeof(double);
817 } else if (value->aType == AGG_COUNT) {
818 value->type = typeInt;
819 value->length = sizeof(int);
820 } else {
821 value->type = fInfo->type;
822 value->length = fInfo->length;
824 value->isNullable = fInfo->isNull;
825 value->value = AllDataType::alloc(value->type, value->length);
826 //table->bindFld(name->fldName, value->value);
827 if(value->paramNo ==1) continue;//For Predecate t1.f1=t2.f1
828 if (value->parsedString == NULL)
830 delete fInfo;
831 printError(ErrSyntaxError, "Condition value should not be NULL");
832 return ErrSyntaxError;
834 if (value->parsedString[0] == '?')
836 //if(!value->opLike) // checks if 'LIKE' operator is used
837 value->paramNo = paramPos++;
839 if (!value->paramNo) {
840 // for valid Integer
841 if (value->type == typeDate || value->type == typeTime ||
842 value->type == typeTimeStamp)
843 parsedData->setCacheWorthy(false);
845 if((value->type == typeInt) || (value->type==typeShort) || (value->type==typeByteInt) || (value->type==typeLongLong) || (value->type==typeLong)){
846 int len=strlen(value->parsedString);
847 for(int n=0;n<len;n++){
848 int p=value->parsedString[n];
849 if(!(p>=48 && p<=57 || p==45))
850 return ErrBadArg;
854 // Here for binary dataType it is not strcpy'd bcos internally memcmp is done for predicates like f2 = 'abcd' where f2 is binary
855 AllDataType::strToValue(value->value, value->parsedString, value->type, value->length);
858 delete fInfo;
859 totalParams = paramPos -1;
860 if (0 == totalParams) return OK;
861 params = (void**) malloc ( totalParams * sizeof(FieldValue*));
862 paramValues = (char**) malloc( totalParams * sizeof(char*));
863 memset(params, 0, totalParams * sizeof(FieldValue*));
864 memset(paramValues, 0, totalParams * sizeof(char*));
865 iter.reset();
866 while(iter.hasElement())
868 value = (ConditionValue*) iter.nextElement();
869 if (value == NULL)
871 free(params); params = NULL;
872 free(paramValues); paramValues = NULL;
873 printError(ErrSysFatal, "Should never happen. value NULL after iteration");
874 return ErrSysFatal;
876 params[value->paramNo -1 ] = value;
878 return OK;
880 bool SelStatement::isGroupFld(char *fieldName)
882 ListIterator giter = parsedData->getGroupFieldNameList().getIterator();
883 FieldName *name = NULL;
884 while (giter.hasElement())
886 name = (FieldName*) giter.nextElement();
887 if (0 == strcmp(name->fldName, fieldName)) return true;
889 return false;
892 void* SelStatement::handleSingleTableAggWithoutGroup()
894 if (isPointReturned) return NULL;
895 TableImpl *tblImpl = (TableImpl*)table;
896 ListIterator iter = parsedData->getFieldNameList().getIterator();
897 int i=0;
898 DbRetVal rv = OK;
899 FieldName *name;
900 FieldValue *fVal = NULL;
901 bool noRec = false;
902 while (iter.hasElement())
904 name = (FieldName*) iter.nextElement();
905 fVal = bindFields[i];
907 rv = tblImpl->fetchAgg(name->fldName, name->aType, fVal->value, noRec);
908 if (OK != rv) return NULL;
909 i++;
910 tblImpl->closeScan();
911 tblImpl->execute();
913 isPointReturned = true;
914 if(noRec && name->aType != AGG_COUNT) return NULL;
915 return fVal;
917 void* SelStatement::fetch()
919 void *tuple = NULL;
920 if(handleAggWithTbl)
922 tuple = handleSingleTableAggWithoutGroup();
923 if (NULL == tuple) return NULL;
924 }else {
925 if (isOffsetReached) {
926 if (!isRecLimitReached) {
927 tuple = table->fetch();
928 if (NULL != tuple) numRecords++;
929 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
932 else {
933 int recordOffset =0;
934 while(recordOffset <= parsedData->getOffset()) {
935 tuple = table->fetch();
936 if (NULL == tuple) break;
937 recordOffset++;
939 isOffsetReached = true;
940 if (NULL != tuple) numRecords++;
941 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
944 if (NULL == tuple) return NULL;
946 //copy values to binded buffer
947 FieldValue *value;
948 for (int i = 0; i < totalFields; i++)
950 value = bindFields[i];
951 if (bindFieldValues[i] == NULL)
953 printError(ErrBadCall, "Fields are not binded properly. Should never happen");
954 return NULL;
956 AllDataType::copyVal(bindFieldValues[i], value->value, value->type, value->length);
958 return tuple;
961 void* SelStatement::fetch(DbRetVal &rv)
963 void *tuple = NULL;
964 if(handleAggWithTbl)
966 tuple = handleSingleTableAggWithoutGroup();
967 if (NULL == tuple) return NULL;
968 }else {
969 if (isOffsetReached) {
970 if (!isRecLimitReached) {
971 tuple = table->fetch(rv);
972 if (NULL != tuple) numRecords++;
973 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
975 } else {
976 int recordOffset =0;
977 while(recordOffset <= parsedData->getOffset()) {
978 tuple = table->fetch(rv);
979 if (NULL == tuple) break;
980 recordOffset++;
982 isOffsetReached = true;
983 if (NULL != tuple) numRecords++;
984 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
987 if (NULL == tuple) return NULL;
988 //copy values to binded buffer
989 FieldValue *value;
990 for (int i = 0; i < totalFields; i++)
992 value = bindFields[i];
993 if (bindFieldValues[i] == NULL)
995 printError(ErrBadCall, "Fields are not binded properly. Should never happen %d", i);
996 return NULL;
998 AllDataType::copyVal(bindFieldValues[i], value->value, value->type, value->length);
1000 return tuple;
1003 DbRetVal SelStatement::close()
1005 isPointReturned = false;
1006 if (table) return table->closeScan();
1007 else return OK;
1010 void* SelStatement::getParamValuePtr( int pos )
1012 ConditionValue *p = (ConditionValue*) params [pos-1];
1013 return ( (void*) p->value );
1016 char* SelStatement::getFieldName ( int pos )
1018 //TODO::if not yet prepared return error
1019 //TODO::check the upper limit for projpos
1020 ListIterator iter = parsedData->getFieldNameList().getIterator();
1021 int position = 1;
1022 while (iter.hasElement())
1024 FieldName *name = (FieldName*) iter.nextElement();
1025 if (position == pos) {
1026 if (NULL == name)
1028 printError(ErrSysFatal, "Should never happen. Field Name list has NULL");
1029 return (char*) 0;
1031 return name->fldName;
1033 position++;
1035 return (char*) 0;
1038 DataType SelStatement::getFieldType( int pos )
1040 FieldValue *v = bindFields[pos];
1041 return ( (DataType) v->type );
1044 int SelStatement::getFieldLength( int pos )
1046 FieldValue *v = bindFields[pos];
1047 return ( (int) v->type );
1050 void* SelStatement::fetchAndPrint(bool SQL)
1052 void *tuple = NULL;
1053 if(handleAggWithTbl)
1055 tuple = handleSingleTableAggWithoutGroup();
1056 }else {
1057 if (isOffsetReached) {
1058 if (!isRecLimitReached) {
1059 tuple = table->fetch();
1060 if (NULL != tuple) numRecords++;
1061 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
1064 else {
1065 int recordOffset =0;
1066 while(recordOffset <= parsedData->getOffset()) {
1067 tuple = table->fetch();
1068 if (NULL == tuple) break;
1069 recordOffset++;
1071 isOffsetReached = true;
1072 if (NULL != tuple) numRecords++;
1073 if (numRecords == parsedData->getLimit()) isRecLimitReached=true;
1076 if (NULL == tuple) return NULL;
1077 FieldValue *value;
1078 bool nullValueSet;
1079 char stmt[128];
1080 if (SQL) {
1081 sprintf(stmt, "INSERT INTO %s VALUES(", table->getName());
1082 printf("%s", stmt);
1084 for (int i = 0; i < totalFields; i++)
1086 value = bindFields[i];
1087 if (!value->isInResSet) continue;
1088 nullValueSet = table->isFldNull(value->fldName);
1089 if (nullValueSet) {
1090 if (SQL) {
1091 if (i==0)
1092 printf("NULL");
1093 else
1094 printf(", NULL");
1096 else if (value->aType != AGG_COUNT) printf("NULL\t");
1097 else printf("0\t");
1099 else {
1100 if (SQL) {
1101 switch(value->type)
1103 case typeString:
1104 case typeBinary:
1105 case typeDate:
1106 case typeTime:
1107 case typeTimeStamp:
1109 if (i==0)
1110 printf(" '");
1111 else
1112 printf(", '");
1113 break;
1115 default:
1117 if (i!=0)
1118 printf(",");
1122 AllDataType::printVal(value->value, value->type, value->length);
1123 if (SQL) {
1124 switch(value->type)
1126 case typeString:
1127 case typeBinary:
1128 case typeDate:
1129 case typeTime:
1130 case typeTimeStamp:
1131 printf("'");
1133 } else printf("\t");
1136 if (SQL) printf(");\n");
1137 return tuple;
1140 void* SelStatement::next()
1142 if(handleAggWithTbl)
1144 return handleSingleTableAggWithoutGroup();
1146 return( table->fetch() );
1150 void* SelStatement::getFieldValuePtr( int pos )
1152 FieldValue *v = bindFields[pos];
1153 return ( (void*) v->value );
1156 void* SelStatement::getFieldValuePtr( char *name )
1158 FieldValue *value;
1159 char fName[IDENTIFIER_LENGTH];
1160 for (int i = 0; i < totalFields; i++)
1162 value = bindFields[i];
1163 table->getFieldNameAlone(value->fldName,fName);
1164 if (strcmp(fName,name)==0)
1166 return ( (void*) value->value );
1170 return NULL;
1172 void SelStatement::getProjFieldType(int *data)
1174 FieldValue *value;
1175 for (int i = 0; i < totalFields; i++)
1177 value = bindFields[i];
1178 data[i+1] = value->type;
1182 int SelStatement::noOfProjFields()
1184 return totalFields;
1187 DbRetVal SelStatement::getProjFldInfo (int projpos, FieldInfo *&fInfo)
1190 DbRetVal rv = OK;
1191 //TODO::if not yet prepared return error
1192 //TODO::check the upper limit for projpos
1193 if (projpos < 0 || projpos >totalFields) return ErrBadArg;
1194 FieldValue *value = bindFields[projpos-1];
1195 fInfo->type = value->type;
1196 fInfo->length= value->length;
1197 fInfo->isNull = value->isNullable;
1198 fInfo->aType = value->aType;
1199 fInfo->offset = value->offset;
1200 fInfo->isPrimary = value->isPrimary;
1201 fInfo->isUnique = value->isUnique;
1202 fInfo->isAutoIncrement= value->isAutoIncrement;
1203 fInfo->isDefault = value->isDefault;
1204 if (fInfo->aType == AGG_UNKNOWN) {
1205 strcpy(fInfo->fldName, value->fldName);
1206 if (fInfo->isDefault) strcpy(fInfo->defaultValueBuf, value->defValBuf);
1207 return OK;
1209 switch(fInfo->aType)
1211 case AGG_COUNT:
1212 sprintf(fInfo->fldName, "COUNT(%s)", value->fldName);
1213 fInfo->type = typeInt;
1214 fInfo->length = sizeof(int);
1215 break;
1216 case AGG_MIN:
1217 sprintf(fInfo->fldName, "MIN(%s)", value->fldName);
1218 break;
1219 case AGG_MAX:
1220 sprintf(fInfo->fldName, "MAX(%s)", value->fldName);
1221 break;
1222 case AGG_SUM:
1223 sprintf(fInfo->fldName, "SUM(%s)", value->fldName);
1224 break;
1225 case AGG_AVG:
1226 sprintf(fInfo->fldName, "AVG(%s)", value->fldName);
1227 fInfo->type = typeDouble;
1228 fInfo->length = sizeof(double);
1229 break;
1230 default:
1231 strcpy(fInfo->fldName, value->fldName);
1232 break;
1234 return rv;
1236 int SelStatement::getFldPos(char *name)
1238 return table->getFldPos(name);
1241 bool SelStatement::isInProjectionList(char *name, AggType aType)
1243 ListIterator iter = parsedData->getFieldNameList().getIterator();
1244 FieldName *fldName = NULL;
1245 while (iter.hasElement()) {
1246 fldName = (FieldName*) iter.nextElement();
1247 if ((strcmp(fldName->fldName, name)==0) && fldName->aType == aType) {
1248 return true;
1251 return false;