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()
34 /* moved to Table class
36 void JoinTableImpl::getFieldNameAlone(char *fname, char *name) {
38 char *fullname = fname;
39 while(*fullname != '\0')
41 if (*fullname == '.') { dotFound = true; break; }
44 if (dotFound) strcpy(name, ++fullname); else strcpy(name, fname);
47 void JoinTableImpl::getTableNameAlone(char *fname, char *name) {
51 if (*name == '.') { *name='\0'; break; }
57 DbRetVal
JoinTableImpl::bindFld(const char *fldname
, void *val
)
59 FieldInfo
*info
= new FieldInfo();
60 char tableName
[IDENTIFIER_LENGTH
];
61 char fieldName
[IDENTIFIER_LENGTH
];
62 getTableNameAlone((char*)fldname
, tableName
);
63 getFieldNameAlone((char*)fldname
, fieldName
);
64 ListIterator iter
= projList
.getIterator();
65 JoinProjFieldInfo
*elem
;
66 while (iter
.hasElement())
68 elem
= (JoinProjFieldInfo
*) iter
.nextElement();
69 if (strcmp(elem
->fieldName
, fieldName
)==0 &&
70 strcmp(elem
->tableName
, tableName
) ==0)
72 printError(ErrBadCall
, "Field already binded %s\n", fldname
);
77 JoinProjFieldInfo
*def
= new JoinProjFieldInfo();
78 strcpy(def
->tableName
, tableName
);
79 strcpy(def
->fieldName
, fieldName
);
80 strcpy(def
->tabFieldName
, fldname
);
82 getFieldInfo(fldname
, info
);
83 def
->bindBuf
= AllDataType::alloc(info
->type
, info
->length
);
85 leftTableHdl
->bindFld(fldname
, def
->bindBuf
);
87 rightTableHdl
->bindFld(fldname
, def
->bindBuf
);
88 def
->type
= info
->type
;
89 def
->length
= info
->length
;
95 DbRetVal
JoinTableImpl::optimize()
97 PredicateImpl
* predImpl
= (PredicateImpl
*) pred
;
98 if (NULL
!= predImpl
&& !predImpl
->isNotOrInvolved())
100 //printf("not or or not involved\n");
101 PredicateImpl
*tblPred
= NULL
;
102 bool isPushed
= false;
105 tblPred
= predImpl
->getTablePredicate();
106 if (NULL
== tblPred
) break;
110 isPushed
= pushPredicate(tblPred
);
113 //printf("optimizer could not push table predicate\n");
117 isPushed
= pushPredicate(tblPred
);
120 //printf("optimizer could not push table predicate\n");
125 tblPred
= predImpl
->getJoinPredicate();
130 if (NULL
== tblPred
) break;
131 isPushed
= pushPredicate(tblPred
);
134 //printf("optimizer could not push join predicate\n");
140 //push predicates leave the predicate nodes empty
141 //here we remove all the unnecessary nodes
142 predImpl
= (PredicateImpl
*) pred
;
143 predImpl
->removeIfNotNecessary();
144 PredicateImpl
*p
= predImpl
->getIfOneSidedPredicate();
147 //TODO::fix this leak below..it dumps core if uncommented
152 if (predImpl
->isDummyPredicate())
154 //TODO::fix this leak below..it dumps core if uncommented
159 DbRetVal rv
= leftTableHdl
->optimize();
161 printError(ErrUnknown
, "Left handle optimize failed");
164 rv
= rightTableHdl
->optimize();
166 printError(ErrUnknown
, "Left handle optimize failed");
172 void JoinTableImpl::optimizeRestrict()
174 ScanType lType
= leftTableHdl
->getScanType();
175 ScanType rType
= rightTableHdl
->getScanType();
176 bool interChange
= false;
177 if (lType
== fullTableScan
&& rType
!= fullTableScan
) interChange
= true;
178 else if (lType
!= hashIndexScan
&& rType
== treeIndexScan
) interChange
=true;
181 Table *tmp = leftTableHdl;
182 leftTableHdl=rightTableHdl;
186 //get the predicate with right table handle name
187 //rightTableHdl->getIndexType();
190 ScanType
JoinTableImpl::getScanType()
192 ScanType lType
= leftTableHdl
->getScanType();
193 ScanType rType
= rightTableHdl
->getScanType();
194 if (lType
== hashIndexScan
|| rType
== hashIndexScan
) return hashIndexScan
;
195 if (lType
== treeIndexScan
|| rType
== treeIndexScan
) return treeIndexScan
;
196 return fullTableScan
;
199 void JoinTableImpl::printPlan(int space
)
201 char spaceBuf
[IDENTIFIER_LENGTH
];
202 memset(spaceBuf
, 32, IDENTIFIER_LENGTH
);
203 spaceBuf
[space
] = '\0';
204 PredicateImpl
* predImpl
= (PredicateImpl
*) pred
;
205 printf("%s <JOIN-NODE>\n", spaceBuf
);
206 if (predImpl
) predImpl
->print(space
);
207 printf("%s <LEFT>\n", spaceBuf
);
208 leftTableHdl
->printPlan(space
+2);
209 printf("%s </LEFT>\n", spaceBuf
);
210 printf("%s <RIGHT>\n", spaceBuf
);
211 rightTableHdl
->printPlan(space
+2);
212 printf("%s </RIGHT>\n", spaceBuf
);
213 printf("%s </JOIN-NODE>\n", spaceBuf
);
215 DbRetVal
JoinTableImpl::execute()
217 PredicateImpl
* predImpl
= (PredicateImpl
*) pred
;
219 if (pred
) predImpl
->setProjectionList(&projList
);
220 //push the table scan predicates
222 leftTableHdl
->execute();
223 leftTableHdl
->fetch();
224 rightTableHdl
->execute();
226 //if join condition is not set then do nl
227 //if it is inner join, hen do nl
228 //nl cannot be done for outer join
232 void* JoinTableImpl::fetch()
234 PredicateImpl
* predImpl
= (PredicateImpl
*) pred
;
238 void *rec
= rightTableHdl
->fetch();
241 rightTableHdl
->closeScan();
242 rec
= leftTableHdl
->fetch();
243 if (rec
== NULL
) return NULL
;
244 rightTableHdl
->execute();
245 rec
= rightTableHdl
->fetch();
246 if (rec
== NULL
) return NULL
;
249 if (pred
) rv
= predImpl
->evaluate(result
);
250 if ( OK
!= rv
) return NULL
;
252 rec
= rightTableHdl
->fetch();
253 if (rec
== NULL
) return fetch();
255 copyValuesToBindBuffer(NULL
);
261 if (pred
) rv
= predImpl
->evaluate(result
);
262 if ( rv
!=OK
) return NULL
;
264 rec
= rightTableHdl
->fetch();
265 if (rec
== NULL
) return fetch();
267 copyValuesToBindBuffer(NULL
);
274 void* JoinTableImpl::fetch(DbRetVal
&rv
)
280 void* JoinTableImpl::fetchNoBind()
285 void* JoinTableImpl::fetchNoBind(DbRetVal
&rv
)
288 return fetchNoBind();
291 DbRetVal
JoinTableImpl::copyValuesToBindBuffer(void *elem
)
293 //Iterate through the bind list and copy the value here
294 ListIterator fIter
= projList
.getIterator();
295 JoinProjFieldInfo
*def
;
296 while (fIter
.hasElement())
298 def
= (JoinProjFieldInfo
*) fIter
.nextElement();
299 if (NULL
!= def
->appBuf
) {
300 AllDataType::copyVal(def
->appBuf
, def
->bindBuf
, def
->type
, def
->length
);
305 DbRetVal
JoinTableImpl::getFieldInfo(const char* fldname
, FieldInfo
*&info
)
307 DbRetVal retCode
= OK
;
308 retCode
= leftTableHdl
->getFieldInfo(fldname
, info
);
314 retCode
= rightTableHdl
->getFieldInfo(fldname
, info
);
317 availableLeft
= false;
323 long JoinTableImpl::numTuples()
327 DbRetVal
JoinTableImpl::closeScan()
329 if (leftTableHdl
) leftTableHdl
->closeScan();
330 if (rightTableHdl
) rightTableHdl
->closeScan();
335 DbRetVal
JoinTableImpl::close()
337 if (leftTableHdl
) { leftTableHdl
->close(); leftTableHdl
= NULL
; }
338 if (rightTableHdl
) { rightTableHdl
->close(); rightTableHdl
= NULL
; }
340 ListIterator iter
= projList
.getIterator();
341 JoinProjFieldInfo
*elem
;
342 while (iter
.hasElement())
344 elem
= (JoinProjFieldInfo
*) iter
.nextElement();
351 void* JoinTableImpl::getBindFldAddr(const char *name
)
353 printf("PRABA::join getBindFldAddr not implemented\n");
356 List
JoinTableImpl::getFieldNameList()
360 List leftList
= leftTableHdl
->getFieldNameList();
361 ListIterator lIter
= leftList
.getIterator();
362 while (lIter
.hasElement())
364 Identifier
*elem
= (Identifier
*) lIter
.nextElement();
365 fldNameList
.append(elem
);
368 List rightList
= rightTableHdl
->getFieldNameList();
369 ListIterator rIter
= rightList
.getIterator();
370 while (rIter
.hasElement())
372 Identifier
*elem
= (Identifier
*) rIter
.nextElement();
373 fldNameList
.append(elem
);
377 bool JoinTableImpl::isTableInvolved(char *tableName
)
379 //printf("isTableInvolved called in join for %s\n", tableName);
380 bool isInvolved
= leftTableHdl
->isTableInvolved(tableName
);
381 if (isInvolved
) return true;
382 isInvolved
= rightTableHdl
->isTableInvolved(tableName
);
385 void* JoinTableImpl::getBindedBuf(char* tName
, char* fName
)
387 ListIterator iter
= projList
.getIterator();
388 JoinProjFieldInfo
*elem
;
389 while (iter
.hasElement())
391 elem
= (JoinProjFieldInfo
*) iter
.nextElement();
392 if (strcmp(elem
->fieldName
, fName
)==0 &&
393 strcmp(elem
->tableName
, tName
) ==0)
395 return elem
->bindBuf
;
400 bool JoinTableImpl::pushPredicate(Predicate
*pr
)
402 //printf("PRABA::pushPredicate called\n");
403 PredicateImpl
*pImpl
= (PredicateImpl
*) pr
;
404 bool pushed
= leftTableHdl
->pushPredicate(pr
);
407 pushed
= rightTableHdl
->pushPredicate(pr
);
411 //printf("PRABA::unable to push the predicate\n");
412 //TODO::check if needs to be placed here
413 char *lTbl
= leftTableHdl
->getName();
414 char *rTbl
= rightTableHdl
->getName();
415 char fullName
[IDENTIFIER_LENGTH
];
416 char lTabName
[IDENTIFIER_LENGTH
];
417 char rTabName
[IDENTIFIER_LENGTH
];
418 char lFldName
[IDENTIFIER_LENGTH
];
419 char rFldName
[IDENTIFIER_LENGTH
];
420 strcpy(fullName
, pImpl
->getFldName1());
421 Table::getTableNameAlone(fullName
, lTabName
);
422 Table::getFieldNameAlone(fullName
, lFldName
);
423 strcpy(fullName
, pImpl
->getFldName2());
424 Table::getTableNameAlone(fullName
, rTabName
);
425 Table::getFieldNameAlone(fullName
, rFldName
);
427 if (NULL
!= lTbl
&& NULL
!= rTbl
)
429 //both size TableImpl handles are there
430 if (0 == strcmp(lTbl
, lTabName
) || 0 == strcmp(lTbl
, rTabName
))
432 if (0 == strcmp(rTbl
, lTabName
) || 0 == strcmp(rTbl
, rTabName
))
434 //printf("PRABA::pushed join predicate here1\n");
436 ComparisionOp op
= pImpl
->getCompOp();
437 if (strcmp(rTbl
, rTabName
) ==0)
439 //bool ind = rightTableHdl->hasIndex(rFldName);
441 void *buf
= getBindedBuf(lTabName
, lFldName
);
442 rightTableHdl
->addPredicate(rFldName
, op
, buf
);
444 }else if (strcmp(rTbl
, lTabName
) ==0)
446 //bool ind = rightTableHdl->hasIndex(lFldName);
448 void *buf
= getBindedBuf(rTabName
, rFldName
);
449 rightTableHdl
->addPredicate(lFldName
, op
, buf
);
458 if(isTableInvolved(lTabName
) && isTableInvolved(rTabName
))
460 //printf("PRABA::pushed join predicate here2\n");
462 ComparisionOp op
= pImpl
->getCompOp();
463 if (strcmp(rTbl
, rTabName
) ==0)
465 //bool ind = rightTableHdl->hasIndex(rFldName);
467 void *buf
= getBindedBuf(lTabName
, lFldName
);
468 rightTableHdl
->addPredicate(rFldName
, op
, buf
);
470 }else if (strcmp(rTbl
, lTabName
) ==0)
472 //bool ind = rightTableHdl->hasIndex(lFldName);
474 void *buf
= getBindedBuf(rTabName
, rFldName
);
475 rightTableHdl
->addPredicate(lFldName
, op
, buf
);
486 void JoinTableImpl::setPredicate(Predicate
*pr
)
488 if (NULL
== pred
) { pred
= pr
; return; }
489 Predicate
*curPred
= pred
;
490 PredicateImpl
*newPred
= new PredicateImpl();
491 newPred
->setTerm(curPred
, OpAnd
, pr
);
492 newPred
->setProjectionList(&projList
);