Fix for Bug : 2410115
[csql.git] / src / storage / TableImpl.cxx
blobf95d92be069b18b47c7cbde40c2543297099bdb1
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>
27 void Table::getFieldNameAlone(char *fname, char *name) {
28 bool dotFound= false;
29 char *fullname = fname;
30 while(*fullname != '\0')
32 if (*fullname == '.') { dotFound = true; break; }
33 fullname++;
35 if (dotFound) strcpy(name, ++fullname); else strcpy(name, fname);
38 void Table::getTableNameAlone(char *fname, char *name) {
39 strcpy(name, fname);
40 char *start = name;
41 bool dotFound = false;
42 while(*name != '\0')
44 if (*name == '.') { *name='\0'; dotFound = true; break; }
45 name++;
47 if (!dotFound) strcpy(start, "");
48 return;
51 DbRetVal TableImpl::bindFld(const char *name, void *val)
53 if (name[0] == '*' ) return OK;
54 //set it in the field list
55 char fieldName[IDENTIFIER_LENGTH];
56 getFieldNameAlone((char*)name, fieldName);
57 DbRetVal rv = fldList_.updateBindVal(fieldName, val);
58 if (OK != rv) {
59 printError(ErrNotExists, "Field %s does not exist", fieldName);
60 return rv;
62 return OK;
65 bool TableImpl::isFldNull(const char *name){
66 char fieldName[IDENTIFIER_LENGTH];
67 getFieldNameAlone((char*)name, fieldName);
68 int colpos = fldList_.getFieldPosition(fieldName);
69 if (-1 == colpos)
71 printError(ErrNotExists, "Field %s does not exist", name);
72 return false;
75 return isFldNull(colpos);
78 int TableImpl::getFldPos(char *name)
80 return fldList_.getFieldPosition(name);
82 bool TableImpl::isFldNull(int colpos)
84 if (!curTuple_) return false;
85 if (colpos <1 || colpos > numFlds_) return false;
86 if (isIntUsedForNULL) {
87 int nullVal = *(int*)((char*)curTuple_ + (length_ - 4));
88 if (BITSET(nullVal, colpos)) return true;
90 else {
91 char *nullOffset = (char*)curTuple_ - os::align(numFlds_);
92 if (nullOffset[colpos-1]) return true;
94 return false;
96 void TableImpl::resetNullinfo()
98 if (isIntUsedForNULL) {
99 iNullInfo =0;
101 else {
102 int i=0;
103 while(i < numFlds_) { cNullInfo[0] = 0;}
106 DbRetVal TableImpl::markFldNull(char const* name)
108 DbRetVal rv = OK;
109 int colpos = fldList_.getFieldPosition(name);
110 if (-1 == colpos)
112 printError(ErrNotExists, "Field %s does not exist", name);
113 return ErrNotExists;
115 rv = markFldNull(colpos);
116 return rv;
119 DbRetVal TableImpl::markFldNull(int fldpos)
121 if (fldpos <1 || fldpos > numFlds_) return ErrBadArg;
122 bool isBitSet = false;
123 if (isIntUsedForNULL) {
124 if (!BITSET(iNotNullInfo, fldpos)) {
125 SETBIT(iNullInfo, fldpos);
126 isBitSet = true;
128 else {
129 printError(ErrNullViolation, "NOT NULL constraint violation");
130 return ErrNullViolation;
133 else {
134 if (!BITSET(iNotNullInfo, fldpos)) cNullInfo[fldpos-1] = 1;
135 else {
136 printError(ErrNullViolation, "NOT NULL constraint violation");
137 return ErrNullViolation;
140 return OK;
143 void TableImpl::clearFldNull(const char *name)
145 int colpos = fldList_.getFieldPosition(name);
146 if (-1 == colpos)
148 printError(ErrNotExists, "Field %s does not exist", name);
149 return;
152 clearFldNull(colpos);
155 void TableImpl::clearFldNull(int colpos)
157 if (colpos <1 || colpos > numFlds_) return;
158 if (isIntUsedForNULL) {
159 CLEARBIT(iNullInfo, colpos);
161 else
162 cNullInfo[colpos-1] = 0;
163 return;
167 DbRetVal TableImpl::execute()
169 if (NULL != iter)
171 printError(ErrAlready,"Scan already open:Close and re execute");
172 return ErrAlready;
174 //table ptr is set in predicate because it needs to access the
175 //type and length to evaluate
176 if( NULL != pred_)
178 PredicateImpl *pred = (PredicateImpl*) pred_;
179 pred->setTable(this);
180 pred->setProjectionList(NULL);
182 DbRetVal ret = OK;
183 bool betcheck=false;
184 ret = createPlan(betcheck);
185 if (OK != ret)
187 printError(ErrSysInternal,"Unable to create the plan");
188 return ErrSysInternal;
190 if (useIndex_ >= 0)
191 iter = new TupleIterator(pred_, scanType_, idxInfo[useIndex_], chunkPtr_, sysDB_->procSlot,betcheck);
192 else if (scanType_ == fullTableScan)
193 iter = new TupleIterator(pred_, scanType_, NULL, chunkPtr_, sysDB_->procSlot,betcheck);
194 else
196 printError(ErrSysFatal,"Unable to create tuple iterator");//should never happen
197 return ErrSysFatal;
199 ret = iter->open();
200 if (OK != ret)
202 printError(ret,"Unable to open the iterator");
203 return ret;
205 return OK;
209 DbRetVal TableImpl::createPlan(bool &bet)
211 if (isPlanCreated) {
212 //will do early return here. plan is generated only when setPredicate is called.
213 if (scanType_ == unknownScan) return ErrSysFatal; //this should never happen
214 else return OK;
216 useIndex_ = -1;
217 //if there are no predicates then go for full scan
218 //if there are no indexes then go for full scan
219 if (NULL == pred_ || NULL == indexPtr_)
221 scanType_ = fullTableScan;
222 isPlanCreated = true;
223 return OK;
225 if (NULL != indexPtr_)
227 PredicateImpl *pred = (PredicateImpl*)pred_;
228 printDebug(DM_Predicate, "predicate does not involve NOT , OR operator");
229 if (!pred->isNotOrInvolved())
231 printDebug(DM_Predicate, "predicate does not involve NOT , OR operator");
232 for (int i =0; i < numIndexes_; i++)
234 HashIndexInfo* info = (HashIndexInfo*) idxInfo[i];
235 FieldIterator iter = info->idxFldList.getIterator();
236 while(iter.hasElement())
238 FieldDef def = iter.nextElement();
239 if (pred->pointLookupInvolved(def.fldName_))
241 printDebug(DM_Predicate, "point lookup involved for field %s",def.fldName_);
242 if(hashIndex == info->indType) scanType_ = hashIndexScan;
243 else scanType_ = treeIndexScan;
244 isPlanCreated = true;
245 useIndex_ = i;
247 else if (pred->isBetweenInvolved(def.fldName_))
249 if (treeIndex == info->indType)
251 scanType_ = treeIndexScan;
252 isPlanCreated = true;
253 useIndex_ = i;
254 bet=true;
255 break; //no composite index for tree index
258 else if (pred->rangeQueryInvolved(def.fldName_))
260 printDebug(DM_Predicate, "range lookup involved for field %s",def.fldName_);
261 if (treeIndex == info->indType)
263 scanType_ = treeIndexScan;
264 isPlanCreated = true;
265 useIndex_ = i;
266 break; //no composite index for tree index
268 }else {
269 useIndex_ = -1;
270 break;
272 }//while iter.hasElement()
273 if (useIndex_ != -1) return OK;
274 }//for
277 scanType_ = fullTableScan;
278 isPlanCreated = true;
279 return OK;
282 void* TableImpl::fetch()
284 fetchNoBind();
285 if (NULL == curTuple_) return curTuple_;
286 copyValuesToBindBuffer(curTuple_);
287 return curTuple_;
289 void* TableImpl::fetch(DbRetVal &rv)
291 fetchNoBind(rv);
292 if (NULL == curTuple_) return curTuple_;
293 copyValuesToBindBuffer(curTuple_);
294 return curTuple_;
297 void* TableImpl::fetchNoBind()
299 if (NULL == iter)
301 printError(ErrNotOpen,"Scan not open or Scan is closed\n");
302 return NULL;
304 void *prevTuple = curTuple_;
305 curTuple_ = iter->next();
306 if (NULL == curTuple_)
308 return NULL;
310 DbRetVal lockRet = OK;
311 if ((*trans)->isoLevel_ == READ_REPEATABLE) {
312 lockRet = lMgr_->getSharedLock(curTuple_, trans);
313 if (OK != lockRet)
315 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
316 curTuple_ = prevTuple;
317 return NULL;
321 else if ((*trans)->isoLevel_ == READ_COMMITTED)
323 //if iso level is read committed, operation duration lock is sufficent
324 //so release it here itself.
325 int tries = 5;
326 struct timeval timeout;
327 timeout.tv_sec = Conf::config.getMutexSecs();
328 timeout.tv_usec = Conf::config.getMutexUSecs();
330 bool status = false;
331 while(true) {
332 lockRet = lMgr_->isExclusiveLocked( curTuple_, trans, status);
333 if (OK != lockRet)
335 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
336 curTuple_ = prevTuple;
337 return NULL;
339 if (!status) break;
340 tries--;
341 if (tries == 0) break;
342 os::select(0, 0, 0, 0, &timeout);
345 if (tries == 0)
347 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
348 curTuple_ = prevTuple;
349 return NULL;
352 return curTuple_;
355 void* TableImpl::fetchNoBind(DbRetVal &rv)
357 rv = OK;
358 if (NULL == iter)
360 printError(ErrNotOpen,"Scan not open or Scan is closed\n");
361 rv = ErrNotOpen;
362 return NULL;
364 void *prevTuple = curTuple_;
365 curTuple_ = iter->next();
366 if (NULL == curTuple_)
368 return NULL;
370 DbRetVal lockRet = OK;
371 if ((*trans)->isoLevel_ == READ_REPEATABLE) {
372 lockRet = lMgr_->getSharedLock(curTuple_, trans);
373 if (OK != lockRet)
375 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
376 rv = ErrLockTimeOut;
377 curTuple_ = prevTuple;
378 return NULL;
382 else if ((*trans)->isoLevel_ == READ_COMMITTED)
384 //if iso level is read committed, operation duration lock is sufficent
385 //so release it here itself.
386 int tries = 5;
387 struct timeval timeout;
388 timeout.tv_sec = Conf::config.getMutexSecs();
389 timeout.tv_usec = Conf::config.getMutexUSecs();
391 bool status = false;
392 while(true) {
393 lockRet = lMgr_->isExclusiveLocked( curTuple_, trans, status);
394 if (OK != lockRet)
396 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
397 curTuple_ = prevTuple;
398 rv = ErrLockTimeOut;
399 return NULL;
401 if (!status) break;
402 tries--;
403 if (tries == 0) break;
404 os::select(0, 0, 0, 0, &timeout);
407 if (tries == 0)
409 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
410 curTuple_ = prevTuple;
411 rv = ErrLockTimeOut;
412 return NULL;
415 return curTuple_;
418 DbRetVal TableImpl::insertTuple()
420 DbRetVal ret =OK;
421 void *tptr = ((Chunk*)chunkPtr_)->allocate(db_, &ret);
422 if (NULL == tptr)
424 printError(ret, "Unable to allocate record from chunk");
425 return ret;
427 ret = lMgr_->getExclusiveLock(tptr, trans);
428 if (OK != ret)
430 ((Chunk*)chunkPtr_)->free(db_, tptr);
431 printError(ret, "Could not get lock for the insert tuple %x", tptr);
432 return ErrLockTimeOut;
435 curTuple_ = tptr;
437 ret = copyValuesFromBindBuffer(tptr);
438 if (ret != OK)
440 printError(ret, "Unable to copy values from bind buffer");
441 (*trans)->removeFromHasList(db_, tptr);
442 lMgr_->releaseLock(tptr);
443 ((Chunk*)chunkPtr_)->free(db_, tptr);
444 return ret;
446 int addSize = 0;
447 if (numFlds_ < 31)
449 addSize = 4;
450 *(int*)((char*)(tptr) + (length_-addSize)) = iNullInfo;
452 else
454 addSize = os::align(numFlds_);
455 os::memcpy(((char*)(tptr) + (length_-addSize)), cNullInfo, addSize);
458 //int tupleSize = length_ + addSize;
459 if (NULL != indexPtr_)
461 int i;
462 //it has index
463 for (i = 0; i < numIndexes_ ; i++)
465 ret = insertIndexNode(*trans, indexPtr_[i], idxInfo[i], tptr);
466 if (ret != OK) { printError(ret, "Error in inserting to index"); break;}
468 if (i != numIndexes_ )
470 for (int j = 0; j < i ; j++) {
471 printError(ErrWarning, "Deleting index node");
472 deleteIndexNode(*trans, indexPtr_[j], idxInfo[j], tptr);
474 lMgr_->releaseLock(tptr);
475 (*trans)->removeFromHasList(db_, tptr);
476 ((Chunk*)chunkPtr_)->free(db_, tptr);
477 //PRABA::TEMP
478 //printError(ret, "Unable to insert index node for tuple %x ", tptr);
479 printError(ret, "Unable to insert index node for tuple %x %d", tptr, *(int*)tptr);
480 return ret;
483 if (undoFlag)
484 ret = (*trans)->appendUndoLog(sysDB_, InsertOperation, tptr, length_);
485 if (ret != OK) {
486 printError(ret, "Unable to create undo log for %x %d", tptr, *(int*)tptr);
487 for (int j = 0; j < numIndexes_ ; j++) {
488 printError(ErrWarning, "Deleting index node");
489 deleteIndexNode(*trans, indexPtr_[j], idxInfo[j], tptr);
491 lMgr_->releaseLock(tptr);
492 (*trans)->removeFromHasList(db_, tptr);
493 ((Chunk*)chunkPtr_)->free(db_, tptr);
495 return ret;
498 DbRetVal TableImpl::deleteTuple()
500 if (NULL == curTuple_)
502 printError(ErrNotOpen, "Scan not open: No Current tuple");
503 return ErrNotOpen;
505 DbRetVal ret = lMgr_->getExclusiveLock(curTuple_, trans);
506 if (OK != ret)
508 printError(ret, "Could not get lock for the delete tuple %x", curTuple_);
509 return ErrLockTimeOut;
512 if (NULL != indexPtr_)
514 int i;
515 //it has index
516 for (i = 0; i < numIndexes_ ; i++)
518 ret = deleteIndexNode(*trans, indexPtr_[i], idxInfo[i], curTuple_);
519 if (ret != OK) break;
521 if (i != numIndexes_ )
523 for (int j = 0; j < i ; j++)
524 insertIndexNode(*trans, indexPtr_[j], idxInfo[j], curTuple_);
525 lMgr_->releaseLock(curTuple_);
526 (*trans)->removeFromHasList(db_, curTuple_);
527 printError(ret, "Unable to insert index node for tuple %x", curTuple_);
528 return ret;
531 ((Chunk*)chunkPtr_)->free(db_, curTuple_);
532 if (undoFlag)
533 ret = (*trans)->appendUndoLog(sysDB_, DeleteOperation, curTuple_, length_);
534 iter->prev();
535 return ret;
538 int TableImpl::deleteWhere()
540 int tuplesDeleted = 0;
541 DbRetVal rv = OK;
542 rv = execute();
543 if (rv !=OK) return (int) rv;
544 while(true){
545 fetchNoBind( rv);
546 if (rv != OK) { tuplesDeleted = (int)rv; break; }
547 if (NULL == curTuple_) break;
548 rv = deleteTuple();
549 if (rv != OK) {
550 printError(rv, "Error: Could only delete %d tuples", tuplesDeleted);
551 close();
552 return (int) rv;
554 tuplesDeleted++;
556 close();
557 return tuplesDeleted;
560 int TableImpl::truncate()
562 //take exclusive lock on the table
563 //get the chunk ptr of the table
564 //traverse the tablechunks and free all the pages except the first one
565 //get the chunk ptr of all its indexes
566 //traverse the indexchunks and free all the pages except the first one
567 //release table lock
569 //TEMPORARY FIX
570 DbRetVal rv = OK;
571 Predicate* tmpPred = pred_;
572 pred_ = NULL;
573 isPlanCreated = false;
574 int tuplesDeleted = deleteWhere();
575 isPlanCreated = false;
576 pred_ = tmpPred;
577 return tuplesDeleted;
580 DbRetVal TableImpl::updateTuple()
582 if (NULL == curTuple_)
584 printError(ErrNotOpen, "Scan not open: No Current tuple");
585 return ErrNotOpen;
587 DbRetVal ret = lMgr_->getExclusiveLock(curTuple_, trans);
588 if (OK != ret)
590 printError(ret, "Could not get lock for the update tuple %x", curTuple_);
591 return ErrLockTimeOut;
593 if (NULL != indexPtr_)
595 //it has index
596 //TODO::If it fails while updating index node, we have to undo all the updates
597 //on other indexes on the table.Currently it will leave the database in an
598 //inconsistent state.
599 for (int i = 0; i < numIndexes_ ; i++)
601 ret = updateIndexNode(*trans, indexPtr_[i], idxInfo[i], curTuple_);
602 if (ret != OK)
604 lMgr_->releaseLock(curTuple_);
605 (*trans)->removeFromHasList(db_, curTuple_);
606 printError(ret, "Unable to update index node for tuple %x", curTuple_);
607 return ret;
611 if (undoFlag)
612 ret = (*trans)->appendUndoLog(sysDB_, UpdateOperation, curTuple_, length_);
613 if (ret != OK) return ret;
614 int addSize = 0;
615 int iNullVal=iNullInfo;
616 if (numFlds_ < 31){
617 addSize=4;
618 if(!iNullVal){
619 iNullInfo = *(int*)((char*)(curTuple_) + (length_- addSize));
621 else
623 *(int*)((char*)(curTuple_) + (length_-addSize)) |= iNullInfo;
626 DbRetVal rv = copyValuesFromBindBuffer(curTuple_, false);
627 if (rv != OK) {
628 lMgr_->releaseLock(curTuple_);
629 (*trans)->removeFromHasList(db_, curTuple_);
630 return rv;
633 if (numFlds_ < 31)
635 if (!iNullVal) {
636 *(int*)((char*)(curTuple_) + (length_-addSize)) = iNullInfo;
637 iNullInfo=0;
639 else iNullInfo=iNullVal;
641 else
643 addSize = os::align(numFlds_);
644 //TODO::Do not do blind memcpy. It should OR each and every char
645 //os::memcpy(((char*)(curTuple_) + (length_-addSize)), cNullInfo, addSize);
648 return OK;
651 void TableImpl::printInfo()
653 printf(" <TableName> %s </TableName>\n", tblName_);
654 printf(" <TupleCount> %d </TupleCount>\n", numTuples());
655 printf(" <PagesUsed> %d </PagesUsed>\n", pagesUsed());
656 printf(" <SpaceUsed> %d </SpaceUsed>\n", spaceUsed());
657 printf(" <Indexes> %d <Indexes>\n", numIndexes_);
658 printf(" <TupleLength> %d </TupleLength>\n", length_);
659 printf(" <Fields> %d </Fields>\n", numFlds_);
660 printf(" <Indexes>\n");
661 for (int i =0; i<numIndexes_; i++)
662 printf("<IndexName> %s </IndexName>\n", CatalogTableINDEX::getName(indexPtr_[i]));
663 printf(" </Indexes>\n");
667 DbRetVal TableImpl::copyValuesFromBindBuffer(void *tuplePtr, bool isInsert)
669 //Iterate through the bind list and copy the value here
670 FieldIterator fIter = fldList_.getIterator();
671 char *colPtr = (char*) tuplePtr;
672 int fldpos=1;
673 while (fIter.hasElement())
675 FieldDef def = fIter.nextElement();
676 if (def.isNull_ && !def.isDefault_ && NULL == def.bindVal_ && isInsert)
678 printError(ErrNullViolation, "NOT NULL constraint violation for field %s\n", def.fldName_);
679 return ErrNullViolation;
681 if (def.isDefault_ && NULL == def.bindVal_ && isInsert)
683 void *dest = AllDataType::alloc(def.type_, def.length_);
684 AllDataType::convert(typeString, def.defaultValueBuf_, def.type_, dest, def.length_);
685 AllDataType::copyVal(colPtr, dest, def.type_, def.length_);
686 colPtr = colPtr + os::align(AllDataType::size(def.type_, def.length_));
687 fldpos++;
688 free (dest);
689 continue;
691 switch(def.type_)
693 case typeString:
694 if (NULL != def.bindVal_)
696 if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);}
697 strcpy((char*)colPtr, (char*)def.bindVal_);
698 *(((char*)colPtr) + (def.length_-1)) = '\0';
700 else if (!def.isNull_ && !def.bindVal_ && isInsert) setNullBit(fldpos);
701 colPtr = colPtr + os::align(def.length_);
702 break;
703 case typeBinary:
704 if (NULL != def.bindVal_ ) {
705 if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);}
706 DbRetVal rv = AllDataType::strToValue(colPtr, (char *) def.bindVal_, def.type_, def.length_);
707 if (rv != OK) return ErrBadArg;
709 else if (!def.isNull_ && isInsert && !def.bindVal_) setNullBit(fldpos);
710 colPtr = colPtr + os::align(def.length_);
711 break;
712 default:
713 if (NULL != def.bindVal_){
714 if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);}
715 AllDataType::copyVal(colPtr, def.bindVal_, def.type_);}
716 else { if (!def.isNull_ && isInsert) setNullBit(fldpos); }
717 colPtr = colPtr + os::align(AllDataType::size(def.type_));
718 break;
720 fldpos++;
722 return OK;
724 void TableImpl::clearNullBit(int fldpos)
726 if (isIntUsedForNULL){
727 CLEARBIT(iNullInfo, fldpos);}
728 else
729 cNullInfo[fldpos-1] = 0;
731 void TableImpl::setNullBit(int fldpos)
733 if (isIntUsedForNULL)
734 SETBIT(iNullInfo, fldpos);
735 else
736 cNullInfo[fldpos-1] = 1;
738 DbRetVal TableImpl::copyValuesToBindBuffer(void *tuplePtr)
740 //Iterate through the bind list and copy the value here
741 FieldIterator fIter = fldList_.getIterator();
742 char *colPtr = (char*) tuplePtr;
743 while (fIter.hasElement())
745 FieldDef def = fIter.nextElement();
746 if (NULL != def.bindVal_)
747 AllDataType::copyVal(def.bindVal_, colPtr, def.type_, def.length_);
748 colPtr = colPtr + os::align(AllDataType::size(def.type_, def.length_));
750 return OK;
753 //-1 index not supported
754 DbRetVal TableImpl::insertIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple)
756 CINDEX *iptr = (CINDEX*)indexPtr;
757 DbRetVal ret = OK;
758 printDebug(DM_Table, "Inside insertIndexNode type %d", iptr->indexType_);
759 Index* idx = Index::getIndex(iptr->indexType_);
760 ret = idx->insert(this, tr, indexPtr, info, tuple,undoFlag);
761 return ret;
764 DbRetVal TableImpl::deleteIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple)
766 CINDEX *iptr = (CINDEX*)indexPtr;
767 DbRetVal ret = OK;
768 Index* idx = Index::getIndex(iptr->indexType_);
769 ret = idx->remove(this, tr, indexPtr, info, tuple, undoFlag);
770 return ret;
772 void TableImpl::printSQLIndexString()
774 CatalogTableINDEXFIELD cIndexField(sysDB_);
775 char fName[IDENTIFIER_LENGTH];
776 char *fldName = fName;
777 DataType type;
778 for (int i = 0; i < numIndexes_ ; i++)
780 CINDEX *iptr = (CINDEX*) indexPtr_[i];
781 printf("CREATE INDEX %s on %s ( ", iptr->indName_, getName());
782 FieldList fldList;
783 cIndexField.getFieldInfo(iptr, fldList);
784 FieldIterator fIter = fldList.getIterator();
785 bool firstFld = true;
786 while(fIter.hasElement())
788 FieldDef def = fIter.nextElement();
789 if (firstFld) { printf(" %s ", def.fldName_); firstFld = false; }
790 else printf(" ,%s ", def.fldName_);
792 printf(" ) ");
793 if (iptr->indexType_ == hashIndex) printf(" HASH ");
794 else printf(" TREE ");
795 if (((HashIndexInfo*) idxInfo[i])->isUnique) printf(" UNIQUE;\n"); else printf(";\n");
800 DbRetVal TableImpl::updateIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple)
802 CINDEX *iptr = (CINDEX*)indexPtr;
803 DbRetVal ret = OK;
804 Index* idx = Index::getIndex(iptr->indexType_);
805 //TODO::currently it updates irrespective of whether the key changed or not
806 //because of this commenting the whole index update code. relook at it and uncomment
808 ret = idx->update(this, tr, indexPtr, info, tuple, undoFlag);
810 return ret;
814 void TableImpl::setTableInfo(char *name, int tblid, size_t length,
815 int numFld, int numIdx, void *chunk)
817 strcpy(tblName_, name);
818 tblID_ = tblid;
819 length_ = length;
820 numFlds_ = numFld;
821 numIndexes_ = numIdx;
822 chunkPtr_ = chunk;
825 long TableImpl::spaceUsed()
827 Chunk *chk = (Chunk*)chunkPtr_;
828 long totSize = chk->getTotalDataNodes() * chk->getSize();
829 totSize = totSize + (chk->totalPages() * sizeof (PageInfo));
830 return totSize;
833 int TableImpl::pagesUsed()
835 Chunk *chk = (Chunk*)chunkPtr_;
836 return chk->totalPages();
839 long TableImpl::numTuples()
841 return ((Chunk*)chunkPtr_)->getTotalDataNodes();
844 List TableImpl::getFieldNameList()
846 List fldNameList;
847 FieldIterator fIter = fldList_.getIterator();
848 char fieldName[IDENTIFIER_LENGTH];
849 while (fIter.hasElement())
851 FieldDef def = fIter.nextElement();
852 Identifier *elem = new Identifier();
853 Table::getFieldNameAlone(def.fldName_, fieldName);
854 sprintf(elem->name, "%s.%s", getName(), fieldName);
855 fldNameList.append(elem);
857 return fldNameList;
859 DbRetVal TableImpl::close()
861 if (NULL == iter)
863 //printError(ErrNotOpen,"Scan not open");
864 //return ErrNotOpen;
865 //PRABA::when called multiple times it gives error
866 return OK;
868 iter->close();
869 delete iter;
870 iter = NULL;
871 return OK;
873 DbRetVal TableImpl::closeScan()
875 //do not throw scan not open error
876 //this function will be called by table handle
877 if (iter) {
878 iter->close();
879 delete iter;
880 iter = NULL;
882 return OK;
884 DbRetVal TableImpl::lock(bool shared)
887 DbRetVal ret = OK;
889 if (shared)
890 ret = lMgr_->getSharedLock(chunkPtr_, NULL);
891 else
892 ret = lMgr_->getExclusiveLock(chunkPtr_, NULL);
893 if (OK != ret)
895 printError(ret, "Could not exclusive lock on the table %x", chunkPtr_);
896 }else {
897 //do not append for S to X upgrade
898 if (!ProcessManager::hasLockList.exists(chunkPtr_))
899 ProcessManager::hasLockList.append(chunkPtr_);
902 return ret;
904 DbRetVal TableImpl::unlock()
907 if (!ProcessManager::hasLockList.exists(chunkPtr_)) return OK;
908 DbRetVal ret = lMgr_->releaseLock(chunkPtr_);
909 if (OK != ret)
911 printError(ret, "Could not release exclusive lock on the table %x", chunkPtr_);
912 }else
914 ProcessManager::hasLockList.remove(chunkPtr_);
917 return OK;
920 TableImpl::~TableImpl()
922 if (NULL != iter ) { delete iter; iter = NULL; }
923 if (NULL != indexPtr_) { delete[] indexPtr_; indexPtr_ = NULL; }
924 if (NULL != idxInfo)
926 for (int i = 0; i < numIndexes_; i++) delete idxInfo[i];
927 delete[] idxInfo;
928 idxInfo = NULL;
930 if (numFlds_ > 31 && cNullInfo != NULL) { free(cNullInfo); cNullInfo = NULL; }
932 fldList_.removeAll();
936 void *TableImpl::getBindFldAddr(const char *name)
938 return fldList_.getBindField(name);
940 bool TableImpl::isTableInvolved(char *tblName)
942 //printf("Table isTableInvolved called for %s with %s\n", tblName, getName());
943 if (0 == strcmp(getName(), tblName)) return true; else return false;
945 bool TableImpl::pushPredicate(Predicate *pred)
947 bool ret = false;
948 PredicateImpl *pImpl = (PredicateImpl*) pred;
949 char tableName[IDENTIFIER_LENGTH];
950 Table::getTableNameAlone(pImpl->getFldName1(), tableName);
951 //printf("predicate tbl name %s\n", tableName);
953 //if predicate is of form t1.f1=t2.f1 then do not push here
954 if (0 != strcmp(pImpl->getFldName2(),"")) return ret;
956 if (0 == strcmp(getName(), tableName))
958 setPredicate(pred);
959 //printf("PRABA::pushed predicate in tablehdl %s\n", getName());
960 ret = true;
962 return ret;
964 void TableImpl::setPredicate(Predicate *pred)
966 if (NULL == pred_) { pred_ = pred; return; }
967 Predicate *curPred = pred_;
968 PredicateImpl *newPred = new PredicateImpl();
969 newPred->setTerm(curPred, OpAnd, pred);
970 newPred->setTable(this);
971 pred_ = newPred;
972 return;
974 void TableImpl::printPlan(int space)
976 char spaceBuf[IDENTIFIER_LENGTH];
977 memset(spaceBuf, 32, IDENTIFIER_LENGTH);
978 spaceBuf[space] = '\0';
979 printf("%s <TABLE-NODE>\n", spaceBuf);
980 printf("%s <NAME> %s </NAME>\n", spaceBuf, getName());
981 printf("%s <ScanType> %s </ScanType>\n", spaceBuf, ScanTypeNames[scanType_]);
982 PredicateImpl *pred = (PredicateImpl*)pred_;
983 if (pred) pred->print(space+2);
984 printf("%s </TABLE-NODE>\n", spaceBuf);