code reorg
[csql.git] / src / relational / table / PredicateEvalImpl.cxx
blobe7bc57ec7c55ba7d816e405fadaa6a9d602102c4
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<JoinTableImpl.h>
25 #include<Util.h>
26 DbRetVal PredicateImpl::evaluateLogical(bool &result)
28 bool rhsResult = false, lhsResult=false;
29 DbRetVal retCode =OK;
30 result = false;
31 if (NULL != lhs)
33 retCode = lhs->evaluate(lhsResult);
34 if (retCode != OK) return ErrInvalidExpr;
35 }else lhsResult = true;
36 if (NULL != rhs)
38 retCode = rhs->evaluate(rhsResult);
39 if (retCode != OK) return ErrInvalidExpr;
40 } else rhsResult = true;
41 if (NULL != lhs)
43 //Means it involves only Logical operator
44 if (OpAnd == logicalOp) {
45 if (lhsResult && rhsResult) result = true;
46 }else if (OpOr == logicalOp) {
47 if (lhsResult || rhsResult) result = true;
48 }else if (OpNot == logicalOp){
49 if (lhsResult) result = false; else result = true;
51 printDebug(DM_Predicate, "result is %d", result);
53 return OK;
56 DbRetVal PredicateImpl::evaluateForHaving(bool &result, AggTableImpl *aImpl, void *aggElement)
58 bool rhsResult = false, lhsResult=false;
59 DbRetVal retCode =OK;
60 result = false;
61 if (NULL != lhs)
63 retCode = lhs->evaluateForHaving(lhsResult, aImpl, aggElement);
64 if (retCode != OK) return ErrInvalidExpr;
65 }else lhsResult = true;
66 if (NULL != rhs)
68 retCode = rhs->evaluateForHaving(rhsResult, aImpl, aggElement);
69 if (retCode != OK) return ErrInvalidExpr;
70 } else rhsResult = true;
71 if (NULL != lhs)
73 if (OpAnd == logicalOp) {
74 if (lhsResult && rhsResult) result = true;
75 }else if (OpOr == logicalOp) {
76 if (lhsResult || rhsResult) result = true;
77 }else if (OpNot == logicalOp){
78 if (lhsResult) result = false; else result = true;
80 printDebug(DM_Predicate, "result is %d", result);
81 return OK;
84 void *val1 = NULL, *val2 =NULL;
85 int offset = aImpl->getAggOffset(fldName1, aggType);
86 val1 = (void*)((char*)aggElement + offset);
87 if (!isBindBufSet) {
88 //sets the type and length when it is called first time
89 FieldInfo *info = new FieldInfo();
90 DbRetVal rv = aImpl->getFieldInfo(fldName1, info);
91 if (aggType == AGG_AVG) {
92 type = typeDouble;
93 length = sizeof(double);
94 } else if (aggType == AGG_COUNT) {
95 type = typeInt;
96 length = sizeof(int);
97 } else {
98 type = info->type;
99 length = info->length;
101 delete info;
102 isBindBufSet = true;
104 if(operand != NULL && operandPtr == NULL)
106 val2 = (char*) operand;
108 else if(operand == NULL && operandPtr != NULL)
110 val2 = *(char**)operandPtr;
112 if (aggType == AGG_AVG) {
113 double dVal2 = 0;
114 AllDataType::convertToDouble(&dVal2, val2, type);
115 result = AllDataType::compareVal(val1, &dVal2, compOp, typeDouble, length);
117 else if (aggType == AGG_COUNT) {
118 int dVal2 = 0;
119 AllDataType::convertToInt(&dVal2, val2, type);
120 result = AllDataType::compareVal(val1, &dVal2, compOp, typeInt, length);
122 else
123 result = AllDataType::compareVal(val1, val2, compOp, type, length);
124 return OK;
127 DbRetVal PredicateImpl::evaluateLogicalForTable(bool &result, char *tuple)
129 bool rhsResult = false, lhsResult=false;
130 DbRetVal retCode =OK;
131 result = false;
132 if (NULL != lhs)
134 lhs->evaluateForTable(lhsResult, tuple);
135 }else lhsResult = true;
136 if (NULL != rhs)
138 rhs->evaluateForTable(rhsResult, tuple);
139 } else rhsResult = true;
140 if (NULL != lhs)
142 //Means it involves only Logical operator
143 if (OpAnd == logicalOp) {
144 if (lhsResult && rhsResult) result = true;
145 }else if (OpOr == logicalOp) {
146 if (lhsResult || rhsResult) result = true;
147 }else if (OpNot == logicalOp){
148 if (lhsResult) result = false; else result = true;
150 printDebug(DM_Predicate, "result is %d", result);
152 return OK;
155 void PredicateImpl::evaluateForTable(bool &result, char *tuple)
157 if (!isNoLeftRight) {
158 bool rhsResult = false;
159 if (NULL != rhs)
161 rhs->evaluateForTable(rhsResult, tuple);
162 if(rhsResult == false && OpAnd == logicalOp) {//do early return
163 result = false;
164 return;
166 } else rhsResult = true;
167 bool lhsResult = false;
168 if (NULL != lhs)
170 lhs->evaluateForTable(lhsResult, tuple);
171 }else lhsResult = true;
172 if (NULL != lhs)
174 //Means it involves only Logical operator
175 if (OpAnd == logicalOp) {
176 if (lhsResult && rhsResult) result = true;
177 }else if (OpOr == logicalOp) {
178 if (lhsResult || rhsResult) result = true;
179 }else if (OpNot == logicalOp){
180 if (lhsResult) result = false; else result = true;
182 printDebug(DM_Predicate, "result is %d", result);
183 return ;
186 //Table null check of condition
187 if(lExp || rExp){
188 void* val=NULL;
189 void* rval = NULL;
190 TableImpl *tImpl = (TableImpl*) table;
191 if(lExp){
192 lExp->setTable(tImpl);
193 lExp->setTuple(tuple);
194 val = lExp->evaluateForFunction(AllDataType::getCsqlTypeFromFunctionType(lExp->getFunctionType()));
196 if(rExp) {
197 rExp->setTable(tImpl);
198 rExp->setTuple(tuple);
199 rval = rExp->evaluateForFunction(AllDataType::getCsqlTypeFromFunctionType(rExp->getFunctionType()));
201 if( val && rval){
202 result = AllDataType::compareVal(val, rval, compOp, AllDataType::getCsqlTypeFromFunctionTypeForComparision(lExp->getFunctionType()),length);
203 }else if( val && operandPtr!=NULL){
204 val2 = *(char**)operandPtr;
205 result = AllDataType::compareVal(val, val2, compOp, AllDataType::getCsqlTypeFromFunctionTypeForComparision(lExp->getFunctionType()),length);
206 }else if(val && (offset2 != -1 && operand == NULL && operandPtr == NULL)){
207 val2 = tuple + offset2;
208 result = AllDataType::compareVal(val, val2, compOp, AllDataType::getCsqlTypeFromFunctionTypeForComparision(lExp->getFunctionType()),length);
209 }else{
210 result =false;
213 return;
215 if (isNullable) {
216 TableImpl *tImpl = (TableImpl*) table;
217 tImpl->setCurTuple(tuple);
218 bool isValueNull = table->isFldNull(fldPos);
219 if(compOp == OpIsNull)
221 if( (isValueNull && isNull) || (!isValueNull && !isNull) )
222 result = true;
223 else
224 result = false;
225 return;
227 if(isValueNull)
229 result=false;
230 return;
233 //the below code works only for single table
234 val1= tuple + offset1;
235 if(offset2 != -1 && operand == NULL && operandPtr == NULL)
236 val2 = tuple + offset2;
237 if (!isBindBufSet) {
238 //Assumes that fldName2 data type is also same for expr f1 <f2
239 //Note:Perf: Do not change the order below
240 if(operand == NULL && operandPtr != NULL)
242 val2 = *(char**)operandPtr;
243 if (compOp == OpLike) {
244 char *c = (char *)val2;
245 //OPT:If LIKE has only %, then no need to evaluate
246 if (*c == '%' && *(c+1) == '\0') {result=true; return;}
247 Util::changeWildcardChar(val2);
250 } else if (operand == NULL && operandPtr == NULL)
252 if(offset2 != -1)
253 val2 = tuple + offset2;
254 } else if(operand != NULL && operandPtr == NULL)
256 val2 = (char*) operand;
257 if (compOp == OpLike) {
258 char *c = (char *)val2;
259 if (*c == '%' && *(c+1) == '\0') {result=true; return;}
260 Util::changeWildcardChar(val2);
263 if(operand2 == NULL && operand2Ptr != NULL)
265 val3 = *(char**)operand2Ptr;
266 } else if(operand2 != NULL && operand2Ptr == NULL)
268 val3 = (char*) operand2;
270 isBindBufSet = true;
272 result = true;
273 if(val3) {
274 //printf(" val1 %d val3 %d\n", *(int*)val1, *(int*)val3);
275 result = AllDataType::compareVal(val1, val3, comp2Op, type,length);
276 if(result==false) return;
278 if (isPushedDown) {
279 return;
281 //printf(" val1 %d val2 %d\n", *(int*)val1, *(int*)val2);
282 if (type != typeVarchar)
283 result = AllDataType::compareVal(val1, val2, compOp, type,length);
284 else
285 result = AllDataType::compareVal((void *) *(long *) val1, val2,
286 compOp, type,length);
287 return;
290 DbRetVal PredicateImpl::evaluate(bool &result)
292 if (!isNoLeftRight) {
293 bool rhsResult = false, lhsResult=false;
294 DbRetVal retCode =OK;
295 result = false;
296 if (NULL != lhs)
298 retCode = lhs->evaluate(lhsResult);
299 if (retCode < OK) return ErrInvalidExpr;
300 }else lhsResult = true;
301 if (NULL != rhs)
303 retCode = rhs->evaluate(rhsResult);
304 if (retCode < OK) return ErrInvalidExpr;
305 } else rhsResult = true;
306 if (NULL != lhs)
308 //Means it involves only Logical operator
309 if (OpAnd == logicalOp) {
310 if (lhsResult && rhsResult) result = true;
311 }else if (OpOr == logicalOp) {
312 if (lhsResult || rhsResult) result = true;
313 }else if (OpNot == logicalOp){
314 if (lhsResult) result = false; else result = true;
315 if ( ErrNullValues == retCode) result = false;
317 printDebug(DM_Predicate, "result is %d", result);
318 return OK;
321 //Means it is relational expression
322 //first operand is always field identifier
323 //get the value in the tuple
324 if (projList) {
325 if (dontEvaluate) {result= true; return OK; }
326 if (!isBindBufSet)
328 //for join node evaluation
329 ListIterator fIter = projList->getIterator();
330 JoinProjFieldInfo *def;
331 //char *val1, *val2;
332 while (fIter.hasElement())
334 def = (JoinProjFieldInfo*) fIter.nextElement();
335 if (NULL != def->bindBuf) {
336 if (0 == strcmp(fldName1, def->tabFieldName))
338 val1 = (char*)def->bindBuf;
339 type = def->type;
340 length = def->length;
341 break;
343 }else{
344 printError(ErrNotExists, "Field not binded %s.%s\n",
345 def->tableName, def->fieldName);
346 return ErrNotExists;
349 if (operand == NULL && operandPtr == NULL)
351 char fieldName2[IDENTIFIER_LENGTH];
352 memset(fieldName2, 0, IDENTIFIER_LENGTH);
353 Table::getFieldNameAlone(fldName2, fieldName2);
354 if (fieldName2) {
355 fIter.reset();
356 while (fIter.hasElement())
358 def = (JoinProjFieldInfo*) fIter.nextElement();
359 if (NULL != def->bindBuf) {
360 if (0 == strcmp(fldName2, def->tabFieldName))
362 val2 = (char*)def->bindBuf;
363 break;
365 }else{
366 printError(ErrNotExists, "Field not binded %s.%s\n",
367 def->tableName, def->fieldName);
368 return ErrNotExists;
373 else if(operand != NULL && operandPtr == NULL)
375 val2 = (char*) operand;
377 else if(operand == NULL && operandPtr != NULL)
379 val2 = *(char**)operandPtr;
381 isBindBufSet = true;
383 JoinTableImpl *jTable = (JoinTableImpl*) table;
384 if (jTable->isFldNullInt(fldName1) || jTable->isFldNullInt(fldName2))
386 result=false;
387 return ErrNullValues;
389 result = AllDataType::compareVal(val1, val2, compOp, type,
390 length);
391 return OK;
394 printf("FATAL::wrong method call\n");
395 //the below code works only for single table
396 val1= (char*)tuple + offset1;
397 if(offset2 != -1 && operand == NULL && operandPtr == NULL)
398 val2 = ((char*)tuple) + offset2;
399 if (!isBindBufSet) {
400 //Assumes that fldName2 data type is also same for expr f1 <f2
401 //Note:Perf: Do not change the order below
402 if(operand == NULL && operandPtr != NULL)
404 val2 = *(char**)operandPtr;
406 else if (operand == NULL && operandPtr == NULL)
408 if(offset2 != -1)
409 val2 = ((char*)tuple) + offset2;
411 else if(operand != NULL && operandPtr == NULL)
413 val2 = (char*) operand;
415 isBindBufSet = true;
417 result = AllDataType::compareVal(val1, val2, compOp, type,length);
418 return OK;