1 /***************************************************************************
2 * Copyright (C) 2007 by www.databasecache.com *
3 * Contact: praba_tuty@databasecache.com *
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. *
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. *
15 ***************************************************************************/
18 #include<CatalogTables.h>
21 #include<PredicateImpl.h>
24 #include<JoinTableImpl.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; }
37 void PredicateImpl::print(int space
)
39 char spaceBuf
[IDENTIFIER_LENGTH
];
40 memset(spaceBuf
, 32, IDENTIFIER_LENGTH
);
41 spaceBuf
[space
] = '\0';
43 printf("%s <PREDICATE>\n", spaceBuf
);
44 if (0 != strcmp(fldName1
, "")) {
45 if (aggType
== AGG_UNKNOWN
)
46 printf("%s <FieldName1> %s </FieldName1>\n", spaceBuf
, fldName1
);
48 printf("%s <FieldName1> %s(%s) </FieldName1>\n", spaceBuf
,
49 aggNames
[aggType
-1], fldName1
);
51 if (0 != strcmp(fldName2
, ""))
52 printf("%s <FieldName2> %s </FieldName2>\n", spaceBuf
, fldName2
);
53 if (compOp
!= OpInvalidComparisionOp
)
54 printf("%s <CompOp> %s </CompOp>\n", spaceBuf
, CompOpNames
[compOp
]);
55 if (logicalOp
!= OpInvalidLogicalOp
)
56 printf("%s <LogOp> %s </LogOp>\n", spaceBuf
, LogOpNames
[logicalOp
]);
57 if (operand
) printf("%s <Operand> VALUE </Operand>\n", spaceBuf
);
58 if (operandPtr
) printf("%s <OperandPtr> VALUE </OperandPtr>\n", spaceBuf
);
59 if (comp2Op
!= OpInvalidComparisionOp
)
60 printf("%s <Comp2Op> %s </Comp2Op>\n", spaceBuf
, CompOpNames
[comp2Op
]);
61 if (operand2
) printf("%s <Operand2> VALUE </Operand2>\n", spaceBuf
);
62 if (operand2Ptr
) printf("%s <Operand2Ptr> VALUE </Operand2Ptr>\n", spaceBuf
);
64 //printf("<ISPUSHEDDOWN> %d </ISPUSHEDDOWN>\n", isPushedDown);
67 printf("%s <PRED-LEFT>\n", spaceBuf
);
69 printf("%s </PRED-LEFT>\n", spaceBuf
);
73 printf("%s <PRED-RIGHT>\n", spaceBuf
);
75 printf("%s </PRED-RIGHT>\n", spaceBuf
);
77 printf("%s </PREDICATE>\n", spaceBuf
);
81 void PredicateImpl::setTerm(const char* fName1
, ComparisionOp op
,
84 strcpy(fldName1
, fName1
);
85 strcpy(fldName2
, fName2
);
91 logicalOp
= OpInvalidLogicalOp
;
92 comp2Op
= OpInvalidComparisionOp
;
97 //Operand should be of the same type of the field.This is must
98 void PredicateImpl::setTerm(const char* fName1
, ComparisionOp op
, void *opnd
)
100 strcpy(fldName1
, fName1
);
106 logicalOp
= OpInvalidLogicalOp
;
107 comp2Op
= OpInvalidComparisionOp
;
112 void PredicateImpl::setTerm(Expression
*exp
, ComparisionOp op
, void **opnd
)
118 logicalOp
= OpInvalidLogicalOp
;
119 comp2Op
= OpInvalidComparisionOp
;
125 void PredicateImpl::setTerm(Expression
*exp1
, ComparisionOp op
, Expression
*exp2
)
131 logicalOp
= OpInvalidLogicalOp
;
132 comp2Op
= OpInvalidComparisionOp
;
139 void PredicateImpl::setTerm(Expression
*exp
, ComparisionOp op
, const char *fName2
)
141 strcpy(fldName2
, fName2
);
147 logicalOp
= OpInvalidLogicalOp
;
148 comp2Op
= OpInvalidComparisionOp
;
155 void PredicateImpl::setTerm(const char* fName1
, ComparisionOp op
,bool nullFlag
)
157 strcpy(fldName1
, fName1
);
163 logicalOp
= OpInvalidLogicalOp
;
164 comp2Op
= OpInvalidComparisionOp
;
169 void PredicateImpl::setTerm(const char* fName1
, ComparisionOp op
, void **opnd
)
171 strcpy(fldName1
, fName1
);
177 logicalOp
= OpInvalidLogicalOp
;
178 comp2Op
= OpInvalidComparisionOp
;
183 void PredicateImpl::setTerm(const char* fName1
, ComparisionOp op
, void **opnd
, AggType aType
)
185 strcpy(fldName1
, fName1
);
192 logicalOp
= OpInvalidLogicalOp
;
193 comp2Op
= OpInvalidComparisionOp
;
198 void PredicateImpl::setTerm(const char* fName1
, ComparisionOp op
, void **opnd
,
199 ComparisionOp op2
, void **opnd2
)
201 strcpy(fldName1
, fName1
);
207 logicalOp
= OpInvalidLogicalOp
;
214 void PredicateImpl::setParent(PredicateImpl
*pImpl
)
216 //if (parent != NULL) printf("Parent already set\n");
221 void PredicateImpl::setTerm(Predicate
*p1
, LogicalOp op
, Predicate
*p2
)
223 if (p2
== NULL
&& op
!= OpNot
|| op
== OpNot
&& p2
!= NULL
)
226 printError(ErrBadArg
, "Wrong argument passed\n");
229 lhs
= (PredicateImpl
*)p1
;
230 rhs
= (PredicateImpl
*)p2
;
232 compOp
= OpInvalidComparisionOp
;
233 if (lhs
!= NULL
) lhs
->setParent(this);
234 if (rhs
!= NULL
) rhs
->setParent(this);
238 void PredicateImpl::setTable(Table
*tbl
)
247 void PredicateImpl::setIfNoLeftRight()
250 lhs
->setIfNoLeftRight();
252 rhs
->setIfNoLeftRight();
253 if(NULL
== lhs
&& NULL
== rhs
) isNoLeftRight
=true;
257 void PredicateImpl::setTuple(void *tpl
)
270 void PredicateImpl::setProjectionList(List
*lst
)
273 lhs
->setProjectionList(lst
);
275 rhs
->setProjectionList(lst
);
277 isBindBufSet
= false;
280 bool PredicateImpl::isSingleTerm()
282 if (NULL
== lhs
&& NULL
== rhs
&& comp2Op
== OpInvalidComparisionOp
)
287 bool PredicateImpl::appendIfSameFld(char *fName
, ComparisionOp op
, void *buf
)
289 char fieldName1
[IDENTIFIER_LENGTH
];
290 Table::getFieldNameAlone(fldName1
, fieldName1
);
291 if (strcmp(fName
,fieldName1
) == 0)
293 printDebug(DM_Predicate
, "Field name matched");
295 //switching so that in case of joins, first other conditions are
296 //evaluated first and then matching tuples for join is evaluated
297 //otherwise it may give wrong result set
298 if (operand) {operand2 = operand; operand2Ptr = NULL; }
299 if (operandPtr) {operand2Ptr = operandPtr; operand2 = NULL; }
313 bool PredicateImpl::isIsNullInvolved()
315 bool lhsResult
= true, rhsResult
= true;
318 lhsResult
= lhs
->isIsNullInvolved();
322 rhsResult
= rhs
->isIsNullInvolved();
326 if (lhsResult
|| rhsResult
) return true;
327 if(compOp
== isNull
) return true;
332 bool PredicateImpl::isNotOrInvolved()
334 bool lhsResult
= true, rhsResult
= true;
337 lhsResult
= lhs
->isNotOrInvolved();
341 rhsResult
= rhs
->isNotOrInvolved();
345 //Means it involves only Logical operator
349 if (lhsResult
|| rhsResult
) return true; else return false;
363 void* PredicateImpl::getValIfPointLookupOnInt(int &offset
)
365 if (NULL
!= lhs
&& NULL
!= rhs
) return NULL
;
366 if(typeInt
!= type
|| comp2Op
!=OpInvalidComparisionOp
) return NULL
;
367 if (compOp
!= OpEquals
) return NULL
;
370 if(operand
== NULL
&& operandPtr
!= NULL
)
372 val
= *(void**)operandPtr
;
373 } else if(operand
!= NULL
&& operandPtr
== NULL
)
375 val
= (void*) operand
;
380 void* PredicateImpl::getVal1IfBetweenOnInt(int &offset
)
382 if (NULL
!= lhs
&& NULL
!= rhs
) return NULL
;
383 if(typeInt
!= type
) return NULL
;
384 if (compOp
!= OpGreaterThanEquals
||
385 comp2Op
!=OpLessThanEquals
) return NULL
;
388 if(operand
== NULL
&& operandPtr
!= NULL
)
390 val
= *(void**)operandPtr
;
391 } else if(operand
!= NULL
&& operandPtr
== NULL
)
393 val
= (void*) operand
;
398 void* PredicateImpl::getVal2IfBetweenOnInt(int &offset
)
400 if (NULL
!= lhs
&& NULL
!= rhs
) return NULL
;
401 if(typeInt
!= type
) return NULL
;
402 if (compOp
!= OpGreaterThanEquals
||
403 comp2Op
!=OpLessThanEquals
) return NULL
;
406 if(operand2
== NULL
&& operand2Ptr
!= NULL
)
408 val
= *(void**)operand2Ptr
;
409 } else if(operand2
!= NULL
&& operand2Ptr
== NULL
)
411 val
= (void*) operand2
;
416 void PredicateImpl::solveForProjList(Table
*tab
)
420 lhs
->solveForProjList(tab
);
424 rhs
->solveForProjList(tab
);
427 if (NULL
!= lhs
) return ;
432 ListIterator fIter
= projList
->getIterator();
433 JoinProjFieldInfo
*def
;
434 while (fIter
.hasElement())
436 def
= (JoinProjFieldInfo
*) fIter
.nextElement();
437 if (!isExist1
&& 0 == strcmp(fldName1
, def
->tabFieldName
))
441 if (!isExist2
&& 0 == strcmp(fldName2
, def
->tabFieldName
) )
448 tab
->bindFld(fldName1
, NULL
);
450 if (!isExist2
&& strcmp(fldName2
, "")!=0)
452 tab
->bindFld(fldName2
, NULL
);
457 void PredicateImpl::setOffsetAndType()
461 lhs
->setOffsetAndType();
465 rhs
->setOffsetAndType();
467 char fieldName1
[IDENTIFIER_LENGTH
];
468 char fieldName2
[IDENTIFIER_LENGTH
];
469 memset(fieldName1
, 0, IDENTIFIER_LENGTH
);
470 memset(fieldName2
, 0, IDENTIFIER_LENGTH
);
471 Table::getFieldNameAlone(fldName1
, fieldName1
);
472 Table::getFieldNameAlone(fldName2
, fieldName2
);
473 //this function is called only from TableImpl
474 TableImpl
*tImpl
= (TableImpl
*) table
;
476 FieldInfo
*info
= new FieldInfo();
477 tImpl
->getFieldInfo(fieldName1
, info
);
478 offset1
= tImpl
->getFieldOffset(fieldName1
);
479 fldPos
= tImpl
->getFldPos(fieldName1
);
481 length
= info
->length
;
483 if (info
->isNull
|| info
->isPrimary
|| info
->isAutoIncrement
)
485 //printf("isNullable is set to %d\n", isNullable);
490 offset2
= tImpl
->getFieldOffset(fieldName2
);
491 if(typeUnknown
== type
)
492 type
= tImpl
->getFieldType(fieldName2
);
497 bool PredicateImpl::pointLookupInvolved(const char *fname
)
499 bool rhsResult
, lhsResult
;
502 lhsResult
= lhs
->pointLookupInvolved(fname
);
506 rhsResult
= rhs
->pointLookupInvolved(fname
);
510 //Means it involves only Logical operator
515 if (lhsResult
|| rhsResult
) return true; else return false;
526 //Means it is relational expression
527 //first operand is always field identifier
528 char fieldName1
[IDENTIFIER_LENGTH
];
529 Table::getFieldNameAlone(fldName1
, fieldName1
);
530 if (OpEquals
== compOp
)
532 //for expressions f1 == f2 use full scan, so return false
533 if(NULL
== operand
&& NULL
== operandPtr
) return false;
534 if(0 == strcmp(fieldName1
, fname
))
542 bool PredicateImpl::isBetweenInvolved(const char *fname
)
544 bool rhsResult
, lhsResult
;
547 lhsResult
= lhs
->isBetweenInvolved(fname
);
551 rhsResult
= rhs
->isBetweenInvolved(fname
);
558 if (lhsResult
&& rhsResult
) return true; else return false;
565 char fieldName1
[IDENTIFIER_LENGTH
];
566 Table::getFieldNameAlone(fldName1
, fieldName1
);
567 if ( OpGreaterThan
== compOp
|| OpGreaterThanEquals
== compOp
)
569 if(0 == strcmp(fieldName1
, fname
))
577 bool PredicateImpl::rangeQueryInvolved(const char *fname
)
579 bool rhsResult
, lhsResult
;
582 lhsResult
= lhs
->rangeQueryInvolved(fname
);
586 rhsResult
= rhs
->rangeQueryInvolved(fname
);
593 if (lhsResult
|| rhsResult
) return true; else return false;
604 //Means it is relational expression
605 //first operand is always field identifier
606 char fieldName1
[IDENTIFIER_LENGTH
];
607 Table::getFieldNameAlone(fldName1
, fieldName1
);
608 if (OpLessThan
== compOp
|| OpLessThanEquals
== compOp
||
609 OpGreaterThan
== compOp
|| OpGreaterThanEquals
== compOp
)
611 //for expressions f1 == f2 use full scan, so return false
612 if(NULL
== operand
&& NULL
== operandPtr
) return false;
613 if(0 == strcmp(fieldName1
, fname
))
621 void* PredicateImpl::opAndValPtrForIndexField(const char *fname
, bool isUnique
,ComparisionOp
&op
)
623 ComparisionOp lhsOp
= OpInvalidComparisionOp
, rhsOp
= OpInvalidComparisionOp
;
624 void *lhsRet
=NULL
, *rhsRet
=NULL
;
627 lhsRet
= lhs
->opAndValPtrForIndexField(fname
, isUnique
, lhsOp
);
631 rhsRet
= rhs
->opAndValPtrForIndexField(fname
, isUnique
,rhsOp
);
633 if (lhsRet
&& lhsOp
== OpEquals
) { op
= lhsOp
; return lhsRet
;}
634 if (rhsRet
&& rhsOp
== OpEquals
) { op
= rhsOp
; return rhsRet
;}
637 if( lhsRet
) { op
= lhsOp
; return lhsRet
; }
638 if( rhsRet
) { op
= rhsOp
; return rhsRet
; }
640 char fieldName1
[IDENTIFIER_LENGTH
];
641 Table::getFieldNameAlone(fldName1
, fieldName1
);
642 //Means it is relational expression
643 //first operand is always field identifier
644 if(0 == strcmp(fieldName1
, fname
))
647 if (isUnique
&& compOp
!= OpLessThan
&&
648 compOp
!= OpLessThanEquals
&&
649 compOp
!= OpNotEquals
) isPushedDown
= true;
650 if (operand
) return operand
; else return *(void**)operandPtr
;
652 op
= OpInvalidComparisionOp
;
657 //called only in case of hash index scan
658 void* PredicateImpl::valPtrForIndexField(const char *fname
, bool isUnique
)
660 void *lhsRet
=NULL
, *rhsRet
=NULL
;
663 lhsRet
= lhs
->valPtrForIndexField(fname
, isUnique
);
664 if ( lhsRet
!= NULL
) return lhsRet
;
668 rhsRet
= rhs
->valPtrForIndexField(fname
, isUnique
);
669 if ( rhsRet
!= NULL
) return rhsRet
;
671 char fieldName1
[IDENTIFIER_LENGTH
];
672 Table::getFieldNameAlone(fldName1
, fieldName1
);
673 //Means it is relational expression
674 //first operand is always field identifier
675 if (OpEquals
== compOp
)
677 if(0 == strcmp(fieldName1
, fname
))
679 if (isUnique
) isPushedDown
= true;
680 if (operand
) return operand
; else return *(void**)operandPtr
;
686 ComparisionOp
PredicateImpl::opForIndexField(const char *fname
)
688 ComparisionOp lhsRet
= OpInvalidComparisionOp
, rhsRet
= OpInvalidComparisionOp
;
691 lhsRet
= lhs
->opForIndexField(fname
);
692 if ( lhsRet
!= OpInvalidComparisionOp
) return lhsRet
;
697 rhsRet
= rhs
->opForIndexField(fname
);
698 if ( rhsRet
!= OpInvalidComparisionOp
) return rhsRet
;
700 char fieldName1
[IDENTIFIER_LENGTH
];
701 Table::getFieldNameAlone(fldName1
, fieldName1
);
702 if(0 == strcmp(fieldName1
, fname
))
706 return OpInvalidComparisionOp
;
709 PredicateImpl
* PredicateImpl::getTablePredicate()
711 PredicateImpl
*lhsRet
= NULL
, *rhsRet
= NULL
;
714 lhsRet
= lhs
->getTablePredicate();
715 if ( lhsRet
!= NULL
) return lhsRet
;
719 rhsRet
= rhs
->getTablePredicate();
720 if ( rhsRet
!= NULL
) return rhsRet
;
722 if (operand
|| operandPtr
)
724 //printf("PRABA::getTablePredicate returning %s %d\n", fldName1, compOp);
727 if (this == parent
->lhs
) {
740 PredicateImpl
* PredicateImpl::getJoinPredicate()
742 PredicateImpl
*lhsRet
= NULL
, *rhsRet
= NULL
;
745 lhsRet
= lhs
->getJoinPredicate();
746 if ( lhsRet
!= NULL
) return lhsRet
;
750 rhsRet
= rhs
->getJoinPredicate();
751 if ( rhsRet
!= NULL
) return rhsRet
;
753 if (0 != strcmp(fldName2
, ""))
755 //printf("PRABA::getJoinPredicate returning %s %s\n", fldName1, fldName2);
758 if (this == parent
->lhs
)
769 void PredicateImpl::removeIfNotNecessary()
773 lhs
->removeIfNotNecessary();
777 rhs
->removeIfNotNecessary();
779 if (logicalOp
!= OpAnd
) return;
780 if (NULL
== lhs
&& NULL
== rhs
)
786 if (this == parent
->rhs
) parent
->rhs
= NULL
;
787 else if (this == parent
->lhs
) parent
->lhs
= NULL
;
788 //TODO::PRABA::fix the leak below. if uncommented dumps core
790 //WARNINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
791 //current object is deleted. do not any code here
794 else if (NULL
== lhs
)
796 //left side of the node is empty means we can remove this AND node
797 //and place it as left or right of my parent where i am currently placed
802 if (this == parent
->rhs
) parent
->rhs
=this->rhs
;
803 else if (this == parent
->lhs
) parent
->lhs
= this->rhs
;
804 //TODO::PRABA::fix the leak below. if uncommented dumps core
806 //WARNINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
807 //current object is deleted. do not any code here
810 else if (NULL
== rhs
)
812 //right side of the node is empty means we can remove this AND node
813 //and place it as left or right of my parent where i am currently placed
818 if (this == parent
->rhs
) parent
->rhs
=this->lhs
;
819 else if (this == parent
->lhs
) parent
->lhs
= this->lhs
;
820 //TODO::PRABA::fix the leak below. if uncommented dumps core
822 //WARNINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
823 //current object is deleted. do not any code here
829 bool PredicateImpl::isDummyPredicate()
831 if (NULL
== lhs
&& NULL
== rhs
&& NULL
== parent
832 && NULL
== operand
&& NULL
== operandPtr
&&
833 (0 == strcmp(fldName1
, "")) && (0==strcmp(fldName2
, "")))
839 PredicateImpl
* PredicateImpl::getIfOneSidedPredicate()
841 if (logicalOp
!= OpAnd
) return NULL
;
842 if (NULL
== lhs
&& NULL
!=rhs
)
846 if (NULL
!= lhs
&& NULL
==rhs
)