Fixing failures in Join and systest failures because of predicate reset
[csql.git] / src / storage / PredicateImpl.cxx
blobd4e808eade01d00ee1bac909ef2aef84d6f96ccf
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<fnmatch.h>
25 #include<JoinTableImpl.h>
26 #include<Util.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);
40 if (lhs) {
41 printf("%s <PRED-LEFT>\n", spaceBuf);
42 lhs->print(space+2);
43 printf("%s </PRED-LEFT>\n", spaceBuf);
45 if (rhs)
47 printf("%s <PRED-RIGHT>\n", spaceBuf);
48 rhs->print(space+2);
49 printf("%s </PRED-RIGHT>\n", spaceBuf);
51 printf("%s </PREDICATE>\n", spaceBuf);
55 void PredicateImpl::setTerm(const char* fName1, ComparisionOp op,
56 const char *fName2)
58 strcpy(fldName1, fName1);
59 strcpy(fldName2, fName2);
60 compOp = op;
61 operand = NULL;
62 operandPtr = NULL;
63 lhs = rhs = NULL;
64 parent = NULL;
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);
72 if (op == OpLike)
74 char *c = (char *) opnd;
75 while (*c != '\0')
77 if (*c == '_') *c = '?';
78 else if(*c == '%') *c = '*';
79 c++;
82 compOp = op;
83 operand = opnd;
84 operandPtr = NULL;
85 lhs = rhs = NULL;
86 parent = NULL;
87 logicalOp = OpInvalidLogicalOp;
90 void PredicateImpl::setTerm(const char* fName1, ComparisionOp op, void **opnd)
92 strcpy(fldName1, fName1);
93 compOp = op;
94 operand = NULL;
95 operandPtr = opnd;
96 lhs = rhs = NULL;
97 parent = NULL;
98 logicalOp = OpInvalidLogicalOp;
101 void PredicateImpl::setParent(PredicateImpl *pImpl)
103 //if (parent != NULL) printf("Parent already set\n");
104 parent = pImpl;
105 return;
107 void PredicateImpl::setTerm(Predicate *p1, LogicalOp op, Predicate *p2 )
109 if (p2 == NULL && op != OpNot || op == OpNot && p2 != NULL)
111 //TODO::printError
112 printError(ErrBadArg, "Wrong argument passed\n");
113 return;
115 lhs = (PredicateImpl*)p1;
116 rhs = (PredicateImpl*)p2;
117 logicalOp = op;
118 compOp = OpInvalidComparisionOp;
119 if (lhs != NULL) lhs->setParent(this);
120 if (rhs != NULL) rhs->setParent(this);
121 return;
124 void PredicateImpl::setTable(Table *tbl)
126 if (NULL != lhs)
127 lhs->setTable((TableImpl*)tbl);
128 if (NULL != rhs)
129 rhs->setTable((TableImpl*)tbl);
130 table = (TableImpl*)tbl;
133 void PredicateImpl::setTuple(void *tpl)
135 if (NULL != lhs)
136 lhs->setTuple(tpl);
137 if (NULL != rhs)
138 rhs->setTuple(tpl);
139 tuple = tpl;
141 void PredicateImpl::setProjectionList(List *lst)
143 if (NULL != lhs)
144 lhs->setProjectionList(lst);
145 if (NULL != rhs)
146 rhs->setProjectionList(lst);
147 //PRABA::commented. may need to remove the code in evaluate at the end
148 //if (operand == NULL && operandPtr == NULL)
149 projList = lst;
151 bool PredicateImpl::isSingleTerm()
153 if (NULL == lhs && NULL == rhs) return true; else false;
157 bool PredicateImpl::isNotOrInvolved()
159 bool lhsResult = true, rhsResult = true;
160 if (NULL != lhs)
162 lhsResult = lhs->isNotOrInvolved();
164 if (NULL != rhs)
166 rhsResult = rhs->isNotOrInvolved();
168 if (NULL != lhs)
170 //Means it involves only Logical operator
171 switch(logicalOp)
173 case OpAnd:
174 if (lhsResult || rhsResult) return true; else return false;
175 break;
176 case OpOr:
177 return true;
178 break;
179 case OpNot:
180 default:
181 return true;
182 break;
185 return false;
188 DbRetVal PredicateImpl::evaluate(bool &result)
190 bool rhsResult = false, lhsResult=false;
191 DbRetVal retCode =OK;
192 result = false;
193 if (NULL != lhs)
195 retCode = lhs->evaluate(lhsResult);
196 if (retCode != OK) return ErrInvalidExpr;
197 }else lhsResult = true;
198 if (NULL != rhs)
200 retCode = rhs->evaluate(rhsResult);
201 if (retCode != OK) return ErrInvalidExpr;
202 } else rhsResult = true;
203 if (NULL != lhs)
205 //Means it involves only Logical operator
206 switch(logicalOp)
208 case OpAnd:
209 if (lhsResult && rhsResult) result = true;
210 break;
211 case OpOr:
212 if (lhsResult || rhsResult) result = true;
213 break;
214 case OpNot:
215 if (lhsResult) result = false; else result = true;
216 break;
217 default:
218 return ErrInvalidExpr;
221 printDebug(DM_Predicate, "result is %d", result);
222 return OK;
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);
233 if (projList)
235 DataType type=typeUnknown;
236 int length=0;
237 //for join node evaluation
238 ListIterator fIter = projList->getIterator();
239 JoinProjFieldInfo *def;
240 char *val1, *val2;
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;
248 type = def->type;
249 length = def->length;
250 break;
252 }else{
253 printError(ErrNotExists, "Field not binded %s.%s\n",
254 def->tableName, def->fieldName);
255 return ErrNotExists;
258 if (operand == NULL && operandPtr == NULL)
260 if (fieldName2) {
261 fIter.reset();
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;
269 break;
271 }else{
272 printError(ErrNotExists, "Field not binded %s.%s\n",
273 def->tableName, def->fieldName);
274 return ErrNotExists;
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,
289 length);
290 return OK;
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
297 char *val1, *val2;
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)
303 if (fieldName2) {
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;
316 int ret = 0;
317 if (compOp == OpLike) result = ! fnmatch(val2, val1, 0);
318 else result = AllDataType::compareVal(val1, val2, compOp, srcType,
319 table->getFieldLength(fieldName1));
320 return OK;
323 bool PredicateImpl::pointLookupInvolved(const char *fname)
325 bool rhsResult, lhsResult;
326 if (NULL != lhs)
328 lhsResult = lhs->pointLookupInvolved(fname);
330 if (NULL != rhs)
332 rhsResult = rhs->pointLookupInvolved(fname);
334 if (NULL != lhs)
336 //Means it involves only Logical operator
337 switch(logicalOp)
339 case OpAnd:
340 //return lhsResult;
341 if (lhsResult || rhsResult) return true; else return false;
342 break;
343 case OpOr:
344 return false;
345 break;
346 case OpNot:
347 default:
348 return false;
349 break;
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))
362 return true;
365 return false;
367 bool PredicateImpl::rangeQueryInvolved(const char *fname)
369 bool rhsResult, lhsResult;
370 if (NULL != lhs)
372 lhsResult = lhs->rangeQueryInvolved(fname);
374 if (NULL != rhs)
376 rhsResult = rhs->rangeQueryInvolved(fname);
378 if (NULL != lhs)
380 switch(logicalOp)
382 case OpAnd:
383 if (lhsResult || rhsResult) return true; else return false;
384 break;
385 case OpOr:
386 return false;
387 break;
388 case OpNot:
389 default:
390 return false;
391 break;
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))
405 return true;
408 return false;
412 void* PredicateImpl::valPtrForIndexField(const char *fname)
414 void *lhsRet=NULL, *rhsRet=NULL;
415 if (NULL != lhs)
417 lhsRet = lhs->valPtrForIndexField(fname);
418 if ( lhsRet != NULL) return lhsRet;
420 if (NULL != rhs)
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;
436 return NULL;
438 ComparisionOp PredicateImpl::opForIndexField(const char *fname)
440 ComparisionOp lhsRet= OpInvalidComparisionOp, rhsRet= OpInvalidComparisionOp;
441 if (NULL != lhs)
443 lhsRet = lhs->opForIndexField(fname);
444 if ( lhsRet != OpInvalidComparisionOp) return lhsRet;
447 if (NULL != rhs)
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))
456 return compOp;
458 return OpInvalidComparisionOp;
460 PredicateImpl* PredicateImpl::getTablePredicate()
462 PredicateImpl *lhsRet = NULL, *rhsRet = NULL;
463 if (NULL != lhs)
465 lhsRet = lhs->getTablePredicate();
466 if ( lhsRet != NULL) return lhsRet;
468 if (NULL != rhs)
470 rhsRet = rhs->getTablePredicate();
471 if ( rhsRet != NULL) return rhsRet;
473 if (operand || operandPtr )
475 //printf("PRABA::getTablePredicate returning %s %d\n", fldName1, compOp);
476 if (parent)
478 if (this == parent->lhs) {
479 parent->lhs = NULL;
481 else {
482 parent->rhs = NULL;
484 parent = NULL;
486 return this;
488 return NULL;
490 PredicateImpl* PredicateImpl::getJoinPredicate()
492 PredicateImpl *lhsRet = NULL, *rhsRet = NULL;
493 if (NULL != lhs)
495 lhsRet = lhs->getJoinPredicate();
496 if ( lhsRet != NULL) return lhsRet;
498 if (NULL != rhs)
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);
506 if (parent)
508 if (this == parent->lhs)
509 parent->lhs = NULL;
510 else
511 parent->rhs = NULL;
512 parent = NULL;
514 return this;
516 return NULL;
518 void PredicateImpl::removeIfNotNecessary()
520 if (NULL != lhs)
522 lhs->removeIfNotNecessary();
524 if (NULL != rhs)
526 rhs->removeIfNotNecessary();
528 if (logicalOp != OpAnd) return;
529 if (NULL == lhs && NULL == rhs)
531 if (NULL == parent)
533 return;
535 if (this == parent->rhs) parent->rhs = NULL;
536 else if (this == parent->lhs) parent->lhs = NULL;
537 delete this;
538 //WARNINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
539 //current object is deleted. do not any code here
540 return;
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
546 if (NULL == parent)
548 return;
550 if (this == parent->rhs) parent->rhs=this->rhs;
551 else if (this == parent->lhs) parent->lhs = this->rhs;
552 delete this;
553 //WARNINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
554 //current object is deleted. do not any code here
555 return;
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
561 if (NULL == parent)
563 return;
565 if (this == parent->rhs) parent->rhs=this->lhs;
566 else if (this == parent->lhs) parent->lhs = this->lhs;
567 delete this;
568 //WARNINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
569 //current object is deleted. do not any code here
570 return;
572 return;
574 bool PredicateImpl::isDummyPredicate()
576 if (NULL == lhs && NULL == rhs && NULL == parent
577 && NULL == operand && NULL == operandPtr &&
578 (0 == strcmp(fldName1, "")) && (0==strcmp(fldName2, "")))
579 return true;
580 else
581 return false;
583 PredicateImpl* PredicateImpl::getIfOneSidedPredicate()
585 if (logicalOp != OpAnd) return NULL;
586 if (NULL == lhs && NULL !=rhs)
588 return rhs;
590 if (NULL != lhs && NULL ==rhs)
592 return lhs;
594 return NULL;