Varchar free when compact table was called.
[csql.git] / src / storage / TableImpl.cxx
blob9c08277558df67a0a992d0da3ad481faf1d2b918
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, bool isNullExpl)
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, isNullExpl);
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, timeval;
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 timeval.tv_sec = timeout.tv_sec;
437 timeval.tv_usec = timeout.tv_usec;
438 os::select(0, 0, 0, 0, &timeval);
440 if (tries == 0)
442 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
443 curTuple_ = prevTuple;
444 return NULL;
447 else if ((*trans)->isoLevel_ == READ_REPEATABLE) {
448 if (OK != trySharedLock(curTuple_, trans))
450 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
451 curTuple_ = prevTuple;
452 return NULL;
457 return curTuple_;
459 DbRetVal TableImpl::trySharedLock(void *curTuple, Transaction **trans)
461 DbRetVal lockRet = OK;
462 int tries = Conf::config.getMutexRetries();
463 while((lockRet = lMgr_->getSharedLock(curTuple_, trans)) == ErrLockTimeOut)
465 tries--;
466 if (tries <=0) break;
468 return lockRet;
470 DbRetVal TableImpl::tryExclusiveLock(void *curTuple, Transaction **trans)
472 DbRetVal lockRet = OK;
473 int tries = Conf::config.getMutexRetries();
474 while((lockRet = lMgr_->getExclusiveLock(curTuple_, trans)) == ErrLockTimeOut)
476 tries--;
477 if (tries <=0) break;
479 return lockRet;
482 void* TableImpl::fetchNoBind(DbRetVal &rv)
484 rv = OK;
485 if (NULL == iter)
487 printError(ErrNotOpen,"Scan not open or Scan is closed\n");
488 rv = ErrNotOpen;
489 return NULL;
491 void *prevTuple = curTuple_;
492 curTuple_ = iter->next();
493 if (NULL == curTuple_)
495 return NULL;
497 DbRetVal lockRet = OK;
498 if (!loadFlag) {
499 if ((*trans)->isoLevel_ == READ_REPEATABLE) {
500 lockRet = lMgr_->getSharedLock(curTuple_, trans);
501 if (OK != lockRet)
503 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
504 rv = ErrLockTimeOut;
505 curTuple_ = prevTuple;
506 return NULL;
510 else if ((*trans)->isoLevel_ == READ_COMMITTED)
512 //if iso level is read committed, operation duration lock is sufficent
513 //so release it here itself.
514 int tries = Conf::config.getMutexRetries();
515 //struct timeval timeout;
516 //timeout.tv_sec = Conf::config.getMutexSecs();
517 //timeout.tv_usec = Conf::config.getMutexUSecs();
519 bool status = false;
520 while(true) {
521 lockRet = lMgr_->isExclusiveLocked( curTuple_, trans, status);
522 if (OK != lockRet)
524 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
525 curTuple_ = prevTuple;
526 rv = ErrLockTimeOut;
527 return NULL;
529 if (!status) break;
530 tries--;
531 if (tries == 0) break;
532 //os::select(0, 0, 0, 0, &timeout);
534 if (tries == 0)
536 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
537 curTuple_ = prevTuple;
538 rv = ErrLockTimeOut;
539 return NULL;
543 return curTuple_;
545 DbRetVal TableImpl::fetchAgg(const char * fldName, AggType aType, void *buf, bool &noRec)
547 FieldInfo *info = new FieldInfo();
548 DbRetVal rv = getFieldInfo(fldName, info);
549 if (OK != rv) return rv;
550 bool res= false;
551 if (AGG_MIN == aType || AGG_MAX == aType) {
552 int pos =0;
553 IndexType iType = getIndexType((char*)fldName, &pos);
554 if(treeIndex == iType && pos >=0) {
555 if (AGG_MIN == aType) {
556 HashIndexInfo* hInfo = (HashIndexInfo*) idxInfo[pos];
557 CINDEX *iptr = (CINDEX*) hInfo->indexPtr;
558 TreeNode *fstNode=(TreeNode *)iptr->hashNodeChunk_;
559 TreeIter *iter=NULL;
560 if(fstNode!=NULL){
561 TreeNode *start = (TreeNode *)*((char**)((char*)fstNode + sizeof(TreeNode)));
562 iter = new TreeIter(start,(TreeNode*)iptr->hashNodeChunk_,sysDB_->procSlot);
563 }else{
564 iter = new TreeIter(NULL,(TreeNode*)iptr->hashNodeChunk_,sysDB_->procSlot);
566 char *tuple = (char*) iter->getFirstElement();
567 if (tuple != NULL) {
568 AllDataType::copyVal(buf,(void*)(tuple+info->offset),
569 info->type, info->length);
570 delete iter;
571 return OK;
573 delete iter; iter = NULL;
575 else if (AGG_MAX == aType) {
576 HashIndexInfo* hInfo = (HashIndexInfo*) idxInfo[pos];
577 CINDEX *iptr = (CINDEX*) hInfo->indexPtr;
578 TreeNode *fstNode=(TreeNode *)iptr->hashNodeChunk_;
579 TreeIter *iter=NULL;
580 if(fstNode!=NULL){
581 TreeNode *start = (TreeNode *)*((char**)((char*)fstNode + sizeof(TreeNode)));
582 iter = new TreeIter(start,(TreeNode*)iptr->hashNodeChunk_,sysDB_->procSlot);
583 }else{
584 iter = new TreeIter(NULL,(TreeNode*)iptr->hashNodeChunk_,sysDB_->procSlot);
586 char *tuple = (char*) iter->getLastElement();
587 if (tuple != NULL) {
588 AllDataType::copyVal(buf,(void*)(tuple+info->offset),
589 info->type, info->length);
590 delete iter; iter = NULL;
591 return OK;
593 delete iter; iter=NULL;
596 }else if (AGG_COUNT == aType) {
597 (*(int*)buf) = 0;
601 DataType type = info->type;
602 int length = info->length;
603 int offset = info->offset;
604 int colPos = fldList_.getFieldPosition(fldName);
605 bool isNullable= true;
606 if (info->isNull || info->isPrimary || info->isDefault || info->isAutoIncrement) {
607 isNullable = false;
609 int nullOffset = length_-4;
610 if (aType == AGG_COUNT) {
611 length = sizeof(int);
612 type = typeInt;
614 if (NULL == pred_ && typeInt == type && aType != AGG_AVG)
615 { //perf opt
616 ChunkIterator cIter = ((Chunk*)chunkPtr_)->getIterator();
617 char *tuple =(char*)cIter.nextElement();
618 if (NULL == tuple) {
619 *(int *) buf = 0;
620 noRec = true;
621 return OK;
623 int count =1;
624 if (isNullable) {
625 if (isIntUsedForNULL) {
626 if (BITSET(*(int*)(tuple+nullOffset), colPos)) count =0;
628 else {
629 curTuple_= tuple;
630 if(isFldNull(colPos)) count =0;
633 if (aType != AGG_COUNT)
634 AllDataType::copyVal(buf, (void*) (tuple+offset), type, length);
635 void *prev=NULL;
636 prev = curTuple_;
637 cIter.pageSize = PAGE_SIZE;
638 while(1)
640 tuple = (char*)cIter.nextElementInt();
641 if (NULL == tuple) break;
642 if (isNullable) {
643 if (isIntUsedForNULL) {
644 if (BITSET(*(int*)(tuple+nullOffset), colPos)) continue;
646 else {
647 curTuple_= tuple;
648 if(isFldNull(colPos)) continue;
651 if (aType == AGG_MIN)
653 if (*(int*)buf >= *((int*)(tuple+offset)))
654 *(int*)buf = *((int*)(tuple+offset));
656 else if (aType == AGG_MAX)
658 if (*(int*)buf <= *((int*)(tuple+offset)))
659 *(int*)buf = *((int*)(tuple+offset));
661 else if (aType == AGG_SUM)
663 *(int*)buf += *((int*)(tuple+offset));
665 else if (aType == AGG_AVG)
667 *(int*)buf = *(int*)buf + *((int*)(tuple+offset));
668 count++;
670 else if (aType == AGG_COUNT)
672 count++;
675 curTuple_= prev;
676 if( AGG_AVG == aType) AllDataType::divVal(buf, &count, type);
677 else if (AGG_COUNT == aType) (*(int*)buf) = count;
678 delete info;
679 return OK;
682 char *tuple = (char*) fetchNoBind(rv);
683 if ( NULL == tuple) { noRec = true; return OK; }
684 int count =1;
686 while(isFldNull(colPos)) {
687 tuple= (char*) fetchNoBind(rv);
688 if (aType == AGG_COUNT) count++;
689 if (tuple) break;
691 if ( NULL == tuple) { noRec = true; return OK; }
693 if (aType == AGG_AVG) {
694 AllDataType::convertToDouble(buf, (void*) (tuple+offset), type);
695 } else if (aType != AGG_COUNT) {
696 AllDataType::copyVal(buf, (void*) (tuple+offset), type, length);
698 while(1) {
699 tuple = (char*) fetchNoBind(rv);
700 if (NULL == tuple) break;
701 if (isNullable) {
702 if (isIntUsedForNULL) {
703 if (BITSET(*(int*)(tuple+nullOffset), colPos)) continue;
705 else {
706 curTuple_= tuple;
707 if(isFldNull(colPos)) continue;
710 switch(aType) {
711 case AGG_MIN:
713 res = AllDataType::compareVal(buf, (void*) (tuple+offset),
714 OpGreaterThanEquals,
715 type, length);
716 if (res) AllDataType::copyVal(buf, (void*) (tuple+offset),
717 type, length);
718 break;
720 case AGG_MAX:
722 res = AllDataType::compareVal(buf, (void*) (tuple+offset),
723 OpLessThanEquals,
724 type, length);
725 if (res) AllDataType::copyVal(buf, (void*) (tuple+offset),
726 type, length);
727 break;
729 case AGG_SUM:
731 AllDataType::addVal(buf, (void*) (tuple+offset),
732 type);
733 break;
735 case AGG_AVG:
737 double tmpBuf=0.0;
738 AllDataType::convertToDouble(&tmpBuf, (void*) (tuple+offset), type);
739 AllDataType::addVal(buf, &tmpBuf, typeDouble);
740 count++;
741 break;
743 case AGG_COUNT:
745 count++;
746 break;
750 switch(aType) {
751 case AGG_AVG:
753 AllDataType::divVal((double *)buf, count, type);
754 break;
756 case AGG_COUNT:
758 (*(int*)buf) = count;
759 break;
762 delete info;
763 return OK;
765 DbRetVal TableImpl::getCheckpointMutex()
767 int tries=0;
768 DbRetVal rv = OK;
769 int totalTries = Conf::config.getMutexRetries();
770 struct timeval timeout, timeval;
771 timeout.tv_sec = Conf::config.getMutexSecs();
772 timeout.tv_usec = Conf::config.getMutexUSecs();
774 while (tries < totalTries)
776 rv = sysDB_->getSCheckpointMutex();
777 if (OK == rv) break;
778 timeval.tv_sec = timeout.tv_sec;
779 timeval.tv_usec = timeout.tv_usec;
780 os::select(0,0,0,0,&timeval);
781 tries++;
783 if (tries == totalTries) {
784 printError(ErrLockTimeOut, "Checkpoint server is running. Retry after sometime.");
785 return ErrLockTimeOut;
787 return OK;
789 DbRetVal TableImpl::insertTuple()
791 DbRetVal ret = getCheckpointMutex();
792 if (ret !=OK) return ret;
793 void *tptr = NULL;
794 int tries=0;
795 int totalTries = Conf::config.getMutexRetries();
796 while (tries < totalTries)
798 ret = OK;
799 tptr = ((Chunk*)chunkPtr_)->allocate(db_, &ret);
800 if (tptr !=NULL) break;
801 if (ret != ErrLockTimeOut)
803 sysDB_->releaseCheckpointMutex();
804 printError(ret, "Unable to allocate record from chunk");
805 return ret;
807 tries++;
809 if (NULL == tptr)
811 sysDB_->releaseCheckpointMutex();
812 printError(ret, "Unable to allocate record from chunk after %d retries", tries);
813 return ret;
815 curTuple_ = tptr;
816 if(isFkTbl){
817 TableImpl *fkTbl =NULL;
818 ListIterator tblIter = tblList.getIterator();
819 tblIter.reset();
820 while (tblIter.hasElement()){
821 fkTbl = (TableImpl *) tblIter.nextElement();
822 bool pkRec = isPkTableHasRecord(fkTbl->getName(),fkTbl,true);
823 if(!pkRec){
824 printError(ErrForeignKeyInsert, "Unable to insert into foreign Key table.Check PK table");
825 ((Chunk*)chunkPtr_)->free(db_, tptr);
826 sysDB_->releaseCheckpointMutex();
827 return ErrForeignKeyInsert;
830 tblIter.reset();
832 if (!loadFlag) {
833 //ret = lMgr_->getExclusiveLock(tptr, trans);
834 if (OK != tryExclusiveLock(tptr, trans))
836 ((Chunk*)chunkPtr_)->free(db_, tptr);
837 printError(ret, "Could not get lock for the insert tuple %x", tptr);
838 sysDB_->releaseCheckpointMutex();
839 return ErrLockTimeOut;
843 ret = copyValuesFromBindBuffer(tptr);
844 if (ret != OK)
846 printError(ret, "Unable to copy values from bind buffer");
847 if (!loadFlag) {
848 (*trans)->removeFromHasList(db_, tptr);
849 lMgr_->releaseLock(tptr);
852 FieldIterator fIter = fldList_.getIterator();
853 char *colPtr = (char*) curTuple_;
854 while (fIter.hasElement()) {
855 FieldDef *def = fIter.nextElement();
856 colPtr = (char *) curTuple_ + def->offset_;
857 if (def->type_ == typeVarchar) {
858 char *ptr = (char *) *(long *) colPtr;
859 if (ptr != 0L) ((Chunk *) vcChunkPtr_)->free(db_, ptr);
862 ((Chunk*)chunkPtr_)->free(db_, tptr);
863 sysDB_->releaseCheckpointMutex();
864 return ret;
866 int addSize = 0;
867 if (numFlds_ < 31)
869 addSize = 4;
870 *(int*)((char*)(tptr) + (length_-addSize)) = iNullInfo;
872 else
874 addSize = os::align(numFlds_);
875 os::memcpy(((char*)(tptr) + (length_-addSize)), cNullInfo, addSize);
878 //int tupleSize = length_ + addSize;
879 if (NULL != indexPtr_)
881 int i;
882 //it has index
883 for (i = 0; i < numIndexes_ ; i++)
885 ret = insertIndexNode(*trans, indexPtr_[i], idxInfo[i], tptr);
886 if (ret != OK) { printError(ret, "Error in inserting to index %x", tptr); break;}
888 if ( ret != OK)
890 for (int j = 0; j < i ; j++) {
891 printError(ErrWarning, "Undo:Deleting index node");
892 deleteIndexNode(*trans, indexPtr_[j], idxInfo[j], tptr);
894 if (!loadFlag) {
895 (*trans)->removeFromHasList(db_, tptr);
896 lMgr_->releaseLock(tptr);
899 FieldIterator fIter = fldList_.getIterator();
900 char *colPtr = (char*) curTuple_;
901 while (fIter.hasElement()) {
902 FieldDef *def = fIter.nextElement();
903 colPtr = (char *) curTuple_ + def->offset_;
904 if (def->type_ == typeVarchar) {
905 char *ptr = (char *) *(long *) colPtr;
906 if (ptr != 0L) ((Chunk *) vcChunkPtr_)->free(db_, ptr);
909 ((Chunk*)chunkPtr_)->free(db_, tptr);
910 sysDB_->releaseCheckpointMutex();
911 return ret;
914 if (!loadFlag) {
915 //TODO: number of varchar fields to be stored as a member in TableImpl
916 int nVarchars = 0;
917 FieldIterator fIter = fldList_.getIterator();
918 while (fIter.hasElement()) {
919 FieldDef *def = fIter.nextElement();
920 if (def->type_ == typeVarchar) nVarchars++;
923 // the undo log for insert should contain
924 // tuple ptr + metadata Ptr + no of varchars + ptrs to varchars for insert opearation
925 int size = (3 + nVarchars) * sizeof(void *) + sizeof(int);
926 void *data = malloc(size);
927 char *ptr = (char *)data;
928 *(long *) ptr = (long) tptr; ptr += sizeof(void *);
929 void *metaData = db_->getMetaDataPtr();
930 *(long *) ptr = (long) metaData; ptr += sizeof(void *);
931 *(int *) ptr = nVarchars; ptr += sizeof(int);
932 *(long *) ptr = (long) vcChunkPtr_; ptr += sizeof(void *);
933 fIter = fldList_.getIterator();
934 char *colPtr = (char*) curTuple_;
935 while (fIter.hasElement()) {
936 FieldDef *def = fIter.nextElement();
937 colPtr = (char *) curTuple_ + def->offset_;
938 if (def->type_ == typeVarchar) {
939 *(long *) ptr = (long)colPtr;
940 ptr += sizeof(void *);
943 ret = (*trans)->appendUndoLog(sysDB_, InsertOperation, data, size);
944 ::free(data);
946 if (ret != OK) {
947 printError(ret, "Unable to create undo log for %x %d", tptr, *(int*)tptr);
948 for (int j = 0; j < numIndexes_ ; j++) {
949 printError(ErrWarning, "Deleting index node");
950 deleteIndexNode(*trans, indexPtr_[j], idxInfo[j], tptr);
952 if (!loadFlag) {
953 (*trans)->removeFromHasList(db_, tptr);
954 lMgr_->releaseLock(tptr);
956 ((Chunk*)chunkPtr_)->free(db_, tptr);
958 sysDB_->releaseCheckpointMutex();
959 return ret;
962 DbRetVal TableImpl::deleteTuple()
964 if (NULL == curTuple_)
966 printError(ErrNotOpen, "Scan not open: No Current tuple");
967 return ErrNotOpen;
969 DbRetVal ret = getCheckpointMutex();
970 if (ret != OK) return ret;
971 if(isPkTbl){
972 TableImpl *fkTbl =NULL;
973 ListIterator tblIter = tblFkList.getIterator();
974 tblIter.reset();
975 while (tblIter.hasElement()){
976 fkTbl = (TableImpl *) tblIter.nextElement();
977 bool pkRec = isFkTableHasRecord(fkTbl->getName(),fkTbl);
978 if(pkRec){
979 printError(ErrForeignKeyDelete, "A Relation Exists. Delete from child table first");
980 sysDB_->releaseCheckpointMutex();
981 return ErrForeignKeyDelete;
984 tblIter.reset();
986 if (!loadFlag) {
987 //ret = lMgr_->getExclusiveLock(curTuple_, trans);
988 if (OK != tryExclusiveLock(curTuple_, trans))
990 printError(ret, "Could not get lock for the delete tuple %x",
991 curTuple_);
992 sysDB_->releaseCheckpointMutex();
993 return ErrLockTimeOut;
997 if (NULL != indexPtr_)
999 int i;
1000 //it has index
1001 for (i = 0; i < numIndexes_ ; i++)
1003 ret = deleteIndexNode(*trans, indexPtr_[i], idxInfo[i], curTuple_);
1004 if (ret != OK) break;
1006 if (i != numIndexes_ )
1008 printError(ErrWarning, "Inserting back index node");
1009 for (int j = 0; j < i ; j++)
1010 insertIndexNode(*trans, indexPtr_[j], idxInfo[j], curTuple_);
1011 if (!loadFlag) {
1012 lMgr_->releaseLock(curTuple_);
1013 (*trans)->removeFromHasList(db_, curTuple_);
1015 printError(ret, "Unable to insert index node for tuple %x", curTuple_);
1016 sysDB_->releaseCheckpointMutex();
1017 return ret;
1020 if (!loadFlag) {
1021 // the undo log for delete should contain
1022 // tupleptr + metadataPtr + nVarchars + varchar chunk ptr +
1023 // ptrs to varchars + size and value pairs for varchars
1025 //TODO: number of varchar fields to be stored as a member in TableImpl
1026 void *tptr = curTuple_;
1027 char *colPtr = (char *)curTuple_;
1028 int nVarchars = 0;
1029 int vcLenValPairSize = 0;
1030 FieldIterator fIter = fldList_.getIterator();
1031 while (fIter.hasElement()) {
1032 FieldDef *def = fIter.nextElement();
1033 colPtr = (char *) curTuple_ + def->offset_;
1034 if (def->type_ == typeVarchar) {
1035 nVarchars++;
1036 if (* (long *) colPtr == 0L)
1037 vcLenValPairSize = vcLenValPairSize + sizeof(int);
1038 else vcLenValPairSize = vcLenValPairSize + sizeof(int) +
1039 + os::align(strlen((char *) *(long *)colPtr) + 1);
1042 int size = (3 + nVarchars) * sizeof(void *) + sizeof(int)
1043 + vcLenValPairSize;
1044 void *data = malloc(size);
1045 char *ptr = (char *)data;
1046 *(long *) ptr = (long) tptr; ptr += sizeof(void *);
1047 void *metaData = db_->getMetaDataPtr();
1048 *(long *) ptr = (long) metaData; ptr += sizeof(void *);
1049 *(int *) ptr = nVarchars; ptr += sizeof(int);
1050 *(long *) ptr = (long) vcChunkPtr_; ptr += sizeof(void *);
1051 fIter = fldList_.getIterator();
1052 colPtr = (char*) curTuple_;
1053 char *valLenPairPtr = ptr + nVarchars * sizeof(void *);
1054 while (fIter.hasElement()) {
1055 FieldDef *def = fIter.nextElement();
1056 colPtr = (char *) curTuple_ + def->offset_;
1057 int vcStrLen = 0;
1058 if (def->type_ == typeVarchar) {
1059 *(long *) ptr = (long )colPtr; ptr += sizeof(void *);
1060 if (*(long *) colPtr == 0L) {
1061 *(int *) valLenPairPtr = vcStrLen = 0;
1062 valLenPairPtr += sizeof(int);
1063 } else {
1064 *(int *) valLenPairPtr = vcStrLen =
1065 os::align(strlen((char *)*(long *)colPtr) + 1);
1066 valLenPairPtr += sizeof(int);
1067 strcpy(valLenPairPtr, (char *)*(long *)colPtr);
1068 valLenPairPtr += vcStrLen;
1072 ret = (*trans)->appendUndoLog(sysDB_, DeleteOperation, data, size);
1073 ::free(data);
1075 if (ret != OK) {
1076 printError(ret, "Unable to create undo log for %x ", curTuple_);
1077 for (int j = 0; j < numIndexes_ ; j++) {
1078 printError(ErrWarning, "Inserting back index node");
1079 insertIndexNode(*trans, indexPtr_[j], idxInfo[j], curTuple_);
1081 if (!loadFlag) {
1082 (*trans)->removeFromHasList(db_, curTuple_);
1083 lMgr_->releaseLock(curTuple_);
1087 FieldIterator fIter = fldList_.getIterator();
1088 char *colPtr = (char*) curTuple_;
1089 while (fIter.hasElement()) {
1090 FieldDef *def = fIter.nextElement();
1091 colPtr = (char *) curTuple_ + def->offset_;
1092 if (def->type_ == typeVarchar) {
1093 if (*(long *) colPtr != 0L) {
1094 char *ptr = (char *) *(long *) colPtr;
1095 ((Chunk *) vcChunkPtr_)->free(db_, ptr);
1099 ((Chunk*)chunkPtr_)->free(db_, curTuple_);
1100 iter->prev();
1101 sysDB_->releaseCheckpointMutex();
1102 return ret;
1105 int TableImpl::deleteWhere()
1107 DbRetVal ret = getCheckpointMutex();
1108 if (ret !=OK) return ret;
1110 int tuplesDeleted = 0;
1111 DbRetVal rv = OK;
1112 rv = execute();
1113 if (rv !=OK) {
1114 sysDB_->releaseCheckpointMutex();
1115 return (int) rv;
1117 while(true){
1118 fetchNoBind( rv);
1119 if (rv != OK) { tuplesDeleted = (int)rv; break; }
1120 if (NULL == curTuple_) break;
1121 rv = deleteTuple();
1122 if (rv != OK) {
1123 printError(rv, "Error: Could only delete %d tuples", tuplesDeleted);
1124 closeScan();
1125 sysDB_->releaseCheckpointMutex();
1126 return (int) rv;
1128 tuplesDeleted++;
1130 closeScan();
1131 sysDB_->releaseCheckpointMutex();
1132 return tuplesDeleted;
1135 int TableImpl::truncate()
1137 //take exclusive lock on the table
1138 //get the chunk ptr of the table
1139 //traverse the tablechunks and free all the pages except the first one
1140 //get the chunk ptr of all its indexes
1141 //traverse the indexchunks and free all the pages except the first one
1142 //release table lock
1144 //TEMPORARY FIX
1145 DbRetVal rv = OK;
1146 Predicate* tmpPred = pred_;
1147 pred_ = NULL;
1148 isPlanCreated = false;
1149 int tuplesDeleted = deleteWhere();
1150 isPlanCreated = false;
1151 pred_ = tmpPred;
1152 return tuplesDeleted;
1155 DbRetVal TableImpl::updateTuple()
1157 if (NULL == curTuple_)
1159 printError(ErrNotOpen, "Scan not open: No Current tuple");
1160 return ErrNotOpen;
1162 DbRetVal ret = getCheckpointMutex();
1163 if (ret !=OK) return ret;
1164 if(isFkTbl){
1165 TableImpl *fkTbl =NULL;
1166 ListIterator tblIter = tblList.getIterator();
1167 tblIter.reset();
1168 while (tblIter.hasElement()){
1169 fkTbl = (TableImpl *) tblIter.nextElement();
1170 bool pkRec = isPkTableHasRecord(fkTbl->getName(),fkTbl,false);
1171 if(!pkRec){
1172 printError(ErrForeignKeyInsert, "Unable to insert into foreign Key table.Check PK table");
1173 sysDB_->releaseCheckpointMutex();
1174 return ErrForeignKeyInsert;
1177 tblIter.reset();
1180 if (!loadFlag) {
1181 //ret = lMgr_->getExclusiveLock(curTuple_, trans);
1182 if (OK != tryExclusiveLock(curTuple_, trans))
1184 printError(ret, "Could not get lock for the update tuple %x", curTuple_);
1185 sysDB_->releaseCheckpointMutex();
1186 return ErrLockTimeOut;
1189 if (NULL != indexPtr_)
1191 //it has index
1192 //TODO::If it fails while updating index node, we have to undo all the updates
1193 //on other indexes on the table.Currently it will leave the database in an
1194 //inconsistent state.
1195 for (int i = 0; i < numIndexes_ ; i++)
1197 ret = updateIndexNode(*trans, indexPtr_[i], idxInfo[i], curTuple_);
1198 if (ret != OK)
1200 if (!loadFlag) {
1201 lMgr_->releaseLock(curTuple_);
1202 (*trans)->removeFromHasList(db_, curTuple_);
1204 printError(ret, "Unable to update index node for tuple %x", curTuple_);
1205 sysDB_->releaseCheckpointMutex();
1206 return ret;
1211 if (!loadFlag) {
1212 // the undo log for update should contain
1213 // tupleptr + tuple length + actual tuple + metadataPtr +
1214 // nVarchars + varchar chunk ptr + ptrs to varchars +
1215 // size and value pairs for varchars
1217 //TODO: number of varchar fields to be stored as a member in TableImpl
1218 void *tptr = curTuple_;
1219 char *colPtr = (char *)curTuple_;
1220 int nVarchars = 0;
1221 int vcLenValPairSize = 0;
1222 FieldIterator fIter = fldList_.getIterator();
1223 while (fIter.hasElement()) {
1224 FieldDef *def = fIter.nextElement();
1225 colPtr = (char *) curTuple_ + def->offset_;
1226 if (def->type_ == typeVarchar) {
1227 nVarchars++;
1228 if (* (long *) colPtr == 0L)
1229 vcLenValPairSize = vcLenValPairSize + sizeof(int);
1230 else vcLenValPairSize = vcLenValPairSize + sizeof(int) +
1231 + os::align(strlen((char *) *(long *)colPtr) + 1);
1234 int size = (3 + nVarchars) * sizeof(void *) + 2 * sizeof(int) +
1235 vcLenValPairSize + length_;
1236 void *data = malloc(size);
1237 char *ptr = (char *) data;
1238 *(long *) ptr = (long) tptr; ptr += sizeof(void *);
1239 *(int *) ptr = length_; ptr += sizeof(int);
1240 os::memcpy(ptr, tptr, length_); ptr += length_;
1241 void *metaData = db_->getMetaDataPtr();
1242 *(long *) ptr = (long) metaData; ptr += sizeof(void *);
1243 *(int *) ptr = nVarchars; ptr += sizeof(int);
1244 *(long *) ptr = (long) vcChunkPtr_; ptr += sizeof(void *);
1245 fIter = fldList_.getIterator();
1246 colPtr = (char*) curTuple_;
1247 char *valLenPairPtr = ptr + nVarchars * sizeof(void *);
1248 while (fIter.hasElement()) {
1249 FieldDef *def = fIter.nextElement();
1250 colPtr = (char *) curTuple_ + def->offset_;
1251 int vcStrLen = 0;
1252 if (def->type_ == typeVarchar) {
1253 *(long *) ptr = (long)colPtr; ptr += sizeof(void *);
1254 if (*(long *) colPtr == 0L) {
1255 *(int *) valLenPairPtr = vcStrLen = 0;
1256 valLenPairPtr += sizeof(int);
1257 } else {
1258 *(int *) valLenPairPtr = vcStrLen =
1259 os::align(strlen((char *)*(long *)colPtr) + 1);
1260 valLenPairPtr += sizeof(int);
1261 strcpy(valLenPairPtr, (char *)*(long *)colPtr);
1262 valLenPairPtr += vcStrLen;
1266 ret = (*trans)->appendUndoLog(sysDB_, UpdateOperation, data, size);
1267 ::free(data);
1269 if (ret != OK) {
1270 if (!loadFlag) {
1271 lMgr_->releaseLock(curTuple_);
1272 (*trans)->removeFromHasList(db_, curTuple_);
1274 sysDB_->releaseCheckpointMutex();
1275 return ret;
1278 int addSize = 0;
1279 int iNullVal=iNullInfo;
1280 if (numFlds_ < 31){
1281 addSize=4;
1282 if(!iNullVal){
1283 iNullInfo = *(int*)((char*)(curTuple_) + (length_- addSize));
1285 else
1287 *(int*)((char*)(curTuple_) + (length_-addSize)) |= iNullInfo;
1290 DbRetVal rv = copyValuesFromBindBuffer(curTuple_, false);
1291 if (rv != OK && !loadFlag) {
1292 lMgr_->releaseLock(curTuple_);
1293 (*trans)->removeFromHasList(db_, curTuple_);
1294 sysDB_->releaseCheckpointMutex();
1295 return rv;
1298 if (numFlds_ < 31)
1300 if (!iNullVal) {
1301 *(int*)((char*)(curTuple_) + (length_-addSize)) = iNullInfo;
1302 iNullInfo=0;
1304 else iNullInfo=iNullVal;
1306 else
1308 addSize = os::align(numFlds_);
1309 //TODO::Do not do blind memcpy. It should OR each and every char
1310 int i=0;
1311 char *null=(char*)(curTuple_) + (length_-addSize);
1312 while(i < numFlds_) {
1313 if(cNullInfo[i]) null[i] |= cNullInfo[i];
1314 i++;
1316 //os::memcpy(((char*)(curTuple_) + (length_-addSize)), cNullInfo, addSize);
1318 sysDB_->releaseCheckpointMutex();
1319 return OK;
1322 void TableImpl::printInfo()
1324 printf(" <TableName> %s </TableName>\n", tblName_);
1325 printf(" <TupleCount> %d </TupleCount>\n", numTuples());
1326 printf(" <PagesUsed> %d </PagesUsed>\n", pagesUsed());
1327 printf(" <SpaceUsed> %d </SpaceUsed>\n", spaceUsed());
1328 printf(" <Indexes> %d <Indexes>\n", numIndexes_);
1329 printf(" <TupleLength> %d </TupleLength>\n", length_);
1330 printf(" <Fields> %d </Fields>\n", numFlds_);
1331 printf(" <Indexes>\n");
1332 for (int i =0; i<numIndexes_; i++)
1333 printf("<IndexName> %s </IndexName>\n", CatalogTableINDEX::getName(indexPtr_[i]));
1334 printf(" </Indexes>\n");
1337 long long TableImpl::getLastInsertedVal(DbRetVal &rv)
1339 rv=OK;
1340 return *(long long*)ptrToAuto;
1342 DbRetVal TableImpl::copyValuesFromBindBuffer(void *tuplePtr, bool isInsert)
1344 //Iterate through the bind list and copy the value here
1345 FieldIterator fIter = fldList_.getIterator();
1346 char *colPtr = (char*) tuplePtr;
1347 int fldpos=1;
1348 while (fIter.hasElement())
1350 FieldDef *def = fIter.nextElement();
1351 if(def->isAutoIncrement_ && isInsert)
1353 void *dest = AllDataType::alloc(def->type_, def->length_);
1354 AllDataType::copyVal(dest,ptrToAuto, def->type_, def->length_);
1355 if(def->bindVal_==NULL)
1357 AllDataType::increment(colPtr, dest , def->type_);
1358 AllDataType::copyVal(ptrToAuto,colPtr, def->type_,
1359 def->length_);
1360 colPtr = colPtr + def->length_;
1361 fldpos++;
1362 free(dest);
1363 continue;
1364 } else {
1365 if(AllDataType::compareVal(def->bindVal_, dest, OpGreaterThan,
1366 def->type_)) {
1367 AllDataType::copyVal(ptrToAuto,def->bindVal_, def->type_,
1368 def->length_);
1370 free(dest);
1373 if (def->isNull_ && !def->isDefault_ && NULL == def->bindVal_ &&
1374 isInsert)
1376 printError(ErrNullViolation,
1377 "NOT NULL constraint violation for field %s", def->fldName_);
1378 return ErrNullViolation;
1380 if (def->isDefault_ && NULL == def->bindVal_ && isInsert)
1382 if (! def->isNullExplicit_) {
1383 if (def->type_ == typeVarchar) {
1384 DbRetVal rv = OK;
1385 void *ptr =
1386 ((Chunk *) vcChunkPtr_)->allocate(db_, def->length_, &rv);
1387 *(long *)colPtr = (long)ptr;
1388 AllDataType::convert(typeString, def->defaultValueBuf_,
1389 def->type_, ptr, def->length_);
1390 } else {
1391 void *dest = AllDataType::alloc(def->type_, def->length_);
1392 AllDataType::convert(typeString, def->defaultValueBuf_,
1393 def->type_, dest, def->length_);
1394 AllDataType::copyVal(colPtr, dest, def->type_,
1395 def->length_);
1396 free (dest);
1398 } else {
1399 setNullBit(fldpos);
1400 *(long *) colPtr = 0L;
1402 if (def->type_ != typeVarchar) colPtr = colPtr + def->length_;
1403 else colPtr = colPtr + sizeof(void *);
1404 fldpos++;
1405 continue;
1407 switch(def->type_)
1409 case typeString:
1410 if (NULL != def->bindVal_)
1412 if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);}
1413 strncpy((char*)colPtr, (char*)def->bindVal_, def->length_);
1414 *(((char*)colPtr) + (def->length_-1)) = '\0';
1415 } else if (!def->isNull_ && !def->bindVal_ && isInsert) {
1416 setNullBit(fldpos);
1418 colPtr = colPtr + def->length_;
1419 break;
1420 case typeBinary:
1421 if (NULL != def->bindVal_ )
1423 if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);}
1424 DbRetVal rv = AllDataType::strToValue(colPtr,
1425 (char *) def->bindVal_, def->type_, def->length_);
1426 if (rv != OK) return ErrBadArg;
1427 } else if (!def->isNull_ && isInsert && !def->bindVal_) {
1428 setNullBit(fldpos);
1430 colPtr = colPtr + def->length_;
1431 break;
1432 case typeVarchar:
1433 if (NULL != def->bindVal_) {
1434 if (!isInsert && isFldNull(fldpos)) {clearNullBit(fldpos);}
1435 DbRetVal rv = OK;
1436 if (!isInsert) {
1437 if (*(long *) colPtr != 0L)
1438 ((Chunk *) vcChunkPtr_)->free(db_,
1439 (void *)*(long *)colPtr);
1440 *(long *) colPtr = 0L;
1442 if (strcmp((char *)def->bindVal_,"") != 0) {
1443 void *ptr =
1444 ((Chunk *) vcChunkPtr_)->allocate(db_,
1445 def->length_, &rv);
1446 if (rv != OK) return ErrBadArg;
1447 *(long *)colPtr = (long)ptr;
1448 strcpy((char *)ptr, (char *)def->bindVal_);
1449 } else { setNullBit(fldpos); }
1450 } else if (!def->isNull_ && isInsert && !def->bindVal_) {
1451 setNullBit(fldpos);
1453 colPtr = colPtr + sizeof(void *);
1454 break;
1455 default:
1456 if (NULL != def->bindVal_) {
1457 if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);}
1458 AllDataType::copyVal(colPtr, def->bindVal_, def->type_);
1459 } else { if (!def->isNull_ && isInsert) setNullBit(fldpos); }
1460 colPtr = colPtr + def->length_;
1461 break;
1463 fldpos++;
1465 return OK;
1467 void TableImpl::clearNullBit(int fldpos)
1469 if (isIntUsedForNULL){
1470 CLEARBIT(iNullInfo, fldpos);}
1471 else
1472 cNullInfo[fldpos-1] = 0;
1474 void TableImpl::setNullBit(int fldpos)
1476 if (isIntUsedForNULL)
1477 SETBIT(iNullInfo, fldpos);
1478 else
1479 cNullInfo[fldpos-1] = 1;
1481 DbRetVal TableImpl::copyValuesToBindBuffer(void *tuplePtr)
1483 //Iterate through the bind list and copy the value here
1484 char *colPtr = (char*) tuplePtr;
1485 FieldDef *def = NULL;
1486 for (int i = 0; i < numBindFlds_; i++) {
1487 def = (FieldDef *) bindListArray_[i];
1488 colPtr = (char *) tuplePtr + def->offset_;
1489 if (def->type_ != typeVarchar)
1490 AllDataType::copyVal(def->bindVal_, colPtr, def->type_,
1491 def->length_);
1492 else {
1493 char *ptr = (char *) *(long *) colPtr;
1494 if (ptr != NULL) strcpy((char *)def->bindVal_, ptr);
1497 return OK;
1500 //-1 index not supported
1501 DbRetVal TableImpl::insertIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple)
1503 CINDEX *iptr = (CINDEX*)indexPtr;
1504 DbRetVal ret = OK;
1505 printDebug(DM_Table, "Inside insertIndexNode type %d", iptr->indexType_);
1506 Index* idx = Index::getIndex(iptr->indexType_);
1507 ret = idx->insert(this, tr, indexPtr, info, tuple,loadFlag);
1508 return ret;
1511 DbRetVal TableImpl::deleteIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple)
1513 CINDEX *iptr = (CINDEX*)indexPtr;
1514 DbRetVal ret = OK;
1515 Index* idx = Index::getIndex(iptr->indexType_);
1516 ret = idx->remove(this, tr, indexPtr, info, tuple, loadFlag);
1517 return ret;
1519 void TableImpl::printSQLIndexString(FILE *fp, int fd)
1521 if (fp == NULL) fp = stdout;
1522 CatalogTableINDEXFIELD cIndexField(sysDB_);
1523 char fName[IDENTIFIER_LENGTH];
1524 char idxName[IDENTIFIER_LENGTH];
1525 char *fldName = fName;
1526 DataType type;
1527 for (int i = 0; i < numIndexes_ ; i++)
1529 CINDEX *iptr = (CINDEX*) indexPtr_[i];
1530 sprintf(idxName,"%s_idx_Auto_increment",getName());
1531 if(strcmp(iptr->indName_,idxName)==0){ continue; }
1532 if (Conf::config.useDurability()) {
1533 struct Object obj;
1534 strcpy(obj.name, iptr->indName_);
1535 if (iptr->indexType_ == hashIndex) {
1536 obj.type = hIdx;
1537 obj.bucketChunk = ((Chunk *)iptr->chunkPtr_)->getFirstPage();
1538 obj.firstPage = ((Chunk *)iptr->hashNodeChunk_)->getFirstPage();
1539 obj.curPage = ((Chunk *)iptr->hashNodeChunk_)->getCurrentPage();
1540 } else if (iptr->indexType_ == treeIndex) {
1541 obj.type = tIdx;
1542 obj.firstPage = ((Chunk *)iptr->chunkPtr_)->getFirstPage();
1543 obj.curPage = ((Chunk *)iptr->chunkPtr_)->getCurrentPage();
1544 long nodes = ((Chunk *)iptr->chunkPtr_)->getTotalDataNodes();
1545 if(nodes) {
1546 ChunkIterator cIter = ((Chunk *)iptr->chunkPtr_)->getIterator();
1547 obj.bucketChunk = cIter.nextElement();
1548 } else obj.bucketChunk = NULL;
1550 void *buf = &obj;
1551 write(fd, buf, sizeof(obj));
1553 fprintf(fp, "CREATE INDEX %s on %s ( ", iptr->indName_, getName());
1554 FieldList fldList;
1555 cIndexField.getFieldInfo(iptr, fldList);
1556 FieldIterator fIter = fldList.getIterator();
1557 bool firstFld = true;
1558 while(fIter.hasElement())
1560 FieldDef *def = fIter.nextElement();
1561 if (firstFld) { fprintf(fp, " %s ", def->fldName_); firstFld = false; }
1562 else fprintf(fp, " ,%s ", def->fldName_);
1564 fldList.removeAll();
1565 fprintf(fp, " ) ");
1566 if (iptr->indexType_ == hashIndex) fprintf(fp, " HASH ");
1567 else fprintf(fp, " TREE ");
1568 if (((HashIndexInfo*) idxInfo[i])->isUnique) fprintf(fp, " UNIQUE");
1569 if(((HashIndexInfo*) idxInfo[i])->noOfBuckets != 1009 ) fprintf(fp, " SIZE %d ",((HashIndexInfo*) idxInfo[i])->noOfBuckets );
1570 fprintf(fp, ";\n");
1575 DbRetVal TableImpl::updateIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple)
1577 CINDEX *iptr = (CINDEX*)indexPtr;
1578 DbRetVal ret = OK;
1579 Index* idx = Index::getIndex(iptr->indexType_);
1580 //TODO::currently it updates irrespective of whether the key changed or not
1581 //because of this commenting the whole index update code. relook at it and uncomment
1583 ret = idx->update(this, tr, indexPtr, info, tuple, loadFlag);
1585 return ret;
1589 void TableImpl::setTableInfo(char *name, int tblid, size_t length,
1590 int numFld, int numIdx, void *chunk, void *vcchunk)
1592 strcpy(tblName_, name);
1593 tblID_ = tblid;
1594 length_ = length;
1595 numFlds_ = numFld;
1596 numIndexes_ = numIdx;
1597 chunkPtr_ = chunk;
1598 vcChunkPtr_ = vcchunk;
1601 long TableImpl::spaceUsed()
1603 Chunk *chk = (Chunk*)chunkPtr_;
1604 long totSize = chk->getTotalDataNodes() * chk->getSize();
1605 totSize = totSize + (chk->totalPages() * sizeof (PageInfo));
1606 return totSize;
1609 int TableImpl::pagesUsed()
1611 Chunk *chk = (Chunk*)chunkPtr_;
1612 return chk->totalPages();
1615 long TableImpl::numTuples()
1617 return ((Chunk*)chunkPtr_)->getTotalDataNodes();
1620 List TableImpl::getFieldNameList()
1622 List fldNameList;
1623 FieldIterator fIter = fldList_.getIterator();
1624 char fieldName[IDENTIFIER_LENGTH];
1625 while (fIter.hasElement())
1627 FieldDef *def = fIter.nextElement();
1628 Identifier *elem = new Identifier();
1629 Table::getFieldNameAlone(def->fldName_, fieldName);
1630 sprintf(elem->name, "%s.%s", getName(), fieldName);
1631 fldNameList.append(elem);
1633 return fldNameList;
1635 DbRetVal TableImpl::close()
1637 if (iter) { iter->close(); delete iter; iter = NULL; }
1638 TableImpl *fkTbl =NULL;
1639 ListIterator tblIter = tblList.getIterator();
1640 tblIter.reset();
1641 while (tblIter.hasElement()){
1642 fkTbl = (TableImpl *) tblIter.nextElement();
1643 fkTbl->close();
1645 tblList.reset();
1646 tblIter = tblFkList.getIterator();
1647 tblIter.reset();
1648 while (tblIter.hasElement()){
1649 fkTbl = (TableImpl *) tblIter.nextElement();
1650 fkTbl->close();
1652 tblFkList.reset();
1653 printDebug(DM_Database,"Closing table handle: %x", this);
1654 //table->unlock();
1655 //delete pred_;
1656 ListIterator pIter = predList.getIterator();
1657 while (pIter.hasElement())
1659 PredicateImpl *pImpl = (PredicateImpl*) pIter.nextElement();
1660 delete pImpl;
1662 predList.reset();
1663 delete this;
1664 logFinest(Conf::logger, "Closing Table");
1665 return OK;
1668 DbRetVal TableImpl::closeScan()
1670 //do not throw scan not open error
1671 //this function will be called by table handle
1672 if (iter) {
1673 iter->close();
1675 return OK;
1677 DbRetVal TableImpl::lock(bool shared)
1680 DbRetVal ret = OK;
1682 if (shared)
1683 ret = lMgr_->getSharedLock(chunkPtr_, NULL);
1684 else
1685 ret = lMgr_->getExclusiveLock(chunkPtr_, NULL);
1686 if (OK != ret)
1688 printError(ret, "Could not exclusive lock on the table %x", chunkPtr_);
1689 }else {
1690 //do not append for S to X upgrade
1691 if (!ProcessManager::hasLockList.exists(chunkPtr_))
1692 ProcessManager::hasLockList.append(chunkPtr_);
1695 return ret;
1697 DbRetVal TableImpl::unlock()
1700 if (!ProcessManager::hasLockList.exists(chunkPtr_)) return OK;
1701 DbRetVal ret = lMgr_->releaseLock(chunkPtr_);
1702 if (OK != ret)
1704 printError(ret, "Could not release exclusive lock on the table %x", chunkPtr_);
1705 }else
1707 ProcessManager::hasLockList.remove(chunkPtr_);
1710 return OK;
1713 TableImpl::~TableImpl()
1715 if (NULL != iter ) { delete iter; iter = NULL; }
1716 if (NULL != indexPtr_) { delete[] indexPtr_; indexPtr_ = NULL; }
1717 if (NULL != idxInfo)
1719 for (int i = 0; i < numIndexes_; i++) delete idxInfo[i];
1720 delete[] idxInfo;
1721 idxInfo = NULL;
1723 if (numFlds_ > 31 && cNullInfo != NULL) { free(cNullInfo); cNullInfo = NULL; }
1724 if (bindList_.size()) bindList_.reset();
1725 if (bindListArray_) { free (bindListArray_); bindListArray_ = NULL; }
1726 fldList_.removeAll();
1730 void *TableImpl::getBindFldAddr(const char *name)
1732 return fldList_.getBindField(name);
1734 bool TableImpl::isTableInvolved(char *tblName)
1736 //printf("Table isTableInvolved called for %s with %s\n", tblName, getName());
1737 if (0 == strcmp(getName(), tblName)) return true; else return false;
1739 bool TableImpl::pushPredicate(Predicate *pred)
1741 bool ret = false;
1742 PredicateImpl *pImpl = (PredicateImpl*) pred;
1743 char tableName[IDENTIFIER_LENGTH];
1744 Table::getTableNameAlone(pImpl->getFldName1(), tableName);
1745 //printf("predicate tbl name %s\n", tableName);
1747 //if predicate is of form t1.f1=t2.f1 then do not push here
1748 bool isAliasSet = (0 !=strcmp(getAliasName(),"")) ;
1749 if (0 != strcmp(pImpl->getFldName2(),"")) return ret;
1751 if (0 == strcmp(getName(), tableName) ||(isAliasSet && 0 == strcmp(getAliasName(), tableName)))
1753 setPredicate(pred);
1754 //printf("PRABA::pushed predicate in tablehdl %s\n", getName());
1755 ret = true;
1757 return ret;
1760 void TableImpl::setCondition(Condition *p)
1762 isPlanCreated = false;
1763 ListIterator pIter = predList.getIterator();
1764 while (pIter.hasElement())
1766 PredicateImpl *pImpl = (PredicateImpl*) pIter.nextElement();
1767 delete pImpl;
1769 predList.reset();
1771 if (p) pred_ = p->getPredicate(); else pred_ = NULL;
1774 void TableImpl::setPredicate(Predicate *pred)
1776 if (NULL == pred_) { pred_ = pred; return; }
1778 Predicate *curPred = pred_;
1779 PredicateImpl *newPred = new PredicateImpl();
1780 newPred->setTerm(curPred, OpAnd, pred);
1781 newPred->setTable(this);
1782 pred_ = newPred;
1783 return;
1785 void TableImpl::printPlan(int space)
1787 char spaceBuf[IDENTIFIER_LENGTH];
1788 memset(spaceBuf, 32, IDENTIFIER_LENGTH);
1789 spaceBuf[space] = '\0';
1790 printf("%s <TABLE-NODE>\n", spaceBuf);
1791 printf("%s <NAME> %s </NAME>\n", spaceBuf, getName());
1792 printf("%s <ScanType> %s </ScanType>\n", spaceBuf, ScanTypeNames[scanType_]);
1793 PredicateImpl *pred = (PredicateImpl*)pred_;
1794 if (pred) pred->print(space+2);
1795 printf("%s </TABLE-NODE>\n", spaceBuf);
1797 void TableImpl::printSQLForeignString()
1799 DbRetVal rv=OK;
1800 FieldNameList pkFieldList,fkFieldList;
1801 void *tPkptr =NULL;
1802 void *tFkptr = NULL;
1803 void *chunkPk = NULL;
1804 void *vcchunkPk = NULL;
1805 CatalogTableTABLE cTable(sysDB_);
1806 TableImpl *fkTbl =NULL;
1807 ListIterator tblIter = tblList.getIterator();
1808 tblIter.reset();
1809 int firstFK=true;
1810 while (tblIter.hasElement()){
1811 fkTbl = (TableImpl *) tblIter.nextElement();
1812 rv = cTable.getChunkAndTblPtr(fkTbl->getName(), chunkPk, tPkptr,vcchunkPk);
1813 if ( OK != rv){return ;}
1814 rv = cTable.getChunkAndTblPtr(getName(), chunkPk, tFkptr, vcchunkPk);
1815 if ( OK != rv){return ;}
1816 CatalogTableFK cFk(sysDB_);
1817 rv = cFk.getPkFkFieldInfo(tPkptr,tFkptr,pkFieldList,fkFieldList);
1818 if ( OK != rv){return;}
1819 pkFieldList.resetIter();
1820 fkFieldList.resetIter();
1821 char *fldName = NULL;
1822 bool firstField=true;
1823 if(!firstFK) printf(", ");
1824 printf(", FOREIGN KEY ( ");
1825 while((fldName = fkFieldList.nextFieldName())!= NULL)
1827 if (firstField) {
1828 printf("%s",fldName);
1829 firstField=false;
1831 else
1832 printf(",%s",fldName);
1834 printf(" ) REFERENCES %s ( ",fkTbl->getName());
1835 firstField=true;
1836 while((fldName = pkFieldList.nextFieldName())!= NULL)
1838 if (firstField) {
1839 printf("%s",fldName);
1840 firstField=false;
1842 else
1843 printf(",%s",fldName);
1845 printf(" )");
1846 firstFK=true;
1847 pkFieldList.removeAll();
1848 fkFieldList.removeAll();
1850 return;
1852 bool TableImpl::isPkTableHasRecord(char *pkTableName, TableImpl *fkTbl,bool isInsert)
1854 DbRetVal rv=OK;
1855 bool isRecExist=false;
1856 FieldNameList pkFieldList,fkFieldList;
1857 void *tPkptr =NULL;
1858 void *tFkptr = NULL;
1859 void *chunkPk = NULL;
1860 void *vcchunkPk = NULL;
1861 CatalogTableTABLE cTable(sysDB_);
1862 rv = cTable.getChunkAndTblPtr(pkTableName, chunkPk, tPkptr, vcchunkPk);
1863 if ( OK != rv){return false;}
1864 rv = cTable.getChunkAndTblPtr(getName(), chunkPk, tFkptr, vcchunkPk);
1865 if ( OK != rv){return false;}
1866 CatalogTableFK cFk(sysDB_);
1867 rv = cFk.getPkFkFieldInfo(tPkptr,tFkptr,pkFieldList,fkFieldList);
1868 if ( OK != rv){return false;}
1869 int totFld = pkFieldList.size();
1870 Condition *condition = new Condition[totFld];
1871 char *pkFldName = NULL;
1872 char *fkFldName = NULL;
1873 FieldDef *def=NULL;
1874 int i=0;
1875 pkFieldList.resetIter();
1876 fkFieldList.resetIter();
1877 void *val=NULL;
1878 while((pkFldName = pkFieldList.nextFieldName())!= NULL)
1880 fkFldName = fkFieldList.nextFieldName();
1881 FieldIterator fIter = fldList_.getIterator();
1882 while (fIter.hasElement())
1884 def = fIter.nextElement();
1885 if (strcmp(def->fldName_, fkFldName) == 0)
1887 if(NULL == def->bindVal_ && isInsert) { return true; }
1888 if(NULL == def->bindVal_) {
1889 if (def->type_ != typeVarchar)
1890 val = (char*)curTuple_+ def->offset_;
1891 else val = (void *) *(long *) ((char*)curTuple_+
1892 def->offset_);
1893 } else {
1894 val = def->bindVal_;
1896 if(def->type_==typeString)
1897 condition[i].setTerm(pkFldName,OpEquals,&val);
1898 else
1899 condition[i].setTerm(pkFldName,OpEquals,val);
1900 i++;
1901 break;
1905 pkFieldList.removeAll();
1906 fkFieldList.removeAll();
1907 Condition *cond = NULL;
1908 if(i == 0 && !isInsert)return true;
1909 if( i > 1){
1910 cond = new Condition[i-1];
1911 int totcon = i;
1912 i=0;
1913 int j=0;
1914 for(j=0;j<totcon-1;j++)
1916 if(j==0)
1917 cond[j].setTerm(condition[i++].getPredicate(),OpAnd,condition[i++].getPredicate());
1918 else
1919 cond[j].setTerm(cond[j-1].getPredicate(), OpAnd, condition[i++].getPredicate());
1921 fkTbl->setCondition(&cond[j-1]);
1923 else{
1924 fkTbl->setCondition(&condition[i-1]);
1926 fkTbl->execute();
1927 if(fkTbl->fetch()){
1928 fkTbl->closeScan();
1929 delete[] cond;
1930 delete[] condition;
1931 return true;
1933 delete[] cond;
1934 delete[] condition;
1935 return false;
1938 bool TableImpl::isFkTableHasRecord(char *pkTableName, TableImpl *fkTbl)
1940 DbRetVal rv=OK;
1941 FieldNameList pkFieldList,fkFieldList;
1942 void *tPkptr =NULL;
1943 void *tFkptr = NULL;
1944 void *chunkPk = NULL;
1945 void *vcchunkPk = NULL;
1946 CatalogTableTABLE cTable(sysDB_);
1947 rv = cTable.getChunkAndTblPtr(getName(), chunkPk, tPkptr, vcchunkPk);
1948 if ( OK != rv){return false;}
1949 rv = cTable.getChunkAndTblPtr(pkTableName, chunkPk, tFkptr, vcchunkPk);
1950 if ( OK != rv){return false;}
1951 CatalogTableFK cFk(sysDB_);
1952 rv = cFk.getPkFkFieldInfo(tPkptr,tFkptr,pkFieldList,fkFieldList);
1953 if ( OK != rv){return false;}
1954 int totFld = pkFieldList.size();
1955 Condition *condition = new Condition[totFld];
1956 char *pkFldName = NULL;
1957 char *fkFldName = NULL;
1958 FieldDef *def=NULL;
1959 int i=0;
1960 pkFieldList.resetIter();
1961 fkFieldList.resetIter();
1962 while((pkFldName = pkFieldList.nextFieldName())!= NULL)
1964 fkFldName = fkFieldList.nextFieldName();
1965 FieldIterator fIter = fldList_.getIterator();
1966 while (fIter.hasElement())
1968 def = fIter.nextElement();
1969 void *val = NULL;
1970 if (def->type_ != typeVarchar)
1971 val = (char*)curTuple_+ def->offset_;
1972 else val = (void *) *(long *) ((char*)curTuple_+ def->offset_);
1973 if (strcmp(def->fldName_, pkFldName) == 0)
1975 if(def->type_==typeString)
1976 condition[i].setTerm(fkFldName,OpEquals,&val);//((char*)curTuple_+def->offset_));
1977 else
1978 condition[i].setTerm(fkFldName,OpEquals,val);//((char*)curTuple_+def->offset_));
1979 i++;
1980 break;
1984 pkFieldList.removeAll();
1985 fkFieldList.removeAll();
1986 if(i == 0 )return true;
1987 Condition *cond = new Condition[i-1];
1988 i=0;
1989 int j=0;
1990 for(j=0;j<totFld-1;j++)
1992 if(j==0)
1993 cond[j].setTerm(condition[i++].getPredicate(),OpAnd,condition[i++].getPredicate());
1994 else
1995 cond[j].setTerm(cond[j-1].getPredicate(), OpAnd, condition[i++].getPredicate());
1997 if(totFld==1)
1998 fkTbl->setCondition(&condition[totFld-1]);
1999 else
2000 fkTbl->setCondition(&cond[j-1]);
2001 fkTbl->execute();
2002 if(fkTbl->fetch()){
2003 fkTbl->closeScan();
2004 delete[] cond;
2005 delete[] condition;
2006 return true;
2008 delete[] cond;
2009 delete[] condition;
2010 return false;
2012 DbRetVal TableImpl::compact()
2014 DbRetVal rv=OK;
2015 int ret =((Chunk*)chunkPtr_)->compact(db_->procSlot);
2016 if(ret!=0) return ErrLockTimeOut;
2017 ret = ((Chunk*)vcChunkPtr_)->compact(db_->procSlot);
2018 if(ret!=0) return ErrLockTimeOut;
2019 if (NULL != indexPtr_)
2021 int i;
2022 //it has index
2023 for (i = 0; i < numIndexes_ ; i++)
2025 rv = compactIndexNode(indexPtr_[i]);
2026 if (rv != OK) { printError(rv, "Error in compacting index Node"); break;}
2029 return rv;
2032 DbRetVal TableImpl::compactIndexNode( void *indexPtr)
2034 CINDEX *iptr = (CINDEX*)indexPtr;
2035 int ret1=0;
2036 printDebug(DM_Table, "Inside insertIndexNode type %d", iptr->indexType_);
2037 if( hashIndex == (iptr->indexType_) )
2039 ret1 =((Chunk*)iptr->hashNodeChunk_)->compact(db_->procSlot);
2040 if(ret1!=0){
2041 return ErrLockTimeOut;
2043 }else
2045 ret1 =((Chunk*)iptr->chunkPtr_)->compact(db_->procSlot);
2046 if(ret1!=0){
2047 return ErrLockTimeOut;
2050 return OK;