Fixing bugs in aggregate and join
[csql.git] / src / storage / PredicateImpl.cxx
blob24493b460cda71bc2486c6dde3051286c0a7bbb1
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 if (operand == NULL && operandPtr == NULL)
148 projList = lst;
150 bool PredicateImpl::isSingleTerm()
152 if (NULL == lhs && NULL == rhs) return true; else false;
156 bool PredicateImpl::isNotOrInvolved()
158 bool lhsResult = true, rhsResult = true;
159 if (NULL != lhs)
161 lhsResult = lhs->isNotOrInvolved();
163 if (NULL != rhs)
165 rhsResult = rhs->isNotOrInvolved();
167 if (NULL != lhs)
169 //Means it involves only Logical operator
170 switch(logicalOp)
172 case OpAnd:
173 if (lhsResult || rhsResult) return true; else return false;
174 break;
175 case OpOr:
176 return true;
177 break;
178 case OpNot:
179 default:
180 return true;
181 break;
184 return false;
187 DbRetVal PredicateImpl::evaluate(bool &result)
189 bool rhsResult = false, lhsResult=false;
190 DbRetVal retCode =OK;
191 result = false;
192 if (NULL != lhs)
194 retCode = lhs->evaluate(lhsResult);
195 if (retCode != OK) return ErrInvalidExpr;
196 }else lhsResult = true;
197 if (NULL != rhs)
199 retCode = rhs->evaluate(rhsResult);
200 if (retCode != OK) return ErrInvalidExpr;
201 } else rhsResult = true;
202 if (NULL != lhs)
204 //Means it involves only Logical operator
205 switch(logicalOp)
207 case OpAnd:
208 if (lhsResult && rhsResult) result = true;
209 break;
210 case OpOr:
211 if (lhsResult || rhsResult) result = true;
212 break;
213 case OpNot:
214 if (lhsResult) result = false; else result = true;
215 break;
216 default:
217 return ErrInvalidExpr;
220 printDebug(DM_Predicate, "result is %d", result);
221 return OK;
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);
232 if (projList)
234 DataType type=typeUnknown;
235 int length=0;
236 //for join node evaluation
237 ListIterator fIter = projList->getIterator();
238 JoinProjFieldInfo *def;
239 char *val1, *val2;
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;
247 type = def->type;
248 length = def->length;
249 break;
251 }else{
252 printError(ErrNotExists, "Field not binded %s.%s\n",
253 def->tableName, def->fieldName);
254 return ErrNotExists;
257 if (operand == NULL && operandPtr == NULL)
259 if (fieldName2) {
260 fIter.reset();
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;
268 break;
270 }else{
271 printError(ErrNotExists, "Field not binded %s.%s\n",
272 def->tableName, def->fieldName);
273 return ErrNotExists;
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,
288 length);
289 return OK;
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
295 char *val1, *val2;
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)
301 if (fieldName2) {
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;
314 int ret = 0;
315 if (compOp == OpLike) result = ! fnmatch(val2, val1, 0);
316 else result = AllDataType::compareVal(val1, val2, compOp, srcType,
317 table->getFieldLength(fieldName1));
318 return OK;
321 bool PredicateImpl::pointLookupInvolved(const char *fname)
323 bool rhsResult, lhsResult;
324 if (NULL != lhs)
326 lhsResult = lhs->pointLookupInvolved(fname);
328 if (NULL != rhs)
330 rhsResult = rhs->pointLookupInvolved(fname);
332 if (NULL != lhs)
334 //Means it involves only Logical operator
335 switch(logicalOp)
337 case OpAnd:
338 //return lhsResult;
339 if (lhsResult || rhsResult) return true; else return false;
340 break;
341 case OpOr:
342 return false;
343 break;
344 case OpNot:
345 default:
346 return false;
347 break;
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))
360 return true;
363 return false;
365 bool PredicateImpl::rangeQueryInvolved(const char *fname)
367 bool rhsResult, lhsResult;
368 if (NULL != lhs)
370 lhsResult = lhs->rangeQueryInvolved(fname);
372 if (NULL != rhs)
374 rhsResult = rhs->rangeQueryInvolved(fname);
376 if (NULL != lhs)
378 switch(logicalOp)
380 case OpAnd:
381 if (lhsResult || rhsResult) return true; else return false;
382 break;
383 case OpOr:
384 return false;
385 break;
386 case OpNot:
387 default:
388 return false;
389 break;
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))
403 return true;
406 return false;
410 void* PredicateImpl::valPtrForIndexField(const char *fname)
412 void *lhsRet=NULL, *rhsRet=NULL;
413 if (NULL != lhs)
415 lhsRet = lhs->valPtrForIndexField(fname);
416 if ( lhsRet != NULL) return lhsRet;
418 if (NULL != rhs)
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;
434 return NULL;
436 ComparisionOp PredicateImpl::opForIndexField(const char *fname)
438 ComparisionOp lhsRet= OpInvalidComparisionOp, rhsRet= OpInvalidComparisionOp;
439 if (NULL != lhs)
441 lhsRet = lhs->opForIndexField(fname);
442 if ( lhsRet != OpInvalidComparisionOp) return lhsRet;
445 if (NULL != rhs)
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))
454 return compOp;
456 return OpInvalidComparisionOp;
458 PredicateImpl* PredicateImpl::getTablePredicate()
460 PredicateImpl *lhsRet = NULL, *rhsRet = NULL;
461 if (NULL != lhs)
463 lhsRet = lhs->getTablePredicate();
464 if ( lhsRet != NULL) return lhsRet;
466 if (NULL != rhs)
468 rhsRet = rhs->getTablePredicate();
469 if ( rhsRet != NULL) return rhsRet;
471 if (operand || operandPtr )
473 printf("PRABA::getTablePredicate returning %s %d\n", fldName1, compOp);
474 if (parent)
476 if (this == parent->lhs) {
477 parent->lhs = NULL;
479 else {
480 parent->rhs = NULL;
482 parent = NULL;
484 return this;
486 return NULL;
488 PredicateImpl* PredicateImpl::getJoinPredicate()
490 PredicateImpl *lhsRet = NULL, *rhsRet = NULL;
491 if (NULL != lhs)
493 lhsRet = lhs->getJoinPredicate();
494 if ( lhsRet != NULL) return lhsRet;
496 if (NULL != rhs)
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);
504 if (parent)
506 if (this == parent->lhs)
507 parent->lhs = NULL;
508 else
509 parent->rhs = NULL;
510 parent = NULL;
512 return this;
514 return NULL;
516 void PredicateImpl::removeIfNotNecessary()
518 if (NULL != lhs)
520 lhs->removeIfNotNecessary();
522 if (NULL != rhs)
524 rhs->removeIfNotNecessary();
526 if (logicalOp != OpAnd) return;
527 if (NULL == lhs && NULL == rhs)
529 if (NULL == parent)
531 return;
533 if (this == parent->rhs) parent->rhs = NULL;
534 else if (this == parent->lhs) parent->lhs = NULL;
535 delete this;
536 //WARNINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
537 //current object is deleted. do not any code here
538 return;
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
544 if (NULL == parent)
546 return;
548 if (this == parent->rhs) parent->rhs=this->rhs;
549 else if (this == parent->lhs) parent->lhs = this->rhs;
550 delete this;
551 //WARNINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
552 //current object is deleted. do not any code here
553 return;
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
559 if (NULL == parent)
561 return;
563 if (this == parent->rhs) parent->rhs=this->lhs;
564 else if (this == parent->lhs) parent->lhs = this->lhs;
565 delete this;
566 //WARNINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
567 //current object is deleted. do not any code here
568 return;
570 return;
572 bool PredicateImpl::isDummyPredicate()
574 if (NULL == lhs && NULL == rhs && NULL == parent
575 && NULL == operand && NULL == operandPtr &&
576 (0 == strcmp(fldName1, "")) && (0==strcmp(fldName2, "")))
577 return true;
578 else
579 return false;
581 PredicateImpl* PredicateImpl::getIfOneSidedPredicate()
583 if (logicalOp != OpAnd) return NULL;
584 if (NULL == lhs && NULL !=rhs)
586 return rhs;
588 if (NULL != lhs && NULL ==rhs)
590 return lhs;
592 return NULL;