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>
25 #include<JoinTableImpl.h>
27 void PredicateImpl::print(int space
)
29 char spaceBuf
[IDENTIFIER_LENGTH
];
30 memset(spaceBuf
, 32, IDENTIFIER_LENGTH
);
31 spaceBuf
[space
] = '\0';
33 printf("%s <PREDICATE>\n", spaceBuf
);
34 printf("%s <FieldName1> %s </FieldName1>\n", spaceBuf
, fldName1
);
35 printf("%s <FieldName2> %s </FieldName2>\n", spaceBuf
, fldName2
);
36 printf("%s <CompOp> %s </CompOp>\n", spaceBuf
, CompOpNames
[compOp
]);
37 printf("%s <LogOp> %s </LogOp>\n", spaceBuf
, LogOpNames
[logicalOp
]);
38 printf("%s <Operand> %x </Operand>\n", spaceBuf
, operand
);
39 printf("%s <OperandPtr> %x </OperandPtr>\n", spaceBuf
, operandPtr
);
41 printf("%s <PRED-LEFT>\n", spaceBuf
);
43 printf("%s </PRED-LEFT>\n", spaceBuf
);
47 printf("%s <PRED-RIGHT>\n", spaceBuf
);
49 printf("%s </PRED-RIGHT>\n", spaceBuf
);
51 printf("%s </PREDICATE>\n", spaceBuf
);
55 void PredicateImpl::setTerm(const char* fName1
, ComparisionOp op
,
58 strcpy(fldName1
, fName1
);
59 strcpy(fldName2
, fName2
);
65 logicalOp
= OpInvalidLogicalOp
;
68 //Operand should be of the same type of the field.This is must
69 void PredicateImpl::setTerm(const char* fName1
, ComparisionOp op
, void *opnd
)
71 strcpy(fldName1
, fName1
);
74 char *c
= (char *) opnd
;
77 if (*c
== '_') *c
= '?';
78 else if(*c
== '%') *c
= '*';
87 logicalOp
= OpInvalidLogicalOp
;
90 void PredicateImpl::setTerm(const char* fName1
, ComparisionOp op
, void **opnd
)
92 strcpy(fldName1
, fName1
);
98 logicalOp
= OpInvalidLogicalOp
;
101 void PredicateImpl::setParent(PredicateImpl
*pImpl
)
103 if (parent
!= NULL
) printf("Parent already set\n");
107 void PredicateImpl::setTerm(Predicate
*p1
, LogicalOp op
, Predicate
*p2
)
109 if (p2
== NULL
&& op
!= OpNot
|| op
== OpNot
&& p2
!= NULL
)
112 printError(ErrBadArg
, "Wrong argument passed\n");
115 lhs
= (PredicateImpl
*)p1
;
116 rhs
= (PredicateImpl
*)p2
;
118 compOp
= OpInvalidComparisionOp
;
119 if (lhs
!= NULL
) lhs
->setParent(this);
120 if (rhs
!= NULL
) rhs
->setParent(this);
124 void PredicateImpl::setTable(Table
*tbl
)
127 lhs
->setTable((TableImpl
*)tbl
);
129 rhs
->setTable((TableImpl
*)tbl
);
130 table
= (TableImpl
*)tbl
;
133 void PredicateImpl::setTuple(void *tpl
)
141 void PredicateImpl::setProjectionList(List
*lst
)
144 lhs
->setProjectionList(lst
);
146 rhs
->setProjectionList(lst
);
147 if (operand
== NULL
&& operandPtr
== NULL
)
150 bool PredicateImpl::isSingleTerm()
152 if (NULL
== lhs
&& NULL
== rhs
) return true; else false;
156 bool PredicateImpl::isNotOrInvolved()
158 bool lhsResult
= true, rhsResult
= true;
161 lhsResult
= lhs
->isNotOrInvolved();
165 rhsResult
= rhs
->isNotOrInvolved();
169 //Means it involves only Logical operator
173 if (lhsResult
|| rhsResult
) return true; else return false;
187 DbRetVal
PredicateImpl::evaluate(bool &result
)
189 bool rhsResult
= false, lhsResult
=false;
190 DbRetVal retCode
=OK
;
194 retCode
= lhs
->evaluate(lhsResult
);
195 if (retCode
!= OK
) return ErrInvalidExpr
;
196 }else lhsResult
= true;
199 retCode
= rhs
->evaluate(rhsResult
);
200 if (retCode
!= OK
) return ErrInvalidExpr
;
201 } else rhsResult
= true;
204 //Means it involves only Logical operator
208 if (lhsResult
&& rhsResult
) result
= true;
211 if (lhsResult
|| rhsResult
) result
= true;
214 if (lhsResult
) result
= false; else result
= true;
217 return ErrInvalidExpr
;
220 printDebug(DM_Predicate
, "result is %d", result
);
223 //Means it is relational expression
224 //first operand is always field identifier
225 //get the value in the tuple
226 char fieldName1
[IDENTIFIER_LENGTH
];
227 char fieldName2
[IDENTIFIER_LENGTH
];
228 memset(fieldName1
, 0, IDENTIFIER_LENGTH
);
229 memset(fieldName2
, 0, IDENTIFIER_LENGTH
);
230 Table::getFieldNameAlone(fldName1
, fieldName1
);
231 Table::getFieldNameAlone(fldName2
, fieldName2
);
234 DataType type
=typeUnknown
;
236 //for join node evaluation
237 ListIterator fIter
= projList
->getIterator();
238 JoinProjFieldInfo
*def
;
240 while (fIter
.hasElement())
242 def
= (JoinProjFieldInfo
*) fIter
.nextElement();
243 if (NULL
!= def
->appBuf
) {
244 if (0 == strcmp(fldName1
, def
->tabFieldName
))
246 val1
= (char*)def
->bindBuf
;
248 length
= def
->length
;
252 printError(ErrNotExists
, "Field not binded %s.%s\n",
253 def
->tableName
, def
->fieldName
);
257 if (operand
== NULL
&& operandPtr
== NULL
)
261 while (fIter
.hasElement())
263 def
= (JoinProjFieldInfo
*) fIter
.nextElement();
264 if (NULL
!= def
->appBuf
) {
265 if (0 == strcmp(fldName2
, def
->tabFieldName
))
267 val2
= (char*)def
->bindBuf
;
271 printError(ErrNotExists
, "Field not binded %s.%s\n",
272 def
->tableName
, def
->fieldName
);
278 else if(operand
!= NULL
&& operandPtr
== NULL
)
280 val2
= (char*) operand
;
282 else if(operand
== NULL
&& operandPtr
!= NULL
)
284 val2
= *(char**)operandPtr
;
286 if (compOp
== OpLike
) result
= ! fnmatch(val2
, val1
, 0);
287 else result
= AllDataType::compareVal(val1
, val2
, compOp
, type
,
291 //the below code works only for single table
292 int offset1
, offset2
;
293 offset1
= table
->getFieldOffset(fieldName1
);
294 //TODO::do not call getFieldXXX many times, instead get it using getFieldInfo
296 //Assumes that fldName2 data type is also same for expr f1 <f2
297 DataType srcType
= table
->getFieldType(fieldName1
);
298 val1
= ((char*) tuple
) + offset1
;
299 if (operand
== NULL
&& operandPtr
== NULL
)
302 offset2
= table
->getFieldOffset(fieldName2
);
303 val2
= ((char*)tuple
) + offset2
;
306 else if(operand
!= NULL
&& operandPtr
== NULL
)
308 val2
= (char*) operand
;
310 else if(operand
== NULL
&& operandPtr
!= NULL
)
312 val2
= *(char**)operandPtr
;
315 if (compOp
== OpLike
) result
= ! fnmatch(val2
, val1
, 0);
316 else result
= AllDataType::compareVal(val1
, val2
, compOp
, srcType
,
317 table
->getFieldLength(fieldName1
));
321 bool PredicateImpl::pointLookupInvolved(const char *fname
)
323 bool rhsResult
, lhsResult
;
326 lhsResult
= lhs
->pointLookupInvolved(fname
);
330 rhsResult
= rhs
->pointLookupInvolved(fname
);
334 //Means it involves only Logical operator
339 if (lhsResult
|| rhsResult
) return true; else return false;
350 //Means it is relational expression
351 //first operand is always field identifier
352 char fieldName1
[IDENTIFIER_LENGTH
];
353 Table::getFieldNameAlone(fldName1
, fieldName1
);
354 if (OpEquals
== compOp
)
356 //for expressions f1 == f2 use full scan, so return false
357 if(NULL
== operand
&& NULL
== operandPtr
) return false;
358 if(0 == strcmp(fieldName1
, fname
))
365 bool PredicateImpl::rangeQueryInvolved(const char *fname
)
367 bool rhsResult
, lhsResult
;
370 lhsResult
= lhs
->rangeQueryInvolved(fname
);
374 rhsResult
= rhs
->rangeQueryInvolved(fname
);
381 if (lhsResult
|| rhsResult
) return true; else return false;
392 //Means it is relational expression
393 //first operand is always field identifier
394 char fieldName1
[IDENTIFIER_LENGTH
];
395 Table::getFieldNameAlone(fldName1
, fieldName1
);
396 if (OpLessThan
== compOp
|| OpLessThanEquals
== compOp
||
397 OpGreaterThan
== compOp
|| OpGreaterThanEquals
== compOp
)
399 //for expressions f1 == f2 use full scan, so return false
400 if(NULL
== operand
&& NULL
== operandPtr
) return false;
401 if(0 == strcmp(fieldName1
, fname
))
410 void* PredicateImpl::valPtrForIndexField(const char *fname
)
412 void *lhsRet
=NULL
, *rhsRet
=NULL
;
415 lhsRet
= lhs
->valPtrForIndexField(fname
);
416 if ( lhsRet
!= NULL
) return lhsRet
;
420 rhsRet
= rhs
->valPtrForIndexField(fname
);
421 if ( rhsRet
!= NULL
) return rhsRet
;
423 char fieldName1
[IDENTIFIER_LENGTH
];
424 Table::getFieldNameAlone(fldName1
, fieldName1
);
425 //Means it is relational expression
426 //first operand is always field identifier
427 //if (OpEquals == compOp)
429 if(0 == strcmp(fieldName1
, fname
))
431 if (operand
) return operand
; else return *(void**)operandPtr
;
436 ComparisionOp
PredicateImpl::opForIndexField(const char *fname
)
438 ComparisionOp lhsRet
= OpInvalidComparisionOp
, rhsRet
= OpInvalidComparisionOp
;
441 lhsRet
= lhs
->opForIndexField(fname
);
442 if ( lhsRet
!= OpInvalidComparisionOp
) return lhsRet
;
447 rhsRet
= rhs
->opForIndexField(fname
);
448 if ( rhsRet
!= OpInvalidComparisionOp
) return rhsRet
;
450 char fieldName1
[IDENTIFIER_LENGTH
];
451 Table::getFieldNameAlone(fldName1
, fieldName1
);
452 if(0 == strcmp(fieldName1
, fname
))
456 return OpInvalidComparisionOp
;
458 PredicateImpl
* PredicateImpl::getTablePredicate()
460 PredicateImpl
*lhsRet
= NULL
, *rhsRet
= NULL
;
463 lhsRet
= lhs
->getTablePredicate();
464 if ( lhsRet
!= NULL
) return lhsRet
;
468 rhsRet
= rhs
->getTablePredicate();
469 if ( rhsRet
!= NULL
) return rhsRet
;
471 if (operand
|| operandPtr
)
473 printf("PRABA::getTablePredicate returning %s %d\n", fldName1
, compOp
);
476 if (this == parent
->lhs
) {
488 PredicateImpl
* PredicateImpl::getJoinPredicate()
490 PredicateImpl
*lhsRet
= NULL
, *rhsRet
= NULL
;
493 lhsRet
= lhs
->getJoinPredicate();
494 if ( lhsRet
!= NULL
) return lhsRet
;
498 rhsRet
= rhs
->getJoinPredicate();
499 if ( rhsRet
!= NULL
) return rhsRet
;
501 if (0 != strcmp(fldName2
, ""))
503 printf("PRABA::getJoinPredicate returning %s %s\n", fldName1
, fldName2
);
506 if (this == parent
->lhs
)
516 void PredicateImpl::removeIfNotNecessary()
520 lhs
->removeIfNotNecessary();
524 rhs
->removeIfNotNecessary();
526 if (logicalOp
!= OpAnd
) return;
527 if (NULL
== lhs
&& NULL
== rhs
)
533 if (this == parent
->rhs
) parent
->rhs
= NULL
;
534 else if (this == parent
->lhs
) parent
->lhs
= NULL
;
536 //WARNINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
537 //current object is deleted. do not any code here
540 else if (NULL
== lhs
)
542 //left side of the node is empty means we can remove this AND node
543 //and place it as left or right of my parent where i am currently placed
548 if (this == parent
->rhs
) parent
->rhs
=this->rhs
;
549 else if (this == parent
->lhs
) parent
->lhs
= this->rhs
;
551 //WARNINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
552 //current object is deleted. do not any code here
555 else if (NULL
== rhs
)
557 //right side of the node is empty means we can remove this AND node
558 //and place it as left or right of my parent where i am currently placed
563 if (this == parent
->rhs
) parent
->rhs
=this->lhs
;
564 else if (this == parent
->lhs
) parent
->lhs
= this->lhs
;
566 //WARNINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
567 //current object is deleted. do not any code here
572 bool PredicateImpl::isDummyPredicate()
574 if (NULL
== lhs
&& NULL
== rhs
&& NULL
== parent
575 && NULL
== operand
&& NULL
== operandPtr
&&
576 (0 == strcmp(fldName1
, "")) && (0==strcmp(fldName2
, "")))
581 PredicateImpl
* PredicateImpl::getIfOneSidedPredicate()
583 if (logicalOp
!= OpAnd
) return NULL
;
584 if (NULL
== lhs
&& NULL
!=rhs
)
588 if (NULL
!= lhs
&& NULL
==rhs
)