Fixing composite index search with atleast one non equal operator fails
[csql.git] / src / storage / PredicateImpl.cxx
blob9e5b0d7e2584bf1844f10f6010ed47fe6c6814ff
1 /***************************************************************************
2 * Copyright (C) 2007 by www.databasecache.com *
3 * Contact: praba_tuty@databasecache.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 ***************************************************************************/
16 #include<Table.h>
17 #include<Index.h>
18 #include<CatalogTables.h>
19 #include<Lock.h>
20 #include<Debug.h>
21 #include<PredicateImpl.h>
22 #include<Table.h>
23 #include<TableImpl.h>
24 #include<JoinTableImpl.h>
25 #include<Util.h>
26 static char aggNames[][10] =
28 "MIN", "MAX", "SUM", "AVG", "COUNT", ""
31 PredicateImpl::~PredicateImpl()
33 // if (lhs) {delete lhs; lhs = NULL; }
34 // if (rhs) { delete rhs; rhs = NULL; }
36 void PredicateImpl::print(int space)
38 char spaceBuf[IDENTIFIER_LENGTH];
39 memset(spaceBuf, 32, IDENTIFIER_LENGTH);
40 spaceBuf[space] = '\0';
42 printf("%s <PREDICATE>\n", spaceBuf);
43 if (0 != strcmp(fldName1, "")) {
44 if (aggType == AGG_UNKNOWN)
45 printf("%s <FieldName1> %s </FieldName1>\n", spaceBuf, fldName1);
46 else
47 printf("%s <FieldName1> %s(%s) </FieldName1>\n", spaceBuf,
48 aggNames[aggType-1], fldName1);
50 if (0 != strcmp(fldName2, ""))
51 printf("%s <FieldName2> %s </FieldName2>\n", spaceBuf, fldName2);
52 if (compOp != OpInvalidComparisionOp)
53 printf("%s <CompOp> %s </CompOp>\n", spaceBuf, CompOpNames[compOp]);
54 if (logicalOp != OpInvalidLogicalOp)
55 printf("%s <LogOp> %s </LogOp>\n", spaceBuf, LogOpNames[logicalOp]);
56 if (operand) printf("%s <Operand> VALUE </Operand>\n", spaceBuf);
57 if (operandPtr) printf("%s <OperandPtr> VALUE </OperandPtr>\n", spaceBuf);
58 if (comp2Op != OpInvalidComparisionOp)
59 printf("%s <Comp2Op> %s </Comp2Op>\n", spaceBuf, CompOpNames[comp2Op]);
60 if (operand2) printf("%s <Operand2> VALUE </Operand2>\n", spaceBuf);
61 if (operand2Ptr) printf("%s <Operand2Ptr> VALUE </Operand2Ptr>\n", spaceBuf);
62 //TEMP
63 //printf("<ISPUSHEDDOWN> %d </ISPUSHEDDOWN>\n", isPushedDown);
65 if (lhs) {
66 printf("%s <PRED-LEFT>\n", spaceBuf);
67 lhs->print(space+2);
68 printf("%s </PRED-LEFT>\n", spaceBuf);
70 if (rhs)
72 printf("%s <PRED-RIGHT>\n", spaceBuf);
73 rhs->print(space+2);
74 printf("%s </PRED-RIGHT>\n", spaceBuf);
76 printf("%s </PREDICATE>\n", spaceBuf);
80 void PredicateImpl::setTerm(const char* fName1, ComparisionOp op,
81 const char *fName2)
83 strcpy(fldName1, fName1);
84 strcpy(fldName2, fName2);
85 compOp = op;
86 operand = NULL;
87 operandPtr = NULL;
88 lhs = rhs = NULL;
89 parent = NULL;
90 logicalOp = OpInvalidLogicalOp;
91 comp2Op = OpInvalidComparisionOp;
92 operand2 =NULL;
93 operand2Ptr = NULL;
96 //Operand should be of the same type of the field.This is must
97 void PredicateImpl::setTerm(const char* fName1, ComparisionOp op, void *opnd)
99 strcpy(fldName1, fName1);
100 if (op == OpLike)
102 char *c = (char *) opnd;
103 while (*c != '\0')
105 if (*c == '_') *c = '?';
106 else if(*c == '%') *c = '*';
107 c++;
110 compOp = op;
111 operand = opnd;
112 operandPtr = NULL;
113 lhs = rhs = NULL;
114 parent = NULL;
115 logicalOp = OpInvalidLogicalOp;
116 comp2Op = OpInvalidComparisionOp;
117 operand2 =NULL;
118 operand2Ptr = NULL;
120 void PredicateImpl::setTerm(const char* fName1, ComparisionOp op,bool nullFlag)
122 strcpy(fldName1, fName1);
123 compOp = op;
124 isNull = nullFlag;
125 lhs = rhs = NULL;
126 operandPtr = NULL;
127 operand = NULL;
128 logicalOp = OpInvalidLogicalOp;
129 comp2Op = OpInvalidComparisionOp;
130 operand2 =NULL;
131 operand2Ptr = NULL;
134 void PredicateImpl::setTerm(const char* fName1, ComparisionOp op, void **opnd)
136 strcpy(fldName1, fName1);
137 compOp = op;
138 operand = NULL;
139 operandPtr = opnd;
140 lhs = rhs = NULL;
141 parent = NULL;
142 logicalOp = OpInvalidLogicalOp;
143 comp2Op = OpInvalidComparisionOp;
144 operand2 =NULL;
145 operand2Ptr = NULL;
147 void PredicateImpl::setTerm(const char* fName1, ComparisionOp op, void **opnd, AggType aType)
149 strcpy(fldName1, fName1);
150 compOp = op;
151 operand = NULL;
152 operandPtr = opnd;
153 lhs = rhs = NULL;
154 parent = NULL;
155 aggType = aType;
156 logicalOp = OpInvalidLogicalOp;
157 comp2Op = OpInvalidComparisionOp;
158 operand2 =NULL;
159 operand2Ptr = NULL;
162 void PredicateImpl::setTerm(const char* fName1, ComparisionOp op, void **opnd,
163 ComparisionOp op2, void **opnd2)
165 strcpy(fldName1, fName1);
166 compOp = op;
167 operand = NULL;
168 operandPtr = opnd;
169 lhs = rhs = NULL;
170 parent = NULL;
171 logicalOp = OpInvalidLogicalOp;
173 comp2Op = op2;
174 operand2=NULL;
175 operand2Ptr = opnd2;
178 void PredicateImpl::setParent(PredicateImpl *pImpl)
180 //if (parent != NULL) printf("Parent already set\n");
181 parent = pImpl;
182 return;
184 void PredicateImpl::setTerm(Predicate *p1, LogicalOp op, Predicate *p2 )
186 if (p2 == NULL && op != OpNot || op == OpNot && p2 != NULL)
188 //TODO::printError
189 printError(ErrBadArg, "Wrong argument passed\n");
190 return;
192 lhs = (PredicateImpl*)p1;
193 rhs = (PredicateImpl*)p2;
194 logicalOp = op;
195 compOp = OpInvalidComparisionOp;
196 if (lhs != NULL) lhs->setParent(this);
197 if (rhs != NULL) rhs->setParent(this);
198 return;
201 void PredicateImpl::setTable(Table *tbl)
203 if (NULL != lhs)
204 lhs->setTable(tbl);
205 if (NULL != rhs)
206 rhs->setTable(tbl);
207 table = tbl;
209 void PredicateImpl::setIfNoLeftRight()
211 if (NULL != lhs)
212 lhs->setIfNoLeftRight();
213 if (NULL != rhs)
214 rhs->setIfNoLeftRight();
215 if(NULL == lhs && NULL == rhs) isNoLeftRight=true;
216 return;
219 void PredicateImpl::setTuple(void *tpl)
221 if (isNoLeftRight) {
222 tuple=tpl;
223 return;
225 if (NULL != lhs)
226 lhs->setTuple(tpl);
227 if (NULL != rhs)
228 rhs->setTuple(tpl);
229 tuple = tpl;
231 void PredicateImpl::setProjectionList(List *lst)
233 if (NULL != lhs)
234 lhs->setProjectionList(lst);
235 if (NULL != rhs)
236 rhs->setProjectionList(lst);
237 projList = lst;
238 isBindBufSet = false;
240 bool PredicateImpl::isSingleTerm()
242 if (NULL == lhs && NULL == rhs && comp2Op == OpInvalidComparisionOp)
243 return true;
244 return false;
247 bool PredicateImpl::appendIfSameFld(char *fName, ComparisionOp op, void *buf)
249 char fieldName1[IDENTIFIER_LENGTH];
250 Table::getFieldNameAlone(fldName1, fieldName1);
251 if (strcmp(fName,fieldName1) == 0)
253 printDebug(DM_Predicate, "Field name matched");
255 //switching so that in case of joins, first other conditions are
256 //evaluated first and then matching tuples for join is evaluated
257 //otherwise it may give wrong result set
258 if (operand) {operand2 = operand; operand2Ptr = NULL; }
259 if (operandPtr) {operand2Ptr = operandPtr; operand2 = NULL; }
260 comp2Op = compOp;
261 compOp = op;
262 operand = buf;
263 operandPtr = NULL;
265 comp2Op = op;
266 operand2 = buf;
268 return true;
270 return false;
272 bool PredicateImpl::isIsNullInvolved()
274 bool lhsResult = true, rhsResult = true;
275 if (NULL != lhs)
277 lhsResult = lhs->isIsNullInvolved();
279 if (NULL != rhs)
281 rhsResult = rhs->isIsNullInvolved();
283 if (NULL != lhs)
285 if (lhsResult || rhsResult) return true;
286 if(compOp == isNull) return true;
288 return false;
290 bool PredicateImpl::isNotOrInvolved()
292 bool lhsResult = true, rhsResult = true;
293 if (NULL != lhs)
295 lhsResult = lhs->isNotOrInvolved();
297 if (NULL != rhs)
299 rhsResult = rhs->isNotOrInvolved();
301 if (NULL != lhs)
303 //Means it involves only Logical operator
304 switch(logicalOp)
306 case OpAnd:
307 if (lhsResult || rhsResult) return true; else return false;
308 break;
309 case OpOr:
310 return true;
311 break;
312 case OpNot:
313 default:
314 return true;
315 break;
318 return false;
321 DbRetVal PredicateImpl::evaluateLogical(bool &result)
323 bool rhsResult = false, lhsResult=false;
324 DbRetVal retCode =OK;
325 result = false;
326 if (NULL != lhs)
328 retCode = lhs->evaluate(lhsResult);
329 if (retCode != OK) return ErrInvalidExpr;
330 }else lhsResult = true;
331 if (NULL != rhs)
333 retCode = rhs->evaluate(rhsResult);
334 if (retCode != OK) return ErrInvalidExpr;
335 } else rhsResult = true;
336 if (NULL != lhs)
338 //Means it involves only Logical operator
339 if (OpAnd == logicalOp) {
340 if (lhsResult && rhsResult) result = true;
341 }else if (OpOr == logicalOp) {
342 if (lhsResult || rhsResult) result = true;
343 }else if (OpNot == logicalOp){
344 if (lhsResult) result = false; else result = true;
346 printDebug(DM_Predicate, "result is %d", result);
348 return OK;
351 DbRetVal PredicateImpl::evaluateForHaving(bool &result, AggTableImpl *aImpl, void *aggElement)
353 bool rhsResult = false, lhsResult=false;
354 DbRetVal retCode =OK;
355 result = false;
356 if (NULL != lhs)
358 retCode = lhs->evaluateForHaving(lhsResult, aImpl, aggElement);
359 if (retCode != OK) return ErrInvalidExpr;
360 }else lhsResult = true;
361 if (NULL != rhs)
363 retCode = rhs->evaluateForHaving(rhsResult, aImpl, aggElement);
364 if (retCode != OK) return ErrInvalidExpr;
365 } else rhsResult = true;
366 if (NULL != lhs)
368 if (OpAnd == logicalOp) {
369 if (lhsResult && rhsResult) result = true;
370 }else if (OpOr == logicalOp) {
371 if (lhsResult || rhsResult) result = true;
372 }else if (OpNot == logicalOp){
373 if (lhsResult) result = false; else result = true;
375 printDebug(DM_Predicate, "result is %d", result);
376 return OK;
379 void *val1 = NULL, *val2 =NULL;
380 int offset = aImpl->getAggOffset(fldName1, aggType);
381 val1 = (void*)((char*)aggElement + offset);
382 if (!isBindBufSet) {
383 //sets the type and length when it is called first time
384 FieldInfo *info = new FieldInfo();
385 DbRetVal rv = aImpl->getFieldInfo(fldName1, info);
386 if (aggType == AGG_AVG) {
387 type = typeDouble;
388 length = sizeof(double);
389 } else if (aggType == AGG_COUNT) {
390 type = typeInt;
391 length = sizeof(int);
392 } else {
393 type = info->type;
394 length = info->length;
396 delete info;
397 isBindBufSet = true;
399 if(operand != NULL && operandPtr == NULL)
401 val2 = (char*) operand;
403 else if(operand == NULL && operandPtr != NULL)
405 val2 = *(char**)operandPtr;
407 if (aggType == AGG_AVG) {
408 double dVal2 = 0;
409 AllDataType::convertToDouble(&dVal2, val2, type);
410 result = AllDataType::compareVal(val1, &dVal2, compOp, typeDouble, length);
412 else if (aggType == AGG_COUNT) {
413 int dVal2 = 0;
414 AllDataType::convertToInt(&dVal2, val2, type);
415 result = AllDataType::compareVal(val1, &dVal2, compOp, typeInt, length);
417 else
418 result = AllDataType::compareVal(val1, val2, compOp, type, length);
419 return OK;
422 DbRetVal PredicateImpl::evaluateLogicalForTable(bool &result, char *tuple)
424 bool rhsResult = false, lhsResult=false;
425 DbRetVal retCode =OK;
426 result = false;
427 if (NULL != lhs)
429 lhs->evaluateForTable(lhsResult, tuple);
430 }else lhsResult = true;
431 if (NULL != rhs)
433 rhs->evaluateForTable(rhsResult, tuple);
434 } else rhsResult = true;
435 if (NULL != lhs)
437 //Means it involves only Logical operator
438 if (OpAnd == logicalOp) {
439 if (lhsResult && rhsResult) result = true;
440 }else if (OpOr == logicalOp) {
441 if (lhsResult || rhsResult) result = true;
442 }else if (OpNot == logicalOp){
443 if (lhsResult) result = false; else result = true;
445 printDebug(DM_Predicate, "result is %d", result);
447 return OK;
449 void PredicateImpl::evaluateForTable(bool &result, char *tuple)
451 if (!isNoLeftRight) {
452 bool rhsResult = false;
453 if (NULL != rhs)
455 rhs->evaluateForTable(rhsResult, tuple);
456 if(rhsResult == false && OpAnd == logicalOp) {//do early return
457 return;
459 } else rhsResult = true;
460 bool lhsResult = false;
461 if (NULL != lhs)
463 lhs->evaluateForTable(lhsResult, tuple);
464 }else lhsResult = true;
465 if (NULL != lhs)
467 //Means it involves only Logical operator
468 if (OpAnd == logicalOp) {
469 if (lhsResult && rhsResult) result = true;
470 }else if (OpOr == logicalOp) {
471 if (lhsResult || rhsResult) result = true;
472 }else if (OpNot == logicalOp){
473 if (lhsResult) result = false; else result = true;
475 printDebug(DM_Predicate, "result is %d", result);
476 return ;
479 //Table null check of condition
480 if (isNullable) {
481 TableImpl *tImpl = (TableImpl*) table;
482 tImpl->setCurTuple(tuple);
483 bool isValueNull = table->isFldNull(fldPos);
484 if(compOp == OpIsNull)
486 if( (isValueNull && isNull) || (!isValueNull && !isNull) )
487 result = true;
488 else
489 result = false;
490 return;
492 if(isValueNull)
494 result=false;
495 return;
498 //the below code works only for single table
499 val1= tuple + offset1;
500 if(offset2 != -1 && operand == NULL && operandPtr == NULL)
501 val2 = tuple + offset2;
502 if (!isBindBufSet) {
503 //Assumes that fldName2 data type is also same for expr f1 <f2
504 //Note:Perf: Do not change the order below
505 if(operand == NULL && operandPtr != NULL)
507 val2 = *(char**)operandPtr;
508 if (compOp == OpLike) {
509 char *c = (char *)val2;
510 //OPT:If LIKE has only %, then no need to evaluate
511 if (*c == '%' && *(c+1) == '\0') {result=true; return;}
512 Util::changeWildcardChar(val2);
515 } else if (operand == NULL && operandPtr == NULL)
517 if(offset2 != -1)
518 val2 = tuple + offset2;
519 } else if(operand != NULL && operandPtr == NULL)
521 val2 = (char*) operand;
522 if (compOp == OpLike) {
523 char *c = (char *)val2;
524 if (*c == '%' && *(c+1) == '\0') {result=true; return;}
525 Util::changeWildcardChar(val2);
528 if(operand2 == NULL && operand2Ptr != NULL)
530 val3 = *(char**)operand2Ptr;
531 } else if(operand2 != NULL && operand2Ptr == NULL)
533 val3 = (char*) operand2;
535 isBindBufSet = true;
537 result = true;
538 if(val3) {
539 //printf(" val1 %d val3 %d\n", *(int*)val1, *(int*)val3);
540 result = AllDataType::compareVal(val1, val3, comp2Op, type,length);
541 if(result==false) return;
543 if (isPushedDown) {
544 return;
546 //printf(" val1 %d val2 %d\n", *(int*)val1, *(int*)val2);
547 result = AllDataType::compareVal(val1, val2, compOp, type,length);
548 //if (!result && val3) AllDataType::copyVal(val3,
549 return;
551 void* PredicateImpl::getValIfPointLookupOnInt(int &offset)
552 { //perf opt
553 if (NULL != lhs && NULL != rhs) return NULL;
554 if(typeInt != type || comp2Op !=OpInvalidComparisionOp) return NULL;
555 if (compOp != OpEquals) return NULL;
556 offset = offset1;
557 void *val =NULL;
558 if(operand == NULL && operandPtr != NULL)
560 val = *(void**)operandPtr;
561 } else if(operand != NULL && operandPtr == NULL)
563 val = (void*) operand;
565 return val;
567 void* PredicateImpl::getVal1IfBetweenOnInt(int &offset)
568 { //perf opt
569 if (NULL != lhs && NULL != rhs) return NULL;
570 if(typeInt != type) return NULL;
571 if (compOp != OpGreaterThanEquals ||
572 comp2Op !=OpLessThanEquals) return NULL;
573 offset = offset1;
574 void *val =NULL;
575 if(operand == NULL && operandPtr != NULL)
577 val = *(void**)operandPtr;
578 } else if(operand != NULL && operandPtr == NULL)
580 val = (void*) operand;
582 return val;
584 void* PredicateImpl::getVal2IfBetweenOnInt(int &offset)
585 { //perf opt
586 if (NULL != lhs && NULL != rhs) return NULL;
587 if(typeInt != type) return NULL;
588 if (compOp != OpGreaterThanEquals ||
589 comp2Op !=OpLessThanEquals) return NULL;
590 offset = offset1;
591 void *val =NULL;
592 if(operand2 == NULL && operand2Ptr != NULL)
594 val = *(void**)operand2Ptr;
595 } else if(operand2 != NULL && operand2Ptr == NULL)
597 val = (void*) operand2;
599 return val;
601 DbRetVal PredicateImpl::evaluate(bool &result)
603 if (!isNoLeftRight) {
604 bool rhsResult = false, lhsResult=false;
605 DbRetVal retCode =OK;
606 result = false;
607 if (NULL != lhs)
609 retCode = lhs->evaluate(lhsResult);
610 if (retCode < OK) return ErrInvalidExpr;
611 }else lhsResult = true;
612 if (NULL != rhs)
614 retCode = rhs->evaluate(rhsResult);
615 if (retCode < OK) return ErrInvalidExpr;
616 } else rhsResult = true;
617 if (NULL != lhs)
619 //Means it involves only Logical operator
620 if (OpAnd == logicalOp) {
621 if (lhsResult && rhsResult) result = true;
622 }else if (OpOr == logicalOp) {
623 if (lhsResult || rhsResult) result = true;
624 }else if (OpNot == logicalOp){
625 if (lhsResult) result = false; else result = true;
626 if ( ErrNullValues == retCode) result = false;
628 printDebug(DM_Predicate, "result is %d", result);
629 return OK;
632 //Means it is relational expression
633 //first operand is always field identifier
634 //get the value in the tuple
635 if (projList) {
636 if (dontEvaluate) {result= true; return OK; }
637 if (!isBindBufSet)
639 //for join node evaluation
640 ListIterator fIter = projList->getIterator();
641 JoinProjFieldInfo *def;
642 //char *val1, *val2;
643 while (fIter.hasElement())
645 def = (JoinProjFieldInfo*) fIter.nextElement();
646 if (NULL != def->bindBuf) {
647 if (0 == strcmp(fldName1, def->tabFieldName))
649 val1 = (char*)def->bindBuf;
650 type = def->type;
651 length = def->length;
652 break;
654 }else{
655 printError(ErrNotExists, "Field not binded %s.%s\n",
656 def->tableName, def->fieldName);
657 return ErrNotExists;
660 if (operand == NULL && operandPtr == NULL)
662 char fieldName2[IDENTIFIER_LENGTH];
663 memset(fieldName2, 0, IDENTIFIER_LENGTH);
664 Table::getFieldNameAlone(fldName2, fieldName2);
665 if (fieldName2) {
666 fIter.reset();
667 while (fIter.hasElement())
669 def = (JoinProjFieldInfo*) fIter.nextElement();
670 if (NULL != def->bindBuf) {
671 if (0 == strcmp(fldName2, def->tabFieldName))
673 val2 = (char*)def->bindBuf;
674 break;
676 }else{
677 printError(ErrNotExists, "Field not binded %s.%s\n",
678 def->tableName, def->fieldName);
679 return ErrNotExists;
684 else if(operand != NULL && operandPtr == NULL)
686 val2 = (char*) operand;
688 else if(operand == NULL && operandPtr != NULL)
690 val2 = *(char**)operandPtr;
692 isBindBufSet = true;
694 JoinTableImpl *jTable = (JoinTableImpl*) table;
695 if (jTable->isFldNullInt(fldName1) || jTable->isFldNullInt(fldName2))
697 result=false;
698 return ErrNullValues;
700 result = AllDataType::compareVal(val1, val2, compOp, type,
701 length);
702 return OK;
705 printf("PRABA::wrong method call\n");
706 //the below code works only for single table
707 val1= (char*)tuple + offset1;
708 if(offset2 != -1 && operand == NULL && operandPtr == NULL)
709 val2 = ((char*)tuple) + offset2;
710 if (!isBindBufSet) {
711 //Assumes that fldName2 data type is also same for expr f1 <f2
712 //Note:Perf: Do not change the order below
713 if(operand == NULL && operandPtr != NULL)
715 val2 = *(char**)operandPtr;
717 else if (operand == NULL && operandPtr == NULL)
719 if(offset2 != -1)
720 val2 = ((char*)tuple) + offset2;
722 else if(operand != NULL && operandPtr == NULL)
724 val2 = (char*) operand;
726 isBindBufSet = true;
728 result = AllDataType::compareVal(val1, val2, compOp, type,length);
729 return OK;
732 void PredicateImpl::solveForProjList(Table *tab)
734 if (NULL != lhs)
736 lhs->solveForProjList(tab);
738 if (NULL != rhs)
740 rhs->solveForProjList(tab);
742 table = tab;
743 if (NULL != lhs) return ;
744 bool isExist1=false;
745 bool isExist2=false;
746 if (projList)
748 ListIterator fIter = projList->getIterator();
749 JoinProjFieldInfo *def;
750 while (fIter.hasElement())
752 def = (JoinProjFieldInfo*) fIter.nextElement();
753 if (!isExist1 && 0 == strcmp(fldName1, def->tabFieldName))
755 isExist1=true;
757 if (!isExist2 && 0 == strcmp(fldName2, def->tabFieldName) )
759 isExist2=true;
762 if (!isExist1)
764 tab->bindFld(fldName1, NULL);
766 if (!isExist2 && strcmp(fldName2, "")!=0)
768 tab->bindFld(fldName2, NULL);
773 void PredicateImpl::setOffsetAndType()
775 if (NULL != lhs)
777 lhs->setOffsetAndType();
779 if (NULL != rhs)
781 rhs->setOffsetAndType();
783 char fieldName1[IDENTIFIER_LENGTH];
784 char fieldName2[IDENTIFIER_LENGTH];
785 memset(fieldName1, 0, IDENTIFIER_LENGTH);
786 memset(fieldName2, 0, IDENTIFIER_LENGTH);
787 Table::getFieldNameAlone(fldName1, fieldName1);
788 Table::getFieldNameAlone(fldName2, fieldName2);
789 //this function is called only from TableImpl
790 TableImpl *tImpl = (TableImpl*) table;
791 if(fieldName1){
792 FieldInfo *info = new FieldInfo();
793 tImpl->getFieldInfo(fieldName1, info);
794 offset1 = tImpl->getFieldOffset(fieldName1);
795 fldPos = tImpl->getFldPos(fieldName1);
796 type = info->type;
797 length = info->length;
798 isNullable = true;
799 if (info->isNull || info->isPrimary ||
800 info->isDefault || info->isAutoIncrement)
801 isNullable = false;
802 //printf("isNullable is set to %d\n", isNullable);
803 delete info;
806 if(fieldName2){
807 offset2 = tImpl->getFieldOffset(fieldName2);
808 if(typeUnknown == type)
809 type = tImpl->getFieldType(fieldName2);
814 bool PredicateImpl::pointLookupInvolved(const char *fname)
816 bool rhsResult, lhsResult;
817 if (NULL != lhs)
819 lhsResult = lhs->pointLookupInvolved(fname);
821 if (NULL != rhs)
823 rhsResult = rhs->pointLookupInvolved(fname);
825 if (NULL != lhs)
827 //Means it involves only Logical operator
828 switch(logicalOp)
830 case OpAnd:
831 //return lhsResult;
832 if (lhsResult || rhsResult) return true; else return false;
833 break;
834 case OpOr:
835 return false;
836 break;
837 case OpNot:
838 default:
839 return false;
840 break;
843 //Means it is relational expression
844 //first operand is always field identifier
845 char fieldName1[IDENTIFIER_LENGTH];
846 Table::getFieldNameAlone(fldName1, fieldName1);
847 if (OpEquals == compOp)
849 //for expressions f1 == f2 use full scan, so return false
850 if(NULL == operand && NULL == operandPtr) return false;
851 if(0 == strcmp(fieldName1, fname))
853 return true;
856 return false;
859 bool PredicateImpl::isBetweenInvolved(const char *fname)
861 bool rhsResult, lhsResult;
862 if (NULL != lhs)
864 lhsResult = lhs->isBetweenInvolved(fname);
866 if (NULL != rhs)
868 rhsResult = rhs->isBetweenInvolved(fname);
870 if (NULL != lhs)
872 switch(logicalOp)
874 case OpAnd:
875 if (lhsResult && rhsResult) return true; else return false;
876 break;
877 default:
878 return false;
879 break;
882 char fieldName1[IDENTIFIER_LENGTH];
883 Table::getFieldNameAlone(fldName1, fieldName1);
884 if ( OpGreaterThan == compOp || OpGreaterThanEquals == compOp)
886 if(0 == strcmp(fieldName1, fname))
888 return true;
891 return false;
894 bool PredicateImpl::rangeQueryInvolved(const char *fname)
896 bool rhsResult, lhsResult;
897 if (NULL != lhs)
899 lhsResult = lhs->rangeQueryInvolved(fname);
901 if (NULL != rhs)
903 rhsResult = rhs->rangeQueryInvolved(fname);
905 if (NULL != lhs)
907 switch(logicalOp)
909 case OpAnd:
910 if (lhsResult || rhsResult) return true; else return false;
911 break;
912 case OpOr:
913 return false;
914 break;
915 case OpNot:
916 default:
917 return false;
918 break;
921 //Means it is relational expression
922 //first operand is always field identifier
923 char fieldName1[IDENTIFIER_LENGTH];
924 Table::getFieldNameAlone(fldName1, fieldName1);
925 if (OpLessThan == compOp || OpLessThanEquals == compOp ||
926 OpGreaterThan == compOp || OpGreaterThanEquals == compOp)
928 //for expressions f1 == f2 use full scan, so return false
929 if(NULL == operand && NULL == operandPtr) return false;
930 if(0 == strcmp(fieldName1, fname))
932 return true;
935 return false;
938 void* PredicateImpl::opAndValPtrForIndexField(const char *fname, bool isUnique,ComparisionOp &op)
940 ComparisionOp lhsOp= OpInvalidComparisionOp, rhsOp= OpInvalidComparisionOp;
941 void *lhsRet=NULL, *rhsRet=NULL;
942 if (NULL != lhs)
944 lhsRet = lhs->opAndValPtrForIndexField(fname, isUnique, lhsOp);
946 if (NULL != rhs)
948 rhsRet = rhs->opAndValPtrForIndexField(fname, isUnique,rhsOp);
950 if (lhsRet && lhsOp == OpEquals) { op = lhsOp; return lhsRet;}
951 if (rhsRet && rhsOp == OpEquals) { op = rhsOp; return rhsRet;}
952 if (NULL != lhs)
954 if( lhsRet) { op = lhsOp; return lhsRet; }
955 if( rhsRet) { op = rhsOp; return rhsRet; }
957 char fieldName1[IDENTIFIER_LENGTH];
958 Table::getFieldNameAlone(fldName1, fieldName1);
959 //Means it is relational expression
960 //first operand is always field identifier
961 if(0 == strcmp(fieldName1, fname))
963 op = compOp;
964 if (isUnique && compOp != OpLessThan &&
965 compOp != OpLessThanEquals) isPushedDown = true;
966 if (operand) return operand; else return *(void**)operandPtr;
968 op = OpInvalidComparisionOp;
969 return NULL;
973 //called only in case of hash index scan
974 void* PredicateImpl::valPtrForIndexField(const char *fname, bool isUnique)
976 void *lhsRet=NULL, *rhsRet=NULL;
977 if (NULL != lhs)
979 lhsRet = lhs->valPtrForIndexField(fname, isUnique);
980 if ( lhsRet != NULL) return lhsRet;
982 if (NULL != rhs)
984 rhsRet = rhs->valPtrForIndexField(fname, isUnique);
985 if ( rhsRet != NULL) return rhsRet;
987 char fieldName1[IDENTIFIER_LENGTH];
988 Table::getFieldNameAlone(fldName1, fieldName1);
989 //Means it is relational expression
990 //first operand is always field identifier
991 if (OpEquals == compOp)
993 if(0 == strcmp(fieldName1, fname))
995 if (isUnique) isPushedDown = true;
996 if (operand) return operand; else return *(void**)operandPtr;
999 return NULL;
1001 ComparisionOp PredicateImpl::opForIndexField(const char *fname)
1003 ComparisionOp lhsRet= OpInvalidComparisionOp, rhsRet= OpInvalidComparisionOp;
1004 if (NULL != lhs)
1006 lhsRet = lhs->opForIndexField(fname);
1007 if ( lhsRet != OpInvalidComparisionOp) return lhsRet;
1010 if (NULL != rhs)
1012 rhsRet = rhs->opForIndexField(fname);
1013 if ( rhsRet != OpInvalidComparisionOp) return rhsRet;
1015 char fieldName1[IDENTIFIER_LENGTH];
1016 Table::getFieldNameAlone(fldName1, fieldName1);
1017 if(0 == strcmp(fieldName1, fname))
1019 return compOp;
1021 return OpInvalidComparisionOp;
1023 PredicateImpl* PredicateImpl::getTablePredicate()
1025 PredicateImpl *lhsRet = NULL, *rhsRet = NULL;
1026 if (NULL != lhs)
1028 lhsRet = lhs->getTablePredicate();
1029 if ( lhsRet != NULL) return lhsRet;
1031 if (NULL != rhs)
1033 rhsRet = rhs->getTablePredicate();
1034 if ( rhsRet != NULL) return rhsRet;
1036 if (operand || operandPtr )
1038 //printf("PRABA::getTablePredicate returning %s %d\n", fldName1, compOp);
1039 if (parent)
1041 if (this == parent->lhs) {
1042 parent->lhs = NULL;
1044 else {
1045 parent->rhs = NULL;
1047 parent = NULL;
1049 return this;
1051 return NULL;
1053 PredicateImpl* PredicateImpl::getJoinPredicate()
1055 PredicateImpl *lhsRet = NULL, *rhsRet = NULL;
1056 if (NULL != lhs)
1058 lhsRet = lhs->getJoinPredicate();
1059 if ( lhsRet != NULL) return lhsRet;
1061 if (NULL != rhs)
1063 rhsRet = rhs->getJoinPredicate();
1064 if ( rhsRet != NULL) return rhsRet;
1066 if (0 != strcmp(fldName2, ""))
1068 //printf("PRABA::getJoinPredicate returning %s %s\n", fldName1, fldName2);
1069 if (parent)
1071 if (this == parent->lhs)
1072 parent->lhs = NULL;
1073 else
1074 parent->rhs = NULL;
1075 parent = NULL;
1077 return this;
1079 return NULL;
1081 void PredicateImpl::removeIfNotNecessary()
1083 if (NULL != lhs)
1085 lhs->removeIfNotNecessary();
1087 if (NULL != rhs)
1089 rhs->removeIfNotNecessary();
1091 if (logicalOp != OpAnd) return;
1092 if (NULL == lhs && NULL == rhs)
1094 if (NULL == parent)
1096 return;
1098 if (this == parent->rhs) parent->rhs = NULL;
1099 else if (this == parent->lhs) parent->lhs = NULL;
1100 //TODO::PRABA::fix the leak below. if uncommented dumps core
1101 //delete this;
1102 //WARNINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
1103 //current object is deleted. do not any code here
1104 return;
1106 else if (NULL == lhs )
1108 //left side of the node is empty means we can remove this AND node
1109 //and place it as left or right of my parent where i am currently placed
1110 if (NULL == parent)
1112 return;
1114 if (this == parent->rhs) parent->rhs=this->rhs;
1115 else if (this == parent->lhs) parent->lhs = this->rhs;
1116 //TODO::PRABA::fix the leak below. if uncommented dumps core
1117 //delete this;
1118 //WARNINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
1119 //current object is deleted. do not any code here
1120 return;
1122 else if (NULL == rhs )
1124 //right side of the node is empty means we can remove this AND node
1125 //and place it as left or right of my parent where i am currently placed
1126 if (NULL == parent)
1128 return;
1130 if (this == parent->rhs) parent->rhs=this->lhs;
1131 else if (this == parent->lhs) parent->lhs = this->lhs;
1132 //TODO::PRABA::fix the leak below. if uncommented dumps core
1133 //delete this;
1134 //WARNINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
1135 //current object is deleted. do not any code here
1136 return;
1138 return;
1140 bool PredicateImpl::isDummyPredicate()
1142 if (NULL == lhs && NULL == rhs && NULL == parent
1143 && NULL == operand && NULL == operandPtr &&
1144 (0 == strcmp(fldName1, "")) && (0==strcmp(fldName2, "")))
1145 return true;
1146 else
1147 return false;
1149 PredicateImpl* PredicateImpl::getIfOneSidedPredicate()
1151 if (logicalOp != OpAnd) return NULL;
1152 if (NULL == lhs && NULL !=rhs)
1154 return rhs;
1156 if (NULL != lhs && NULL ==rhs)
1158 return lhs;
1160 return NULL;