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 //PRABA::commented. may need to remove the code in evaluate at the end
148 //if (operand == NULL && operandPtr == NULL)
151 bool PredicateImpl::isSingleTerm()
153 if (NULL
== lhs
&& NULL
== rhs
) return true; else false;
157 bool PredicateImpl::isNotOrInvolved()
159 bool lhsResult
= true, rhsResult
= true;
162 lhsResult
= lhs
->isNotOrInvolved();
166 rhsResult
= rhs
->isNotOrInvolved();
170 //Means it involves only Logical operator
174 if (lhsResult
|| rhsResult
) return true; else return false;
188 DbRetVal
PredicateImpl::evaluate(bool &result
)
190 bool rhsResult
= false, lhsResult
=false;
191 DbRetVal retCode
=OK
;
195 retCode
= lhs
->evaluate(lhsResult
);
196 if (retCode
!= OK
) return ErrInvalidExpr
;
197 }else lhsResult
= true;
200 retCode
= rhs
->evaluate(rhsResult
);
201 if (retCode
!= OK
) return ErrInvalidExpr
;
202 } else rhsResult
= true;
205 //Means it involves only Logical operator
209 if (lhsResult
&& rhsResult
) result
= true;
212 if (lhsResult
|| rhsResult
) result
= true;
215 if (lhsResult
) result
= false; else result
= true;
218 return ErrInvalidExpr
;
221 printDebug(DM_Predicate
, "result is %d", result
);
224 //Means it is relational expression
225 //first operand is always field identifier
226 //get the value in the tuple
227 char fieldName1
[IDENTIFIER_LENGTH
];
228 char fieldName2
[IDENTIFIER_LENGTH
];
229 memset(fieldName1
, 0, IDENTIFIER_LENGTH
);
230 memset(fieldName2
, 0, IDENTIFIER_LENGTH
);
231 Table::getFieldNameAlone(fldName1
, fieldName1
);
232 Table::getFieldNameAlone(fldName2
, fieldName2
);
235 DataType type
=typeUnknown
;
237 //for join node evaluation
238 ListIterator fIter
= projList
->getIterator();
239 JoinProjFieldInfo
*def
;
241 while (fIter
.hasElement())
243 def
= (JoinProjFieldInfo
*) fIter
.nextElement();
244 if (NULL
!= def
->appBuf
) {
245 if (0 == strcmp(fldName1
, def
->tabFieldName
))
247 val1
= (char*)def
->bindBuf
;
249 length
= def
->length
;
253 printError(ErrNotExists
, "Field not binded %s.%s\n",
254 def
->tableName
, def
->fieldName
);
258 if (operand
== NULL
&& operandPtr
== NULL
)
262 while (fIter
.hasElement())
264 def
= (JoinProjFieldInfo
*) fIter
.nextElement();
265 if (NULL
!= def
->appBuf
) {
266 if (0 == strcmp(fldName2
, def
->tabFieldName
))
268 val2
= (char*)def
->bindBuf
;
272 printError(ErrNotExists
, "Field not binded %s.%s\n",
273 def
->tableName
, def
->fieldName
);
279 else if(operand
!= NULL
&& operandPtr
== NULL
)
281 val2
= (char*) operand
;
283 else if(operand
== NULL
&& operandPtr
!= NULL
)
285 val2
= *(char**)operandPtr
;
287 if (compOp
== OpLike
) result
= ! fnmatch(val2
, val1
, 0);
288 else result
= AllDataType::compareVal(val1
, val2
, compOp
, type
,
292 //the below code works only for single table
293 int offset1
, offset2
;
295 offset1
= table
->getFieldOffset(fieldName1
);
296 //TODO::do not call getFieldXXX many times, instead get it using getFieldInfo
298 //Assumes that fldName2 data type is also same for expr f1 <f2
299 DataType srcType
= table
->getFieldType(fieldName1
);
300 val1
= ((char*) tuple
) + offset1
;
301 if (operand
== NULL
&& operandPtr
== NULL
)
304 offset2
= table
->getFieldOffset(fieldName2
);
305 val2
= ((char*)tuple
) + offset2
;
308 else if(operand
!= NULL
&& operandPtr
== NULL
)
310 val2
= (char*) operand
;
312 else if(operand
== NULL
&& operandPtr
!= NULL
)
314 val2
= *(char**)operandPtr
;
317 if (compOp
== OpLike
) result
= ! fnmatch(val2
, val1
, 0);
318 else result
= AllDataType::compareVal(val1
, val2
, compOp
, srcType
,
319 table
->getFieldLength(fieldName1
));
323 bool PredicateImpl::pointLookupInvolved(const char *fname
)
325 bool rhsResult
, lhsResult
;
328 lhsResult
= lhs
->pointLookupInvolved(fname
);
332 rhsResult
= rhs
->pointLookupInvolved(fname
);
336 //Means it involves only Logical operator
341 if (lhsResult
|| rhsResult
) return true; else return false;
352 //Means it is relational expression
353 //first operand is always field identifier
354 char fieldName1
[IDENTIFIER_LENGTH
];
355 Table::getFieldNameAlone(fldName1
, fieldName1
);
356 if (OpEquals
== compOp
)
358 //for expressions f1 == f2 use full scan, so return false
359 if(NULL
== operand
&& NULL
== operandPtr
) return false;
360 if(0 == strcmp(fieldName1
, fname
))
367 bool PredicateImpl::rangeQueryInvolved(const char *fname
)
369 bool rhsResult
, lhsResult
;
372 lhsResult
= lhs
->rangeQueryInvolved(fname
);
376 rhsResult
= rhs
->rangeQueryInvolved(fname
);
383 if (lhsResult
|| rhsResult
) return true; else return false;
394 //Means it is relational expression
395 //first operand is always field identifier
396 char fieldName1
[IDENTIFIER_LENGTH
];
397 Table::getFieldNameAlone(fldName1
, fieldName1
);
398 if (OpLessThan
== compOp
|| OpLessThanEquals
== compOp
||
399 OpGreaterThan
== compOp
|| OpGreaterThanEquals
== compOp
)
401 //for expressions f1 == f2 use full scan, so return false
402 if(NULL
== operand
&& NULL
== operandPtr
) return false;
403 if(0 == strcmp(fieldName1
, fname
))
412 void* PredicateImpl::valPtrForIndexField(const char *fname
)
414 void *lhsRet
=NULL
, *rhsRet
=NULL
;
417 lhsRet
= lhs
->valPtrForIndexField(fname
);
418 if ( lhsRet
!= NULL
) return lhsRet
;
422 rhsRet
= rhs
->valPtrForIndexField(fname
);
423 if ( rhsRet
!= NULL
) return rhsRet
;
425 char fieldName1
[IDENTIFIER_LENGTH
];
426 Table::getFieldNameAlone(fldName1
, fieldName1
);
427 //Means it is relational expression
428 //first operand is always field identifier
429 //if (OpEquals == compOp)
431 if(0 == strcmp(fieldName1
, fname
))
433 if (operand
) return operand
; else return *(void**)operandPtr
;
438 ComparisionOp
PredicateImpl::opForIndexField(const char *fname
)
440 ComparisionOp lhsRet
= OpInvalidComparisionOp
, rhsRet
= OpInvalidComparisionOp
;
443 lhsRet
= lhs
->opForIndexField(fname
);
444 if ( lhsRet
!= OpInvalidComparisionOp
) return lhsRet
;
449 rhsRet
= rhs
->opForIndexField(fname
);
450 if ( rhsRet
!= OpInvalidComparisionOp
) return rhsRet
;
452 char fieldName1
[IDENTIFIER_LENGTH
];
453 Table::getFieldNameAlone(fldName1
, fieldName1
);
454 if(0 == strcmp(fieldName1
, fname
))
458 return OpInvalidComparisionOp
;
460 PredicateImpl
* PredicateImpl::getTablePredicate()
462 PredicateImpl
*lhsRet
= NULL
, *rhsRet
= NULL
;
465 lhsRet
= lhs
->getTablePredicate();
466 if ( lhsRet
!= NULL
) return lhsRet
;
470 rhsRet
= rhs
->getTablePredicate();
471 if ( rhsRet
!= NULL
) return rhsRet
;
473 if (operand
|| operandPtr
)
475 //printf("PRABA::getTablePredicate returning %s %d\n", fldName1, compOp);
478 if (this == parent
->lhs
) {
490 PredicateImpl
* PredicateImpl::getJoinPredicate()
492 PredicateImpl
*lhsRet
= NULL
, *rhsRet
= NULL
;
495 lhsRet
= lhs
->getJoinPredicate();
496 if ( lhsRet
!= NULL
) return lhsRet
;
500 rhsRet
= rhs
->getJoinPredicate();
501 if ( rhsRet
!= NULL
) return rhsRet
;
503 if (0 != strcmp(fldName2
, ""))
505 //printf("PRABA::getJoinPredicate returning %s %s\n", fldName1, fldName2);
508 if (this == parent
->lhs
)
518 void PredicateImpl::removeIfNotNecessary()
522 lhs
->removeIfNotNecessary();
526 rhs
->removeIfNotNecessary();
528 if (logicalOp
!= OpAnd
) return;
529 if (NULL
== lhs
&& NULL
== rhs
)
535 if (this == parent
->rhs
) parent
->rhs
= NULL
;
536 else if (this == parent
->lhs
) parent
->lhs
= NULL
;
538 //WARNINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
539 //current object is deleted. do not any code here
542 else if (NULL
== lhs
)
544 //left side of the node is empty means we can remove this AND node
545 //and place it as left or right of my parent where i am currently placed
550 if (this == parent
->rhs
) parent
->rhs
=this->rhs
;
551 else if (this == parent
->lhs
) parent
->lhs
= this->rhs
;
553 //WARNINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
554 //current object is deleted. do not any code here
557 else if (NULL
== rhs
)
559 //right side of the node is empty means we can remove this AND node
560 //and place it as left or right of my parent where i am currently placed
565 if (this == parent
->rhs
) parent
->rhs
=this->lhs
;
566 else if (this == parent
->lhs
) parent
->lhs
= this->lhs
;
568 //WARNINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
569 //current object is deleted. do not any code here
574 bool PredicateImpl::isDummyPredicate()
576 if (NULL
== lhs
&& NULL
== rhs
&& NULL
== parent
577 && NULL
== operand
&& NULL
== operandPtr
&&
578 (0 == strcmp(fldName1
, "")) && (0==strcmp(fldName2
, "")))
583 PredicateImpl
* PredicateImpl::getIfOneSidedPredicate()
585 if (logicalOp
!= OpAnd
) return NULL
;
586 if (NULL
== lhs
&& NULL
!=rhs
)
590 if (NULL
!= lhs
&& NULL
==rhs
)