commiting changes from enterprise version for V2.4
[csql.git] / src / storage / TableImpl.cxx
blob3924ba3f35210f0e4366417c7433022178aca937
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 char fieldName[IDENTIFIER_LENGTH];
69 getFieldNameAlone((char*)name, fieldName);
70 int colpos = fldList_.getFieldPosition(fieldName);
71 if (-1 == colpos)
73 printError(ErrNotExists, "Field %s does not exist", name);
74 return false;
77 return isFldNull(colpos);
80 int TableImpl::getFldPos(char *name)
82 return fldList_.getFieldPosition(name);
84 bool TableImpl::isFldNull(int colpos)
86 if (!curTuple_) return false;
87 if (colpos <1 || colpos > numFlds_) return false;
88 if (isIntUsedForNULL) {
89 int nullVal = *(int*)((char*)curTuple_ + (length_ - 4));
90 if (BITSET(nullVal, colpos)) return true;
92 else {
93 char *nullOffset = (char*)curTuple_ - os::align(numFlds_);
94 if (nullOffset[colpos-1]) return true;
96 return false;
98 void TableImpl::resetNullinfo()
100 if (isIntUsedForNULL) {
101 iNullInfo =0;
103 else {
104 int i=0;
105 while(i < numFlds_) { cNullInfo[0] = 0;}
108 DbRetVal TableImpl::markFldNull(char const* name)
110 DbRetVal rv = OK;
111 int colpos = fldList_.getFieldPosition(name);
112 if (-1 == colpos)
114 printError(ErrNotExists, "Field %s does not exist", name);
115 return ErrNotExists;
117 rv = markFldNull(colpos);
118 return rv;
121 DbRetVal TableImpl::markFldNull(int fldpos)
123 if (fldpos <1 || fldpos > numFlds_) return ErrBadArg;
124 bool isBitSet = false;
125 if (isIntUsedForNULL) {
126 if (!BITSET(iNotNullInfo, fldpos)) {
127 SETBIT(iNullInfo, fldpos);
128 isBitSet = true;
130 else {
131 printError(ErrNullViolation, "NOT NULL constraint violation");
132 return ErrNullViolation;
135 else {
136 if (!BITSET(iNotNullInfo, fldpos)) cNullInfo[fldpos-1] = 1;
137 else {
138 printError(ErrNullViolation, "NOT NULL constraint violation");
139 return ErrNullViolation;
142 return OK;
145 void TableImpl::clearFldNull(const char *name)
147 int colpos = fldList_.getFieldPosition(name);
148 if (-1 == colpos)
150 printError(ErrNotExists, "Field %s does not exist", name);
151 return;
154 clearFldNull(colpos);
157 void TableImpl::clearFldNull(int colpos)
159 if (colpos <1 || colpos > numFlds_) return;
160 if (isIntUsedForNULL) {
161 CLEARBIT(iNullInfo, colpos);
163 else
164 cNullInfo[colpos-1] = 0;
165 return;
168 bool TableImpl::hasIndex(char* fName)
170 if (NULL == indexPtr_) return false;
171 for (int i =0; i < numIndexes_; i++)
173 HashIndexInfo* info = (HashIndexInfo*) idxInfo[i];
174 FieldIterator iter = info->idxFldList.getIterator();
175 if(iter.hasElement())
177 FieldDef *def = iter.nextElement();
178 if(strcmp(def->fldName_, fName) == 0)
179 if(!iter.hasElement())//neglet if it is composite index
180 return true;
183 return false;
186 IndexType TableImpl::getIndexType(char *fName, int *pos)
188 if (NULL == indexPtr_) return unknownIndex;
189 for (int i =0; i < numIndexes_; i++)
191 HashIndexInfo* info = (HashIndexInfo*) idxInfo[i];
192 FieldIterator iter = info->idxFldList.getIterator();
193 if(iter.hasElement())
195 FieldDef *def = iter.nextElement();
196 if(strcmp(def->fldName_, fName) == 0)
197 if(!iter.hasElement()) {//neglet if it is composite index
198 *(int*)pos = i;
199 return info->indType;
203 *(int*)pos = -1;
204 return unknownIndex;
206 void TableImpl::addPredicate(char *fName, ComparisionOp op, void *buf)
208 char fieldName[IDENTIFIER_LENGTH];
209 Table::getFieldNameAlone(fName, fieldName);
210 PredicateImpl *pred = (PredicateImpl*) pred_;
211 PredicateImpl *newPred = new PredicateImpl();
212 newPred->setTerm(fName, op, buf);
213 if (NULL == pred) { pred_ = newPred; return; }
214 if (pred->isSingleTerm())
216 bool res = pred->appendIfSameFld(fName, op, buf);
217 if(res) {
218 delete newPred;
219 return;
222 PredicateImpl *bothPred = new PredicateImpl();
223 bothPred->setTerm(pred, OpAnd, newPred);
224 pred_ = bothPred;
227 DbRetVal TableImpl::optimize()
229 //table ptr is set in predicate because it needs to access the
230 //type and length to evaluate
231 if( NULL != pred_)
233 PredicateImpl *pred = (PredicateImpl*) pred_;
234 pred->setTable(this);
235 pred->setProjectionList(NULL);
236 pred->setOffsetAndType();
238 return createPlan();
241 DbRetVal TableImpl::execute()
243 if (NULL != iter)
245 //printError(ErrAlready,"Scan already open:Close and re execute");
246 return ErrAlready;
248 DbRetVal ret = OK;
249 ret = optimize();
250 if (OK != ret)
252 printError(ErrSysInternal,"Unable to create the plan");
253 return ErrSysInternal;
255 if (useIndex_ >= 0)
256 iter = new TupleIterator(pred_, scanType_, idxInfo[useIndex_], chunkPtr_, sysDB_->procSlot,isBetween,isPointLook);
257 else if (scanType_ == fullTableScan)
258 iter = new TupleIterator(pred_, scanType_, NULL, chunkPtr_, sysDB_->procSlot,isBetween,isPointLook);
259 else
261 printError(ErrSysFatal,"Unable to create tuple iterator");//should never happen
262 return ErrSysFatal;
264 ret = iter->open();
265 if (OK != ret)
267 printError(ret,"Unable to open the iterator");
268 return ret;
270 return OK;
274 DbRetVal TableImpl::createPlan()
276 if (isPlanCreated) {
277 //will do early return here. plan is generated only when setPredicate is called.
278 if (scanType_ == unknownScan) return ErrSysFatal; //this should never happen
279 else return OK;
281 isBetween=false;
282 isPointLook = false;
283 useIndex_ = -1;
285 FieldIterator fIter = fldList_.getIterator();
286 FieldDef *def = NULL;
287 while ((def = fIter.nextElement())!= NULL) {
288 if (NULL != def->bindVal_) bindList_.append(def);
290 numBindFlds_ = bindList_.size();
291 bindListArray_ = (void **) malloc(numBindFlds_ * sizeof (void *));
292 void *elem = NULL;
293 int i = 0;
294 ListIterator it = bindList_.getIterator();
295 while ((elem = it.nextElement()) != NULL) bindListArray_[i++] = elem;
297 //if there are no predicates then go for full scan
298 //if there are no indexes then go for full scan
299 if (NULL == pred_ || NULL == indexPtr_)
301 scanType_ = fullTableScan;
302 isPlanCreated = true;
303 return OK;
305 if (NULL != indexPtr_)
307 PredicateImpl *pred = (PredicateImpl*)pred_;
308 printDebug(DM_Predicate, "predicate does not involve NOT , OR operator");
309 if (!pred->isNotOrInvolved())
311 printDebug(DM_Predicate, "predicate does not involve NOT , OR operator");
312 for (int i =0; i < numIndexes_; i++)
314 HashIndexInfo* info = (HashIndexInfo*) idxInfo[i];
315 FieldIterator iter = info->idxFldList.getIterator();
316 while(iter.hasElement())
318 FieldDef *def = iter.nextElement();
319 if (pred->pointLookupInvolved(def->fldName_))
321 printDebug(DM_Predicate, "point lookup involved for field %s",def->fldName_);
322 if(hashIndex == info->indType) scanType_ = hashIndexScan;
323 else scanType_ = treeIndexScan;
324 isPlanCreated = true;
325 isPointLook = true;
326 useIndex_ = i;
328 else if (pred->isBetweenInvolved(def->fldName_))
330 if (treeIndex == info->indType)
332 scanType_ = treeIndexScan;
333 isPlanCreated = true;
334 useIndex_ = i;
335 isBetween=true;
336 break; //no composite index for tree index
339 else if (pred->rangeQueryInvolved(def->fldName_))
341 printDebug(DM_Predicate, "range lookup involved for field %s",def->fldName_);
342 if (treeIndex == info->indType)
344 scanType_ = treeIndexScan;
345 isPlanCreated = true;
346 useIndex_ = i;
347 break; //no composite index for tree index
349 }else {
350 useIndex_ = -1;
351 break;
353 }//while iter.hasElement()
354 if (useIndex_ != -1) return OK;
355 }//for
358 scanType_ = fullTableScan;
359 isPlanCreated = true;
360 return OK;
363 void* TableImpl::fetch()
365 fetchNoBind();
366 if (NULL == curTuple_) return curTuple_;
367 copyValuesToBindBuffer(curTuple_);
368 return curTuple_;
370 void* TableImpl::fetch(DbRetVal &rv)
372 fetchNoBind(rv);
373 if (NULL == curTuple_) return curTuple_;
374 copyValuesToBindBuffer(curTuple_);
375 return curTuple_;
378 void* TableImpl::fetchNoBind()
380 if (NULL == iter)
382 printError(ErrNotOpen,"Scan not open or Scan is closed\n");
383 return NULL;
385 void *prevTuple = curTuple_;
386 curTuple_ = iter->next();
387 if (NULL == curTuple_)
389 return NULL;
391 DbRetVal lockRet = OK;
392 if ((*trans)->isoLevel_ == READ_COMMITTED)
394 //if iso level is read committed, operation duration lock is sufficent
395 //so release it here itself.
396 int tries = 5;
397 struct timeval timeout;
398 timeout.tv_sec = Conf::config.getMutexSecs();
399 timeout.tv_usec = Conf::config.getMutexUSecs();
401 bool status = false;
402 while(true) {
403 lockRet = lMgr_->isExclusiveLocked( curTuple_, trans, status);
404 if (OK != lockRet)
406 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
407 curTuple_ = prevTuple;
408 return NULL;
410 if (!status) break;
411 tries--;
412 if (tries == 0) break;
413 os::select(0, 0, 0, 0, &timeout);
416 if (tries == 0)
418 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
419 curTuple_ = prevTuple;
420 return NULL;
423 else if ((*trans)->isoLevel_ == READ_REPEATABLE) {
424 lockRet = lMgr_->getSharedLock(curTuple_, trans);
425 if (OK != lockRet)
427 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
428 curTuple_ = prevTuple;
429 return NULL;
433 return curTuple_;
436 void* TableImpl::fetchNoBind(DbRetVal &rv)
438 rv = OK;
439 if (NULL == iter)
441 printError(ErrNotOpen,"Scan not open or Scan is closed\n");
442 rv = ErrNotOpen;
443 return NULL;
445 void *prevTuple = curTuple_;
446 curTuple_ = iter->next();
447 if (NULL == curTuple_)
449 return NULL;
451 DbRetVal lockRet = OK;
452 if ((*trans)->isoLevel_ == READ_REPEATABLE) {
453 lockRet = lMgr_->getSharedLock(curTuple_, trans);
454 if (OK != lockRet)
456 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
457 rv = ErrLockTimeOut;
458 curTuple_ = prevTuple;
459 return NULL;
463 else if ((*trans)->isoLevel_ == READ_COMMITTED)
465 //if iso level is read committed, operation duration lock is sufficent
466 //so release it here itself.
467 int tries = 5;
468 struct timeval timeout;
469 timeout.tv_sec = Conf::config.getMutexSecs();
470 timeout.tv_usec = Conf::config.getMutexUSecs();
472 bool status = false;
473 while(true) {
474 lockRet = lMgr_->isExclusiveLocked( curTuple_, trans, status);
475 if (OK != lockRet)
477 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
478 curTuple_ = prevTuple;
479 rv = ErrLockTimeOut;
480 return NULL;
482 if (!status) break;
483 tries--;
484 if (tries == 0) break;
485 os::select(0, 0, 0, 0, &timeout);
488 if (tries == 0)
490 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
491 curTuple_ = prevTuple;
492 rv = ErrLockTimeOut;
493 return NULL;
496 return curTuple_;
498 DbRetVal TableImpl::fetchAgg(const char * fldName, AggType aType, void *buf)
500 FieldInfo *info = new FieldInfo();
501 DbRetVal rv = getFieldInfo(fldName, info);
502 if (OK != rv) return rv;
503 bool res= false;
504 if (AGG_MIN == aType || AGG_MAX == aType) {
505 int pos =0;
506 IndexType iType = getIndexType((char*)fldName, &pos);
507 if(treeIndex == iType && pos >=0) {
508 if (AGG_MIN == aType) {
509 HashIndexInfo* hInfo = (HashIndexInfo*) idxInfo[pos];
510 CINDEX *iptr = (CINDEX*) hInfo->indexPtr;
511 TreeIter *iter = new TreeIter((TreeNode*)iptr->hashNodeChunk_);
512 char *tuple = (char*) iter->getFirstElement();
513 if (tuple != NULL) {
514 AllDataType::copyVal(buf,(void*)(tuple+info->offset),
515 info->type, info->length);
516 delete iter;
517 return OK;
519 delete iter;
521 else if (AGG_MAX == aType) {
522 HashIndexInfo* hInfo = (HashIndexInfo*) idxInfo[pos];
523 CINDEX *iptr = (CINDEX*) hInfo->indexPtr;
524 TreeIter *iter = new TreeIter((TreeNode*)iptr->hashNodeChunk_);
525 char *tuple = (char*) iter->getLastElement();
526 if (tuple != NULL) {
527 AllDataType::copyVal(buf,(void*)(tuple+info->offset),
528 info->type, info->length);
529 delete iter;
530 return OK;
532 delete iter;
537 DataType type = info->type;
538 int length = info->length;
539 int offset = info->offset;
541 if (NULL == pred_ && typeInt == type)
542 { //perf opt
543 ChunkIterator cIter = ((Chunk*)chunkPtr_)->getIterator();
544 char *tuple =(char*)cIter.nextElement();
545 if (NULL == tuple) return OK;
546 int count =1;
547 AllDataType::copyVal(buf, (void*) (tuple+offset), type, length);
548 while(1) {
549 tuple = (char*)cIter.nextElement();
550 if (NULL == tuple) break;
551 switch(aType) {
552 case AGG_MIN:
554 if (*(int*)buf >= *((int*)(tuple+offset)))
555 *(int*)buf = *((int*)(tuple+offset));
556 break;
558 case AGG_MAX:
560 if (*(int*)buf <= *((int*)(tuple+offset)))
561 *(int*)buf = *((int*)(tuple+offset));
562 break;
564 case AGG_SUM:
566 *(int*)buf = *(int*)buf + *((int*)(tuple+offset));
567 break;
569 case AGG_AVG:
571 *(int*)buf = *(int*)buf + *((int*)(tuple+offset));
572 count++;
573 break;
575 case AGG_COUNT:
577 count++;
578 break;
582 if( AGG_AVG == aType) AllDataType::divVal(buf, &count, type);
583 else if (AGG_COUNT == aType) (*(int*)buf) = count;
584 delete info;
585 return OK;
588 char *tuple = (char*) fetchNoBind(rv);
589 if ( NULL == tuple) return OK;
590 int count =1;
591 AllDataType::copyVal(buf, (void*) (tuple+offset), type, length);
592 while(1) {
593 tuple = (char*) fetchNoBind(rv);
594 if (NULL == tuple) break;
595 switch(aType) {
596 case AGG_MIN:
598 res = AllDataType::compareVal(buf, (void*) (tuple+offset),
599 OpGreaterThanEquals,
600 type, length);
601 if (res) AllDataType::copyVal(buf, (void*) (tuple+offset),
602 type, length);
603 break;
605 case AGG_MAX:
607 res = AllDataType::compareVal(buf, (void*) (tuple+offset),
608 OpLessThanEquals,
609 type, length);
610 if (res) AllDataType::copyVal(buf, (void*) (tuple+offset),
611 type, length);
612 break;
614 case AGG_SUM:
616 AllDataType::addVal(buf, (void*) (tuple+offset),
617 type);
618 break;
620 case AGG_AVG:
622 AllDataType::addVal(buf, (void*) (tuple+offset),
623 type);
624 count++;
625 break;
627 case AGG_COUNT:
629 count++;
630 break;
634 switch(aType) {
635 case AGG_AVG:
637 AllDataType::divVal(buf, &count,type);
638 break;
640 case AGG_COUNT:
642 (*(int*)buf) = count;
643 break;
646 delete info;
647 return OK;
649 DbRetVal TableImpl::insertTuple()
651 DbRetVal ret =OK;
652 void *tptr = ((Chunk*)chunkPtr_)->allocate(db_, &ret);
653 if (NULL == tptr)
655 printError(ret, "Unable to allocate record from chunk");
656 return ret;
658 ret = lMgr_->getExclusiveLock(tptr, trans);
659 if (OK != ret)
661 ((Chunk*)chunkPtr_)->free(db_, tptr);
662 printError(ret, "Could not get lock for the insert tuple %x", tptr);
663 return ErrLockTimeOut;
666 curTuple_ = tptr;
668 ret = copyValuesFromBindBuffer(tptr);
669 if (ret != OK)
671 printError(ret, "Unable to copy values from bind buffer");
672 (*trans)->removeFromHasList(db_, tptr);
673 lMgr_->releaseLock(tptr);
674 ((Chunk*)chunkPtr_)->free(db_, tptr);
675 return ret;
677 int addSize = 0;
678 if (numFlds_ < 31)
680 addSize = 4;
681 *(int*)((char*)(tptr) + (length_-addSize)) = iNullInfo;
683 else
685 addSize = os::align(numFlds_);
686 os::memcpy(((char*)(tptr) + (length_-addSize)), cNullInfo, addSize);
689 //int tupleSize = length_ + addSize;
690 if (NULL != indexPtr_)
692 int i;
693 //it has index
694 for (i = 0; i < numIndexes_ ; i++)
696 ret = insertIndexNode(*trans, indexPtr_[i], idxInfo[i], tptr);
697 if (ret != OK) { printError(ret, "Error in inserting to index"); break;}
699 if (i != numIndexes_ )
701 for (int j = 0; j < i ; j++) {
702 printError(ErrWarning, "Deleting index node");
703 deleteIndexNode(*trans, indexPtr_[j], idxInfo[j], tptr);
705 lMgr_->releaseLock(tptr);
706 (*trans)->removeFromHasList(db_, tptr);
707 ((Chunk*)chunkPtr_)->free(db_, tptr);
708 //PRABA::TEMP
709 //printError(ret, "Unable to insert index node for tuple %x ", tptr);
710 printError(ret, "Unable to insert index node for tuple %x %d", tptr, *(int*)tptr);
711 return ret;
714 if (undoFlag)
715 ret = (*trans)->appendUndoLog(sysDB_, InsertOperation, tptr, length_);
716 if (ret != OK) {
717 printError(ret, "Unable to create undo log for %x %d", tptr, *(int*)tptr);
718 for (int j = 0; j < numIndexes_ ; j++) {
719 printError(ErrWarning, "Deleting index node");
720 deleteIndexNode(*trans, indexPtr_[j], idxInfo[j], tptr);
722 lMgr_->releaseLock(tptr);
723 (*trans)->removeFromHasList(db_, tptr);
724 ((Chunk*)chunkPtr_)->free(db_, tptr);
726 return ret;
729 DbRetVal TableImpl::deleteTuple()
731 if (NULL == curTuple_)
733 printError(ErrNotOpen, "Scan not open: No Current tuple");
734 return ErrNotOpen;
736 DbRetVal ret = lMgr_->getExclusiveLock(curTuple_, trans);
737 if (OK != ret)
739 printError(ret, "Could not get lock for the delete tuple %x", curTuple_);
740 return ErrLockTimeOut;
743 if (NULL != indexPtr_)
745 int i;
746 //it has index
747 for (i = 0; i < numIndexes_ ; i++)
749 ret = deleteIndexNode(*trans, indexPtr_[i], idxInfo[i], curTuple_);
750 if (ret != OK) break;
752 if (i != numIndexes_ )
754 for (int j = 0; j < i ; j++)
755 insertIndexNode(*trans, indexPtr_[j], idxInfo[j], curTuple_);
756 lMgr_->releaseLock(curTuple_);
757 (*trans)->removeFromHasList(db_, curTuple_);
758 printError(ret, "Unable to insert index node for tuple %x", curTuple_);
759 return ret;
762 ((Chunk*)chunkPtr_)->free(db_, curTuple_);
763 if (undoFlag)
764 ret = (*trans)->appendUndoLog(sysDB_, DeleteOperation, curTuple_, length_);
765 iter->prev();
766 return ret;
769 int TableImpl::deleteWhere()
771 int tuplesDeleted = 0;
772 DbRetVal rv = OK;
773 rv = execute();
774 if (rv !=OK) return (int) rv;
775 while(true){
776 fetchNoBind( rv);
777 if (rv != OK) { tuplesDeleted = (int)rv; break; }
778 if (NULL == curTuple_) break;
779 rv = deleteTuple();
780 if (rv != OK) {
781 printError(rv, "Error: Could only delete %d tuples", tuplesDeleted);
782 closeScan();
783 return (int) rv;
785 tuplesDeleted++;
787 closeScan();
788 return tuplesDeleted;
791 int TableImpl::truncate()
793 //take exclusive lock on the table
794 //get the chunk ptr of the table
795 //traverse the tablechunks and free all the pages except the first one
796 //get the chunk ptr of all its indexes
797 //traverse the indexchunks and free all the pages except the first one
798 //release table lock
800 //TEMPORARY FIX
801 DbRetVal rv = OK;
802 Predicate* tmpPred = pred_;
803 pred_ = NULL;
804 isPlanCreated = false;
805 int tuplesDeleted = deleteWhere();
806 isPlanCreated = false;
807 pred_ = tmpPred;
808 return tuplesDeleted;
811 DbRetVal TableImpl::updateTuple()
813 if (NULL == curTuple_)
815 printError(ErrNotOpen, "Scan not open: No Current tuple");
816 return ErrNotOpen;
818 DbRetVal ret = lMgr_->getExclusiveLock(curTuple_, trans);
819 if (OK != ret)
821 printError(ret, "Could not get lock for the update tuple %x", curTuple_);
822 return ErrLockTimeOut;
824 if (NULL != indexPtr_)
826 //it has index
827 //TODO::If it fails while updating index node, we have to undo all the updates
828 //on other indexes on the table.Currently it will leave the database in an
829 //inconsistent state.
830 for (int i = 0; i < numIndexes_ ; i++)
832 ret = updateIndexNode(*trans, indexPtr_[i], idxInfo[i], curTuple_);
833 if (ret != OK)
835 lMgr_->releaseLock(curTuple_);
836 (*trans)->removeFromHasList(db_, curTuple_);
837 printError(ret, "Unable to update index node for tuple %x", curTuple_);
838 return ret;
842 if (undoFlag)
843 ret = (*trans)->appendUndoLog(sysDB_, UpdateOperation, curTuple_, length_);
844 if (ret != OK) return ret;
845 int addSize = 0;
846 int iNullVal=iNullInfo;
847 if (numFlds_ < 31){
848 addSize=4;
849 if(!iNullVal){
850 iNullInfo = *(int*)((char*)(curTuple_) + (length_- addSize));
852 else
854 *(int*)((char*)(curTuple_) + (length_-addSize)) |= iNullInfo;
857 DbRetVal rv = copyValuesFromBindBuffer(curTuple_, false);
858 if (rv != OK) {
859 lMgr_->releaseLock(curTuple_);
860 (*trans)->removeFromHasList(db_, curTuple_);
861 return rv;
864 if (numFlds_ < 31)
866 if (!iNullVal) {
867 *(int*)((char*)(curTuple_) + (length_-addSize)) = iNullInfo;
868 iNullInfo=0;
870 else iNullInfo=iNullVal;
872 else
874 addSize = os::align(numFlds_);
875 //TODO::Do not do blind memcpy. It should OR each and every char
876 //os::memcpy(((char*)(curTuple_) + (length_-addSize)), cNullInfo, addSize);
879 return OK;
882 void TableImpl::printInfo()
884 printf(" <TableName> %s </TableName>\n", tblName_);
885 printf(" <TupleCount> %d </TupleCount>\n", numTuples());
886 printf(" <PagesUsed> %d </PagesUsed>\n", pagesUsed());
887 printf(" <SpaceUsed> %d </SpaceUsed>\n", spaceUsed());
888 printf(" <Indexes> %d <Indexes>\n", numIndexes_);
889 printf(" <TupleLength> %d </TupleLength>\n", length_);
890 printf(" <Fields> %d </Fields>\n", numFlds_);
891 printf(" <Indexes>\n");
892 for (int i =0; i<numIndexes_; i++)
893 printf("<IndexName> %s </IndexName>\n", CatalogTableINDEX::getName(indexPtr_[i]));
894 printf(" </Indexes>\n");
898 DbRetVal TableImpl::copyValuesFromBindBuffer(void *tuplePtr, bool isInsert)
900 //Iterate through the bind list and copy the value here
901 FieldIterator fIter = fldList_.getIterator();
902 char *colPtr = (char*) tuplePtr;
903 int fldpos=1;
904 while (fIter.hasElement())
906 FieldDef *def = fIter.nextElement();
907 if(def->isAutoIncrement_ && isInsert)
909 void *dest = AllDataType::alloc(def->type_, def->length_);
910 AllDataType::copyVal(dest,ptrToAuto, def->type_, def->length_);
911 if(def->bindVal_==NULL)
913 AllDataType::increment(colPtr, dest , def->type_);
914 AllDataType::copyVal(ptrToAuto,colPtr, def->type_, def->length_);
915 colPtr = colPtr + def->length_;
916 fldpos++;
917 free(dest);
918 continue;
919 }else {
920 if(AllDataType::compareVal(def->bindVal_, dest, OpGreaterThan, def->type_)){
921 AllDataType::copyVal(ptrToAuto,def->bindVal_, def->type_, def->length_);
923 free(dest);
926 if (def->isNull_ && !def->isDefault_ && NULL == def->bindVal_ && isInsert)
928 printError(ErrNullViolation, "NOT NULL constraint violation for field %s\n", def->fldName_);
929 return ErrNullViolation;
931 if (def->isDefault_ && NULL == def->bindVal_ && isInsert)
933 void *dest = AllDataType::alloc(def->type_, def->length_);
934 AllDataType::convert(typeString, def->defaultValueBuf_, def->type_, dest, def->length_);
935 AllDataType::copyVal(colPtr, dest, def->type_, def->length_);
936 colPtr = colPtr + def->length_;
937 fldpos++;
938 free (dest);
939 continue;
941 switch(def->type_)
943 case typeString:
944 if (NULL != def->bindVal_)
946 if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);}
947 strcpy((char*)colPtr, (char*)def->bindVal_);
948 *(((char*)colPtr) + (def->length_-1)) = '\0';
950 else if (!def->isNull_ && !def->bindVal_ && isInsert) setNullBit(fldpos);
951 colPtr = colPtr + def->length_;
952 break;
953 case typeBinary:
954 if (NULL != def->bindVal_ )
956 if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);}
957 DbRetVal rv = AllDataType::strToValue(colPtr, (char *) def->bindVal_, def->type_, def->length_);
958 if (rv != OK) return ErrBadArg;
960 else if (!def->isNull_ && isInsert && !def->bindVal_) setNullBit(fldpos);
961 colPtr = colPtr + def->length_;
962 break;
963 default:
964 if (NULL != def->bindVal_){
965 if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);}
966 AllDataType::copyVal(colPtr, def->bindVal_, def->type_);}
967 else { if (!def->isNull_ && isInsert) setNullBit(fldpos); }
968 colPtr = colPtr + def->length_;
969 break;
971 fldpos++;
973 return OK;
975 void TableImpl::clearNullBit(int fldpos)
977 if (isIntUsedForNULL){
978 CLEARBIT(iNullInfo, fldpos);}
979 else
980 cNullInfo[fldpos-1] = 0;
982 void TableImpl::setNullBit(int fldpos)
984 if (isIntUsedForNULL)
985 SETBIT(iNullInfo, fldpos);
986 else
987 cNullInfo[fldpos-1] = 1;
989 DbRetVal TableImpl::copyValuesToBindBuffer(void *tuplePtr)
991 //Iterate through the bind list and copy the value here
992 char *colPtr = (char*) tuplePtr;
993 FieldDef *def = NULL;
994 for (int i = 0; i < numBindFlds_; i++) {
995 def = (FieldDef *) bindListArray_[i];
996 colPtr = (char *) tuplePtr + def->offset_;
997 AllDataType::copyVal(def->bindVal_, colPtr, def->type_, def->length_);
999 return OK;
1002 //-1 index not supported
1003 DbRetVal TableImpl::insertIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple)
1005 CINDEX *iptr = (CINDEX*)indexPtr;
1006 DbRetVal ret = OK;
1007 printDebug(DM_Table, "Inside insertIndexNode type %d", iptr->indexType_);
1008 Index* idx = Index::getIndex(iptr->indexType_);
1009 ret = idx->insert(this, tr, indexPtr, info, tuple,undoFlag);
1010 return ret;
1013 DbRetVal TableImpl::deleteIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple)
1015 CINDEX *iptr = (CINDEX*)indexPtr;
1016 DbRetVal ret = OK;
1017 Index* idx = Index::getIndex(iptr->indexType_);
1018 ret = idx->remove(this, tr, indexPtr, info, tuple, undoFlag);
1019 return ret;
1021 void TableImpl::printSQLIndexString()
1023 CatalogTableINDEXFIELD cIndexField(sysDB_);
1024 char fName[IDENTIFIER_LENGTH];
1025 char *fldName = fName;
1026 char idxName[IDENTIFIER_LENGTH];
1027 DataType type;
1028 for (int i = 0; i < numIndexes_ ; i++)
1030 CINDEX *iptr = (CINDEX*) indexPtr_[i];
1031 sprintf(idxName,"%s_idx_Auto_increment",getName());
1032 if(strcmp(iptr->indName_,idxName)==0){ continue; }
1033 printf("CREATE INDEX %s on %s ( ", iptr->indName_, getName());
1034 FieldList fldList;
1035 cIndexField.getFieldInfo(iptr, fldList);
1036 FieldIterator fIter = fldList.getIterator();
1037 bool firstFld = true;
1038 while(fIter.hasElement())
1040 FieldDef *def = fIter.nextElement();
1041 if (firstFld) { printf(" %s ", def->fldName_); firstFld = false; }
1042 else printf(" ,%s ", def->fldName_);
1044 printf(" ) ");
1045 if (iptr->indexType_ == hashIndex) printf(" HASH ");
1046 else printf(" TREE ");
1047 if (((HashIndexInfo*) idxInfo[i])->isUnique) printf(" UNIQUE");
1048 if(((HashIndexInfo*) idxInfo[i])->noOfBuckets != 1009 ) printf(" SIZE %d ",((HashIndexInfo*) idxInfo[i])->noOfBuckets );
1049 printf(";\n");
1054 DbRetVal TableImpl::updateIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple)
1056 CINDEX *iptr = (CINDEX*)indexPtr;
1057 DbRetVal ret = OK;
1058 Index* idx = Index::getIndex(iptr->indexType_);
1059 //TODO::currently it updates irrespective of whether the key changed or not
1060 //because of this commenting the whole index update code. relook at it and uncomment
1062 ret = idx->update(this, tr, indexPtr, info, tuple, undoFlag);
1064 return ret;
1068 void TableImpl::setTableInfo(char *name, int tblid, size_t length,
1069 int numFld, int numIdx, void *chunk)
1071 strcpy(tblName_, name);
1072 tblID_ = tblid;
1073 length_ = length;
1074 numFlds_ = numFld;
1075 numIndexes_ = numIdx;
1076 chunkPtr_ = chunk;
1079 long TableImpl::spaceUsed()
1081 Chunk *chk = (Chunk*)chunkPtr_;
1082 long totSize = chk->getTotalDataNodes() * chk->getSize();
1083 totSize = totSize + (chk->totalPages() * sizeof (PageInfo));
1084 return totSize;
1087 int TableImpl::pagesUsed()
1089 Chunk *chk = (Chunk*)chunkPtr_;
1090 return chk->totalPages();
1093 long TableImpl::numTuples()
1095 return ((Chunk*)chunkPtr_)->getTotalDataNodes();
1098 List TableImpl::getFieldNameList()
1100 List fldNameList;
1101 FieldIterator fIter = fldList_.getIterator();
1102 char fieldName[IDENTIFIER_LENGTH];
1103 while (fIter.hasElement())
1105 FieldDef *def = fIter.nextElement();
1106 Identifier *elem = new Identifier();
1107 Table::getFieldNameAlone(def->fldName_, fieldName);
1108 sprintf(elem->name, "%s.%s", getName(), fieldName);
1109 fldNameList.append(elem);
1111 return fldNameList;
1113 DbRetVal TableImpl::close()
1115 if (iter) { iter->close(); delete iter; iter = NULL; }
1116 printDebug(DM_Database,"Closing table handle: %x", this);
1117 //table->unlock();
1118 delete pred_;
1119 delete this;
1120 logFinest(logger, "Closing Table");
1121 return OK;
1124 DbRetVal TableImpl::closeScan()
1126 //do not throw scan not open error
1127 //this function will be called by table handle
1128 if (iter) {
1129 // iter->reset();
1130 //PRABA::TEMP::otherwise fails.check with kishor
1131 delete iter;
1132 iter = NULL;
1134 return OK;
1136 DbRetVal TableImpl::lock(bool shared)
1139 DbRetVal ret = OK;
1141 if (shared)
1142 ret = lMgr_->getSharedLock(chunkPtr_, NULL);
1143 else
1144 ret = lMgr_->getExclusiveLock(chunkPtr_, NULL);
1145 if (OK != ret)
1147 printError(ret, "Could not exclusive lock on the table %x", chunkPtr_);
1148 }else {
1149 //do not append for S to X upgrade
1150 if (!ProcessManager::hasLockList.exists(chunkPtr_))
1151 ProcessManager::hasLockList.append(chunkPtr_);
1154 return ret;
1156 DbRetVal TableImpl::unlock()
1159 if (!ProcessManager::hasLockList.exists(chunkPtr_)) return OK;
1160 DbRetVal ret = lMgr_->releaseLock(chunkPtr_);
1161 if (OK != ret)
1163 printError(ret, "Could not release exclusive lock on the table %x", chunkPtr_);
1164 }else
1166 ProcessManager::hasLockList.remove(chunkPtr_);
1169 return OK;
1172 TableImpl::~TableImpl()
1174 if (NULL != iter ) { delete iter; iter = NULL; }
1175 if (NULL != indexPtr_) { delete[] indexPtr_; indexPtr_ = NULL; }
1176 if (NULL != idxInfo)
1178 for (int i = 0; i < numIndexes_; i++) delete idxInfo[i];
1179 delete[] idxInfo;
1180 idxInfo = NULL;
1182 if (numFlds_ > 31 && cNullInfo != NULL) { free(cNullInfo); cNullInfo = NULL; }
1183 if (bindList_.size()) bindList_.reset();
1184 if (bindListArray_) { free (bindListArray_); bindListArray_ = NULL; }
1185 fldList_.removeAll();
1189 void *TableImpl::getBindFldAddr(const char *name)
1191 return fldList_.getBindField(name);
1193 bool TableImpl::isTableInvolved(char *tblName)
1195 //printf("Table isTableInvolved called for %s with %s\n", tblName, getName());
1196 if (0 == strcmp(getName(), tblName)) return true; else return false;
1198 bool TableImpl::pushPredicate(Predicate *pred)
1200 bool ret = false;
1201 PredicateImpl *pImpl = (PredicateImpl*) pred;
1202 char tableName[IDENTIFIER_LENGTH];
1203 Table::getTableNameAlone(pImpl->getFldName1(), tableName);
1204 //printf("predicate tbl name %s\n", tableName);
1206 //if predicate is of form t1.f1=t2.f1 then do not push here
1207 if (0 != strcmp(pImpl->getFldName2(),"")) return ret;
1209 if (0 == strcmp(getName(), tableName))
1211 setPredicate(pred);
1212 //printf("PRABA::pushed predicate in tablehdl %s\n", getName());
1213 ret = true;
1215 return ret;
1217 void TableImpl::setPredicate(Predicate *pred)
1219 if (NULL == pred_) { pred_ = pred; return; }
1220 Predicate *curPred = pred_;
1221 PredicateImpl *newPred = new PredicateImpl();
1222 newPred->setTerm(curPred, OpAnd, pred);
1223 newPred->setTable(this);
1224 pred_ = newPred;
1225 return;
1227 void TableImpl::printPlan(int space)
1229 char spaceBuf[IDENTIFIER_LENGTH];
1230 memset(spaceBuf, 32, IDENTIFIER_LENGTH);
1231 spaceBuf[space] = '\0';
1232 printf("%s <TABLE-NODE>\n", spaceBuf);
1233 printf("%s <NAME> %s </NAME>\n", spaceBuf, getName());
1234 printf("%s <ScanType> %s </ScanType>\n", spaceBuf, ScanTypeNames[scanType_]);
1235 PredicateImpl *pred = (PredicateImpl*)pred_;
1236 if (pred) pred->print(space+2);
1237 printf("%s </TABLE-NODE>\n", spaceBuf);