Fixing composite index search with atleast one non equal operator fails
[csql.git] / src / storage / TableImpl.cxx
blob6b07d68ef8b235e8e8c78d272c1d59a4126372ef
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<Index.h>
17 #include<CatalogTables.h>
18 #include<Lock.h>
19 #include<Debug.h>
20 #include<Table.h>
21 #include<TableImpl.h>
22 #include<Predicate.h>
23 #include<PredicateImpl.h>
24 #include<Index.h>
25 #include<Config.h>
26 #include<AggTableImpl.h> //for AggType
28 void Table::getFieldNameAlone(char *fname, char *name) {
29 bool dotFound= false;
30 char *fullname = fname;
31 while(*fullname != '\0')
33 if (*fullname == '.') { dotFound = true; break; }
34 fullname++;
36 if (dotFound) strcpy(name, ++fullname); else strcpy(name, fname);
39 void Table::getTableNameAlone(char *fname, char *name) {
40 strcpy(name, fname);
41 char *start = name;
42 bool dotFound = false;
43 while(*name != '\0')
45 if (*name == '.') { *name='\0'; dotFound = true; break; }
46 name++;
48 if (!dotFound) strcpy(start, "");
49 return;
52 DbRetVal TableImpl::bindFld(const char *name, void *val)
54 if (name[0] == '*' ) return OK;
55 //set it in the field list
56 char fieldName[IDENTIFIER_LENGTH];
57 getFieldNameAlone((char*)name, fieldName);
58 DbRetVal rv = fldList_.updateBindVal(fieldName, val);
59 if (OK != rv) {
60 printError(ErrNotExists, "Field %s does not exist", fieldName);
61 return rv;
63 return OK;
66 bool TableImpl::isFldNull(const char *name){
67 if (name[0] == '*') return false;
68 if ( strncasecmp(name,"COUNT",5) == 0 || strncasecmp(name,"AVG",3) == 0 ||
69 strncasecmp(name,"MIN",3) == 0 || strncasecmp(name,"MAX",3) == 0 ||
70 strncasecmp(name,"SUM",3) == 0 ) return false;
71 char fieldName[IDENTIFIER_LENGTH];
72 getFieldNameAlone((char*)name, fieldName);
73 int colpos = fldList_.getFieldPosition(fieldName);
74 if (-1 == colpos)
76 printError(ErrNotExists, "Field %s does not exist", name);
77 return false;
80 return isFldNull(colpos);
83 int TableImpl::getFldPos(char *name)
85 return fldList_.getFieldPosition(name);
87 void TableImpl::setAliasName(char *name)
89 strcpy(aliasName, name);
91 bool TableImpl::isFldNull(int colpos)
93 if (!curTuple_) return false;
94 if (colpos <1 || colpos > numFlds_) return false;
95 if (isIntUsedForNULL) {
96 int nullVal = *(int*)((char*)curTuple_ + (length_ - 4));
97 if (BITSET(nullVal, colpos)) return true;
99 else {
100 char *nullOffset = (char*)curTuple_ + (length_ - os::align(numFlds_));
101 if (nullOffset[colpos-1]) return true;
103 return false;
105 void TableImpl::resetNullinfo()
107 if (isIntUsedForNULL) {
108 iNullInfo =0;
110 else {
111 int i=0;
112 while(i < numFlds_) { cNullInfo[i++] = 0;}
115 DbRetVal TableImpl::markFldNull(char const* name)
117 DbRetVal rv = OK;
118 int colpos = fldList_.getFieldPosition(name);
119 if (-1 == colpos)
121 printError(ErrNotExists, "Field %s does not exist", name);
122 return ErrNotExists;
124 rv = markFldNull(colpos);
125 return rv;
128 DbRetVal TableImpl::markFldNull(int fldpos)
130 if (fldpos <1 || fldpos > numFlds_) return ErrBadArg;
131 bool isBitSet = false;
132 if (isIntUsedForNULL) {
133 if (!BITSET(iNotNullInfo, fldpos)) {
134 SETBIT(iNullInfo, fldpos);
135 isBitSet = true;
137 else {
138 printError(ErrNullViolation, "NOT NULL constraint violation");
139 return ErrNullViolation;
142 else {
143 if (!cNotNullInfo[fldpos-1]) cNullInfo[fldpos-1] = 1;
144 else {
145 printError(ErrNullViolation, "NOT NULL constraint violation");
146 return ErrNullViolation;
149 return OK;
152 void TableImpl::clearFldNull(const char *name)
154 int colpos = fldList_.getFieldPosition(name);
155 if (-1 == colpos)
157 printError(ErrNotExists, "Field %s does not exist", name);
158 return;
160 clearFldNull(colpos);
163 void TableImpl::clearFldNull(int colpos)
165 if (colpos <1 || colpos > numFlds_) return;
166 if (isIntUsedForNULL) {
167 CLEARBIT(iNullInfo, colpos);
169 else
170 cNullInfo[colpos-1] = 0;
171 return;
174 bool TableImpl::hasIndex(char* fName)
176 if (NULL == indexPtr_) return false;
177 for (int i =0; i < numIndexes_; i++)
179 HashIndexInfo* info = (HashIndexInfo*) idxInfo[i];
180 FieldIterator iter = info->idxFldList.getIterator();
181 if(iter.hasElement())
183 FieldDef *def = iter.nextElement();
184 if(strcmp(def->fldName_, fName) == 0)
185 if(!iter.hasElement())//neglet if it is composite index
186 return true;
189 return false;
192 IndexType TableImpl::getIndexType(char *fName, int *pos)
194 if (NULL == indexPtr_) return unknownIndex;
195 for (int i =0; i < numIndexes_; i++)
197 HashIndexInfo* info = (HashIndexInfo*) idxInfo[i];
198 FieldIterator iter = info->idxFldList.getIterator();
199 if(iter.hasElement())
201 FieldDef *def = iter.nextElement();
202 if(strcmp(def->fldName_, fName) == 0)
203 if(!iter.hasElement()) {//neglet if it is composite index
204 *(int*)pos = i;
205 return info->indType;
209 *(int*)pos = -1;
210 return unknownIndex;
212 void TableImpl::addPredicate(char *fName, ComparisionOp op, void *buf)
214 char fieldName[IDENTIFIER_LENGTH];
215 Table::getFieldNameAlone(fName, fieldName);
216 PredicateImpl *pred = (PredicateImpl*) pred_;
217 PredicateImpl *newPred = new PredicateImpl();
218 newPred->setTerm(fName, op, buf);
219 if (NULL == pred) { pred_ = newPred; predList.append(newPred); return; }
220 if (pred->isSingleTerm())
222 bool res = pred->appendIfSameFld(fName, op, buf);
223 if(res) {
224 delete newPred;
225 return;
228 PredicateImpl *bothPred = new PredicateImpl();
229 bothPred->setTerm(pred, OpAnd, newPred);
230 predList.append(bothPred);
231 pred_ = bothPred;
234 DbRetVal TableImpl::optimize()
236 //table ptr is set in predicate because it needs to access the
237 //type and length to evaluate
238 if( NULL != pred_)
240 PredicateImpl *pred = (PredicateImpl*) pred_;
241 pred->setTable(this);
242 pred->setProjectionList(NULL);
243 pred->setOffsetAndType();
245 DbRetVal rv = createPlan();
246 if (rv != OK) return rv;
247 if (iter) { iter->close(); delete iter; iter = NULL; }
248 if (useIndex_ >= 0)
249 iter = new TupleIterator(pred_, scanType_, idxInfo[useIndex_], chunkPtr_, sysDB_->procSlot,isBetween,isPointLook,shouldNullSearch);
250 else if (scanType_ == fullTableScan)
251 iter = new TupleIterator(pred_, scanType_, NULL, chunkPtr_, sysDB_->procSlot,isBetween,isPointLook,shouldNullSearch);
252 else
254 printError(ErrSysFatal,"Unable to create tuple iterator");
255 //should never happen
256 return ErrSysFatal;
258 iter->setPlan();
259 return OK;
262 DbRetVal TableImpl::execute()
264 if (iter && !iter->isIterClosed())
266 //printError(ErrAlready,"Scan already open:Close and re execute");
267 return ErrAlready;
269 DbRetVal ret = OK;
270 if (!isPlanCreated) ret = optimize();
271 if (OK != ret)
273 printError(ErrSysInternal,"Unable to create the plan");
274 return ErrSysInternal;
276 ret = iter->open();
277 if (OK != ret)
279 printError(ret,"Unable to open the iterator");
280 return ret;
282 return OK;
286 DbRetVal TableImpl::createPlan()
288 if (isPlanCreated) {
289 //will do early return here. plan is generated only when setPredicate is called.
290 if (scanType_ == unknownScan) return ErrSysFatal; //this should never happen
291 else return OK;
293 isBetween=false;
294 isPointLook = false;
295 useIndex_ = -1;
297 FieldIterator fIter = fldList_.getIterator();
298 FieldDef *def = NULL;
299 while ((def = fIter.nextElement())!= NULL) {
300 if (NULL != def->bindVal_) bindList_.append(def);
302 numBindFlds_ = bindList_.size();
303 if (bindListArray_) { ::free(bindListArray_); bindListArray_ = NULL; }
304 bindListArray_ = (void **) malloc(numBindFlds_ * sizeof (void *));
305 void *elem = NULL;
306 int i = 0;
307 ListIterator it = bindList_.getIterator();
308 while ((elem = it.nextElement()) != NULL) bindListArray_[i++] = elem;
309 scanType_ = fullTableScan;
310 isPlanCreated = true;
312 //if there are no predicates then go for full scan
313 //if there are no indexes then go for full scan
314 if (NULL == pred_ || NULL == indexPtr_)
316 return OK;
318 if (NULL != indexPtr_)
320 PredicateImpl *pred = (PredicateImpl*)pred_;
321 //If searching for IS NULL or IS NOT NULL then fullscan
322 if(pred->isIsNullInvolved())
324 scanType_ = fullTableScan;
325 shouldNullSearch=true;
326 return OK;
328 printDebug(DM_Predicate, "predicate does not involve NOT , OR operator");
329 if (!pred->isNotOrInvolved())
331 printDebug(DM_Predicate, "predicate does not involve NOT , OR operator");
332 bool isAllFldPointLookup = true;
333 for (int i =0; i < numIndexes_; i++)
335 HashIndexInfo* info = (HashIndexInfo*) idxInfo[i];
336 FieldIterator iter = info->idxFldList.getIterator();
337 while(iter.hasElement())
339 FieldDef *def = iter.nextElement();
340 if (pred->pointLookupInvolved(def->fldName_))
342 if (!isAllFldPointLookup) break;
343 printDebug(DM_Predicate, "point lookup involved for field %s",def->fldName_);
344 if(hashIndex == info->indType) scanType_ = hashIndexScan;
345 else scanType_ = treeIndexScan;
346 isPointLook = true;
347 useIndex_ = i;
349 else if (pred->isBetweenInvolved(def->fldName_))
351 if (treeIndex == info->indType)
353 scanType_ = treeIndexScan;
354 useIndex_ = i;
355 isBetween=true;
356 break; //no composite index for tree index
357 } else isAllFldPointLookup= false;
359 else if (pred->rangeQueryInvolved(def->fldName_))
361 printDebug(DM_Predicate, "range lookup involved for field %s",def->fldName_);
362 if (treeIndex == info->indType)
364 scanType_ = treeIndexScan;
365 useIndex_ = i;
366 break; //no composite index for tree index
367 } else isAllFldPointLookup=false;
368 }else {
369 useIndex_ = -1;
370 isAllFldPointLookup = false;
371 break;
373 }//while iter.hasElement()
374 if (!isAllFldPointLookup && useIndex_ != -1) return OK;
375 }//for
378 scanType_ = fullTableScan;
379 return OK;
382 void* TableImpl::fetch()
384 fetchNoBind();
385 if (NULL == curTuple_) return curTuple_;
386 copyValuesToBindBuffer(curTuple_);
387 return curTuple_;
389 void* TableImpl::fetch(DbRetVal &rv)
391 fetchNoBind(rv);
392 if (NULL == curTuple_) return curTuple_;
393 copyValuesToBindBuffer(curTuple_);
394 return curTuple_;
397 void* TableImpl::fetchNoBind()
399 if (NULL == iter)
401 printError(ErrNotOpen,"Scan not open or Scan is closed\n");
402 return NULL;
404 void *prevTuple = curTuple_;
405 curTuple_ = iter->next();
406 if (NULL == curTuple_)
408 return NULL;
410 DbRetVal lockRet = OK;
411 if (!loadFlag) {
412 if ((*trans)->isoLevel_ == READ_COMMITTED)
414 //if iso level is read committed, operation duration lock is sufficent
415 //so release it here itself.
416 int tries = Conf::config.getMutexRetries();
417 struct timeval timeout;
418 timeout.tv_sec = Conf::config.getMutexSecs();
419 timeout.tv_usec = Conf::config.getMutexUSecs();
421 bool status = false;
422 while(true) {
423 lockRet = lMgr_->isExclusiveLocked( curTuple_, trans, status);
424 if (OK != lockRet)
426 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
427 curTuple_ = prevTuple;
428 return NULL;
430 if (!status) break;
431 tries--;
432 if (tries == 0) break;
433 os::select(0, 0, 0, 0, &timeout);
435 if (tries == 0)
437 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
438 curTuple_ = prevTuple;
439 return NULL;
442 else if ((*trans)->isoLevel_ == READ_REPEATABLE) {
443 if (OK != trySharedLock(curTuple_, trans))
445 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
446 curTuple_ = prevTuple;
447 return NULL;
452 return curTuple_;
454 DbRetVal TableImpl::trySharedLock(void *curTuple, Transaction **trans)
456 DbRetVal lockRet = OK;
457 int tries = Conf::config.getMutexRetries();
458 while((lockRet = lMgr_->getSharedLock(curTuple_, trans)) == ErrLockTimeOut)
460 tries--;
461 if (tries <=0) break;
463 return lockRet;
465 DbRetVal TableImpl::tryExclusiveLock(void *curTuple, Transaction **trans)
467 DbRetVal lockRet = OK;
468 int tries = Conf::config.getMutexRetries();
469 while((lockRet = lMgr_->getExclusiveLock(curTuple_, trans)) == ErrLockTimeOut)
471 tries--;
472 if (tries <=0) break;
474 return lockRet;
477 void* TableImpl::fetchNoBind(DbRetVal &rv)
479 rv = OK;
480 if (NULL == iter)
482 printError(ErrNotOpen,"Scan not open or Scan is closed\n");
483 rv = ErrNotOpen;
484 return NULL;
486 void *prevTuple = curTuple_;
487 curTuple_ = iter->next();
488 if (NULL == curTuple_)
490 return NULL;
492 DbRetVal lockRet = OK;
493 if (!loadFlag) {
494 if ((*trans)->isoLevel_ == READ_REPEATABLE) {
495 lockRet = lMgr_->getSharedLock(curTuple_, trans);
496 if (OK != lockRet)
498 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
499 rv = ErrLockTimeOut;
500 curTuple_ = prevTuple;
501 return NULL;
505 else if ((*trans)->isoLevel_ == READ_COMMITTED)
507 //if iso level is read committed, operation duration lock is sufficent
508 //so release it here itself.
509 int tries = Conf::config.getMutexRetries();
510 //struct timeval timeout;
511 //timeout.tv_sec = Conf::config.getMutexSecs();
512 //timeout.tv_usec = Conf::config.getMutexUSecs();
514 bool status = false;
515 while(true) {
516 lockRet = lMgr_->isExclusiveLocked( curTuple_, trans, status);
517 if (OK != lockRet)
519 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
520 curTuple_ = prevTuple;
521 rv = ErrLockTimeOut;
522 return NULL;
524 if (!status) break;
525 tries--;
526 if (tries == 0) break;
527 //os::select(0, 0, 0, 0, &timeout);
529 if (tries == 0)
531 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
532 curTuple_ = prevTuple;
533 rv = ErrLockTimeOut;
534 return NULL;
538 return curTuple_;
540 DbRetVal TableImpl::fetchAgg(const char * fldName, AggType aType, void *buf, bool &noRec)
542 FieldInfo *info = new FieldInfo();
543 DbRetVal rv = getFieldInfo(fldName, info);
544 if (OK != rv) return rv;
545 bool res= false;
546 if (AGG_MIN == aType || AGG_MAX == aType) {
547 int pos =0;
548 IndexType iType = getIndexType((char*)fldName, &pos);
549 if(treeIndex == iType && pos >=0) {
550 if (AGG_MIN == aType) {
551 HashIndexInfo* hInfo = (HashIndexInfo*) idxInfo[pos];
552 CINDEX *iptr = (CINDEX*) hInfo->indexPtr;
553 TreeNode *fstNode=(TreeNode *)iptr->hashNodeChunk_;
554 TreeIter *iter=NULL;
555 if(fstNode!=NULL){
556 TreeNode *start = (TreeNode *)*((char**)((char*)fstNode + sizeof(TreeNode)));
557 iter = new TreeIter(start,(TreeNode*)iptr->hashNodeChunk_,sysDB_->procSlot);
558 }else{
559 iter = new TreeIter(NULL,(TreeNode*)iptr->hashNodeChunk_,sysDB_->procSlot);
561 char *tuple = (char*) iter->getFirstElement();
562 if (tuple != NULL) {
563 AllDataType::copyVal(buf,(void*)(tuple+info->offset),
564 info->type, info->length);
565 delete iter;
566 return OK;
568 delete iter; iter = NULL;
570 else if (AGG_MAX == aType) {
571 HashIndexInfo* hInfo = (HashIndexInfo*) idxInfo[pos];
572 CINDEX *iptr = (CINDEX*) hInfo->indexPtr;
573 TreeNode *fstNode=(TreeNode *)iptr->hashNodeChunk_;
574 TreeIter *iter=NULL;
575 if(fstNode!=NULL){
576 TreeNode *start = (TreeNode *)*((char**)((char*)fstNode + sizeof(TreeNode)));
577 iter = new TreeIter(start,(TreeNode*)iptr->hashNodeChunk_,sysDB_->procSlot);
578 }else{
579 iter = new TreeIter(NULL,(TreeNode*)iptr->hashNodeChunk_,sysDB_->procSlot);
581 char *tuple = (char*) iter->getLastElement();
582 if (tuple != NULL) {
583 AllDataType::copyVal(buf,(void*)(tuple+info->offset),
584 info->type, info->length);
585 delete iter; iter = NULL;
586 return OK;
588 delete iter; iter=NULL;
591 }else if (AGG_COUNT == aType) {
592 (*(int*)buf) = 0;
596 DataType type = info->type;
597 int length = info->length;
598 int offset = info->offset;
599 int colPos = fldList_.getFieldPosition(fldName);
600 bool isNullable= true;
601 if (info->isNull || info->isPrimary || info->isDefault || info->isAutoIncrement) {
602 isNullable = false;
604 int nullOffset = length_-4;
605 if (aType == AGG_COUNT) {
606 length = sizeof(int);
607 type = typeInt;
609 if (NULL == pred_ && typeInt == type && aType != AGG_AVG)
610 { //perf opt
611 ChunkIterator cIter = ((Chunk*)chunkPtr_)->getIterator();
612 char *tuple =(char*)cIter.nextElement();
613 if (NULL == tuple) {
614 *(int *) buf = 0;
615 noRec = true;
616 return OK;
618 int count =1;
619 if (isNullable) {
620 if (isIntUsedForNULL) {
621 if (BITSET(*(int*)(tuple+nullOffset), colPos)) count =0;
623 else {
624 curTuple_= tuple;
625 if(isFldNull(colPos)) count =0;
628 if (aType != AGG_COUNT)
629 AllDataType::copyVal(buf, (void*) (tuple+offset), type, length);
630 void *prev=NULL;
631 prev = curTuple_;
632 cIter.pageSize = PAGE_SIZE;
633 while(1)
635 tuple = (char*)cIter.nextElementInt();
636 if (NULL == tuple) break;
637 if (isNullable) {
638 if (isIntUsedForNULL) {
639 if (BITSET(*(int*)(tuple+nullOffset), colPos)) continue;
641 else {
642 curTuple_= tuple;
643 if(isFldNull(colPos)) continue;
646 if (aType == AGG_MIN)
648 if (*(int*)buf >= *((int*)(tuple+offset)))
649 *(int*)buf = *((int*)(tuple+offset));
651 else if (aType == AGG_MAX)
653 if (*(int*)buf <= *((int*)(tuple+offset)))
654 *(int*)buf = *((int*)(tuple+offset));
656 else if (aType == AGG_SUM)
658 *(int*)buf += *((int*)(tuple+offset));
660 else if (aType == AGG_AVG)
662 *(int*)buf = *(int*)buf + *((int*)(tuple+offset));
663 count++;
665 else if (aType == AGG_COUNT)
667 count++;
670 curTuple_= prev;
671 if( AGG_AVG == aType) AllDataType::divVal(buf, &count, type);
672 else if (AGG_COUNT == aType) (*(int*)buf) = count;
673 delete info;
674 return OK;
677 char *tuple = (char*) fetchNoBind(rv);
678 if ( NULL == tuple) { noRec = true; return OK; }
679 int count =1;
681 while(isFldNull(colPos)) {
682 tuple= (char*) fetchNoBind(rv);
683 if (aType == AGG_COUNT) count++;
684 if (tuple) break;
686 if ( NULL == tuple) { noRec = true; return OK; }
688 if (aType == AGG_AVG) {
689 AllDataType::convertToDouble(buf, (void*) (tuple+offset), type);
690 } else if (aType != AGG_COUNT) {
691 AllDataType::copyVal(buf, (void*) (tuple+offset), type, length);
693 while(1) {
694 tuple = (char*) fetchNoBind(rv);
695 if (NULL == tuple) break;
696 if (isNullable) {
697 if (isIntUsedForNULL) {
698 if (BITSET(*(int*)(tuple+nullOffset), colPos)) continue;
700 else {
701 curTuple_= tuple;
702 if(isFldNull(colPos)) continue;
705 switch(aType) {
706 case AGG_MIN:
708 res = AllDataType::compareVal(buf, (void*) (tuple+offset),
709 OpGreaterThanEquals,
710 type, length);
711 if (res) AllDataType::copyVal(buf, (void*) (tuple+offset),
712 type, length);
713 break;
715 case AGG_MAX:
717 res = AllDataType::compareVal(buf, (void*) (tuple+offset),
718 OpLessThanEquals,
719 type, length);
720 if (res) AllDataType::copyVal(buf, (void*) (tuple+offset),
721 type, length);
722 break;
724 case AGG_SUM:
726 AllDataType::addVal(buf, (void*) (tuple+offset),
727 type);
728 break;
730 case AGG_AVG:
732 double tmpBuf=0.0;
733 AllDataType::convertToDouble(&tmpBuf, (void*) (tuple+offset), type);
734 AllDataType::addVal(buf, &tmpBuf, typeDouble);
735 count++;
736 break;
738 case AGG_COUNT:
740 count++;
741 break;
745 switch(aType) {
746 case AGG_AVG:
748 AllDataType::divVal((double *)buf, count, type);
749 break;
751 case AGG_COUNT:
753 (*(int*)buf) = count;
754 break;
757 delete info;
758 return OK;
760 DbRetVal TableImpl::insertTuple()
762 DbRetVal ret =OK;
763 void *tptr = NULL;// ((Chunk*)chunkPtr_)->allocate(db_, &ret);
764 int tries=0;
765 int totalTries = Conf::config.getMutexRetries();
766 while (tries < totalTries)
768 ret = OK;
769 tptr = ((Chunk*)chunkPtr_)->allocate(db_, &ret);
770 if (tptr !=NULL) break;
771 if (ret != ErrLockTimeOut)
773 printError(ret, "Unable to allocate record from chunk");
774 return ret;
776 tries++;
778 if (NULL == tptr)
780 printError(ret, "Unable to allocate record from chunk after %d retries", tries);
781 return ret;
783 curTuple_ = tptr;
784 if(isFkTbl){
785 TableImpl *fkTbl =NULL;
786 ListIterator tblIter = tblList.getIterator();
787 tblIter.reset();
788 while (tblIter.hasElement()){
789 fkTbl = (TableImpl *) tblIter.nextElement();
790 bool pkRec = isPkTableHasRecord(fkTbl->getName(),fkTbl,true);
791 if(!pkRec){
792 printError(ErrForeignKeyInsert, "Unable to insert into foreign Key table.Check PK table");
793 ((Chunk*)chunkPtr_)->free(db_, tptr);
794 return ErrForeignKeyInsert;
797 tblIter.reset();
799 if (!loadFlag) {
800 //ret = lMgr_->getExclusiveLock(tptr, trans);
801 if (OK != tryExclusiveLock(tptr, trans))
803 ((Chunk*)chunkPtr_)->free(db_, tptr);
804 printError(ret, "Could not get lock for the insert tuple %x", tptr);
805 return ErrLockTimeOut;
809 ret = copyValuesFromBindBuffer(tptr);
810 if (ret != OK)
812 printError(ret, "Unable to copy values from bind buffer");
813 if (!loadFlag) {
814 (*trans)->removeFromHasList(db_, tptr);
815 lMgr_->releaseLock(tptr);
817 ((Chunk*)chunkPtr_)->free(db_, tptr);
818 return ret;
820 int addSize = 0;
821 if (numFlds_ < 31)
823 addSize = 4;
824 *(int*)((char*)(tptr) + (length_-addSize)) = iNullInfo;
826 else
828 addSize = os::align(numFlds_);
829 os::memcpy(((char*)(tptr) + (length_-addSize)), cNullInfo, addSize);
832 //int tupleSize = length_ + addSize;
833 if (NULL != indexPtr_)
835 int i;
836 //it has index
837 for (i = 0; i < numIndexes_ ; i++)
839 ret = insertIndexNode(*trans, indexPtr_[i], idxInfo[i], tptr);
840 if (ret != OK) { printError(ret, "Error in inserting to index %x", tptr); break;}
842 if ( ret != OK)
844 for (int j = 0; j < i ; j++) {
845 printError(ErrWarning, "Undo:Deleting index node");
846 deleteIndexNode(*trans, indexPtr_[j], idxInfo[j], tptr);
848 if (!loadFlag) {
849 (*trans)->removeFromHasList(db_, tptr);
850 lMgr_->releaseLock(tptr);
852 ((Chunk*)chunkPtr_)->free(db_, tptr);
853 return ret;
856 if (!loadFlag)
857 ret = (*trans)->appendUndoLog(sysDB_, InsertOperation, tptr, length_);
858 if (ret != OK) {
859 printError(ret, "Unable to create undo log for %x %d", tptr, *(int*)tptr);
860 for (int j = 0; j < numIndexes_ ; j++) {
861 printError(ErrWarning, "Deleting index node");
862 deleteIndexNode(*trans, indexPtr_[j], idxInfo[j], tptr);
864 if (!loadFlag) {
865 (*trans)->removeFromHasList(db_, tptr);
866 lMgr_->releaseLock(tptr);
868 ((Chunk*)chunkPtr_)->free(db_, tptr);
870 return ret;
873 DbRetVal TableImpl::deleteTuple()
875 if (NULL == curTuple_)
877 printError(ErrNotOpen, "Scan not open: No Current tuple");
878 return ErrNotOpen;
880 if(isPkTbl){
881 TableImpl *fkTbl =NULL;
882 ListIterator tblIter = tblFkList.getIterator();
883 tblIter.reset();
884 while (tblIter.hasElement()){
885 fkTbl = (TableImpl *) tblIter.nextElement();
886 bool pkRec = isFkTableHasRecord(fkTbl->getName(),fkTbl);
887 if(pkRec){
888 printError(ErrForeignKeyDelete, "A Relation Exists. Delete from child table first");
889 return ErrForeignKeyDelete;
892 tblIter.reset();
894 DbRetVal ret = OK;
895 if (!loadFlag) {
896 //ret = lMgr_->getExclusiveLock(curTuple_, trans);
897 if (OK != tryExclusiveLock(curTuple_, trans))
899 printError(ret, "Could not get lock for the delete tuple %x",
900 curTuple_);
901 return ErrLockTimeOut;
905 if (NULL != indexPtr_)
907 int i;
908 //it has index
909 for (i = 0; i < numIndexes_ ; i++)
911 ret = deleteIndexNode(*trans, indexPtr_[i], idxInfo[i], curTuple_);
912 if (ret != OK) break;
914 if (i != numIndexes_ )
916 printError(ErrWarning, "Inserting back index node");
917 for (int j = 0; j < i ; j++)
918 insertIndexNode(*trans, indexPtr_[j], idxInfo[j], curTuple_);
919 if (!loadFlag) {
920 lMgr_->releaseLock(curTuple_);
921 (*trans)->removeFromHasList(db_, curTuple_);
923 printError(ret, "Unable to insert index node for tuple %x", curTuple_);
924 return ret;
927 if (!loadFlag)
928 ret = (*trans)->appendUndoLog(sysDB_, DeleteOperation, curTuple_, 0);
929 if (ret != OK) {
930 printError(ret, "Unable to create undo log for %x ", curTuple_);
931 for (int j = 0; j < numIndexes_ ; j++) {
932 printError(ErrWarning, "Inserting back index node");
933 insertIndexNode(*trans, indexPtr_[j], idxInfo[j], curTuple_);
935 if (!loadFlag) {
936 (*trans)->removeFromHasList(db_, curTuple_);
937 lMgr_->releaseLock(curTuple_);
940 ((Chunk*)chunkPtr_)->free(db_, curTuple_);
942 iter->prev();
943 return ret;
946 int TableImpl::deleteWhere()
948 int tuplesDeleted = 0;
949 DbRetVal rv = OK;
950 rv = execute();
951 if (rv !=OK) return (int) rv;
952 while(true){
953 fetchNoBind( rv);
954 if (rv != OK) { tuplesDeleted = (int)rv; break; }
955 if (NULL == curTuple_) break;
956 rv = deleteTuple();
957 if (rv != OK) {
958 printError(rv, "Error: Could only delete %d tuples", tuplesDeleted);
959 closeScan();
960 return (int) rv;
962 tuplesDeleted++;
964 closeScan();
965 return tuplesDeleted;
968 int TableImpl::truncate()
970 //take exclusive lock on the table
971 //get the chunk ptr of the table
972 //traverse the tablechunks and free all the pages except the first one
973 //get the chunk ptr of all its indexes
974 //traverse the indexchunks and free all the pages except the first one
975 //release table lock
977 //TEMPORARY FIX
978 DbRetVal rv = OK;
979 Predicate* tmpPred = pred_;
980 pred_ = NULL;
981 isPlanCreated = false;
982 int tuplesDeleted = deleteWhere();
983 isPlanCreated = false;
984 pred_ = tmpPred;
985 return tuplesDeleted;
988 DbRetVal TableImpl::updateTuple()
990 if (NULL == curTuple_)
992 printError(ErrNotOpen, "Scan not open: No Current tuple");
993 return ErrNotOpen;
995 if(isFkTbl){
996 TableImpl *fkTbl =NULL;
997 ListIterator tblIter = tblList.getIterator();
998 tblIter.reset();
999 while (tblIter.hasElement()){
1000 fkTbl = (TableImpl *) tblIter.nextElement();
1001 bool pkRec = isPkTableHasRecord(fkTbl->getName(),fkTbl,false);
1002 if(!pkRec){
1003 printError(ErrForeignKeyInsert, "Unable to insert into foreign Key table.Check PK table");
1004 return ErrForeignKeyInsert;
1007 tblIter.reset();
1010 DbRetVal ret=OK;
1011 if (!loadFlag) {
1012 //ret = lMgr_->getExclusiveLock(curTuple_, trans);
1013 if (OK != tryExclusiveLock(curTuple_, trans))
1015 printError(ret, "Could not get lock for the update tuple %x", curTuple_);
1016 return ErrLockTimeOut;
1019 if (NULL != indexPtr_)
1021 //it has index
1022 //TODO::If it fails while updating index node, we have to undo all the updates
1023 //on other indexes on the table.Currently it will leave the database in an
1024 //inconsistent state.
1025 for (int i = 0; i < numIndexes_ ; i++)
1027 ret = updateIndexNode(*trans, indexPtr_[i], idxInfo[i], curTuple_);
1028 if (ret != OK)
1030 if (!loadFlag) {
1031 lMgr_->releaseLock(curTuple_);
1032 (*trans)->removeFromHasList(db_, curTuple_);
1034 printError(ret, "Unable to update index node for tuple %x", curTuple_);
1035 return ret;
1039 if (!loadFlag)
1040 ret = (*trans)->appendUndoLog(sysDB_, UpdateOperation, curTuple_, length_);
1041 if (ret != OK) {
1042 if (!loadFlag) {
1043 lMgr_->releaseLock(curTuple_);
1044 (*trans)->removeFromHasList(db_, curTuple_);
1046 return ret;
1048 int addSize = 0;
1049 int iNullVal=iNullInfo;
1050 if (numFlds_ < 31){
1051 addSize=4;
1052 if(!iNullVal){
1053 iNullInfo = *(int*)((char*)(curTuple_) + (length_- addSize));
1055 else
1057 *(int*)((char*)(curTuple_) + (length_-addSize)) |= iNullInfo;
1060 DbRetVal rv = copyValuesFromBindBuffer(curTuple_, false);
1061 if (rv != OK && !loadFlag) {
1062 lMgr_->releaseLock(curTuple_);
1063 (*trans)->removeFromHasList(db_, curTuple_);
1064 return rv;
1067 if (numFlds_ < 31)
1069 if (!iNullVal) {
1070 *(int*)((char*)(curTuple_) + (length_-addSize)) = iNullInfo;
1071 iNullInfo=0;
1073 else iNullInfo=iNullVal;
1075 else
1077 addSize = os::align(numFlds_);
1078 //TODO::Do not do blind memcpy. It should OR each and every char
1079 int i=0;
1080 char *null=(char*)(curTuple_) + (length_-addSize);
1081 while(i < numFlds_) {
1082 if(cNullInfo[i]) null[i] |= cNullInfo[i];
1083 i++;
1085 //os::memcpy(((char*)(curTuple_) + (length_-addSize)), cNullInfo, addSize);
1089 return OK;
1092 void TableImpl::printInfo()
1094 printf(" <TableName> %s </TableName>\n", tblName_);
1095 printf(" <TupleCount> %d </TupleCount>\n", numTuples());
1096 printf(" <PagesUsed> %d </PagesUsed>\n", pagesUsed());
1097 printf(" <SpaceUsed> %d </SpaceUsed>\n", spaceUsed());
1098 printf(" <Indexes> %d <Indexes>\n", numIndexes_);
1099 printf(" <TupleLength> %d </TupleLength>\n", length_);
1100 printf(" <Fields> %d </Fields>\n", numFlds_);
1101 printf(" <Indexes>\n");
1102 for (int i =0; i<numIndexes_; i++)
1103 printf("<IndexName> %s </IndexName>\n", CatalogTableINDEX::getName(indexPtr_[i]));
1104 printf(" </Indexes>\n");
1108 DbRetVal TableImpl::copyValuesFromBindBuffer(void *tuplePtr, bool isInsert)
1110 //Iterate through the bind list and copy the value here
1111 FieldIterator fIter = fldList_.getIterator();
1112 char *colPtr = (char*) tuplePtr;
1113 int fldpos=1;
1114 while (fIter.hasElement())
1116 FieldDef *def = fIter.nextElement();
1117 if(def->isAutoIncrement_ && isInsert)
1119 void *dest = AllDataType::alloc(def->type_, def->length_);
1120 AllDataType::copyVal(dest,ptrToAuto, def->type_, def->length_);
1121 if(def->bindVal_==NULL)
1123 AllDataType::increment(colPtr, dest , def->type_);
1124 AllDataType::copyVal(ptrToAuto,colPtr, def->type_, def->length_);
1125 colPtr = colPtr + def->length_;
1126 fldpos++;
1127 free(dest);
1128 continue;
1129 }else {
1130 if(AllDataType::compareVal(def->bindVal_, dest, OpGreaterThan, def->type_)){
1131 AllDataType::copyVal(ptrToAuto,def->bindVal_, def->type_, def->length_);
1133 free(dest);
1136 if (def->isNull_ && !def->isDefault_ && NULL == def->bindVal_ && isInsert)
1138 printError(ErrNullViolation, "NOT NULL constraint violation for field %s", def->fldName_);
1139 return ErrNullViolation;
1141 if (def->isDefault_ && NULL == def->bindVal_ && isInsert)
1143 void *dest = AllDataType::alloc(def->type_, def->length_);
1144 AllDataType::convert(typeString, def->defaultValueBuf_, def->type_, dest, def->length_);
1145 AllDataType::copyVal(colPtr, dest, def->type_, def->length_);
1146 colPtr = colPtr + def->length_;
1147 fldpos++;
1148 free (dest);
1149 continue;
1151 switch(def->type_)
1153 case typeString:
1154 if (NULL != def->bindVal_)
1156 if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);}
1157 strncpy((char*)colPtr, (char*)def->bindVal_, def->length_);
1158 *(((char*)colPtr) + (def->length_-1)) = '\0';
1160 else if (!def->isNull_ && !def->bindVal_ && isInsert) setNullBit(fldpos);
1161 colPtr = colPtr + def->length_;
1162 break;
1163 case typeBinary:
1164 if (NULL != def->bindVal_ )
1166 if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);}
1167 DbRetVal rv = AllDataType::strToValue(colPtr, (char *) def->bindVal_, def->type_, def->length_);
1168 if (rv != OK) return ErrBadArg;
1170 else if (!def->isNull_ && isInsert && !def->bindVal_) setNullBit(fldpos);
1171 colPtr = colPtr + def->length_;
1172 break;
1173 default:
1174 if (NULL != def->bindVal_){
1175 if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);}
1176 AllDataType::copyVal(colPtr, def->bindVal_, def->type_);}
1177 else { if (!def->isNull_ && isInsert) setNullBit(fldpos); }
1178 colPtr = colPtr + def->length_;
1179 break;
1181 fldpos++;
1183 return OK;
1185 void TableImpl::clearNullBit(int fldpos)
1187 if (isIntUsedForNULL){
1188 CLEARBIT(iNullInfo, fldpos);}
1189 else
1190 cNullInfo[fldpos-1] = 0;
1192 void TableImpl::setNullBit(int fldpos)
1194 if (isIntUsedForNULL)
1195 SETBIT(iNullInfo, fldpos);
1196 else
1197 cNullInfo[fldpos-1] = 1;
1199 DbRetVal TableImpl::copyValuesToBindBuffer(void *tuplePtr)
1201 //Iterate through the bind list and copy the value here
1202 char *colPtr = (char*) tuplePtr;
1203 FieldDef *def = NULL;
1204 for (int i = 0; i < numBindFlds_; i++) {
1205 def = (FieldDef *) bindListArray_[i];
1206 colPtr = (char *) tuplePtr + def->offset_;
1207 AllDataType::copyVal(def->bindVal_, colPtr, def->type_, def->length_);
1209 return OK;
1212 //-1 index not supported
1213 DbRetVal TableImpl::insertIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple)
1215 CINDEX *iptr = (CINDEX*)indexPtr;
1216 DbRetVal ret = OK;
1217 printDebug(DM_Table, "Inside insertIndexNode type %d", iptr->indexType_);
1218 Index* idx = Index::getIndex(iptr->indexType_);
1219 ret = idx->insert(this, tr, indexPtr, info, tuple,loadFlag);
1220 return ret;
1223 DbRetVal TableImpl::deleteIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple)
1225 CINDEX *iptr = (CINDEX*)indexPtr;
1226 DbRetVal ret = OK;
1227 Index* idx = Index::getIndex(iptr->indexType_);
1228 ret = idx->remove(this, tr, indexPtr, info, tuple, loadFlag);
1229 return ret;
1231 void TableImpl::printSQLIndexString(FILE *fp, int fd)
1233 if (fp == NULL) fp = stdout;
1234 CatalogTableINDEXFIELD cIndexField(sysDB_);
1235 char fName[IDENTIFIER_LENGTH];
1236 char idxName[IDENTIFIER_LENGTH];
1237 char *fldName = fName;
1238 DataType type;
1239 for (int i = 0; i < numIndexes_ ; i++)
1241 CINDEX *iptr = (CINDEX*) indexPtr_[i];
1242 sprintf(idxName,"%s_idx_Auto_increment",getName());
1243 if(strcmp(iptr->indName_,idxName)==0){ continue; }
1244 if (Conf::config.useDurability()) {
1245 struct Object obj;
1246 strcpy(obj.name, iptr->indName_);
1247 if (iptr->indexType_ == hashIndex) {
1248 obj.type = hIdx;
1249 obj.bucketChunk = ((Chunk *)iptr->chunkPtr_)->getFirstPage();
1250 obj.firstPage = ((Chunk *)iptr->hashNodeChunk_)->getFirstPage();
1251 obj.curPage = ((Chunk *)iptr->hashNodeChunk_)->getCurrentPage();
1252 } else if (iptr->indexType_ == treeIndex) {
1253 obj.type = tIdx;
1254 obj.firstPage = ((Chunk *)iptr->chunkPtr_)->getFirstPage();
1255 obj.curPage = ((Chunk *)iptr->chunkPtr_)->getCurrentPage();
1256 long nodes = ((Chunk *)iptr->chunkPtr_)->getTotalDataNodes();
1257 if(nodes) {
1258 ChunkIterator cIter = ((Chunk *)iptr->chunkPtr_)->getIterator();
1259 obj.bucketChunk = cIter.nextElement();
1260 } else obj.bucketChunk = NULL;
1262 void *buf = &obj;
1263 write(fd, buf, sizeof(obj));
1265 fprintf(fp, "CREATE INDEX %s on %s ( ", iptr->indName_, getName());
1266 FieldList fldList;
1267 cIndexField.getFieldInfo(iptr, fldList);
1268 FieldIterator fIter = fldList.getIterator();
1269 bool firstFld = true;
1270 while(fIter.hasElement())
1272 FieldDef *def = fIter.nextElement();
1273 if (firstFld) { fprintf(fp, " %s ", def->fldName_); firstFld = false; }
1274 else fprintf(fp, " ,%s ", def->fldName_);
1276 fldList.removeAll();
1277 fprintf(fp, " ) ");
1278 if (iptr->indexType_ == hashIndex) fprintf(fp, " HASH ");
1279 else fprintf(fp, " TREE ");
1280 if (((HashIndexInfo*) idxInfo[i])->isUnique) fprintf(fp, " UNIQUE");
1281 if(((HashIndexInfo*) idxInfo[i])->noOfBuckets != 1009 ) fprintf(fp, " SIZE %d ",((HashIndexInfo*) idxInfo[i])->noOfBuckets );
1282 fprintf(fp, ";\n");
1287 DbRetVal TableImpl::updateIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple)
1289 CINDEX *iptr = (CINDEX*)indexPtr;
1290 DbRetVal ret = OK;
1291 Index* idx = Index::getIndex(iptr->indexType_);
1292 //TODO::currently it updates irrespective of whether the key changed or not
1293 //because of this commenting the whole index update code. relook at it and uncomment
1295 ret = idx->update(this, tr, indexPtr, info, tuple, loadFlag);
1297 return ret;
1301 void TableImpl::setTableInfo(char *name, int tblid, size_t length,
1302 int numFld, int numIdx, void *chunk)
1304 strcpy(tblName_, name);
1305 tblID_ = tblid;
1306 length_ = length;
1307 numFlds_ = numFld;
1308 numIndexes_ = numIdx;
1309 chunkPtr_ = chunk;
1312 long TableImpl::spaceUsed()
1314 Chunk *chk = (Chunk*)chunkPtr_;
1315 long totSize = chk->getTotalDataNodes() * chk->getSize();
1316 totSize = totSize + (chk->totalPages() * sizeof (PageInfo));
1317 return totSize;
1320 int TableImpl::pagesUsed()
1322 Chunk *chk = (Chunk*)chunkPtr_;
1323 return chk->totalPages();
1326 long TableImpl::numTuples()
1328 return ((Chunk*)chunkPtr_)->getTotalDataNodes();
1331 List TableImpl::getFieldNameList()
1333 List fldNameList;
1334 FieldIterator fIter = fldList_.getIterator();
1335 char fieldName[IDENTIFIER_LENGTH];
1336 while (fIter.hasElement())
1338 FieldDef *def = fIter.nextElement();
1339 Identifier *elem = new Identifier();
1340 Table::getFieldNameAlone(def->fldName_, fieldName);
1341 sprintf(elem->name, "%s.%s", getName(), fieldName);
1342 fldNameList.append(elem);
1344 return fldNameList;
1346 DbRetVal TableImpl::close()
1348 if (iter) { iter->close(); delete iter; iter = NULL; }
1349 TableImpl *fkTbl =NULL;
1350 ListIterator tblIter = tblList.getIterator();
1351 tblIter.reset();
1352 while (tblIter.hasElement()){
1353 fkTbl = (TableImpl *) tblIter.nextElement();
1354 fkTbl->close();
1356 tblList.reset();
1357 tblIter = tblFkList.getIterator();
1358 tblIter.reset();
1359 while (tblIter.hasElement()){
1360 fkTbl = (TableImpl *) tblIter.nextElement();
1361 fkTbl->close();
1363 tblFkList.reset();
1364 printDebug(DM_Database,"Closing table handle: %x", this);
1365 //table->unlock();
1366 //delete pred_;
1367 ListIterator pIter = predList.getIterator();
1368 while (pIter.hasElement())
1370 PredicateImpl *pImpl = (PredicateImpl*) pIter.nextElement();
1371 delete pImpl;
1373 predList.reset();
1374 delete this;
1375 logFinest(Conf::logger, "Closing Table");
1376 return OK;
1379 DbRetVal TableImpl::closeScan()
1381 //do not throw scan not open error
1382 //this function will be called by table handle
1383 if (iter) {
1384 iter->close();
1386 return OK;
1388 DbRetVal TableImpl::lock(bool shared)
1391 DbRetVal ret = OK;
1393 if (shared)
1394 ret = lMgr_->getSharedLock(chunkPtr_, NULL);
1395 else
1396 ret = lMgr_->getExclusiveLock(chunkPtr_, NULL);
1397 if (OK != ret)
1399 printError(ret, "Could not exclusive lock on the table %x", chunkPtr_);
1400 }else {
1401 //do not append for S to X upgrade
1402 if (!ProcessManager::hasLockList.exists(chunkPtr_))
1403 ProcessManager::hasLockList.append(chunkPtr_);
1406 return ret;
1408 DbRetVal TableImpl::unlock()
1411 if (!ProcessManager::hasLockList.exists(chunkPtr_)) return OK;
1412 DbRetVal ret = lMgr_->releaseLock(chunkPtr_);
1413 if (OK != ret)
1415 printError(ret, "Could not release exclusive lock on the table %x", chunkPtr_);
1416 }else
1418 ProcessManager::hasLockList.remove(chunkPtr_);
1421 return OK;
1424 TableImpl::~TableImpl()
1426 if (NULL != iter ) { delete iter; iter = NULL; }
1427 if (NULL != indexPtr_) { delete[] indexPtr_; indexPtr_ = NULL; }
1428 if (NULL != idxInfo)
1430 for (int i = 0; i < numIndexes_; i++) delete idxInfo[i];
1431 delete[] idxInfo;
1432 idxInfo = NULL;
1434 if (numFlds_ > 31 && cNullInfo != NULL) { free(cNullInfo); cNullInfo = NULL; }
1435 if (bindList_.size()) bindList_.reset();
1436 if (bindListArray_) { free (bindListArray_); bindListArray_ = NULL; }
1437 fldList_.removeAll();
1441 void *TableImpl::getBindFldAddr(const char *name)
1443 return fldList_.getBindField(name);
1445 bool TableImpl::isTableInvolved(char *tblName)
1447 //printf("Table isTableInvolved called for %s with %s\n", tblName, getName());
1448 if (0 == strcmp(getName(), tblName)) return true; else return false;
1450 bool TableImpl::pushPredicate(Predicate *pred)
1452 bool ret = false;
1453 PredicateImpl *pImpl = (PredicateImpl*) pred;
1454 char tableName[IDENTIFIER_LENGTH];
1455 Table::getTableNameAlone(pImpl->getFldName1(), tableName);
1456 //printf("predicate tbl name %s\n", tableName);
1458 //if predicate is of form t1.f1=t2.f1 then do not push here
1459 if (0 != strcmp(pImpl->getFldName2(),"")) return ret;
1461 if (0 == strcmp(getName(), tableName))
1463 setPredicate(pred);
1464 //printf("PRABA::pushed predicate in tablehdl %s\n", getName());
1465 ret = true;
1467 return ret;
1470 void TableImpl::setCondition(Condition *p)
1472 isPlanCreated = false;
1473 ListIterator pIter = predList.getIterator();
1474 while (pIter.hasElement())
1476 PredicateImpl *pImpl = (PredicateImpl*) pIter.nextElement();
1477 delete pImpl;
1479 predList.reset();
1481 if (p) pred_ = p->getPredicate(); else pred_ = NULL;
1484 void TableImpl::setPredicate(Predicate *pred)
1486 if (NULL == pred_) { pred_ = pred; return; }
1488 Predicate *curPred = pred_;
1489 PredicateImpl *newPred = new PredicateImpl();
1490 newPred->setTerm(curPred, OpAnd, pred);
1491 newPred->setTable(this);
1492 pred_ = newPred;
1493 return;
1495 void TableImpl::printPlan(int space)
1497 char spaceBuf[IDENTIFIER_LENGTH];
1498 memset(spaceBuf, 32, IDENTIFIER_LENGTH);
1499 spaceBuf[space] = '\0';
1500 printf("%s <TABLE-NODE>\n", spaceBuf);
1501 printf("%s <NAME> %s </NAME>\n", spaceBuf, getName());
1502 printf("%s <ScanType> %s </ScanType>\n", spaceBuf, ScanTypeNames[scanType_]);
1503 PredicateImpl *pred = (PredicateImpl*)pred_;
1504 if (pred) pred->print(space+2);
1505 printf("%s </TABLE-NODE>\n", spaceBuf);
1507 void TableImpl::printSQLForeignString()
1509 DbRetVal rv=OK;
1510 FieldNameList pkFieldList,fkFieldList;
1511 void *tPkptr =NULL;
1512 void *tFkptr = NULL;
1513 void *chunkPk = NULL;
1514 CatalogTableTABLE cTable(sysDB_);
1515 TableImpl *fkTbl =NULL;
1516 ListIterator tblIter = tblList.getIterator();
1517 tblIter.reset();
1518 int firstFK=true;
1519 while (tblIter.hasElement()){
1520 fkTbl = (TableImpl *) tblIter.nextElement();
1521 rv = cTable.getChunkAndTblPtr(fkTbl->getName(), chunkPk, tPkptr);
1522 if ( OK != rv){return ;}
1523 rv = cTable.getChunkAndTblPtr(getName(), chunkPk, tFkptr);
1524 if ( OK != rv){return ;}
1525 CatalogTableFK cFk(sysDB_);
1526 rv = cFk.getPkFkFieldInfo(tPkptr,tFkptr,pkFieldList,fkFieldList);
1527 if ( OK != rv){return;}
1528 pkFieldList.resetIter();
1529 fkFieldList.resetIter();
1530 char *fldName = NULL;
1531 bool firstField=true;
1532 if(!firstFK) printf(", ");
1533 printf(", FOREIGN KEY ( ");
1534 while((fldName = fkFieldList.nextFieldName())!= NULL)
1536 if (firstField) {
1537 printf("%s",fldName);
1538 firstField=false;
1540 else
1541 printf(",%s",fldName);
1543 printf(" ) REFERENCES %s ( ",fkTbl->getName());
1544 firstField=true;
1545 while((fldName = pkFieldList.nextFieldName())!= NULL)
1547 if (firstField) {
1548 printf("%s",fldName);
1549 firstField=false;
1551 else
1552 printf(",%s",fldName);
1554 printf(" )");
1555 firstFK=true;
1556 pkFieldList.removeAll();
1557 fkFieldList.removeAll();
1559 return;
1561 bool TableImpl::isPkTableHasRecord(char *pkTableName, TableImpl *fkTbl,bool isInsert)
1563 DbRetVal rv=OK;
1564 bool isRecExist=false;
1565 FieldNameList pkFieldList,fkFieldList;
1566 void *tPkptr =NULL;
1567 void *tFkptr = NULL;
1568 void *chunkPk = NULL;
1569 CatalogTableTABLE cTable(sysDB_);
1570 rv = cTable.getChunkAndTblPtr(pkTableName, chunkPk, tPkptr);
1571 if ( OK != rv){return false;}
1572 rv = cTable.getChunkAndTblPtr(getName(), chunkPk, tFkptr);
1573 if ( OK != rv){return false;}
1574 CatalogTableFK cFk(sysDB_);
1575 rv = cFk.getPkFkFieldInfo(tPkptr,tFkptr,pkFieldList,fkFieldList);
1576 if ( OK != rv){return false;}
1577 int totFld = pkFieldList.size();
1578 Condition *condition = new Condition[totFld];
1579 char *pkFldName = NULL;
1580 char *fkFldName = NULL;
1581 FieldDef *def=NULL;
1582 int i=0;
1583 pkFieldList.resetIter();
1584 fkFieldList.resetIter();
1585 void *val=NULL;
1586 while((pkFldName = pkFieldList.nextFieldName())!= NULL)
1588 fkFldName = fkFieldList.nextFieldName();
1589 FieldIterator fIter = fldList_.getIterator();
1590 while (fIter.hasElement())
1592 def = fIter.nextElement();
1593 if (strcmp(def->fldName_, fkFldName) == 0)
1595 if(NULL == def->bindVal_ && isInsert) { return true; }
1596 if(NULL == def->bindVal_) {
1597 val = (char*)curTuple_+ def->offset_;
1598 } else {
1599 val = def->bindVal_;
1601 if(def->type_==typeString)
1602 condition[i].setTerm(pkFldName,OpEquals,&val);
1603 else
1604 condition[i].setTerm(pkFldName,OpEquals,val);
1605 i++;
1606 break;
1610 pkFieldList.removeAll();
1611 fkFieldList.removeAll();
1612 Condition *cond = NULL;
1613 if(i == 0 && !isInsert)return true;
1614 if( i > 1){
1615 cond = new Condition[i-1];
1616 int totcon = i;
1617 i=0;
1618 int j=0;
1619 for(j=0;j<totcon-1;j++)
1621 if(j==0)
1622 cond[j].setTerm(condition[i++].getPredicate(),OpAnd,condition[i++].getPredicate());
1623 else
1624 cond[j].setTerm(cond[j-1].getPredicate(), OpAnd, condition[i++].getPredicate());
1626 fkTbl->setCondition(&cond[j-1]);
1628 else{
1629 fkTbl->setCondition(&condition[i-1]);
1631 fkTbl->execute();
1632 if(fkTbl->fetch()){
1633 fkTbl->closeScan();
1634 delete[] cond;
1635 delete[] condition;
1636 return true;
1638 delete[] cond;
1639 delete[] condition;
1640 return false;
1643 bool TableImpl::isFkTableHasRecord(char *pkTableName, TableImpl *fkTbl)
1645 DbRetVal rv=OK;
1646 FieldNameList pkFieldList,fkFieldList;
1647 void *tPkptr =NULL;
1648 void *tFkptr = NULL;
1649 void *chunkPk = NULL;
1650 CatalogTableTABLE cTable(sysDB_);
1651 rv = cTable.getChunkAndTblPtr(getName(), chunkPk, tPkptr);
1652 if ( OK != rv){return false;}
1653 rv = cTable.getChunkAndTblPtr(pkTableName, chunkPk, tFkptr);
1654 if ( OK != rv){return false;}
1655 CatalogTableFK cFk(sysDB_);
1656 rv = cFk.getPkFkFieldInfo(tPkptr,tFkptr,pkFieldList,fkFieldList);
1657 if ( OK != rv){return false;}
1658 int totFld = pkFieldList.size();
1659 Condition *condition = new Condition[totFld];
1660 char *pkFldName = NULL;
1661 char *fkFldName = NULL;
1662 FieldDef *def=NULL;
1663 int i=0;
1664 pkFieldList.resetIter();
1665 fkFieldList.resetIter();
1666 while((pkFldName = pkFieldList.nextFieldName())!= NULL)
1668 fkFldName = fkFieldList.nextFieldName();
1669 FieldIterator fIter = fldList_.getIterator();
1670 while (fIter.hasElement())
1672 def = fIter.nextElement();
1673 void *val = (char*)curTuple_+ def->offset_;
1674 if (strcmp(def->fldName_, pkFldName) == 0)
1676 if(def->type_==typeString)
1677 condition[i].setTerm(fkFldName,OpEquals,&val);//((char*)curTuple_+def->offset_));
1678 else
1679 condition[i].setTerm(fkFldName,OpEquals,val);//((char*)curTuple_+def->offset_));
1680 i++;
1681 break;
1685 pkFieldList.removeAll();
1686 fkFieldList.removeAll();
1687 if(i == 0 )return true;
1688 Condition *cond = new Condition[i-1];
1689 i=0;
1690 int j=0;
1691 for(j=0;j<totFld-1;j++)
1693 if(j==0)
1694 cond[j].setTerm(condition[i++].getPredicate(),OpAnd,condition[i++].getPredicate());
1695 else
1696 cond[j].setTerm(cond[j-1].getPredicate(), OpAnd, condition[i++].getPredicate());
1698 if(totFld==1)
1699 fkTbl->setCondition(&condition[totFld-1]);
1700 else
1701 fkTbl->setCondition(&cond[j-1]);
1702 fkTbl->execute();
1703 if(fkTbl->fetch()){
1704 fkTbl->closeScan();
1705 delete[] cond;
1706 delete[] condition;
1707 return true;
1709 delete[] cond;
1710 delete[] condition;
1711 return false;
1713 DbRetVal TableImpl::compact()
1715 DbRetVal rv=OK;
1716 int ret =((Chunk*)chunkPtr_)->compact(db_->procSlot);
1717 if(ret!=0){
1718 return ErrLockTimeOut;
1720 if (NULL != indexPtr_)
1722 int i;
1723 //it has index
1724 for (i = 0; i < numIndexes_ ; i++)
1726 rv = compactIndexNode(indexPtr_[i]);
1727 if (rv != OK) { printError(rv, "Error in compacting index Node"); break;}
1730 return rv;
1733 DbRetVal TableImpl::compactIndexNode( void *indexPtr)
1735 CINDEX *iptr = (CINDEX*)indexPtr;
1736 int ret1=0;
1737 printDebug(DM_Table, "Inside insertIndexNode type %d", iptr->indexType_);
1738 if( hashIndex == (iptr->indexType_) )
1740 ret1 =((Chunk*)iptr->hashNodeChunk_)->compact(db_->procSlot);
1741 if(ret1!=0){
1742 return ErrLockTimeOut;
1744 }else
1746 ret1 =((Chunk*)iptr->chunkPtr_)->compact(db_->procSlot);
1747 if(ret1!=0){
1748 return ErrLockTimeOut;
1751 return OK;