Fixing bugs in aggregate and join
[csql.git] / src / storage / TableImpl.cxx
blobd3255661625b6d60217178cc67f119d05d77b453
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 //set it in the field list
54 char fieldName[IDENTIFIER_LENGTH];
55 getFieldNameAlone((char*)name, fieldName);
56 DbRetVal rv = fldList_.updateBindVal(fieldName, val);
57 if (OK != rv) {
58 printError(ErrNotExists, "Field %s does not exist", fieldName);
59 return rv;
61 return OK;
64 bool TableImpl::isFldNull(const char *name){
65 char fieldName[IDENTIFIER_LENGTH];
66 getFieldNameAlone((char*)name, fieldName);
67 int colpos = fldList_.getFieldPosition(fieldName);
68 if (-1 == colpos)
70 printError(ErrNotExists, "Field %s does not exist", name);
71 return false;
74 return isFldNull(colpos);
77 int TableImpl::getFldPos(char *name)
79 return fldList_.getFieldPosition(name);
81 bool TableImpl::isFldNull(int colpos)
83 if (!curTuple_) return false;
84 if (colpos <1 || colpos > numFlds_) return false;
85 if (isIntUsedForNULL) {
86 int nullVal = *(int*)((char*)curTuple_ + (length_ - 4));
87 if (BITSET(nullVal, colpos)) return true;
89 else {
90 char *nullOffset = (char*)curTuple_ - os::align(numFlds_);
91 if (nullOffset[colpos-1]) return true;
93 return false;
95 void TableImpl::resetNullinfo()
97 if (isIntUsedForNULL) {
98 iNullInfo =0;
100 else {
101 int i=0;
102 while(i < numFlds_) { cNullInfo[0] = 0;}
105 void TableImpl::markFldNull(char const* name)
107 int colpos = fldList_.getFieldPosition(name);
108 if (-1 == colpos)
110 printError(ErrNotExists, "Field %s does not exist", name);
111 return;
113 markFldNull(colpos);
116 void TableImpl::markFldNull(int fldpos)
118 if (fldpos <1 || fldpos > numFlds_) return;
119 if (isIntUsedForNULL) {
120 if (!BITSET(iNotNullInfo, fldpos)) SETBIT(iNullInfo, fldpos);
122 else
123 if (!BITSET(iNotNullInfo, fldpos)) cNullInfo[fldpos-1] = 1;
124 return;
127 void TableImpl::clearFldNull(const char *name)
129 int colpos = fldList_.getFieldPosition(name);
130 if (-1 == colpos)
132 printError(ErrNotExists, "Field %s does not exist", name);
133 return;
136 clearFldNull(colpos);
139 void TableImpl::clearFldNull(int colpos)
141 if (colpos <1 || colpos > numFlds_) return;
142 if (isIntUsedForNULL) {
143 CLEARBIT(iNullInfo, colpos);
145 else
146 cNullInfo[colpos-1] = 0;
147 return;
151 DbRetVal TableImpl::execute()
153 if (NULL != iter)
155 printError(ErrAlready,"Scan already open:Close and re execute");
156 return ErrAlready;
158 //table ptr is set in predicate because it needs to access the
159 //type and length to evaluate
160 if( NULL != pred_)
162 PredicateImpl *pred = (PredicateImpl*) pred_;
163 pred->setTable(this);
165 DbRetVal ret = OK;
167 ret = createPlan();
168 if (OK != ret)
170 printError(ErrSysInternal,"Unable to create the plan");
171 return ErrSysInternal;
173 if (useIndex_ >= 0)
174 iter = new TupleIterator(pred_, scanType_, idxInfo[useIndex_], chunkPtr_, sysDB_->procSlot);
175 else if (scanType_ == fullTableScan)
176 iter = new TupleIterator(pred_, scanType_, NULL, chunkPtr_, sysDB_->procSlot);
177 else
179 printError(ErrSysFatal,"Unable to create tuple iterator");//should never happen
180 return ErrSysFatal;
182 ret = iter->open();
183 if (OK != ret)
185 printError(ret,"Unable to open the iterator");
186 return ret;
188 return OK;
192 DbRetVal TableImpl::createPlan()
194 if (isPlanCreated) {
195 //will do early return here. plan is generated only when setPredicate is called.
196 if (scanType_ == unknownScan) return ErrSysFatal; //this should never happen
197 else return OK;
199 useIndex_ = -1;
200 //if there are no predicates then go for full scan
201 //if there are no indexes then go for full scan
202 if (NULL == pred_ || NULL == indexPtr_)
204 scanType_ = fullTableScan;
205 isPlanCreated = true;
206 return OK;
208 if (NULL != indexPtr_)
210 PredicateImpl *pred = (PredicateImpl*)pred_;
211 printDebug(DM_Predicate, "predicate does not involve NOT , OR operator");
212 if (!pred->isNotOrInvolved())
214 printDebug(DM_Predicate, "predicate does not involve NOT , OR operator");
215 for (int i =0; i < numIndexes_; i++)
217 HashIndexInfo* info = (HashIndexInfo*) idxInfo[i];
218 FieldIterator iter = info->idxFldList.getIterator();
219 while(iter.hasElement())
221 FieldDef def = iter.nextElement();
222 if (pred->pointLookupInvolved(def.fldName_))
224 printDebug(DM_Predicate, "point lookup involved for field %s",def.fldName_);
225 if(hashIndex == info->indType) scanType_ = hashIndexScan;
226 else scanType_ = treeIndexScan;
227 isPlanCreated = true;
228 useIndex_ = i;
230 else if (pred->rangeQueryInvolved(def.fldName_))
232 printDebug(DM_Predicate, "range lookup involved for field %s",def.fldName_);
233 if (treeIndex == info->indType)
235 scanType_ = treeIndexScan;
236 isPlanCreated = true;
237 useIndex_ = i;
238 break; //no composite index for tree index
240 }else {
241 useIndex_ = -1;
242 break;
244 }//while iter.hasElement()
245 if (useIndex_ != -1) return OK;
246 }//for
249 scanType_ = fullTableScan;
250 isPlanCreated = true;
251 return OK;
254 void* TableImpl::fetch()
256 fetchNoBind();
257 if (NULL == curTuple_) return curTuple_;
258 copyValuesToBindBuffer(curTuple_);
259 return curTuple_;
261 void* TableImpl::fetch(DbRetVal &rv)
263 fetchNoBind(rv);
264 if (NULL == curTuple_) return curTuple_;
265 copyValuesToBindBuffer(curTuple_);
266 return curTuple_;
269 void* TableImpl::fetchNoBind()
271 if (NULL == iter)
273 printError(ErrNotOpen,"Scan not open or Scan is closed\n");
274 return NULL;
276 void *prevTuple = curTuple_;
277 curTuple_ = iter->next();
278 if (NULL == curTuple_)
280 return NULL;
282 DbRetVal lockRet = OK;
283 if ((*trans)->isoLevel_ == READ_REPEATABLE) {
284 lockRet = lMgr_->getSharedLock(curTuple_, trans);
285 if (OK != lockRet)
287 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
288 curTuple_ = prevTuple;
289 return NULL;
293 else if ((*trans)->isoLevel_ == READ_COMMITTED)
295 //if iso level is read committed, operation duration lock is sufficent
296 //so release it here itself.
297 int tries = 5;
298 struct timeval timeout;
299 timeout.tv_sec = Conf::config.getMutexSecs();
300 timeout.tv_usec = Conf::config.getMutexUSecs();
302 bool status = false;
303 while(true) {
304 lockRet = lMgr_->isExclusiveLocked( curTuple_, trans, status);
305 if (OK != lockRet)
307 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
308 curTuple_ = prevTuple;
309 return NULL;
311 if (!status) break;
312 tries--;
313 if (tries == 0) break;
314 os::select(0, 0, 0, 0, &timeout);
317 if (tries == 0)
319 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
320 curTuple_ = prevTuple;
321 return NULL;
324 return curTuple_;
327 void* TableImpl::fetchNoBind(DbRetVal &rv)
329 rv = OK;
330 if (NULL == iter)
332 printError(ErrNotOpen,"Scan not open or Scan is closed\n");
333 rv = ErrNotOpen;
334 return NULL;
336 void *prevTuple = curTuple_;
337 curTuple_ = iter->next();
338 if (NULL == curTuple_)
340 return NULL;
342 DbRetVal lockRet = OK;
343 if ((*trans)->isoLevel_ == READ_REPEATABLE) {
344 lockRet = lMgr_->getSharedLock(curTuple_, trans);
345 if (OK != lockRet)
347 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
348 rv = ErrLockTimeOut;
349 curTuple_ = prevTuple;
350 return NULL;
354 else if ((*trans)->isoLevel_ == READ_COMMITTED)
356 //if iso level is read committed, operation duration lock is sufficent
357 //so release it here itself.
358 int tries = 5;
359 struct timeval timeout;
360 timeout.tv_sec = Conf::config.getMutexSecs();
361 timeout.tv_usec = Conf::config.getMutexUSecs();
363 bool status = false;
364 while(true) {
365 lockRet = lMgr_->isExclusiveLocked( curTuple_, trans, status);
366 if (OK != lockRet)
368 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
369 curTuple_ = prevTuple;
370 rv = ErrLockTimeOut;
371 return NULL;
373 if (!status) break;
374 tries--;
375 if (tries == 0) break;
376 os::select(0, 0, 0, 0, &timeout);
379 if (tries == 0)
381 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
382 curTuple_ = prevTuple;
383 rv = ErrLockTimeOut;
384 return NULL;
387 return curTuple_;
390 DbRetVal TableImpl::insertTuple()
392 DbRetVal ret =OK;
393 void *tptr = ((Chunk*)chunkPtr_)->allocate(db_, &ret);
394 if (NULL == tptr)
396 printError(ret, "Unable to allocate record from chunk");
397 return ret;
399 ret = lMgr_->getExclusiveLock(tptr, trans);
400 if (OK != ret)
402 ((Chunk*)chunkPtr_)->free(db_, tptr);
403 printError(ret, "Could not get lock for the insert tuple %x", tptr);
404 return ErrLockTimeOut;
408 ret = copyValuesFromBindBuffer(tptr);
409 if (ret != OK)
411 printError(ret, "Unable to copy values from bind buffer");
412 (*trans)->removeFromHasList(db_, tptr);
413 lMgr_->releaseLock(tptr);
414 ((Chunk*)chunkPtr_)->free(db_, tptr);
415 return ret;
418 int addSize = 0;
419 if (numFlds_ < 31)
421 addSize = 4;
422 *(int*)((char*)(tptr) + (length_-addSize)) = iNullInfo;
424 else
426 addSize = os::align(numFlds_);
427 os::memcpy(((char*)(tptr) + (length_-addSize)), cNullInfo, addSize);
430 //int tupleSize = length_ + addSize;
431 if (NULL != indexPtr_)
433 int i;
434 //it has index
435 for (i = 0; i < numIndexes_ ; i++)
437 ret = insertIndexNode(*trans, indexPtr_[i], idxInfo[i], tptr);
438 if (ret != OK) { printError(ret, "Error in inserting to index"); break;}
440 if (i != numIndexes_ )
442 for (int j = 0; j < i ; j++) {
443 printError(ErrWarning, "Deleting index node");
444 deleteIndexNode(*trans, indexPtr_[j], idxInfo[j], tptr);
446 lMgr_->releaseLock(tptr);
447 (*trans)->removeFromHasList(db_, tptr);
448 ((Chunk*)chunkPtr_)->free(db_, tptr);
449 //PRABA::TEMP
450 //printError(ret, "Unable to insert index node for tuple %x ", tptr);
451 printError(ret, "Unable to insert index node for tuple %x %d", tptr, *(int*)tptr);
452 return ret;
455 if (undoFlag)
456 ret = (*trans)->appendUndoLog(sysDB_, InsertOperation, tptr, length_);
457 if (ret != OK) {
458 printError(ret, "Unable to create undo log for %x %d", tptr, *(int*)tptr);
459 for (int j = 0; j < numIndexes_ ; j++) {
460 printError(ErrWarning, "Deleting index node");
461 deleteIndexNode(*trans, indexPtr_[j], idxInfo[j], tptr);
463 lMgr_->releaseLock(tptr);
464 (*trans)->removeFromHasList(db_, tptr);
465 ((Chunk*)chunkPtr_)->free(db_, tptr);
467 return ret;
470 DbRetVal TableImpl::deleteTuple()
472 if (NULL == curTuple_)
474 printError(ErrNotOpen, "Scan not open: No Current tuple");
475 return ErrNotOpen;
477 DbRetVal ret = lMgr_->getExclusiveLock(curTuple_, trans);
478 if (OK != ret)
480 printError(ret, "Could not get lock for the delete tuple %x", curTuple_);
481 return ErrLockTimeOut;
484 if (NULL != indexPtr_)
486 int i;
487 //it has index
488 for (i = 0; i < numIndexes_ ; i++)
490 ret = deleteIndexNode(*trans, indexPtr_[i], idxInfo[i], curTuple_);
491 if (ret != OK) break;
493 if (i != numIndexes_ )
495 for (int j = 0; j < i ; j++)
496 insertIndexNode(*trans, indexPtr_[j], idxInfo[j], curTuple_);
497 lMgr_->releaseLock(curTuple_);
498 (*trans)->removeFromHasList(db_, curTuple_);
499 printError(ret, "Unable to insert index node for tuple %x", curTuple_);
500 return ret;
503 ((Chunk*)chunkPtr_)->free(db_, curTuple_);
504 if (undoFlag)
505 ret = (*trans)->appendUndoLog(sysDB_, DeleteOperation, curTuple_, length_);
506 iter->prev();
507 return ret;
510 int TableImpl::deleteWhere()
512 int tuplesDeleted = 0;
513 DbRetVal rv = OK;
514 rv = execute();
515 if (rv !=OK) return (int) rv;
516 while(true){
517 fetchNoBind( rv);
518 if (rv != OK) { tuplesDeleted = (int)rv; break; }
519 if (NULL == curTuple_) break;
520 rv = deleteTuple();
521 if (rv != OK) {
522 printError(rv, "Error: Could only delete %d tuples", tuplesDeleted);
523 close();
524 return (int) rv;
526 tuplesDeleted++;
528 close();
529 return tuplesDeleted;
532 int TableImpl::truncate()
534 //take exclusive lock on the table
535 //get the chunk ptr of the table
536 //traverse the tablechunks and free all the pages except the first one
537 //get the chunk ptr of all its indexes
538 //traverse the indexchunks and free all the pages except the first one
539 //release table lock
541 //TEMPORARY FIX
542 DbRetVal rv = OK;
543 Predicate* tmpPred = pred_;
544 pred_ = NULL;
545 isPlanCreated = false;
546 int tuplesDeleted = deleteWhere();
547 isPlanCreated = false;
548 pred_ = tmpPred;
549 return tuplesDeleted;
552 DbRetVal TableImpl::updateTuple()
554 if (NULL == curTuple_)
556 printError(ErrNotOpen, "Scan not open: No Current tuple");
557 return ErrNotOpen;
559 DbRetVal ret = lMgr_->getExclusiveLock(curTuple_, trans);
560 if (OK != ret)
562 printError(ret, "Could not get lock for the update tuple %x", curTuple_);
563 return ErrLockTimeOut;
565 if (NULL != indexPtr_)
567 //it has index
568 //TODO::If it fails while updating index node, we have to undo all the updates
569 //on other indexes on the table.Currently it will leave the database in an
570 //inconsistent state.
571 for (int i = 0; i < numIndexes_ ; i++)
573 ret = updateIndexNode(*trans, indexPtr_[i], idxInfo[i], curTuple_);
574 if (ret != OK)
576 lMgr_->releaseLock(curTuple_);
577 (*trans)->removeFromHasList(db_, curTuple_);
578 printError(ret, "Unable to update index node for tuple %x", curTuple_);
579 return ret;
583 if (undoFlag)
584 ret = (*trans)->appendUndoLog(sysDB_, UpdateOperation, curTuple_, length_);
585 if (ret != OK) return ret;
586 int addSize = 0;
587 int iNullVal=iNullInfo;
588 if (numFlds_ < 31){
589 addSize=4;
590 if(!iNullVal){
591 iNullInfo = *(int*)((char*)(curTuple_) + (length_- addSize));
593 else
595 *(int*)((char*)(curTuple_) + (length_-addSize)) |= iNullInfo;
598 DbRetVal rv = copyValuesFromBindBuffer(curTuple_, false);
599 if (rv != OK) {
600 lMgr_->releaseLock(curTuple_);
601 (*trans)->removeFromHasList(db_, curTuple_);
602 return rv;
605 if (numFlds_ < 31)
607 if (!iNullVal) {
608 *(int*)((char*)(curTuple_) + (length_-addSize)) = iNullInfo;
609 iNullInfo=0;
611 else iNullInfo=iNullVal;
613 else
615 addSize = os::align(numFlds_);
616 //TODO::Do not do blind memcpy. It should OR each and every char
617 //os::memcpy(((char*)(curTuple_) + (length_-addSize)), cNullInfo, addSize);
620 return OK;
623 void TableImpl::printInfo()
625 printf(" <TableName> %s </TableName>\n", tblName_);
626 printf(" <TupleCount> %d </TupleCount>\n", numTuples());
627 printf(" <PagesUsed> %d </PagesUsed>\n", pagesUsed());
628 printf(" <SpaceUsed> %d </SpaceUsed>\n", spaceUsed());
629 printf(" <Indexes> %d <Indexes>\n", numIndexes_);
630 printf(" <TupleLength> %d </TupleLength>\n", length_);
631 printf(" <Fields> %d </Fields>\n", numFlds_);
632 printf(" <Indexes>\n");
633 for (int i =0; i<numIndexes_; i++)
634 printf("<IndexName> %s </IndexName>\n", CatalogTableINDEX::getName(indexPtr_[i]));
635 printf(" </Indexes>\n");
639 DbRetVal TableImpl::copyValuesFromBindBuffer(void *tuplePtr, bool isInsert)
641 //Iterate through the bind list and copy the value here
642 FieldIterator fIter = fldList_.getIterator();
643 char *colPtr = (char*) tuplePtr;
644 int fldpos=1;
645 while (fIter.hasElement())
647 FieldDef def = fIter.nextElement();
648 if (def.isNull_ && !def.isDefault_ && NULL == def.bindVal_ && isInsert)
650 printError(ErrNullViolation, "NOT NULL constraint violation for field %s\n", def.fldName_);
651 return ErrNullViolation;
653 if (def.isDefault_ && NULL == def.bindVal_ && isInsert)
655 void *dest = AllDataType::alloc(def.type_, def.length_);
656 AllDataType::convert(typeString, def.defaultValueBuf_, def.type_, dest, def.length_);
657 AllDataType::copyVal(colPtr, dest, def.type_, def.length_);
658 colPtr = colPtr + os::align(AllDataType::size(def.type_, def.length_));
659 fldpos++;
660 free (dest);
661 continue;
663 switch(def.type_)
665 case typeString:
666 if (NULL != def.bindVal_)
668 if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);}
669 strcpy((char*)colPtr, (char*)def.bindVal_);
670 *(((char*)colPtr) + (def.length_-1)) = '\0';
672 else if (!def.isNull_ && isInsert) setNullBit(fldpos);
673 colPtr = colPtr + os::align(def.length_);
674 break;
675 case typeBinary:
676 if (NULL != def.bindVal_ ) {
677 if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);}
678 DbRetVal rv = AllDataType::strToValue(colPtr, (char *) def.bindVal_, def.type_, def.length_);
679 if (rv != OK) return ErrBadArg;
681 else if (!def.isNull_ && isInsert) setNullBit(fldpos);
682 colPtr = colPtr + os::align(def.length_);
683 break;
684 default:
685 if (NULL != def.bindVal_){
686 if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);}
687 AllDataType::copyVal(colPtr, def.bindVal_, def.type_);}
688 else { if (!def.isNull_ && isInsert) setNullBit(fldpos); }
689 colPtr = colPtr + os::align(AllDataType::size(def.type_));
690 break;
692 fldpos++;
694 return OK;
696 void TableImpl::clearNullBit(int fldpos)
698 if (isIntUsedForNULL){
699 CLEARBIT(iNullInfo, fldpos);}
700 else
701 cNullInfo[fldpos-1] = 0;
703 void TableImpl::setNullBit(int fldpos)
705 if (isIntUsedForNULL)
706 SETBIT(iNullInfo, fldpos);
707 else
708 cNullInfo[fldpos-1] = 1;
710 DbRetVal TableImpl::copyValuesToBindBuffer(void *tuplePtr)
712 //Iterate through the bind list and copy the value here
713 FieldIterator fIter = fldList_.getIterator();
714 char *colPtr = (char*) tuplePtr;
715 while (fIter.hasElement())
717 FieldDef def = fIter.nextElement();
718 if (NULL != def.bindVal_)
719 AllDataType::copyVal(def.bindVal_, colPtr, def.type_, def.length_);
720 colPtr = colPtr + os::align(AllDataType::size(def.type_, def.length_));
722 return OK;
725 //-1 index not supported
726 DbRetVal TableImpl::insertIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple)
728 CINDEX *iptr = (CINDEX*)indexPtr;
729 DbRetVal ret = OK;
730 printDebug(DM_Table, "Inside insertIndexNode type %d", iptr->indexType_);
731 Index* idx = Index::getIndex(iptr->indexType_);
732 ret = idx->insert(this, tr, indexPtr, info, tuple,undoFlag);
733 return ret;
736 DbRetVal TableImpl::deleteIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple)
738 CINDEX *iptr = (CINDEX*)indexPtr;
739 DbRetVal ret = OK;
740 Index* idx = Index::getIndex(iptr->indexType_);
741 ret = idx->remove(this, tr, indexPtr, info, tuple, undoFlag);
742 return ret;
744 void TableImpl::printSQLIndexString()
746 CatalogTableINDEXFIELD cIndexField(sysDB_);
747 char fName[IDENTIFIER_LENGTH];
748 char *fldName = fName;
749 DataType type;
750 for (int i = 0; i < numIndexes_ ; i++)
752 CINDEX *iptr = (CINDEX*) indexPtr_[i];
753 printf("CREATE INDEX %s on %s ( ", iptr->indName_, getName());
754 FieldList fldList;
755 cIndexField.getFieldInfo(iptr, fldList);
756 FieldIterator fIter = fldList.getIterator();
757 bool firstFld = true;
758 while(fIter.hasElement())
760 FieldDef def = fIter.nextElement();
761 if (firstFld) { printf(" %s ", def.fldName_); firstFld = false; }
762 else printf(" ,%s ", def.fldName_);
764 printf(" ) ");
765 if (iptr->indexType_ == hashIndex) printf(" HASH ");
766 else printf(" TREE ");
767 if (((HashIndexInfo*) idxInfo[i])->isUnique) printf(" UNIQUE;\n"); else printf(";\n");
772 DbRetVal TableImpl::updateIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple)
774 CINDEX *iptr = (CINDEX*)indexPtr;
775 DbRetVal ret = OK;
776 Index* idx = Index::getIndex(iptr->indexType_);
777 //TODO::currently it updates irrespective of whether the key changed or not
778 //because of this commenting the whole index update code. relook at it and uncomment
780 ret = idx->update(this, tr, indexPtr, info, tuple, undoFlag);
782 return ret;
786 void TableImpl::setTableInfo(char *name, int tblid, size_t length,
787 int numFld, int numIdx, void *chunk)
789 strcpy(tblName_, name);
790 tblID_ = tblid;
791 length_ = length;
792 numFlds_ = numFld;
793 numIndexes_ = numIdx;
794 chunkPtr_ = chunk;
797 long TableImpl::spaceUsed()
799 Chunk *chk = (Chunk*)chunkPtr_;
800 long totSize = chk->getTotalDataNodes() * chk->getSize();
801 totSize = totSize + (chk->totalPages() * sizeof (PageInfo));
802 return totSize;
805 int TableImpl::pagesUsed()
807 Chunk *chk = (Chunk*)chunkPtr_;
808 return chk->totalPages();
811 long TableImpl::numTuples()
813 return ((Chunk*)chunkPtr_)->getTotalDataNodes();
816 List TableImpl::getFieldNameList()
818 List fldNameList;
819 FieldIterator fIter = fldList_.getIterator();
820 char fieldName[IDENTIFIER_LENGTH];
821 while (fIter.hasElement())
823 FieldDef def = fIter.nextElement();
824 Identifier *elem = new Identifier();
825 Table::getFieldNameAlone(def.fldName_, fieldName);
826 sprintf(elem->name, "%s.%s", getName(), fieldName);
827 fldNameList.append(elem);
829 return fldNameList;
831 DbRetVal TableImpl::close()
833 if (NULL == iter)
835 printError(ErrNotOpen,"Scan not open");
836 return ErrNotOpen;
838 iter->close();
839 delete iter;
840 iter = NULL;
841 return OK;
843 DbRetVal TableImpl::closeScan()
845 //do not throw scan not open error
846 //this function will be called by table handle
847 if (iter) {
848 iter->close();
849 delete iter;
850 iter = NULL;
852 return OK;
854 DbRetVal TableImpl::lock(bool shared)
857 DbRetVal ret = OK;
859 if (shared)
860 ret = lMgr_->getSharedLock(chunkPtr_, NULL);
861 else
862 ret = lMgr_->getExclusiveLock(chunkPtr_, NULL);
863 if (OK != ret)
865 printError(ret, "Could not exclusive lock on the table %x", chunkPtr_);
866 }else {
867 //do not append for S to X upgrade
868 if (!ProcessManager::hasLockList.exists(chunkPtr_))
869 ProcessManager::hasLockList.append(chunkPtr_);
872 return ret;
874 DbRetVal TableImpl::unlock()
877 if (!ProcessManager::hasLockList.exists(chunkPtr_)) return OK;
878 DbRetVal ret = lMgr_->releaseLock(chunkPtr_);
879 if (OK != ret)
881 printError(ret, "Could not release exclusive lock on the table %x", chunkPtr_);
882 }else
884 ProcessManager::hasLockList.remove(chunkPtr_);
887 return OK;
890 TableImpl::~TableImpl()
892 if (NULL != iter ) { delete iter; iter = NULL; }
893 if (NULL != indexPtr_) { delete[] indexPtr_; indexPtr_ = NULL; }
894 if (NULL != idxInfo)
896 for (int i = 0; i < numIndexes_; i++) delete idxInfo[i];
897 delete[] idxInfo;
898 idxInfo = NULL;
900 if (numFlds_ > 31 && cNullInfo != NULL) { free(cNullInfo); cNullInfo = NULL; }
902 fldList_.removeAll();
906 void *TableImpl::getBindFldAddr(const char *name)
908 return fldList_.getBindField(name);
910 bool TableImpl::isTableInvolved(char *tblName)
912 printf("Table isTableInvolved called for %s with %s\n", tblName, getName());
913 if (0 == strcmp(getName(), tblName)) return true; else return false;
915 bool TableImpl::pushPredicate(Predicate *pred)
917 bool ret = false;
918 PredicateImpl *pImpl = (PredicateImpl*) pred;
919 char tableName[IDENTIFIER_LENGTH];
920 Table::getTableNameAlone(pImpl->getFldName1(), tableName);
921 printf("predicate tbl name %s\n", tableName);
923 //if predicate is of form t1.f1=t2.f1 then do not push here
924 if (0 != strcmp(pImpl->getFldName2(),"")) return ret;
926 if (0 == strcmp(getName(), tableName))
928 setPredicate(pred);
929 printf("PRABA::pushed predicate in tablehdl %s\n", getName());
930 ret = true;
932 return ret;
934 void TableImpl::setPredicate(Predicate *pred)
936 if (NULL == pred_) { pred_ = pred; return; }
937 Predicate *curPred = pred_;
938 PredicateImpl *newPred = new PredicateImpl();
939 newPred->setTerm(curPred, OpAnd, pred);
940 newPred->setTable(this);
941 pred_ = newPred;
942 return;
944 void TableImpl::printPlan(int space)
946 char spaceBuf[IDENTIFIER_LENGTH];
947 memset(spaceBuf, 32, IDENTIFIER_LENGTH);
948 spaceBuf[space] = '\0';
949 printf("%s <TABLE-NODE>\n", spaceBuf);
950 printf("%s <NAME> %s </NAME>\n", spaceBuf, getName());
951 printf("%s <ScanType> %s </ScanType>\n", spaceBuf, ScanTypeNames[scanType_]);
952 PredicateImpl *pred = (PredicateImpl*)pred_;
953 if (pred) pred->print(space+2);
954 printf("%s </TABLE-NODE>\n", spaceBuf);