Varchar Implementation part 1
[csql.git] / src / storage / TableImpl.cxx
blobcde18d1d9d1295ff27f2ad5ce52b5702ee9b634d
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 for (int i =0; i < numIndexes_; i++)
334 bool isAllFldPointLookup = true;
335 HashIndexInfo* info = (HashIndexInfo*) idxInfo[i];
336 FieldIterator iter = info->idxFldList.getIterator();
337 int noOfIfld =0;
338 while(iter.hasElement())
340 noOfIfld++;
341 FieldDef *def = iter.nextElement();
342 if (pred->pointLookupInvolved(def->fldName_))
344 if (!isAllFldPointLookup) break;
345 printDebug(DM_Predicate, "point lookup involved for field %s",def->fldName_);
346 if(hashIndex == info->indType) scanType_ = hashIndexScan;
347 else scanType_ = treeIndexScan;
348 isPointLook = true;
349 useIndex_ = i;
351 else if (pred->isBetweenInvolved(def->fldName_))
353 if (treeIndex == info->indType)
355 scanType_ = treeIndexScan;
356 useIndex_ = i;
357 isBetween=true;
358 break; //no composite index for tree index
359 } else isAllFldPointLookup= false;
361 else if (pred->rangeQueryInvolved(def->fldName_))
363 printDebug(DM_Predicate, "range lookup involved for field %s",def->fldName_);
364 if (treeIndex == info->indType)
366 scanType_ = treeIndexScan;
367 useIndex_ = i;
368 break; //no composite index for tree index
369 } else isAllFldPointLookup=false;
370 }else {
371 useIndex_ = -1;
372 isAllFldPointLookup = false;
373 break;
375 }//while iter.hasElement()
376 if( noOfIfld == 1 && useIndex_ != -1)return OK;
377 if (!isAllFldPointLookup && useIndex_ != -1) return OK;
378 }//for
381 scanType_ = fullTableScan;
382 return OK;
385 void* TableImpl::fetch()
387 fetchNoBind();
388 if (NULL == curTuple_) return curTuple_;
389 copyValuesToBindBuffer(curTuple_);
390 return curTuple_;
392 void* TableImpl::fetch(DbRetVal &rv)
394 fetchNoBind(rv);
395 if (NULL == curTuple_) return curTuple_;
396 copyValuesToBindBuffer(curTuple_);
397 return curTuple_;
400 void* TableImpl::fetchNoBind()
402 if (NULL == iter)
404 printError(ErrNotOpen,"Scan not open or Scan is closed\n");
405 return NULL;
407 void *prevTuple = curTuple_;
408 curTuple_ = iter->next();
409 if (NULL == curTuple_)
411 return NULL;
413 DbRetVal lockRet = OK;
414 if (!loadFlag) {
415 if ((*trans)->isoLevel_ == READ_COMMITTED)
417 //if iso level is read committed, operation duration lock is sufficent
418 //so release it here itself.
419 int tries = Conf::config.getMutexRetries();
420 struct timeval timeout;
421 timeout.tv_sec = Conf::config.getMutexSecs();
422 timeout.tv_usec = Conf::config.getMutexUSecs();
424 bool status = false;
425 while(true) {
426 lockRet = lMgr_->isExclusiveLocked( curTuple_, trans, status);
427 if (OK != lockRet)
429 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
430 curTuple_ = prevTuple;
431 return NULL;
433 if (!status) break;
434 tries--;
435 if (tries == 0) break;
436 os::select(0, 0, 0, 0, &timeout);
438 if (tries == 0)
440 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
441 curTuple_ = prevTuple;
442 return NULL;
445 else if ((*trans)->isoLevel_ == READ_REPEATABLE) {
446 if (OK != trySharedLock(curTuple_, trans))
448 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
449 curTuple_ = prevTuple;
450 return NULL;
455 return curTuple_;
457 DbRetVal TableImpl::trySharedLock(void *curTuple, Transaction **trans)
459 DbRetVal lockRet = OK;
460 int tries = Conf::config.getMutexRetries();
461 while((lockRet = lMgr_->getSharedLock(curTuple_, trans)) == ErrLockTimeOut)
463 tries--;
464 if (tries <=0) break;
466 return lockRet;
468 DbRetVal TableImpl::tryExclusiveLock(void *curTuple, Transaction **trans)
470 DbRetVal lockRet = OK;
471 int tries = Conf::config.getMutexRetries();
472 while((lockRet = lMgr_->getExclusiveLock(curTuple_, trans)) == ErrLockTimeOut)
474 tries--;
475 if (tries <=0) break;
477 return lockRet;
480 void* TableImpl::fetchNoBind(DbRetVal &rv)
482 rv = OK;
483 if (NULL == iter)
485 printError(ErrNotOpen,"Scan not open or Scan is closed\n");
486 rv = ErrNotOpen;
487 return NULL;
489 void *prevTuple = curTuple_;
490 curTuple_ = iter->next();
491 if (NULL == curTuple_)
493 return NULL;
495 DbRetVal lockRet = OK;
496 if (!loadFlag) {
497 if ((*trans)->isoLevel_ == READ_REPEATABLE) {
498 lockRet = lMgr_->getSharedLock(curTuple_, trans);
499 if (OK != lockRet)
501 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
502 rv = ErrLockTimeOut;
503 curTuple_ = prevTuple;
504 return NULL;
508 else if ((*trans)->isoLevel_ == READ_COMMITTED)
510 //if iso level is read committed, operation duration lock is sufficent
511 //so release it here itself.
512 int tries = Conf::config.getMutexRetries();
513 //struct timeval timeout;
514 //timeout.tv_sec = Conf::config.getMutexSecs();
515 //timeout.tv_usec = Conf::config.getMutexUSecs();
517 bool status = false;
518 while(true) {
519 lockRet = lMgr_->isExclusiveLocked( curTuple_, trans, status);
520 if (OK != lockRet)
522 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
523 curTuple_ = prevTuple;
524 rv = ErrLockTimeOut;
525 return NULL;
527 if (!status) break;
528 tries--;
529 if (tries == 0) break;
530 //os::select(0, 0, 0, 0, &timeout);
532 if (tries == 0)
534 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
535 curTuple_ = prevTuple;
536 rv = ErrLockTimeOut;
537 return NULL;
541 return curTuple_;
543 DbRetVal TableImpl::fetchAgg(const char * fldName, AggType aType, void *buf, bool &noRec)
545 FieldInfo *info = new FieldInfo();
546 DbRetVal rv = getFieldInfo(fldName, info);
547 if (OK != rv) return rv;
548 bool res= false;
549 if (AGG_MIN == aType || AGG_MAX == aType) {
550 int pos =0;
551 IndexType iType = getIndexType((char*)fldName, &pos);
552 if(treeIndex == iType && pos >=0) {
553 if (AGG_MIN == aType) {
554 HashIndexInfo* hInfo = (HashIndexInfo*) idxInfo[pos];
555 CINDEX *iptr = (CINDEX*) hInfo->indexPtr;
556 TreeNode *fstNode=(TreeNode *)iptr->hashNodeChunk_;
557 TreeIter *iter=NULL;
558 if(fstNode!=NULL){
559 TreeNode *start = (TreeNode *)*((char**)((char*)fstNode + sizeof(TreeNode)));
560 iter = new TreeIter(start,(TreeNode*)iptr->hashNodeChunk_,sysDB_->procSlot);
561 }else{
562 iter = new TreeIter(NULL,(TreeNode*)iptr->hashNodeChunk_,sysDB_->procSlot);
564 char *tuple = (char*) iter->getFirstElement();
565 if (tuple != NULL) {
566 AllDataType::copyVal(buf,(void*)(tuple+info->offset),
567 info->type, info->length);
568 delete iter;
569 return OK;
571 delete iter; iter = NULL;
573 else if (AGG_MAX == aType) {
574 HashIndexInfo* hInfo = (HashIndexInfo*) idxInfo[pos];
575 CINDEX *iptr = (CINDEX*) hInfo->indexPtr;
576 TreeNode *fstNode=(TreeNode *)iptr->hashNodeChunk_;
577 TreeIter *iter=NULL;
578 if(fstNode!=NULL){
579 TreeNode *start = (TreeNode *)*((char**)((char*)fstNode + sizeof(TreeNode)));
580 iter = new TreeIter(start,(TreeNode*)iptr->hashNodeChunk_,sysDB_->procSlot);
581 }else{
582 iter = new TreeIter(NULL,(TreeNode*)iptr->hashNodeChunk_,sysDB_->procSlot);
584 char *tuple = (char*) iter->getLastElement();
585 if (tuple != NULL) {
586 AllDataType::copyVal(buf,(void*)(tuple+info->offset),
587 info->type, info->length);
588 delete iter; iter = NULL;
589 return OK;
591 delete iter; iter=NULL;
594 }else if (AGG_COUNT == aType) {
595 (*(int*)buf) = 0;
599 DataType type = info->type;
600 int length = info->length;
601 int offset = info->offset;
602 int colPos = fldList_.getFieldPosition(fldName);
603 bool isNullable= true;
604 if (info->isNull || info->isPrimary || info->isDefault || info->isAutoIncrement) {
605 isNullable = false;
607 int nullOffset = length_-4;
608 if (aType == AGG_COUNT) {
609 length = sizeof(int);
610 type = typeInt;
612 if (NULL == pred_ && typeInt == type && aType != AGG_AVG)
613 { //perf opt
614 ChunkIterator cIter = ((Chunk*)chunkPtr_)->getIterator();
615 char *tuple =(char*)cIter.nextElement();
616 if (NULL == tuple) {
617 *(int *) buf = 0;
618 noRec = true;
619 return OK;
621 int count =1;
622 if (isNullable) {
623 if (isIntUsedForNULL) {
624 if (BITSET(*(int*)(tuple+nullOffset), colPos)) count =0;
626 else {
627 curTuple_= tuple;
628 if(isFldNull(colPos)) count =0;
631 if (aType != AGG_COUNT)
632 AllDataType::copyVal(buf, (void*) (tuple+offset), type, length);
633 void *prev=NULL;
634 prev = curTuple_;
635 cIter.pageSize = PAGE_SIZE;
636 while(1)
638 tuple = (char*)cIter.nextElementInt();
639 if (NULL == tuple) break;
640 if (isNullable) {
641 if (isIntUsedForNULL) {
642 if (BITSET(*(int*)(tuple+nullOffset), colPos)) continue;
644 else {
645 curTuple_= tuple;
646 if(isFldNull(colPos)) continue;
649 if (aType == AGG_MIN)
651 if (*(int*)buf >= *((int*)(tuple+offset)))
652 *(int*)buf = *((int*)(tuple+offset));
654 else if (aType == AGG_MAX)
656 if (*(int*)buf <= *((int*)(tuple+offset)))
657 *(int*)buf = *((int*)(tuple+offset));
659 else if (aType == AGG_SUM)
661 *(int*)buf += *((int*)(tuple+offset));
663 else if (aType == AGG_AVG)
665 *(int*)buf = *(int*)buf + *((int*)(tuple+offset));
666 count++;
668 else if (aType == AGG_COUNT)
670 count++;
673 curTuple_= prev;
674 if( AGG_AVG == aType) AllDataType::divVal(buf, &count, type);
675 else if (AGG_COUNT == aType) (*(int*)buf) = count;
676 delete info;
677 return OK;
680 char *tuple = (char*) fetchNoBind(rv);
681 if ( NULL == tuple) { noRec = true; return OK; }
682 int count =1;
684 while(isFldNull(colPos)) {
685 tuple= (char*) fetchNoBind(rv);
686 if (aType == AGG_COUNT) count++;
687 if (tuple) break;
689 if ( NULL == tuple) { noRec = true; return OK; }
691 if (aType == AGG_AVG) {
692 AllDataType::convertToDouble(buf, (void*) (tuple+offset), type);
693 } else if (aType != AGG_COUNT) {
694 AllDataType::copyVal(buf, (void*) (tuple+offset), type, length);
696 while(1) {
697 tuple = (char*) fetchNoBind(rv);
698 if (NULL == tuple) break;
699 if (isNullable) {
700 if (isIntUsedForNULL) {
701 if (BITSET(*(int*)(tuple+nullOffset), colPos)) continue;
703 else {
704 curTuple_= tuple;
705 if(isFldNull(colPos)) continue;
708 switch(aType) {
709 case AGG_MIN:
711 res = AllDataType::compareVal(buf, (void*) (tuple+offset),
712 OpGreaterThanEquals,
713 type, length);
714 if (res) AllDataType::copyVal(buf, (void*) (tuple+offset),
715 type, length);
716 break;
718 case AGG_MAX:
720 res = AllDataType::compareVal(buf, (void*) (tuple+offset),
721 OpLessThanEquals,
722 type, length);
723 if (res) AllDataType::copyVal(buf, (void*) (tuple+offset),
724 type, length);
725 break;
727 case AGG_SUM:
729 AllDataType::addVal(buf, (void*) (tuple+offset),
730 type);
731 break;
733 case AGG_AVG:
735 double tmpBuf=0.0;
736 AllDataType::convertToDouble(&tmpBuf, (void*) (tuple+offset), type);
737 AllDataType::addVal(buf, &tmpBuf, typeDouble);
738 count++;
739 break;
741 case AGG_COUNT:
743 count++;
744 break;
748 switch(aType) {
749 case AGG_AVG:
751 AllDataType::divVal((double *)buf, count, type);
752 break;
754 case AGG_COUNT:
756 (*(int*)buf) = count;
757 break;
760 delete info;
761 return OK;
763 DbRetVal TableImpl::insertTuple()
765 DbRetVal ret =OK;
766 void *tptr = NULL;// ((Chunk*)chunkPtr_)->allocate(db_, &ret);
767 int tries=0;
768 int totalTries = Conf::config.getMutexRetries();
769 while (tries < totalTries)
771 ret = OK;
772 tptr = ((Chunk*)chunkPtr_)->allocate(db_, &ret);
773 if (tptr !=NULL) break;
774 if (ret != ErrLockTimeOut)
776 printError(ret, "Unable to allocate record from chunk");
777 return ret;
779 tries++;
781 if (NULL == tptr)
783 printError(ret, "Unable to allocate record from chunk after %d retries", tries);
784 return ret;
786 curTuple_ = tptr;
787 if(isFkTbl){
788 TableImpl *fkTbl =NULL;
789 ListIterator tblIter = tblList.getIterator();
790 tblIter.reset();
791 while (tblIter.hasElement()){
792 fkTbl = (TableImpl *) tblIter.nextElement();
793 bool pkRec = isPkTableHasRecord(fkTbl->getName(),fkTbl,true);
794 if(!pkRec){
795 printError(ErrForeignKeyInsert, "Unable to insert into foreign Key table.Check PK table");
796 ((Chunk*)chunkPtr_)->free(db_, tptr);
797 return ErrForeignKeyInsert;
800 tblIter.reset();
802 if (!loadFlag) {
803 //ret = lMgr_->getExclusiveLock(tptr, trans);
804 if (OK != tryExclusiveLock(tptr, trans))
806 ((Chunk*)chunkPtr_)->free(db_, tptr);
807 printError(ret, "Could not get lock for the insert tuple %x", tptr);
808 return ErrLockTimeOut;
812 ret = copyValuesFromBindBuffer(tptr);
813 if (ret != OK)
815 printError(ret, "Unable to copy values from bind buffer");
816 if (!loadFlag) {
817 (*trans)->removeFromHasList(db_, tptr);
818 lMgr_->releaseLock(tptr);
820 ((Chunk*)chunkPtr_)->free(db_, tptr);
821 return ret;
823 int addSize = 0;
824 if (numFlds_ < 31)
826 addSize = 4;
827 *(int*)((char*)(tptr) + (length_-addSize)) = iNullInfo;
829 else
831 addSize = os::align(numFlds_);
832 os::memcpy(((char*)(tptr) + (length_-addSize)), cNullInfo, addSize);
835 //int tupleSize = length_ + addSize;
836 if (NULL != indexPtr_)
838 int i;
839 //it has index
840 for (i = 0; i < numIndexes_ ; i++)
842 ret = insertIndexNode(*trans, indexPtr_[i], idxInfo[i], tptr);
843 if (ret != OK) { printError(ret, "Error in inserting to index %x", tptr); break;}
845 if ( ret != OK)
847 for (int j = 0; j < i ; j++) {
848 printError(ErrWarning, "Undo:Deleting index node");
849 deleteIndexNode(*trans, indexPtr_[j], idxInfo[j], tptr);
851 if (!loadFlag) {
852 (*trans)->removeFromHasList(db_, tptr);
853 lMgr_->releaseLock(tptr);
855 ((Chunk*)chunkPtr_)->free(db_, tptr);
856 return ret;
859 if (!loadFlag)
860 ret = (*trans)->appendUndoLog(sysDB_, InsertOperation, tptr, length_);
861 if (ret != OK) {
862 printError(ret, "Unable to create undo log for %x %d", tptr, *(int*)tptr);
863 for (int j = 0; j < numIndexes_ ; j++) {
864 printError(ErrWarning, "Deleting index node");
865 deleteIndexNode(*trans, indexPtr_[j], idxInfo[j], tptr);
867 if (!loadFlag) {
868 (*trans)->removeFromHasList(db_, tptr);
869 lMgr_->releaseLock(tptr);
871 ((Chunk*)chunkPtr_)->free(db_, tptr);
873 return ret;
876 DbRetVal TableImpl::deleteTuple()
878 if (NULL == curTuple_)
880 printError(ErrNotOpen, "Scan not open: No Current tuple");
881 return ErrNotOpen;
883 if(isPkTbl){
884 TableImpl *fkTbl =NULL;
885 ListIterator tblIter = tblFkList.getIterator();
886 tblIter.reset();
887 while (tblIter.hasElement()){
888 fkTbl = (TableImpl *) tblIter.nextElement();
889 bool pkRec = isFkTableHasRecord(fkTbl->getName(),fkTbl);
890 if(pkRec){
891 printError(ErrForeignKeyDelete, "A Relation Exists. Delete from child table first");
892 return ErrForeignKeyDelete;
895 tblIter.reset();
897 DbRetVal ret = OK;
898 if (!loadFlag) {
899 //ret = lMgr_->getExclusiveLock(curTuple_, trans);
900 if (OK != tryExclusiveLock(curTuple_, trans))
902 printError(ret, "Could not get lock for the delete tuple %x",
903 curTuple_);
904 return ErrLockTimeOut;
908 if (NULL != indexPtr_)
910 int i;
911 //it has index
912 for (i = 0; i < numIndexes_ ; i++)
914 ret = deleteIndexNode(*trans, indexPtr_[i], idxInfo[i], curTuple_);
915 if (ret != OK) break;
917 if (i != numIndexes_ )
919 printError(ErrWarning, "Inserting back index node");
920 for (int j = 0; j < i ; j++)
921 insertIndexNode(*trans, indexPtr_[j], idxInfo[j], curTuple_);
922 if (!loadFlag) {
923 lMgr_->releaseLock(curTuple_);
924 (*trans)->removeFromHasList(db_, curTuple_);
926 printError(ret, "Unable to insert index node for tuple %x", curTuple_);
927 return ret;
930 if (!loadFlag)
931 ret = (*trans)->appendUndoLog(sysDB_, DeleteOperation, curTuple_, 0);
932 if (ret != OK) {
933 printError(ret, "Unable to create undo log for %x ", curTuple_);
934 for (int j = 0; j < numIndexes_ ; j++) {
935 printError(ErrWarning, "Inserting back index node");
936 insertIndexNode(*trans, indexPtr_[j], idxInfo[j], curTuple_);
938 if (!loadFlag) {
939 (*trans)->removeFromHasList(db_, curTuple_);
940 lMgr_->releaseLock(curTuple_);
944 FieldIterator fIter = fldList_.getIterator();
945 char *colPtr = (char*) curTuple_;
946 while (fIter.hasElement()) {
947 FieldDef *def = fIter.nextElement();
948 colPtr = (char *) curTuple_ + def->offset_;
949 if (def->type_ == typeVarchar) {
950 char *ptr = (char *) *(int *) colPtr;
951 ((Chunk *) vcChunkPtr_)->free(db_, ptr);
955 ((Chunk*)chunkPtr_)->free(db_, curTuple_);
957 iter->prev();
958 return ret;
961 int TableImpl::deleteWhere()
963 int tuplesDeleted = 0;
964 DbRetVal rv = OK;
965 rv = execute();
966 if (rv !=OK) return (int) rv;
967 while(true){
968 fetchNoBind( rv);
969 if (rv != OK) { tuplesDeleted = (int)rv; break; }
970 if (NULL == curTuple_) break;
971 rv = deleteTuple();
972 if (rv != OK) {
973 printError(rv, "Error: Could only delete %d tuples", tuplesDeleted);
974 closeScan();
975 return (int) rv;
977 tuplesDeleted++;
979 closeScan();
980 return tuplesDeleted;
983 int TableImpl::truncate()
985 //take exclusive lock on the table
986 //get the chunk ptr of the table
987 //traverse the tablechunks and free all the pages except the first one
988 //get the chunk ptr of all its indexes
989 //traverse the indexchunks and free all the pages except the first one
990 //release table lock
992 //TEMPORARY FIX
993 DbRetVal rv = OK;
994 Predicate* tmpPred = pred_;
995 pred_ = NULL;
996 isPlanCreated = false;
997 int tuplesDeleted = deleteWhere();
998 isPlanCreated = false;
999 pred_ = tmpPred;
1000 return tuplesDeleted;
1003 DbRetVal TableImpl::updateTuple()
1005 if (NULL == curTuple_)
1007 printError(ErrNotOpen, "Scan not open: No Current tuple");
1008 return ErrNotOpen;
1010 if(isFkTbl){
1011 TableImpl *fkTbl =NULL;
1012 ListIterator tblIter = tblList.getIterator();
1013 tblIter.reset();
1014 while (tblIter.hasElement()){
1015 fkTbl = (TableImpl *) tblIter.nextElement();
1016 bool pkRec = isPkTableHasRecord(fkTbl->getName(),fkTbl,false);
1017 if(!pkRec){
1018 printError(ErrForeignKeyInsert, "Unable to insert into foreign Key table.Check PK table");
1019 return ErrForeignKeyInsert;
1022 tblIter.reset();
1025 DbRetVal ret=OK;
1026 if (!loadFlag) {
1027 //ret = lMgr_->getExclusiveLock(curTuple_, trans);
1028 if (OK != tryExclusiveLock(curTuple_, trans))
1030 printError(ret, "Could not get lock for the update tuple %x", curTuple_);
1031 return ErrLockTimeOut;
1034 if (NULL != indexPtr_)
1036 //it has index
1037 //TODO::If it fails while updating index node, we have to undo all the updates
1038 //on other indexes on the table.Currently it will leave the database in an
1039 //inconsistent state.
1040 for (int i = 0; i < numIndexes_ ; i++)
1042 ret = updateIndexNode(*trans, indexPtr_[i], idxInfo[i], curTuple_);
1043 if (ret != OK)
1045 if (!loadFlag) {
1046 lMgr_->releaseLock(curTuple_);
1047 (*trans)->removeFromHasList(db_, curTuple_);
1049 printError(ret, "Unable to update index node for tuple %x", curTuple_);
1050 return ret;
1055 FieldIterator fIter = fldList_.getIterator();
1056 char *colPtr = (char*) curTuple_;
1057 while (fIter.hasElement()) {
1058 FieldDef *def = fIter.nextElement();
1059 colPtr = (char *) curTuple_ + def->offset_;
1060 if (def->type_ == typeVarchar) {
1061 char *ptr = (char *) *(int *) colPtr;
1062 ((Chunk *) vcChunkPtr_)->free(db_, ptr);
1066 if (!loadFlag)
1067 ret = (*trans)->appendUndoLog(sysDB_, UpdateOperation, curTuple_, length_);
1068 if (ret != OK) {
1069 if (!loadFlag) {
1070 lMgr_->releaseLock(curTuple_);
1071 (*trans)->removeFromHasList(db_, curTuple_);
1073 return ret;
1075 int addSize = 0;
1076 int iNullVal=iNullInfo;
1077 if (numFlds_ < 31){
1078 addSize=4;
1079 if(!iNullVal){
1080 iNullInfo = *(int*)((char*)(curTuple_) + (length_- addSize));
1082 else
1084 *(int*)((char*)(curTuple_) + (length_-addSize)) |= iNullInfo;
1087 DbRetVal rv = copyValuesFromBindBuffer(curTuple_, false);
1088 if (rv != OK && !loadFlag) {
1089 lMgr_->releaseLock(curTuple_);
1090 (*trans)->removeFromHasList(db_, curTuple_);
1091 return rv;
1094 if (numFlds_ < 31)
1096 if (!iNullVal) {
1097 *(int*)((char*)(curTuple_) + (length_-addSize)) = iNullInfo;
1098 iNullInfo=0;
1100 else iNullInfo=iNullVal;
1102 else
1104 addSize = os::align(numFlds_);
1105 //TODO::Do not do blind memcpy. It should OR each and every char
1106 int i=0;
1107 char *null=(char*)(curTuple_) + (length_-addSize);
1108 while(i < numFlds_) {
1109 if(cNullInfo[i]) null[i] |= cNullInfo[i];
1110 i++;
1112 //os::memcpy(((char*)(curTuple_) + (length_-addSize)), cNullInfo, addSize);
1116 return OK;
1119 void TableImpl::printInfo()
1121 printf(" <TableName> %s </TableName>\n", tblName_);
1122 printf(" <TupleCount> %d </TupleCount>\n", numTuples());
1123 printf(" <PagesUsed> %d </PagesUsed>\n", pagesUsed());
1124 printf(" <SpaceUsed> %d </SpaceUsed>\n", spaceUsed());
1125 printf(" <Indexes> %d <Indexes>\n", numIndexes_);
1126 printf(" <TupleLength> %d </TupleLength>\n", length_);
1127 printf(" <Fields> %d </Fields>\n", numFlds_);
1128 printf(" <Indexes>\n");
1129 for (int i =0; i<numIndexes_; i++)
1130 printf("<IndexName> %s </IndexName>\n", CatalogTableINDEX::getName(indexPtr_[i]));
1131 printf(" </Indexes>\n");
1135 DbRetVal TableImpl::copyValuesFromBindBuffer(void *tuplePtr, bool isInsert)
1137 //Iterate through the bind list and copy the value here
1138 FieldIterator fIter = fldList_.getIterator();
1139 char *colPtr = (char*) tuplePtr;
1140 int fldpos=1;
1141 while (fIter.hasElement())
1143 FieldDef *def = fIter.nextElement();
1144 if(def->isAutoIncrement_ && isInsert)
1146 void *dest = AllDataType::alloc(def->type_, def->length_);
1147 AllDataType::copyVal(dest,ptrToAuto, def->type_, def->length_);
1148 if(def->bindVal_==NULL)
1150 AllDataType::increment(colPtr, dest , def->type_);
1151 AllDataType::copyVal(ptrToAuto,colPtr, def->type_, def->length_);
1152 colPtr = colPtr + def->length_;
1153 fldpos++;
1154 free(dest);
1155 continue;
1156 }else {
1157 if(AllDataType::compareVal(def->bindVal_, dest, OpGreaterThan, def->type_)){
1158 AllDataType::copyVal(ptrToAuto,def->bindVal_, def->type_, def->length_);
1160 free(dest);
1163 if (def->isNull_ && !def->isDefault_ && NULL == def->bindVal_ && isInsert)
1165 printError(ErrNullViolation, "NOT NULL constraint violation for field %s", def->fldName_);
1166 return ErrNullViolation;
1168 if (def->isDefault_ && NULL == def->bindVal_ && isInsert)
1170 void *dest = AllDataType::alloc(def->type_, def->length_);
1171 AllDataType::convert(typeString, def->defaultValueBuf_, def->type_, dest, def->length_);
1172 AllDataType::copyVal(colPtr, dest, def->type_, def->length_);
1173 colPtr = colPtr + def->length_;
1174 fldpos++;
1175 free (dest);
1176 continue;
1178 switch(def->type_)
1180 case typeString:
1181 if (NULL != def->bindVal_)
1183 if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);}
1184 strncpy((char*)colPtr, (char*)def->bindVal_, def->length_);
1185 *(((char*)colPtr) + (def->length_-1)) = '\0';
1187 else if (!def->isNull_ && !def->bindVal_ && isInsert) setNullBit(fldpos);
1188 colPtr = colPtr + def->length_;
1189 break;
1190 case typeBinary:
1191 if (NULL != def->bindVal_ )
1193 if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);}
1194 DbRetVal rv = AllDataType::strToValue(colPtr, (char *) def->bindVal_, def->type_, def->length_);
1195 if (rv != OK) return ErrBadArg;
1197 else if (!def->isNull_ && isInsert && !def->bindVal_) setNullBit(fldpos);
1198 colPtr = colPtr + def->length_;
1199 break;
1200 case typeVarchar:
1202 DbRetVal rv = OK;
1203 void *ptr =
1204 ((Chunk *) vcChunkPtr_)->allocate(db_, def->length_+1 , &rv);
1205 memset(ptr, 0, def->length_+1);
1206 memcpy(colPtr, &ptr, sizeof(void *));
1207 strcpy((char *)ptr, (char *)def->bindVal_);
1208 colPtr = colPtr + sizeof(void *);
1209 break;
1211 default:
1212 if (NULL != def->bindVal_){
1213 if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);}
1214 AllDataType::copyVal(colPtr, def->bindVal_, def->type_);}
1215 else { if (!def->isNull_ && isInsert) setNullBit(fldpos); }
1216 colPtr = colPtr + def->length_;
1217 break;
1219 fldpos++;
1221 return OK;
1223 void TableImpl::clearNullBit(int fldpos)
1225 if (isIntUsedForNULL){
1226 CLEARBIT(iNullInfo, fldpos);}
1227 else
1228 cNullInfo[fldpos-1] = 0;
1230 void TableImpl::setNullBit(int fldpos)
1232 if (isIntUsedForNULL)
1233 SETBIT(iNullInfo, fldpos);
1234 else
1235 cNullInfo[fldpos-1] = 1;
1237 DbRetVal TableImpl::copyValuesToBindBuffer(void *tuplePtr)
1239 //Iterate through the bind list and copy the value here
1240 char *colPtr = (char*) tuplePtr;
1241 FieldDef *def = NULL;
1242 for (int i = 0; i < numBindFlds_; i++) {
1243 def = (FieldDef *) bindListArray_[i];
1244 colPtr = (char *) tuplePtr + def->offset_;
1245 if (def->type_ != typeVarchar)
1246 AllDataType::copyVal(def->bindVal_, colPtr, def->type_,
1247 def->length_);
1248 else {
1249 char *ptr = (char *) *(int *) colPtr;
1250 strcpy((char *)def->bindVal_, ptr);
1253 return OK;
1256 //-1 index not supported
1257 DbRetVal TableImpl::insertIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple)
1259 CINDEX *iptr = (CINDEX*)indexPtr;
1260 DbRetVal ret = OK;
1261 printDebug(DM_Table, "Inside insertIndexNode type %d", iptr->indexType_);
1262 Index* idx = Index::getIndex(iptr->indexType_);
1263 ret = idx->insert(this, tr, indexPtr, info, tuple,loadFlag);
1264 return ret;
1267 DbRetVal TableImpl::deleteIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple)
1269 CINDEX *iptr = (CINDEX*)indexPtr;
1270 DbRetVal ret = OK;
1271 Index* idx = Index::getIndex(iptr->indexType_);
1272 ret = idx->remove(this, tr, indexPtr, info, tuple, loadFlag);
1273 return ret;
1275 void TableImpl::printSQLIndexString(FILE *fp, int fd)
1277 if (fp == NULL) fp = stdout;
1278 CatalogTableINDEXFIELD cIndexField(sysDB_);
1279 char fName[IDENTIFIER_LENGTH];
1280 char idxName[IDENTIFIER_LENGTH];
1281 char *fldName = fName;
1282 DataType type;
1283 for (int i = 0; i < numIndexes_ ; i++)
1285 CINDEX *iptr = (CINDEX*) indexPtr_[i];
1286 sprintf(idxName,"%s_idx_Auto_increment",getName());
1287 if(strcmp(iptr->indName_,idxName)==0){ continue; }
1288 if (Conf::config.useDurability()) {
1289 struct Object obj;
1290 strcpy(obj.name, iptr->indName_);
1291 if (iptr->indexType_ == hashIndex) {
1292 obj.type = hIdx;
1293 obj.bucketChunk = ((Chunk *)iptr->chunkPtr_)->getFirstPage();
1294 obj.firstPage = ((Chunk *)iptr->hashNodeChunk_)->getFirstPage();
1295 obj.curPage = ((Chunk *)iptr->hashNodeChunk_)->getCurrentPage();
1296 } else if (iptr->indexType_ == treeIndex) {
1297 obj.type = tIdx;
1298 obj.firstPage = ((Chunk *)iptr->chunkPtr_)->getFirstPage();
1299 obj.curPage = ((Chunk *)iptr->chunkPtr_)->getCurrentPage();
1300 long nodes = ((Chunk *)iptr->chunkPtr_)->getTotalDataNodes();
1301 if(nodes) {
1302 ChunkIterator cIter = ((Chunk *)iptr->chunkPtr_)->getIterator();
1303 obj.bucketChunk = cIter.nextElement();
1304 } else obj.bucketChunk = NULL;
1306 void *buf = &obj;
1307 write(fd, buf, sizeof(obj));
1309 fprintf(fp, "CREATE INDEX %s on %s ( ", iptr->indName_, getName());
1310 FieldList fldList;
1311 cIndexField.getFieldInfo(iptr, fldList);
1312 FieldIterator fIter = fldList.getIterator();
1313 bool firstFld = true;
1314 while(fIter.hasElement())
1316 FieldDef *def = fIter.nextElement();
1317 if (firstFld) { fprintf(fp, " %s ", def->fldName_); firstFld = false; }
1318 else fprintf(fp, " ,%s ", def->fldName_);
1320 fldList.removeAll();
1321 fprintf(fp, " ) ");
1322 if (iptr->indexType_ == hashIndex) fprintf(fp, " HASH ");
1323 else fprintf(fp, " TREE ");
1324 if (((HashIndexInfo*) idxInfo[i])->isUnique) fprintf(fp, " UNIQUE");
1325 if(((HashIndexInfo*) idxInfo[i])->noOfBuckets != 1009 ) fprintf(fp, " SIZE %d ",((HashIndexInfo*) idxInfo[i])->noOfBuckets );
1326 fprintf(fp, ";\n");
1331 DbRetVal TableImpl::updateIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple)
1333 CINDEX *iptr = (CINDEX*)indexPtr;
1334 DbRetVal ret = OK;
1335 Index* idx = Index::getIndex(iptr->indexType_);
1336 //TODO::currently it updates irrespective of whether the key changed or not
1337 //because of this commenting the whole index update code. relook at it and uncomment
1339 ret = idx->update(this, tr, indexPtr, info, tuple, loadFlag);
1341 return ret;
1345 void TableImpl::setTableInfo(char *name, int tblid, size_t length,
1346 int numFld, int numIdx, void *chunk, void *vcchunk)
1348 strcpy(tblName_, name);
1349 tblID_ = tblid;
1350 length_ = length;
1351 numFlds_ = numFld;
1352 numIndexes_ = numIdx;
1353 chunkPtr_ = chunk;
1354 vcChunkPtr_ = vcchunk;
1357 long TableImpl::spaceUsed()
1359 Chunk *chk = (Chunk*)chunkPtr_;
1360 long totSize = chk->getTotalDataNodes() * chk->getSize();
1361 totSize = totSize + (chk->totalPages() * sizeof (PageInfo));
1362 return totSize;
1365 int TableImpl::pagesUsed()
1367 Chunk *chk = (Chunk*)chunkPtr_;
1368 return chk->totalPages();
1371 long TableImpl::numTuples()
1373 return ((Chunk*)chunkPtr_)->getTotalDataNodes();
1376 List TableImpl::getFieldNameList()
1378 List fldNameList;
1379 FieldIterator fIter = fldList_.getIterator();
1380 char fieldName[IDENTIFIER_LENGTH];
1381 while (fIter.hasElement())
1383 FieldDef *def = fIter.nextElement();
1384 Identifier *elem = new Identifier();
1385 Table::getFieldNameAlone(def->fldName_, fieldName);
1386 sprintf(elem->name, "%s.%s", getName(), fieldName);
1387 fldNameList.append(elem);
1389 return fldNameList;
1391 DbRetVal TableImpl::close()
1393 if (iter) { iter->close(); delete iter; iter = NULL; }
1394 TableImpl *fkTbl =NULL;
1395 ListIterator tblIter = tblList.getIterator();
1396 tblIter.reset();
1397 while (tblIter.hasElement()){
1398 fkTbl = (TableImpl *) tblIter.nextElement();
1399 fkTbl->close();
1401 tblList.reset();
1402 tblIter = tblFkList.getIterator();
1403 tblIter.reset();
1404 while (tblIter.hasElement()){
1405 fkTbl = (TableImpl *) tblIter.nextElement();
1406 fkTbl->close();
1408 tblFkList.reset();
1409 printDebug(DM_Database,"Closing table handle: %x", this);
1410 //table->unlock();
1411 //delete pred_;
1412 ListIterator pIter = predList.getIterator();
1413 while (pIter.hasElement())
1415 PredicateImpl *pImpl = (PredicateImpl*) pIter.nextElement();
1416 delete pImpl;
1418 predList.reset();
1419 delete this;
1420 logFinest(Conf::logger, "Closing Table");
1421 return OK;
1424 DbRetVal TableImpl::closeScan()
1426 //do not throw scan not open error
1427 //this function will be called by table handle
1428 if (iter) {
1429 iter->close();
1431 return OK;
1433 DbRetVal TableImpl::lock(bool shared)
1436 DbRetVal ret = OK;
1438 if (shared)
1439 ret = lMgr_->getSharedLock(chunkPtr_, NULL);
1440 else
1441 ret = lMgr_->getExclusiveLock(chunkPtr_, NULL);
1442 if (OK != ret)
1444 printError(ret, "Could not exclusive lock on the table %x", chunkPtr_);
1445 }else {
1446 //do not append for S to X upgrade
1447 if (!ProcessManager::hasLockList.exists(chunkPtr_))
1448 ProcessManager::hasLockList.append(chunkPtr_);
1451 return ret;
1453 DbRetVal TableImpl::unlock()
1456 if (!ProcessManager::hasLockList.exists(chunkPtr_)) return OK;
1457 DbRetVal ret = lMgr_->releaseLock(chunkPtr_);
1458 if (OK != ret)
1460 printError(ret, "Could not release exclusive lock on the table %x", chunkPtr_);
1461 }else
1463 ProcessManager::hasLockList.remove(chunkPtr_);
1466 return OK;
1469 TableImpl::~TableImpl()
1471 if (NULL != iter ) { delete iter; iter = NULL; }
1472 if (NULL != indexPtr_) { delete[] indexPtr_; indexPtr_ = NULL; }
1473 if (NULL != idxInfo)
1475 for (int i = 0; i < numIndexes_; i++) delete idxInfo[i];
1476 delete[] idxInfo;
1477 idxInfo = NULL;
1479 if (numFlds_ > 31 && cNullInfo != NULL) { free(cNullInfo); cNullInfo = NULL; }
1480 if (bindList_.size()) bindList_.reset();
1481 if (bindListArray_) { free (bindListArray_); bindListArray_ = NULL; }
1482 fldList_.removeAll();
1486 void *TableImpl::getBindFldAddr(const char *name)
1488 return fldList_.getBindField(name);
1490 bool TableImpl::isTableInvolved(char *tblName)
1492 //printf("Table isTableInvolved called for %s with %s\n", tblName, getName());
1493 if (0 == strcmp(getName(), tblName)) return true; else return false;
1495 bool TableImpl::pushPredicate(Predicate *pred)
1497 bool ret = false;
1498 PredicateImpl *pImpl = (PredicateImpl*) pred;
1499 char tableName[IDENTIFIER_LENGTH];
1500 Table::getTableNameAlone(pImpl->getFldName1(), tableName);
1501 //printf("predicate tbl name %s\n", tableName);
1503 //if predicate is of form t1.f1=t2.f1 then do not push here
1504 bool isAliasSet = (0 !=strcmp(getAliasName(),"")) ;
1505 if (0 != strcmp(pImpl->getFldName2(),"")) return ret;
1507 if (0 == strcmp(getName(), tableName) ||(isAliasSet && 0 == strcmp(getAliasName(), tableName)))
1509 setPredicate(pred);
1510 //printf("PRABA::pushed predicate in tablehdl %s\n", getName());
1511 ret = true;
1513 return ret;
1516 void TableImpl::setCondition(Condition *p)
1518 isPlanCreated = false;
1519 ListIterator pIter = predList.getIterator();
1520 while (pIter.hasElement())
1522 PredicateImpl *pImpl = (PredicateImpl*) pIter.nextElement();
1523 delete pImpl;
1525 predList.reset();
1527 if (p) pred_ = p->getPredicate(); else pred_ = NULL;
1530 void TableImpl::setPredicate(Predicate *pred)
1532 if (NULL == pred_) { pred_ = pred; return; }
1534 Predicate *curPred = pred_;
1535 PredicateImpl *newPred = new PredicateImpl();
1536 newPred->setTerm(curPred, OpAnd, pred);
1537 newPred->setTable(this);
1538 pred_ = newPred;
1539 return;
1541 void TableImpl::printPlan(int space)
1543 char spaceBuf[IDENTIFIER_LENGTH];
1544 memset(spaceBuf, 32, IDENTIFIER_LENGTH);
1545 spaceBuf[space] = '\0';
1546 printf("%s <TABLE-NODE>\n", spaceBuf);
1547 printf("%s <NAME> %s </NAME>\n", spaceBuf, getName());
1548 printf("%s <ScanType> %s </ScanType>\n", spaceBuf, ScanTypeNames[scanType_]);
1549 PredicateImpl *pred = (PredicateImpl*)pred_;
1550 if (pred) pred->print(space+2);
1551 printf("%s </TABLE-NODE>\n", spaceBuf);
1553 void TableImpl::printSQLForeignString()
1555 DbRetVal rv=OK;
1556 FieldNameList pkFieldList,fkFieldList;
1557 void *tPkptr =NULL;
1558 void *tFkptr = NULL;
1559 void *chunkPk = NULL;
1560 void *vcchunkPk = NULL;
1561 CatalogTableTABLE cTable(sysDB_);
1562 TableImpl *fkTbl =NULL;
1563 ListIterator tblIter = tblList.getIterator();
1564 tblIter.reset();
1565 int firstFK=true;
1566 while (tblIter.hasElement()){
1567 fkTbl = (TableImpl *) tblIter.nextElement();
1568 rv = cTable.getChunkAndTblPtr(fkTbl->getName(), chunkPk, tPkptr, vcchunkPk );
1569 if ( OK != rv){return ;}
1570 rv = cTable.getChunkAndTblPtr(getName(), chunkPk, tFkptr, vcchunkPk);
1571 if ( OK != rv){return ;}
1572 CatalogTableFK cFk(sysDB_);
1573 rv = cFk.getPkFkFieldInfo(tPkptr,tFkptr,pkFieldList,fkFieldList);
1574 if ( OK != rv){return;}
1575 pkFieldList.resetIter();
1576 fkFieldList.resetIter();
1577 char *fldName = NULL;
1578 bool firstField=true;
1579 if(!firstFK) printf(", ");
1580 printf(", FOREIGN KEY ( ");
1581 while((fldName = fkFieldList.nextFieldName())!= NULL)
1583 if (firstField) {
1584 printf("%s",fldName);
1585 firstField=false;
1587 else
1588 printf(",%s",fldName);
1590 printf(" ) REFERENCES %s ( ",fkTbl->getName());
1591 firstField=true;
1592 while((fldName = pkFieldList.nextFieldName())!= NULL)
1594 if (firstField) {
1595 printf("%s",fldName);
1596 firstField=false;
1598 else
1599 printf(",%s",fldName);
1601 printf(" )");
1602 firstFK=true;
1603 pkFieldList.removeAll();
1604 fkFieldList.removeAll();
1606 return;
1608 bool TableImpl::isPkTableHasRecord(char *pkTableName, TableImpl *fkTbl,bool isInsert)
1610 DbRetVal rv=OK;
1611 bool isRecExist=false;
1612 FieldNameList pkFieldList,fkFieldList;
1613 void *tPkptr =NULL;
1614 void *tFkptr = NULL;
1615 void *chunkPk = NULL;
1616 void *vcchunkPk = NULL;
1617 CatalogTableTABLE cTable(sysDB_);
1618 rv = cTable.getChunkAndTblPtr(pkTableName, chunkPk, tPkptr, vcchunkPk);
1619 if ( OK != rv){return false;}
1620 rv = cTable.getChunkAndTblPtr(getName(), chunkPk, tFkptr, vcchunkPk);
1621 if ( OK != rv){return false;}
1622 CatalogTableFK cFk(sysDB_);
1623 rv = cFk.getPkFkFieldInfo(tPkptr,tFkptr,pkFieldList,fkFieldList);
1624 if ( OK != rv){return false;}
1625 int totFld = pkFieldList.size();
1626 Condition *condition = new Condition[totFld];
1627 char *pkFldName = NULL;
1628 char *fkFldName = NULL;
1629 FieldDef *def=NULL;
1630 int i=0;
1631 pkFieldList.resetIter();
1632 fkFieldList.resetIter();
1633 void *val=NULL;
1634 while((pkFldName = pkFieldList.nextFieldName())!= NULL)
1636 fkFldName = fkFieldList.nextFieldName();
1637 FieldIterator fIter = fldList_.getIterator();
1638 while (fIter.hasElement())
1640 def = fIter.nextElement();
1641 if (strcmp(def->fldName_, fkFldName) == 0)
1643 if(NULL == def->bindVal_ && isInsert) { return true; }
1644 if(NULL == def->bindVal_) {
1645 val = (char*)curTuple_+ def->offset_;
1646 } else {
1647 val = def->bindVal_;
1649 if(def->type_==typeString)
1650 condition[i].setTerm(pkFldName,OpEquals,&val);
1651 else
1652 condition[i].setTerm(pkFldName,OpEquals,val);
1653 i++;
1654 break;
1658 pkFieldList.removeAll();
1659 fkFieldList.removeAll();
1660 Condition *cond = NULL;
1661 if(i == 0 && !isInsert)return true;
1662 if( i > 1){
1663 cond = new Condition[i-1];
1664 int totcon = i;
1665 i=0;
1666 int j=0;
1667 for(j=0;j<totcon-1;j++)
1669 if(j==0)
1670 cond[j].setTerm(condition[i++].getPredicate(),OpAnd,condition[i++].getPredicate());
1671 else
1672 cond[j].setTerm(cond[j-1].getPredicate(), OpAnd, condition[i++].getPredicate());
1674 fkTbl->setCondition(&cond[j-1]);
1676 else{
1677 fkTbl->setCondition(&condition[i-1]);
1679 fkTbl->execute();
1680 if(fkTbl->fetch()){
1681 fkTbl->closeScan();
1682 delete[] cond;
1683 delete[] condition;
1684 return true;
1686 delete[] cond;
1687 delete[] condition;
1688 return false;
1691 bool TableImpl::isFkTableHasRecord(char *pkTableName, TableImpl *fkTbl)
1693 DbRetVal rv=OK;
1694 FieldNameList pkFieldList,fkFieldList;
1695 void *tPkptr =NULL;
1696 void *tFkptr = NULL;
1697 void *chunkPk = NULL;
1698 void *vcchunkPk = NULL;
1699 CatalogTableTABLE cTable(sysDB_);
1700 rv = cTable.getChunkAndTblPtr(getName(), chunkPk, tPkptr, vcchunkPk);
1701 if ( OK != rv){return false;}
1702 rv = cTable.getChunkAndTblPtr(pkTableName, chunkPk, tFkptr, vcchunkPk);
1703 if ( OK != rv){return false;}
1704 CatalogTableFK cFk(sysDB_);
1705 rv = cFk.getPkFkFieldInfo(tPkptr,tFkptr,pkFieldList,fkFieldList);
1706 if ( OK != rv){return false;}
1707 int totFld = pkFieldList.size();
1708 Condition *condition = new Condition[totFld];
1709 char *pkFldName = NULL;
1710 char *fkFldName = NULL;
1711 FieldDef *def=NULL;
1712 int i=0;
1713 pkFieldList.resetIter();
1714 fkFieldList.resetIter();
1715 while((pkFldName = pkFieldList.nextFieldName())!= NULL)
1717 fkFldName = fkFieldList.nextFieldName();
1718 FieldIterator fIter = fldList_.getIterator();
1719 while (fIter.hasElement())
1721 def = fIter.nextElement();
1722 void *val = (char*)curTuple_+ def->offset_;
1723 if (strcmp(def->fldName_, pkFldName) == 0)
1725 if(def->type_==typeString)
1726 condition[i].setTerm(fkFldName,OpEquals,&val);//((char*)curTuple_+def->offset_));
1727 else
1728 condition[i].setTerm(fkFldName,OpEquals,val);//((char*)curTuple_+def->offset_));
1729 i++;
1730 break;
1734 pkFieldList.removeAll();
1735 fkFieldList.removeAll();
1736 if(i == 0 )return true;
1737 Condition *cond = new Condition[i-1];
1738 i=0;
1739 int j=0;
1740 for(j=0;j<totFld-1;j++)
1742 if(j==0)
1743 cond[j].setTerm(condition[i++].getPredicate(),OpAnd,condition[i++].getPredicate());
1744 else
1745 cond[j].setTerm(cond[j-1].getPredicate(), OpAnd, condition[i++].getPredicate());
1747 if(totFld==1)
1748 fkTbl->setCondition(&condition[totFld-1]);
1749 else
1750 fkTbl->setCondition(&cond[j-1]);
1751 fkTbl->execute();
1752 if(fkTbl->fetch()){
1753 fkTbl->closeScan();
1754 delete[] cond;
1755 delete[] condition;
1756 return true;
1758 delete[] cond;
1759 delete[] condition;
1760 return false;
1762 DbRetVal TableImpl::compact()
1764 DbRetVal rv=OK;
1765 int ret =((Chunk*)chunkPtr_)->compact(db_->procSlot);
1766 if(ret!=0){
1767 return ErrLockTimeOut;
1769 if (NULL != indexPtr_)
1771 int i;
1772 //it has index
1773 for (i = 0; i < numIndexes_ ; i++)
1775 rv = compactIndexNode(indexPtr_[i]);
1776 if (rv != OK) { printError(rv, "Error in compacting index Node"); break;}
1779 return rv;
1782 DbRetVal TableImpl::compactIndexNode( void *indexPtr)
1784 CINDEX *iptr = (CINDEX*)indexPtr;
1785 int ret1=0;
1786 printDebug(DM_Table, "Inside insertIndexNode type %d", iptr->indexType_);
1787 if( hashIndex == (iptr->indexType_) )
1789 ret1 =((Chunk*)iptr->hashNodeChunk_)->compact(db_->procSlot);
1790 if(ret1!=0){
1791 return ErrLockTimeOut;
1793 }else
1795 ret1 =((Chunk*)iptr->chunkPtr_)->compact(db_->procSlot);
1796 if(ret1!=0){
1797 return ErrLockTimeOut;
1800 return OK;