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 ***************************************************************************/
19 #include<JoinTableImpl.h>
20 #include<PredicateImpl.h>
22 JoinTableImpl::JoinTableImpl()
30 JoinTableImpl::~JoinTableImpl() {}
31 /* moved to Table class
33 void JoinTableImpl::getFieldNameAlone(char *fname, char *name) {
35 char *fullname = fname;
36 while(*fullname != '\0')
38 if (*fullname == '.') { dotFound = true; break; }
41 if (dotFound) strcpy(name, ++fullname); else strcpy(name, fname);
44 void JoinTableImpl::getTableNameAlone(char *fname, char *name) {
48 if (*name == '.') { *name='\0'; break; }
54 DbRetVal
JoinTableImpl::bindFld(const char *fldname
, void *val
)
56 FieldInfo
*info
= new FieldInfo();
57 char tableName
[IDENTIFIER_LENGTH
];
58 char fieldName
[IDENTIFIER_LENGTH
];
59 getTableNameAlone((char*)fldname
, tableName
);
60 getFieldNameAlone((char*)fldname
, fieldName
);
61 ListIterator iter
= projList
.getIterator();
62 JoinProjFieldInfo
*elem
;
63 while (iter
.hasElement())
65 elem
= (JoinProjFieldInfo
*) iter
.nextElement();
66 if (strcmp(elem
->fieldName
, fieldName
)==0 &&
67 strcmp(elem
->tableName
, tableName
) ==0)
69 printError(ErrBadCall
, "Field already binded %s\n", fldname
);
74 JoinProjFieldInfo
*def
= new JoinProjFieldInfo();
75 strcpy(def
->tableName
, tableName
);
76 strcpy(def
->fieldName
, fieldName
);
77 strcpy(def
->tabFieldName
, fldname
);
79 getFieldInfo(fldname
, info
);
80 def
->bindBuf
= AllDataType::alloc(info
->type
, info
->length
);
82 leftTableHdl
->bindFld(fldname
, def
->bindBuf
);
84 rightTableHdl
->bindFld(fldname
, def
->bindBuf
);
85 def
->type
= info
->type
;
86 def
->length
= info
->length
;
92 DbRetVal
JoinTableImpl::optimize()
94 PredicateImpl
* predImpl
= (PredicateImpl
*) pred
;
95 if (NULL
!= predImpl
&& !predImpl
->isNotOrInvolved())
97 //printf("not or or not involved\n");
98 PredicateImpl
*tblPred
= NULL
;
99 bool isPushed
= false;
102 tblPred
= predImpl
->getTablePredicate();
103 if (NULL
== tblPred
) break;
107 isPushed
= pushPredicate(tblPred
);
110 //printf("optimizer could not push table predicate\n");
114 isPushed
= pushPredicate(tblPred
);
117 //printf("optimizer could not push table predicate\n");
122 tblPred
= predImpl
->getJoinPredicate();
127 if (NULL
== tblPred
) break;
128 isPushed
= pushPredicate(tblPred
);
131 //printf("optimizer could not push join predicate\n");
137 //push predicates leave the predicate nodes empty
138 //here we remove all the unnecessary nodes
139 predImpl
= (PredicateImpl
*) pred
;
140 predImpl
->removeIfNotNecessary();
141 PredicateImpl
*p
= predImpl
->getIfOneSidedPredicate();
144 //TODO::fix this leak below..it dumps core if uncommented
149 if (predImpl
->isDummyPredicate())
151 //TODO::fix this leak below..it dumps core if uncommented
156 DbRetVal rv
= leftTableHdl
->optimize();
158 printError(ErrUnknown
, "Left handle optimize failed");
161 rv
= rightTableHdl
->optimize();
163 printError(ErrUnknown
, "Left handle optimize failed");
169 void JoinTableImpl::optimizeRestrict()
171 ScanType lType
= leftTableHdl
->getScanType();
172 ScanType rType
= rightTableHdl
->getScanType();
173 bool interChange
= false;
174 if (lType
== fullTableScan
&& rType
!= fullTableScan
) interChange
= true;
175 else if (lType
!= hashIndexScan
&& rType
== treeIndexScan
) interChange
=true;
178 Table *tmp = leftTableHdl;
179 leftTableHdl=rightTableHdl;
183 //get the predicate with right table handle name
184 //rightTableHdl->getIndexType();
187 ScanType
JoinTableImpl::getScanType()
189 ScanType lType
= leftTableHdl
->getScanType();
190 ScanType rType
= rightTableHdl
->getScanType();
191 if (lType
== hashIndexScan
|| rType
== hashIndexScan
) return hashIndexScan
;
192 if (lType
== treeIndexScan
|| rType
== treeIndexScan
) return treeIndexScan
;
193 return fullTableScan
;
196 void JoinTableImpl::printPlan(int space
)
198 char spaceBuf
[IDENTIFIER_LENGTH
];
199 memset(spaceBuf
, 32, IDENTIFIER_LENGTH
);
200 spaceBuf
[space
] = '\0';
201 PredicateImpl
* predImpl
= (PredicateImpl
*) pred
;
202 printf("%s <JOIN-NODE>\n", spaceBuf
);
203 if (predImpl
) predImpl
->print(space
);
204 printf("%s <LEFT>\n", spaceBuf
);
205 leftTableHdl
->printPlan(space
+2);
206 printf("%s </LEFT>\n", spaceBuf
);
207 printf("%s <RIGHT>\n", spaceBuf
);
208 rightTableHdl
->printPlan(space
+2);
209 printf("%s </RIGHT>\n", spaceBuf
);
210 printf("%s </JOIN-NODE>\n", spaceBuf
);
212 DbRetVal
JoinTableImpl::execute()
214 PredicateImpl
* predImpl
= (PredicateImpl
*) pred
;
216 if (pred
) predImpl
->setProjectionList(&projList
);
217 //push the table scan predicates
219 leftTableHdl
->execute();
220 leftTableHdl
->fetch();
221 rightTableHdl
->execute();
223 //if join condition is not set then do nl
224 //if it is inner join, hen do nl
225 //nl cannot be done for outer join
229 void* JoinTableImpl::fetch()
231 PredicateImpl
* predImpl
= (PredicateImpl
*) pred
;
235 void *rec
= rightTableHdl
->fetch();
238 rightTableHdl
->closeScan();
239 rec
= leftTableHdl
->fetch();
240 if (rec
== NULL
) return NULL
;
241 rightTableHdl
->execute();
242 rec
= rightTableHdl
->fetch();
243 if (rec
== NULL
) return NULL
;
246 if (pred
) rv
= predImpl
->evaluate(result
);
247 if ( OK
!= rv
) return NULL
;
249 rec
= rightTableHdl
->fetch();
250 if (rec
== NULL
) return fetch();
252 copyValuesToBindBuffer(NULL
);
258 if (pred
) rv
= predImpl
->evaluate(result
);
259 if ( rv
!=OK
) return NULL
;
261 rec
= rightTableHdl
->fetch();
262 if (rec
== NULL
) return fetch();
264 copyValuesToBindBuffer(NULL
);
271 void* JoinTableImpl::fetch(DbRetVal
&rv
)
277 void* JoinTableImpl::fetchNoBind()
282 void* JoinTableImpl::fetchNoBind(DbRetVal
&rv
)
285 return fetchNoBind();
288 DbRetVal
JoinTableImpl::copyValuesToBindBuffer(void *elem
)
290 //Iterate through the bind list and copy the value here
291 ListIterator fIter
= projList
.getIterator();
292 JoinProjFieldInfo
*def
;
293 while (fIter
.hasElement())
295 def
= (JoinProjFieldInfo
*) fIter
.nextElement();
296 if (NULL
!= def
->appBuf
) {
297 AllDataType::copyVal(def
->appBuf
, def
->bindBuf
, def
->type
, def
->length
);
302 DbRetVal
JoinTableImpl::getFieldInfo(const char* fldname
, FieldInfo
*&info
)
304 DbRetVal retCode
= OK
;
305 retCode
= leftTableHdl
->getFieldInfo(fldname
, info
);
311 retCode
= rightTableHdl
->getFieldInfo(fldname
, info
);
314 availableLeft
= false;
320 long JoinTableImpl::numTuples()
324 DbRetVal
JoinTableImpl::closeScan()
326 if (leftTableHdl
) leftTableHdl
->closeScan();
327 if (rightTableHdl
) rightTableHdl
->closeScan();
332 DbRetVal
JoinTableImpl::close()
334 if (leftTableHdl
) { leftTableHdl
->close(); leftTableHdl
= NULL
; }
335 if (rightTableHdl
) { rightTableHdl
->close(); rightTableHdl
= NULL
; }
337 ListIterator iter
= projList
.getIterator();
338 JoinProjFieldInfo
*elem
;
339 while (iter
.hasElement())
341 elem
= (JoinProjFieldInfo
*) iter
.nextElement();
350 void* JoinTableImpl::getBindFldAddr(const char *name
)
352 printf("PRABA::join getBindFldAddr not implemented\n");
355 List
JoinTableImpl::getFieldNameList()
359 List leftList
= leftTableHdl
->getFieldNameList();
360 ListIterator lIter
= leftList
.getIterator();
361 while (lIter
.hasElement())
363 Identifier
*elem
= (Identifier
*) lIter
.nextElement();
364 fldNameList
.append(elem
);
367 List rightList
= rightTableHdl
->getFieldNameList();
368 ListIterator rIter
= rightList
.getIterator();
369 while (rIter
.hasElement())
371 Identifier
*elem
= (Identifier
*) rIter
.nextElement();
372 fldNameList
.append(elem
);
378 bool JoinTableImpl::isTableInvolved(char *tableName
)
380 //printf("isTableInvolved called in join for %s\n", tableName);
381 bool isInvolved
= leftTableHdl
->isTableInvolved(tableName
);
382 if (isInvolved
) return true;
383 isInvolved
= rightTableHdl
->isTableInvolved(tableName
);
386 void* JoinTableImpl::getBindedBuf(char* tName
, char* fName
)
388 ListIterator iter
= projList
.getIterator();
389 JoinProjFieldInfo
*elem
;
390 while (iter
.hasElement())
392 elem
= (JoinProjFieldInfo
*) iter
.nextElement();
393 if (strcmp(elem
->fieldName
, fName
)==0 &&
394 strcmp(elem
->tableName
, tName
) ==0)
396 return elem
->bindBuf
;
401 bool JoinTableImpl::pushPredicate(Predicate
*pr
)
403 //printf("PRABA::pushPredicate called\n");
404 PredicateImpl
*pImpl
= (PredicateImpl
*) pr
;
405 bool pushed
= leftTableHdl
->pushPredicate(pr
);
408 pushed
= rightTableHdl
->pushPredicate(pr
);
412 //printf("PRABA::unable to push the predicate\n");
413 //TODO::check if needs to be placed here
414 char *lTbl
= leftTableHdl
->getName();
415 char *rTbl
= rightTableHdl
->getName();
416 char fullName
[IDENTIFIER_LENGTH
];
417 char lTabName
[IDENTIFIER_LENGTH
];
418 char rTabName
[IDENTIFIER_LENGTH
];
419 char lFldName
[IDENTIFIER_LENGTH
];
420 char rFldName
[IDENTIFIER_LENGTH
];
421 strcpy(fullName
, pImpl
->getFldName1());
422 Table::getTableNameAlone(fullName
, lTabName
);
423 Table::getFieldNameAlone(fullName
, lFldName
);
424 strcpy(fullName
, pImpl
->getFldName2());
425 Table::getTableNameAlone(fullName
, rTabName
);
426 Table::getFieldNameAlone(fullName
, rFldName
);
428 if (NULL
!= lTbl
&& NULL
!= rTbl
)
430 //both size TableImpl handles are there
431 if (0 == strcmp(lTbl
, lTabName
) || 0 == strcmp(lTbl
, rTabName
))
433 if (0 == strcmp(rTbl
, lTabName
) || 0 == strcmp(rTbl
, rTabName
))
435 //printf("PRABA::pushed join predicate here1\n");
437 ComparisionOp op
= pImpl
->getCompOp();
438 if (strcmp(rTbl
, rTabName
) ==0)
440 //bool ind = rightTableHdl->hasIndex(rFldName);
442 void *buf
= getBindedBuf(lTabName
, lFldName
);
443 rightTableHdl
->addPredicate(rFldName
, op
, buf
);
444 pImpl
->setDontEvaluate();
446 }else if (strcmp(rTbl
, lTabName
) ==0)
448 //bool ind = rightTableHdl->hasIndex(lFldName);
450 void *buf
= getBindedBuf(rTabName
, rFldName
);
451 rightTableHdl
->addPredicate(lFldName
, op
, buf
);
452 pImpl
->setDontEvaluate();
461 if(isTableInvolved(lTabName
) && isTableInvolved(rTabName
))
463 //printf("PRABA::pushed join predicate here2\n");
465 ComparisionOp op
= pImpl
->getCompOp();
466 if (strcmp(rTbl
, rTabName
) ==0)
468 //bool ind = rightTableHdl->hasIndex(rFldName);
470 void *buf
= getBindedBuf(lTabName
, lFldName
);
471 rightTableHdl
->addPredicate(rFldName
, op
, buf
);
472 pImpl
->setDontEvaluate();
474 }else if (strcmp(rTbl
, lTabName
) ==0)
476 //bool ind = rightTableHdl->hasIndex(lFldName);
478 void *buf
= getBindedBuf(rTabName
, rFldName
);
479 rightTableHdl
->addPredicate(lFldName
, op
, buf
);
480 pImpl
->setDontEvaluate();
491 void JoinTableImpl::setPredicate(Predicate
*pr
)
493 if (NULL
== pred
) { pred
= pr
; return; }
494 Predicate
*curPred
= pred
;
495 PredicateImpl
*newPred
= new PredicateImpl();
496 newPred
->setTerm(curPred
, OpAnd
, pr
);
497 newPred
->setProjectionList(&projList
);
501 bool JoinTableImpl::isFldNull(const char *name
)
504 if(NULL
==leftTableHdl
->getName())
506 ret
= leftTableHdl
->isFldNull(name
);
507 if(ret
==true) return true;
511 char tableName
[IDENTIFIER_LENGTH
];
512 Table::getTableNameAlone((char*)name
, tableName
);
513 if(0 == strcmp(tableName
,leftTableHdl
->getName()))
515 return leftTableHdl
->isFldNull(name
);
518 if(NULL
==rightTableHdl
->getName())
520 ret
= rightTableHdl
->isFldNull(name
);
521 if(ret
==true) return true;
524 char tableName
[IDENTIFIER_LENGTH
];
525 Table::getTableNameAlone((char*)name
, tableName
);
526 if(0==strcmp(tableName
,rightTableHdl
->getName()))
528 return rightTableHdl
->isFldNull(name
);