cleanup
[csql.git] / src / storage / TableImpl.cxx
blob8bd05b7d62d4f813d000e6ae2a5119d283a18e44
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;
310 //if there are no predicates then go for full scan
311 //if there are no indexes then go for full scan
312 if (NULL == pred_ || NULL == indexPtr_)
314 scanType_ = fullTableScan;
315 isPlanCreated = true;
316 return OK;
318 //If serching for IS NULL or IS NOT NULL then fullscan
319 if (NULL != indexPtr_)
321 PredicateImpl *pred = (PredicateImpl*)pred_;
322 if(pred->isIsNullInvolved())
324 scanType_ = fullTableScan;
325 isPlanCreated = true;
326 shouldNullSearch=true;
327 return OK;
329 printDebug(DM_Predicate, "predicate does not involve NOT , OR operator");
330 if (!pred->isNotOrInvolved())
332 printDebug(DM_Predicate, "predicate does not involve NOT , OR operator");
333 for (int i =0; i < numIndexes_; i++)
335 HashIndexInfo* info = (HashIndexInfo*) idxInfo[i];
336 FieldIterator iter = info->idxFldList.getIterator();
337 while(iter.hasElement())
339 FieldDef *def = iter.nextElement();
340 if (pred->pointLookupInvolved(def->fldName_))
342 printDebug(DM_Predicate, "point lookup involved for field %s",def->fldName_);
343 if(hashIndex == info->indType) scanType_ = hashIndexScan;
344 else scanType_ = treeIndexScan;
345 isPlanCreated = true;
346 isPointLook = true;
347 useIndex_ = i;
349 else if (pred->isBetweenInvolved(def->fldName_))
351 if (treeIndex == info->indType)
353 scanType_ = treeIndexScan;
354 isPlanCreated = true;
355 useIndex_ = i;
356 isBetween=true;
357 break; //no composite index for tree index
360 else if (pred->rangeQueryInvolved(def->fldName_))
362 printDebug(DM_Predicate, "range lookup involved for field %s",def->fldName_);
363 if (treeIndex == info->indType)
365 scanType_ = treeIndexScan;
366 isPlanCreated = true;
367 useIndex_ = i;
368 break; //no composite index for tree index
370 }else {
371 useIndex_ = -1;
372 break;
374 }//while iter.hasElement()
375 if (useIndex_ != -1) return OK;
376 }//for
379 scanType_ = fullTableScan;
380 isPlanCreated = true;
381 return OK;
384 void* TableImpl::fetch()
386 fetchNoBind();
387 if (NULL == curTuple_) return curTuple_;
388 copyValuesToBindBuffer(curTuple_);
389 return curTuple_;
391 void* TableImpl::fetch(DbRetVal &rv)
393 fetchNoBind(rv);
394 if (NULL == curTuple_) return curTuple_;
395 copyValuesToBindBuffer(curTuple_);
396 return curTuple_;
399 void* TableImpl::fetchNoBind()
401 if (NULL == iter)
403 printError(ErrNotOpen,"Scan not open or Scan is closed\n");
404 return NULL;
406 void *prevTuple = curTuple_;
407 curTuple_ = iter->next();
408 if (NULL == curTuple_)
410 return NULL;
412 DbRetVal lockRet = OK;
413 if (!loadFlag) {
414 if ((*trans)->isoLevel_ == READ_COMMITTED)
416 //if iso level is read committed, operation duration lock is sufficent
417 //so release it here itself.
418 int tries = Conf::config.getMutexRetries();
419 struct timeval timeout;
420 timeout.tv_sec = Conf::config.getMutexSecs();
421 timeout.tv_usec = Conf::config.getMutexUSecs();
423 bool status = false;
424 while(true) {
425 lockRet = lMgr_->isExclusiveLocked( curTuple_, trans, status);
426 if (OK != lockRet)
428 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
429 curTuple_ = prevTuple;
430 return NULL;
432 if (!status) break;
433 tries--;
434 if (tries == 0) break;
435 os::select(0, 0, 0, 0, &timeout);
437 if (tries == 0)
439 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
440 curTuple_ = prevTuple;
441 return NULL;
444 else if ((*trans)->isoLevel_ == READ_REPEATABLE) {
445 if (OK != trySharedLock(curTuple_, trans))
447 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
448 curTuple_ = prevTuple;
449 return NULL;
454 return curTuple_;
456 DbRetVal TableImpl::trySharedLock(void *curTuple, Transaction **trans)
458 DbRetVal lockRet = OK;
459 int tries = Conf::config.getMutexRetries();
460 while((lockRet = lMgr_->getSharedLock(curTuple_, trans)) == ErrLockTimeOut)
462 tries--;
463 if (tries <=0) break;
465 return lockRet;
467 DbRetVal TableImpl::tryExclusiveLock(void *curTuple, Transaction **trans)
469 DbRetVal lockRet = OK;
470 int tries = Conf::config.getMutexRetries();
471 while((lockRet = lMgr_->getExclusiveLock(curTuple_, trans)) == ErrLockTimeOut)
473 tries--;
474 if (tries <=0) break;
476 return lockRet;
479 void* TableImpl::fetchNoBind(DbRetVal &rv)
481 rv = OK;
482 if (NULL == iter)
484 printError(ErrNotOpen,"Scan not open or Scan is closed\n");
485 rv = ErrNotOpen;
486 return NULL;
488 void *prevTuple = curTuple_;
489 curTuple_ = iter->next();
490 if (NULL == curTuple_)
492 return NULL;
494 DbRetVal lockRet = OK;
495 if (!loadFlag) {
496 if ((*trans)->isoLevel_ == READ_REPEATABLE) {
497 lockRet = lMgr_->getSharedLock(curTuple_, trans);
498 if (OK != lockRet)
500 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
501 rv = ErrLockTimeOut;
502 curTuple_ = prevTuple;
503 return NULL;
507 else if ((*trans)->isoLevel_ == READ_COMMITTED)
509 //if iso level is read committed, operation duration lock is sufficent
510 //so release it here itself.
511 int tries = Conf::config.getMutexRetries();
512 //struct timeval timeout;
513 //timeout.tv_sec = Conf::config.getMutexSecs();
514 //timeout.tv_usec = Conf::config.getMutexUSecs();
516 bool status = false;
517 while(true) {
518 lockRet = lMgr_->isExclusiveLocked( curTuple_, trans, status);
519 if (OK != lockRet)
521 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
522 curTuple_ = prevTuple;
523 rv = ErrLockTimeOut;
524 return NULL;
526 if (!status) break;
527 tries--;
528 if (tries == 0) break;
529 //os::select(0, 0, 0, 0, &timeout);
531 if (tries == 0)
533 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
534 curTuple_ = prevTuple;
535 rv = ErrLockTimeOut;
536 return NULL;
540 return curTuple_;
542 DbRetVal TableImpl::fetchAgg(const char * fldName, AggType aType, void *buf, bool &noRec)
544 FieldInfo *info = new FieldInfo();
545 DbRetVal rv = getFieldInfo(fldName, info);
546 if (OK != rv) return rv;
547 bool res= false;
548 if (AGG_MIN == aType || AGG_MAX == aType) {
549 int pos =0;
550 IndexType iType = getIndexType((char*)fldName, &pos);
551 if(treeIndex == iType && pos >=0) {
552 if (AGG_MIN == aType) {
553 HashIndexInfo* hInfo = (HashIndexInfo*) idxInfo[pos];
554 CINDEX *iptr = (CINDEX*) hInfo->indexPtr;
555 TreeNode *fstNode=(TreeNode *)iptr->hashNodeChunk_;
556 TreeIter *iter=NULL;
557 if(fstNode!=NULL){
558 TreeNode *start = (TreeNode *)*((char**)((char*)fstNode + sizeof(TreeNode)));
559 iter = new TreeIter(start,(TreeNode*)iptr->hashNodeChunk_,sysDB_->procSlot);
560 }else{
561 iter = new TreeIter(NULL,(TreeNode*)iptr->hashNodeChunk_,sysDB_->procSlot);
563 char *tuple = (char*) iter->getFirstElement();
564 if (tuple != NULL) {
565 AllDataType::copyVal(buf,(void*)(tuple+info->offset),
566 info->type, info->length);
567 delete iter;
568 return OK;
570 delete iter; iter = NULL;
572 else if (AGG_MAX == aType) {
573 HashIndexInfo* hInfo = (HashIndexInfo*) idxInfo[pos];
574 CINDEX *iptr = (CINDEX*) hInfo->indexPtr;
575 TreeNode *fstNode=(TreeNode *)iptr->hashNodeChunk_;
576 TreeIter *iter=NULL;
577 if(fstNode!=NULL){
578 TreeNode *start = (TreeNode *)*((char**)((char*)fstNode + sizeof(TreeNode)));
579 iter = new TreeIter(start,(TreeNode*)iptr->hashNodeChunk_,sysDB_->procSlot);
580 }else{
581 iter = new TreeIter(NULL,(TreeNode*)iptr->hashNodeChunk_,sysDB_->procSlot);
583 char *tuple = (char*) iter->getLastElement();
584 if (tuple != NULL) {
585 AllDataType::copyVal(buf,(void*)(tuple+info->offset),
586 info->type, info->length);
587 delete iter; iter = NULL;
588 return OK;
590 delete iter; iter=NULL;
593 }else if (AGG_COUNT == aType) {
594 (*(int*)buf) = 0;
598 DataType type = info->type;
599 int length = info->length;
600 int offset = info->offset;
601 int colPos = fldList_.getFieldPosition(fldName);
602 bool isNullable= true;
603 if (info->isNull || info->isPrimary || info->isDefault || info->isAutoIncrement) {
604 isNullable = false;
606 int nullOffset = length_-4;
607 if (aType == AGG_COUNT) {
608 length = sizeof(int);
609 type = typeInt;
611 if (NULL == pred_ && typeInt == type && aType != AGG_AVG)
612 { //perf opt
613 ChunkIterator cIter = ((Chunk*)chunkPtr_)->getIterator();
614 char *tuple =(char*)cIter.nextElement();
615 if (NULL == tuple) {
616 *(int *) buf = 0;
617 noRec = true;
618 return OK;
620 int count =1;
621 if (isNullable) {
622 if (isIntUsedForNULL) {
623 if (BITSET(*(int*)(tuple+nullOffset), colPos)) count =0;
625 else {
626 curTuple_= tuple;
627 if(isFldNull(colPos)) count =0;
630 if (aType != AGG_COUNT)
631 AllDataType::copyVal(buf, (void*) (tuple+offset), type, length);
632 void *prev=NULL;
633 prev = curTuple_;
634 cIter.pageSize = PAGE_SIZE;
635 while(1)
637 tuple = (char*)cIter.nextElementInt();
638 if (NULL == tuple) break;
639 if (isNullable) {
640 if (isIntUsedForNULL) {
641 if (BITSET(*(int*)(tuple+nullOffset), colPos)) continue;
643 else {
644 curTuple_= tuple;
645 if(isFldNull(colPos)) continue;
648 if (aType == AGG_MIN)
650 if (*(int*)buf >= *((int*)(tuple+offset)))
651 *(int*)buf = *((int*)(tuple+offset));
653 else if (aType == AGG_MAX)
655 if (*(int*)buf <= *((int*)(tuple+offset)))
656 *(int*)buf = *((int*)(tuple+offset));
658 else if (aType == AGG_SUM)
660 *(int*)buf += *((int*)(tuple+offset));
662 else if (aType == AGG_AVG)
664 *(int*)buf = *(int*)buf + *((int*)(tuple+offset));
665 count++;
667 else if (aType == AGG_COUNT)
669 count++;
672 curTuple_= prev;
673 if( AGG_AVG == aType) AllDataType::divVal(buf, &count, type);
674 else if (AGG_COUNT == aType) (*(int*)buf) = count;
675 delete info;
676 return OK;
679 char *tuple = (char*) fetchNoBind(rv);
680 if ( NULL == tuple) { noRec = true; return OK; }
681 int count =1;
683 while(isFldNull(colPos)) {
684 tuple= (char*) fetchNoBind(rv);
685 if (aType == AGG_COUNT) count++;
686 if (tuple) break;
688 if ( NULL == tuple) { noRec = true; return OK; }
690 if (aType == AGG_AVG) {
691 AllDataType::convertToDouble(buf, (void*) (tuple+offset), type);
692 } else if (aType != AGG_COUNT) {
693 AllDataType::copyVal(buf, (void*) (tuple+offset), type, length);
695 while(1) {
696 tuple = (char*) fetchNoBind(rv);
697 if (NULL == tuple) break;
698 if (isNullable) {
699 if (isIntUsedForNULL) {
700 if (BITSET(*(int*)(tuple+nullOffset), colPos)) continue;
702 else {
703 curTuple_= tuple;
704 if(isFldNull(colPos)) continue;
707 switch(aType) {
708 case AGG_MIN:
710 res = AllDataType::compareVal(buf, (void*) (tuple+offset),
711 OpGreaterThanEquals,
712 type, length);
713 if (res) AllDataType::copyVal(buf, (void*) (tuple+offset),
714 type, length);
715 break;
717 case AGG_MAX:
719 res = AllDataType::compareVal(buf, (void*) (tuple+offset),
720 OpLessThanEquals,
721 type, length);
722 if (res) AllDataType::copyVal(buf, (void*) (tuple+offset),
723 type, length);
724 break;
726 case AGG_SUM:
728 AllDataType::addVal(buf, (void*) (tuple+offset),
729 type);
730 break;
732 case AGG_AVG:
734 double tmpBuf=0.0;
735 AllDataType::convertToDouble(&tmpBuf, (void*) (tuple+offset), type);
736 AllDataType::addVal(buf, &tmpBuf, typeDouble);
737 count++;
738 break;
740 case AGG_COUNT:
742 count++;
743 break;
747 switch(aType) {
748 case AGG_AVG:
750 AllDataType::divVal((double *)buf, count, type);
751 break;
753 case AGG_COUNT:
755 (*(int*)buf) = count;
756 break;
759 delete info;
760 return OK;
762 DbRetVal TableImpl::insertTuple()
764 DbRetVal ret =OK;
765 void *tptr = NULL;// ((Chunk*)chunkPtr_)->allocate(db_, &ret);
766 int tries=0;
767 int totalTries = Conf::config.getMutexRetries();
768 while (tries < totalTries)
770 ret = OK;
771 tptr = ((Chunk*)chunkPtr_)->allocate(db_, &ret);
772 if (tptr !=NULL) break;
773 if (ret != ErrLockTimeOut)
775 printError(ret, "Unable to allocate record from chunk");
776 return ret;
778 tries++;
780 if (NULL == tptr)
782 printError(ret, "Unable to allocate record from chunk after %d retries", tries);
783 return ret;
785 curTuple_ = tptr;
786 if(isFkTbl){
787 TableImpl *fkTbl =NULL;
788 ListIterator tblIter = tblList.getIterator();
789 tblIter.reset();
790 while (tblIter.hasElement()){
791 fkTbl = (TableImpl *) tblIter.nextElement();
792 bool pkRec = isPkTableHasRecord(fkTbl->getName(),fkTbl,true);
793 if(!pkRec){
794 printError(ErrForeignKeyInsert, "Unable to insert into foreign Key table.Check PK table");
795 ((Chunk*)chunkPtr_)->free(db_, tptr);
796 return ErrForeignKeyInsert;
799 tblIter.reset();
801 if (!loadFlag) {
802 //ret = lMgr_->getExclusiveLock(tptr, trans);
803 if (OK != tryExclusiveLock(tptr, trans))
805 ((Chunk*)chunkPtr_)->free(db_, tptr);
806 printError(ret, "Could not get lock for the insert tuple %x", tptr);
807 return ErrLockTimeOut;
811 ret = copyValuesFromBindBuffer(tptr);
812 if (ret != OK)
814 printError(ret, "Unable to copy values from bind buffer");
815 if (!loadFlag) {
816 (*trans)->removeFromHasList(db_, tptr);
817 lMgr_->releaseLock(tptr);
819 ((Chunk*)chunkPtr_)->free(db_, tptr);
820 return ret;
822 int addSize = 0;
823 if (numFlds_ < 31)
825 addSize = 4;
826 *(int*)((char*)(tptr) + (length_-addSize)) = iNullInfo;
828 else
830 addSize = os::align(numFlds_);
831 os::memcpy(((char*)(tptr) + (length_-addSize)), cNullInfo, addSize);
834 //int tupleSize = length_ + addSize;
835 if (NULL != indexPtr_)
837 int i;
838 //it has index
839 for (i = 0; i < numIndexes_ ; i++)
841 ret = insertIndexNode(*trans, indexPtr_[i], idxInfo[i], tptr);
842 if (ret != OK) { printError(ret, "Error in inserting to index %x", tptr); break;}
844 if ( ret != OK)
846 for (int j = 0; j < i ; j++) {
847 printError(ErrWarning, "Undo:Deleting index node");
848 deleteIndexNode(*trans, indexPtr_[j], idxInfo[j], tptr);
850 if (!loadFlag) {
851 (*trans)->removeFromHasList(db_, tptr);
852 lMgr_->releaseLock(tptr);
854 ((Chunk*)chunkPtr_)->free(db_, tptr);
855 return ret;
858 if (!loadFlag)
859 ret = (*trans)->appendUndoLog(sysDB_, InsertOperation, tptr, length_);
860 if (ret != OK) {
861 printError(ret, "Unable to create undo log for %x %d", tptr, *(int*)tptr);
862 for (int j = 0; j < numIndexes_ ; j++) {
863 printError(ErrWarning, "Deleting index node");
864 deleteIndexNode(*trans, indexPtr_[j], idxInfo[j], tptr);
866 if (!loadFlag) {
867 (*trans)->removeFromHasList(db_, tptr);
868 lMgr_->releaseLock(tptr);
870 ((Chunk*)chunkPtr_)->free(db_, tptr);
872 return ret;
875 DbRetVal TableImpl::deleteTuple()
877 if (NULL == curTuple_)
879 printError(ErrNotOpen, "Scan not open: No Current tuple");
880 return ErrNotOpen;
882 if(isPkTbl){
883 TableImpl *fkTbl =NULL;
884 ListIterator tblIter = tblFkList.getIterator();
885 tblIter.reset();
886 while (tblIter.hasElement()){
887 fkTbl = (TableImpl *) tblIter.nextElement();
888 bool pkRec = isFkTableHasRecord(fkTbl->getName(),fkTbl);
889 if(pkRec){
890 printError(ErrForeignKeyDelete, "A Relation Exists. Delete from child table first");
891 return ErrForeignKeyDelete;
894 tblIter.reset();
896 DbRetVal ret = OK;
897 if (!loadFlag) {
898 //ret = lMgr_->getExclusiveLock(curTuple_, trans);
899 if (OK != tryExclusiveLock(curTuple_, trans))
901 printError(ret, "Could not get lock for the delete tuple %x",
902 curTuple_);
903 return ErrLockTimeOut;
907 if (NULL != indexPtr_)
909 int i;
910 //it has index
911 for (i = 0; i < numIndexes_ ; i++)
913 ret = deleteIndexNode(*trans, indexPtr_[i], idxInfo[i], curTuple_);
914 if (ret != OK) break;
916 if (i != numIndexes_ )
918 printError(ErrWarning, "Inserting back index node");
919 for (int j = 0; j < i ; j++)
920 insertIndexNode(*trans, indexPtr_[j], idxInfo[j], curTuple_);
921 if (!loadFlag) {
922 lMgr_->releaseLock(curTuple_);
923 (*trans)->removeFromHasList(db_, curTuple_);
925 printError(ret, "Unable to insert index node for tuple %x", curTuple_);
926 return ret;
929 if (!loadFlag)
930 ret = (*trans)->appendUndoLog(sysDB_, DeleteOperation, curTuple_, 0);
931 if (ret != OK) {
932 printError(ret, "Unable to create undo log for %x ", curTuple_);
933 for (int j = 0; j < numIndexes_ ; j++) {
934 printError(ErrWarning, "Inserting back index node");
935 insertIndexNode(*trans, indexPtr_[j], idxInfo[j], curTuple_);
937 if (!loadFlag) {
938 (*trans)->removeFromHasList(db_, curTuple_);
939 lMgr_->releaseLock(curTuple_);
942 ((Chunk*)chunkPtr_)->free(db_, curTuple_);
944 iter->prev();
945 return ret;
948 int TableImpl::deleteWhere()
950 int tuplesDeleted = 0;
951 DbRetVal rv = OK;
952 rv = execute();
953 if (rv !=OK) return (int) rv;
954 while(true){
955 fetchNoBind( rv);
956 if (rv != OK) { tuplesDeleted = (int)rv; break; }
957 if (NULL == curTuple_) break;
958 rv = deleteTuple();
959 if (rv != OK) {
960 printError(rv, "Error: Could only delete %d tuples", tuplesDeleted);
961 closeScan();
962 return (int) rv;
964 tuplesDeleted++;
966 closeScan();
967 return tuplesDeleted;
970 int TableImpl::truncate()
972 //take exclusive lock on the table
973 //get the chunk ptr of the table
974 //traverse the tablechunks and free all the pages except the first one
975 //get the chunk ptr of all its indexes
976 //traverse the indexchunks and free all the pages except the first one
977 //release table lock
979 //TEMPORARY FIX
980 DbRetVal rv = OK;
981 Predicate* tmpPred = pred_;
982 pred_ = NULL;
983 isPlanCreated = false;
984 int tuplesDeleted = deleteWhere();
985 isPlanCreated = false;
986 pred_ = tmpPred;
987 return tuplesDeleted;
990 DbRetVal TableImpl::updateTuple()
992 if (NULL == curTuple_)
994 printError(ErrNotOpen, "Scan not open: No Current tuple");
995 return ErrNotOpen;
997 if(isFkTbl){
998 TableImpl *fkTbl =NULL;
999 ListIterator tblIter = tblList.getIterator();
1000 tblIter.reset();
1001 while (tblIter.hasElement()){
1002 fkTbl = (TableImpl *) tblIter.nextElement();
1003 bool pkRec = isPkTableHasRecord(fkTbl->getName(),fkTbl,false);
1004 if(!pkRec){
1005 printError(ErrForeignKeyInsert, "Unable to insert into foreign Key table.Check PK table");
1006 return ErrForeignKeyInsert;
1009 tblIter.reset();
1012 DbRetVal ret=OK;
1013 if (!loadFlag) {
1014 //ret = lMgr_->getExclusiveLock(curTuple_, trans);
1015 if (OK != tryExclusiveLock(curTuple_, trans))
1017 printError(ret, "Could not get lock for the update tuple %x", curTuple_);
1018 return ErrLockTimeOut;
1021 if (NULL != indexPtr_)
1023 //it has index
1024 //TODO::If it fails while updating index node, we have to undo all the updates
1025 //on other indexes on the table.Currently it will leave the database in an
1026 //inconsistent state.
1027 for (int i = 0; i < numIndexes_ ; i++)
1029 ret = updateIndexNode(*trans, indexPtr_[i], idxInfo[i], curTuple_);
1030 if (ret != OK)
1032 if (!loadFlag) {
1033 lMgr_->releaseLock(curTuple_);
1034 (*trans)->removeFromHasList(db_, curTuple_);
1036 printError(ret, "Unable to update index node for tuple %x", curTuple_);
1037 return ret;
1041 if (!loadFlag)
1042 ret = (*trans)->appendUndoLog(sysDB_, UpdateOperation, curTuple_, length_);
1043 if (ret != OK) {
1044 if (!loadFlag) {
1045 lMgr_->releaseLock(curTuple_);
1046 (*trans)->removeFromHasList(db_, curTuple_);
1048 return ret;
1050 int addSize = 0;
1051 int iNullVal=iNullInfo;
1052 if (numFlds_ < 31){
1053 addSize=4;
1054 if(!iNullVal){
1055 iNullInfo = *(int*)((char*)(curTuple_) + (length_- addSize));
1057 else
1059 *(int*)((char*)(curTuple_) + (length_-addSize)) |= iNullInfo;
1062 DbRetVal rv = copyValuesFromBindBuffer(curTuple_, false);
1063 if (rv != OK && !loadFlag) {
1064 lMgr_->releaseLock(curTuple_);
1065 (*trans)->removeFromHasList(db_, curTuple_);
1066 return rv;
1069 if (numFlds_ < 31)
1071 if (!iNullVal) {
1072 *(int*)((char*)(curTuple_) + (length_-addSize)) = iNullInfo;
1073 iNullInfo=0;
1075 else iNullInfo=iNullVal;
1077 else
1079 addSize = os::align(numFlds_);
1080 //TODO::Do not do blind memcpy. It should OR each and every char
1081 int i=0;
1082 char *null=(char*)(curTuple_) + (length_-addSize);
1083 while(i < numFlds_) {
1084 if(cNullInfo[i]) null[i] |= cNullInfo[i];
1085 i++;
1087 //os::memcpy(((char*)(curTuple_) + (length_-addSize)), cNullInfo, addSize);
1091 return OK;
1094 void TableImpl::printInfo()
1096 printf(" <TableName> %s </TableName>\n", tblName_);
1097 printf(" <TupleCount> %d </TupleCount>\n", numTuples());
1098 printf(" <PagesUsed> %d </PagesUsed>\n", pagesUsed());
1099 printf(" <SpaceUsed> %d </SpaceUsed>\n", spaceUsed());
1100 printf(" <Indexes> %d <Indexes>\n", numIndexes_);
1101 printf(" <TupleLength> %d </TupleLength>\n", length_);
1102 printf(" <Fields> %d </Fields>\n", numFlds_);
1103 printf(" <Indexes>\n");
1104 for (int i =0; i<numIndexes_; i++)
1105 printf("<IndexName> %s </IndexName>\n", CatalogTableINDEX::getName(indexPtr_[i]));
1106 printf(" </Indexes>\n");
1110 DbRetVal TableImpl::copyValuesFromBindBuffer(void *tuplePtr, bool isInsert)
1112 //Iterate through the bind list and copy the value here
1113 FieldIterator fIter = fldList_.getIterator();
1114 char *colPtr = (char*) tuplePtr;
1115 int fldpos=1;
1116 while (fIter.hasElement())
1118 FieldDef *def = fIter.nextElement();
1119 if(def->isAutoIncrement_ && isInsert)
1121 void *dest = AllDataType::alloc(def->type_, def->length_);
1122 AllDataType::copyVal(dest,ptrToAuto, def->type_, def->length_);
1123 if(def->bindVal_==NULL)
1125 AllDataType::increment(colPtr, dest , def->type_);
1126 AllDataType::copyVal(ptrToAuto,colPtr, def->type_, def->length_);
1127 colPtr = colPtr + def->length_;
1128 fldpos++;
1129 free(dest);
1130 continue;
1131 }else {
1132 if(AllDataType::compareVal(def->bindVal_, dest, OpGreaterThan, def->type_)){
1133 AllDataType::copyVal(ptrToAuto,def->bindVal_, def->type_, def->length_);
1135 free(dest);
1138 if (def->isNull_ && !def->isDefault_ && NULL == def->bindVal_ && isInsert)
1140 printError(ErrNullViolation, "NOT NULL constraint violation for field %s", def->fldName_);
1141 return ErrNullViolation;
1143 if (def->isDefault_ && NULL == def->bindVal_ && isInsert)
1145 void *dest = AllDataType::alloc(def->type_, def->length_);
1146 AllDataType::convert(typeString, def->defaultValueBuf_, def->type_, dest, def->length_);
1147 AllDataType::copyVal(colPtr, dest, def->type_, def->length_);
1148 colPtr = colPtr + def->length_;
1149 fldpos++;
1150 free (dest);
1151 continue;
1153 switch(def->type_)
1155 case typeString:
1156 if (NULL != def->bindVal_)
1158 if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);}
1159 strncpy((char*)colPtr, (char*)def->bindVal_, def->length_);
1160 *(((char*)colPtr) + (def->length_-1)) = '\0';
1162 else if (!def->isNull_ && !def->bindVal_ && isInsert) setNullBit(fldpos);
1163 colPtr = colPtr + def->length_;
1164 break;
1165 case typeBinary:
1166 if (NULL != def->bindVal_ )
1168 if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);}
1169 DbRetVal rv = AllDataType::strToValue(colPtr, (char *) def->bindVal_, def->type_, def->length_);
1170 if (rv != OK) return ErrBadArg;
1172 else if (!def->isNull_ && isInsert && !def->bindVal_) setNullBit(fldpos);
1173 colPtr = colPtr + def->length_;
1174 break;
1175 default:
1176 if (NULL != def->bindVal_){
1177 if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);}
1178 AllDataType::copyVal(colPtr, def->bindVal_, def->type_);}
1179 else { if (!def->isNull_ && isInsert) setNullBit(fldpos); }
1180 colPtr = colPtr + def->length_;
1181 break;
1183 fldpos++;
1185 return OK;
1187 void TableImpl::clearNullBit(int fldpos)
1189 if (isIntUsedForNULL){
1190 CLEARBIT(iNullInfo, fldpos);}
1191 else
1192 cNullInfo[fldpos-1] = 0;
1194 void TableImpl::setNullBit(int fldpos)
1196 if (isIntUsedForNULL)
1197 SETBIT(iNullInfo, fldpos);
1198 else
1199 cNullInfo[fldpos-1] = 1;
1201 DbRetVal TableImpl::copyValuesToBindBuffer(void *tuplePtr)
1203 //Iterate through the bind list and copy the value here
1204 char *colPtr = (char*) tuplePtr;
1205 FieldDef *def = NULL;
1206 for (int i = 0; i < numBindFlds_; i++) {
1207 def = (FieldDef *) bindListArray_[i];
1208 colPtr = (char *) tuplePtr + def->offset_;
1209 AllDataType::copyVal(def->bindVal_, colPtr, def->type_, def->length_);
1211 return OK;
1214 //-1 index not supported
1215 DbRetVal TableImpl::insertIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple)
1217 CINDEX *iptr = (CINDEX*)indexPtr;
1218 DbRetVal ret = OK;
1219 printDebug(DM_Table, "Inside insertIndexNode type %d", iptr->indexType_);
1220 Index* idx = Index::getIndex(iptr->indexType_);
1221 ret = idx->insert(this, tr, indexPtr, info, tuple,loadFlag);
1222 return ret;
1225 DbRetVal TableImpl::deleteIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple)
1227 CINDEX *iptr = (CINDEX*)indexPtr;
1228 DbRetVal ret = OK;
1229 Index* idx = Index::getIndex(iptr->indexType_);
1230 ret = idx->remove(this, tr, indexPtr, info, tuple, loadFlag);
1231 return ret;
1233 void TableImpl::printSQLIndexString(FILE *fp, int fd)
1235 if (fp == NULL) fp = stdout;
1236 CatalogTableINDEXFIELD cIndexField(sysDB_);
1237 char fName[IDENTIFIER_LENGTH];
1238 char idxName[IDENTIFIER_LENGTH];
1239 char *fldName = fName;
1240 DataType type;
1241 for (int i = 0; i < numIndexes_ ; i++)
1243 CINDEX *iptr = (CINDEX*) indexPtr_[i];
1244 sprintf(idxName,"%s_idx_Auto_increment",getName());
1245 if(strcmp(iptr->indName_,idxName)==0){ continue; }
1246 if (Conf::config.useDurability()) {
1247 struct Object obj;
1248 strcpy(obj.name, iptr->indName_);
1249 if (iptr->indexType_ == hashIndex) {
1250 obj.type = hIdx;
1251 obj.bucketChunk = ((Chunk *)iptr->chunkPtr_)->getFirstPage();
1252 obj.firstPage = ((Chunk *)iptr->hashNodeChunk_)->getFirstPage();
1253 obj.curPage = ((Chunk *)iptr->hashNodeChunk_)->getCurrentPage();
1254 } else if (iptr->indexType_ == treeIndex) {
1255 obj.type = tIdx;
1256 obj.firstPage = ((Chunk *)iptr->chunkPtr_)->getFirstPage();
1257 obj.curPage = ((Chunk *)iptr->chunkPtr_)->getCurrentPage();
1258 long nodes = ((Chunk *)iptr->chunkPtr_)->getTotalDataNodes();
1259 if(nodes) {
1260 ChunkIterator cIter = ((Chunk *)iptr->chunkPtr_)->getIterator();
1261 obj.bucketChunk = cIter.nextElement();
1262 } else obj.bucketChunk = NULL;
1264 void *buf = &obj;
1265 write(fd, buf, sizeof(obj));
1267 fprintf(fp, "CREATE INDEX %s on %s ( ", iptr->indName_, getName());
1268 FieldList fldList;
1269 cIndexField.getFieldInfo(iptr, fldList);
1270 FieldIterator fIter = fldList.getIterator();
1271 bool firstFld = true;
1272 while(fIter.hasElement())
1274 FieldDef *def = fIter.nextElement();
1275 if (firstFld) { fprintf(fp, " %s ", def->fldName_); firstFld = false; }
1276 else fprintf(fp, " ,%s ", def->fldName_);
1278 fldList.removeAll();
1279 fprintf(fp, " ) ");
1280 if (iptr->indexType_ == hashIndex) fprintf(fp, " HASH ");
1281 else fprintf(fp, " TREE ");
1282 if (((HashIndexInfo*) idxInfo[i])->isUnique) fprintf(fp, " UNIQUE");
1283 if(((HashIndexInfo*) idxInfo[i])->noOfBuckets != 1009 ) fprintf(fp, " SIZE %d ",((HashIndexInfo*) idxInfo[i])->noOfBuckets );
1284 fprintf(fp, ";\n");
1289 DbRetVal TableImpl::updateIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple)
1291 CINDEX *iptr = (CINDEX*)indexPtr;
1292 DbRetVal ret = OK;
1293 Index* idx = Index::getIndex(iptr->indexType_);
1294 //TODO::currently it updates irrespective of whether the key changed or not
1295 //because of this commenting the whole index update code. relook at it and uncomment
1297 ret = idx->update(this, tr, indexPtr, info, tuple, loadFlag);
1299 return ret;
1303 void TableImpl::setTableInfo(char *name, int tblid, size_t length,
1304 int numFld, int numIdx, void *chunk)
1306 strcpy(tblName_, name);
1307 tblID_ = tblid;
1308 length_ = length;
1309 numFlds_ = numFld;
1310 numIndexes_ = numIdx;
1311 chunkPtr_ = chunk;
1314 long TableImpl::spaceUsed()
1316 Chunk *chk = (Chunk*)chunkPtr_;
1317 long totSize = chk->getTotalDataNodes() * chk->getSize();
1318 totSize = totSize + (chk->totalPages() * sizeof (PageInfo));
1319 return totSize;
1322 int TableImpl::pagesUsed()
1324 Chunk *chk = (Chunk*)chunkPtr_;
1325 return chk->totalPages();
1328 long TableImpl::numTuples()
1330 return ((Chunk*)chunkPtr_)->getTotalDataNodes();
1333 List TableImpl::getFieldNameList()
1335 List fldNameList;
1336 FieldIterator fIter = fldList_.getIterator();
1337 char fieldName[IDENTIFIER_LENGTH];
1338 while (fIter.hasElement())
1340 FieldDef *def = fIter.nextElement();
1341 Identifier *elem = new Identifier();
1342 Table::getFieldNameAlone(def->fldName_, fieldName);
1343 sprintf(elem->name, "%s.%s", getName(), fieldName);
1344 fldNameList.append(elem);
1346 return fldNameList;
1348 DbRetVal TableImpl::close()
1350 if (iter) { iter->close(); delete iter; iter = NULL; }
1351 TableImpl *fkTbl =NULL;
1352 ListIterator tblIter = tblList.getIterator();
1353 tblIter.reset();
1354 while (tblIter.hasElement()){
1355 fkTbl = (TableImpl *) tblIter.nextElement();
1356 fkTbl->close();
1358 tblList.reset();
1359 tblIter = tblFkList.getIterator();
1360 tblIter.reset();
1361 while (tblIter.hasElement()){
1362 fkTbl = (TableImpl *) tblIter.nextElement();
1363 fkTbl->close();
1365 tblFkList.reset();
1366 printDebug(DM_Database,"Closing table handle: %x", this);
1367 //table->unlock();
1368 //delete pred_;
1369 ListIterator pIter = predList.getIterator();
1370 while (pIter.hasElement())
1372 PredicateImpl *pImpl = (PredicateImpl*) pIter.nextElement();
1373 delete pImpl;
1375 predList.reset();
1376 delete this;
1377 logFinest(Conf::logger, "Closing Table");
1378 return OK;
1381 DbRetVal TableImpl::closeScan()
1383 //do not throw scan not open error
1384 //this function will be called by table handle
1385 if (iter) {
1386 iter->close();
1388 return OK;
1390 DbRetVal TableImpl::lock(bool shared)
1393 DbRetVal ret = OK;
1395 if (shared)
1396 ret = lMgr_->getSharedLock(chunkPtr_, NULL);
1397 else
1398 ret = lMgr_->getExclusiveLock(chunkPtr_, NULL);
1399 if (OK != ret)
1401 printError(ret, "Could not exclusive lock on the table %x", chunkPtr_);
1402 }else {
1403 //do not append for S to X upgrade
1404 if (!ProcessManager::hasLockList.exists(chunkPtr_))
1405 ProcessManager::hasLockList.append(chunkPtr_);
1408 return ret;
1410 DbRetVal TableImpl::unlock()
1413 if (!ProcessManager::hasLockList.exists(chunkPtr_)) return OK;
1414 DbRetVal ret = lMgr_->releaseLock(chunkPtr_);
1415 if (OK != ret)
1417 printError(ret, "Could not release exclusive lock on the table %x", chunkPtr_);
1418 }else
1420 ProcessManager::hasLockList.remove(chunkPtr_);
1423 return OK;
1426 TableImpl::~TableImpl()
1428 if (NULL != iter ) { delete iter; iter = NULL; }
1429 if (NULL != indexPtr_) { delete[] indexPtr_; indexPtr_ = NULL; }
1430 if (NULL != idxInfo)
1432 for (int i = 0; i < numIndexes_; i++) delete idxInfo[i];
1433 delete[] idxInfo;
1434 idxInfo = NULL;
1436 if (numFlds_ > 31 && cNullInfo != NULL) { free(cNullInfo); cNullInfo = NULL; }
1437 if (bindList_.size()) bindList_.reset();
1438 if (bindListArray_) { free (bindListArray_); bindListArray_ = NULL; }
1439 fldList_.removeAll();
1443 void *TableImpl::getBindFldAddr(const char *name)
1445 return fldList_.getBindField(name);
1447 bool TableImpl::isTableInvolved(char *tblName)
1449 //printf("Table isTableInvolved called for %s with %s\n", tblName, getName());
1450 if (0 == strcmp(getName(), tblName)) return true; else return false;
1452 bool TableImpl::pushPredicate(Predicate *pred)
1454 bool ret = false;
1455 PredicateImpl *pImpl = (PredicateImpl*) pred;
1456 char tableName[IDENTIFIER_LENGTH];
1457 Table::getTableNameAlone(pImpl->getFldName1(), tableName);
1458 //printf("predicate tbl name %s\n", tableName);
1460 //if predicate is of form t1.f1=t2.f1 then do not push here
1461 if (0 != strcmp(pImpl->getFldName2(),"")) return ret;
1463 if (0 == strcmp(getName(), tableName))
1465 setPredicate(pred);
1466 //printf("PRABA::pushed predicate in tablehdl %s\n", getName());
1467 ret = true;
1469 return ret;
1472 void TableImpl::setCondition(Condition *p)
1474 isPlanCreated = false;
1475 ListIterator pIter = predList.getIterator();
1476 while (pIter.hasElement())
1478 PredicateImpl *pImpl = (PredicateImpl*) pIter.nextElement();
1479 delete pImpl;
1481 predList.reset();
1483 if (p) pred_ = p->getPredicate(); else pred_ = NULL;
1486 void TableImpl::setPredicate(Predicate *pred)
1488 if (NULL == pred_) { pred_ = pred; return; }
1490 Predicate *curPred = pred_;
1491 PredicateImpl *newPred = new PredicateImpl();
1492 newPred->setTerm(curPred, OpAnd, pred);
1493 newPred->setTable(this);
1494 pred_ = newPred;
1495 return;
1497 void TableImpl::printPlan(int space)
1499 char spaceBuf[IDENTIFIER_LENGTH];
1500 memset(spaceBuf, 32, IDENTIFIER_LENGTH);
1501 spaceBuf[space] = '\0';
1502 printf("%s <TABLE-NODE>\n", spaceBuf);
1503 printf("%s <NAME> %s </NAME>\n", spaceBuf, getName());
1504 printf("%s <ScanType> %s </ScanType>\n", spaceBuf, ScanTypeNames[scanType_]);
1505 PredicateImpl *pred = (PredicateImpl*)pred_;
1506 if (pred) pred->print(space+2);
1507 printf("%s </TABLE-NODE>\n", spaceBuf);
1509 void TableImpl::printSQLForeignString()
1511 DbRetVal rv=OK;
1512 FieldNameList pkFieldList,fkFieldList;
1513 void *tPkptr =NULL;
1514 void *tFkptr = NULL;
1515 void *chunkPk = NULL;
1516 CatalogTableTABLE cTable(sysDB_);
1517 TableImpl *fkTbl =NULL;
1518 ListIterator tblIter = tblList.getIterator();
1519 tblIter.reset();
1520 int firstFK=true;
1521 while (tblIter.hasElement()){
1522 fkTbl = (TableImpl *) tblIter.nextElement();
1523 rv = cTable.getChunkAndTblPtr(fkTbl->getName(), chunkPk, tPkptr);
1524 if ( OK != rv){return ;}
1525 rv = cTable.getChunkAndTblPtr(getName(), chunkPk, tFkptr);
1526 if ( OK != rv){return ;}
1527 CatalogTableFK cFk(sysDB_);
1528 rv = cFk.getPkFkFieldInfo(tPkptr,tFkptr,pkFieldList,fkFieldList);
1529 if ( OK != rv){return;}
1530 pkFieldList.resetIter();
1531 fkFieldList.resetIter();
1532 char *fldName = NULL;
1533 bool firstField=true;
1534 if(!firstFK) printf(", ");
1535 printf(", FOREIGN KEY ( ");
1536 while((fldName = fkFieldList.nextFieldName())!= NULL)
1538 if (firstField) {
1539 printf("%s",fldName);
1540 firstField=false;
1542 else
1543 printf(",%s",fldName);
1545 printf(" ) REFERENCES %s ( ",fkTbl->getName());
1546 firstField=true;
1547 while((fldName = pkFieldList.nextFieldName())!= NULL)
1549 if (firstField) {
1550 printf("%s",fldName);
1551 firstField=false;
1553 else
1554 printf(",%s",fldName);
1556 printf(" )");
1557 firstFK=true;
1558 pkFieldList.removeAll();
1559 fkFieldList.removeAll();
1561 return;
1563 bool TableImpl::isPkTableHasRecord(char *pkTableName, TableImpl *fkTbl,bool isInsert)
1565 DbRetVal rv=OK;
1566 bool isRecExist=false;
1567 FieldNameList pkFieldList,fkFieldList;
1568 void *tPkptr =NULL;
1569 void *tFkptr = NULL;
1570 void *chunkPk = NULL;
1571 CatalogTableTABLE cTable(sysDB_);
1572 rv = cTable.getChunkAndTblPtr(pkTableName, chunkPk, tPkptr);
1573 if ( OK != rv){return false;}
1574 rv = cTable.getChunkAndTblPtr(getName(), chunkPk, tFkptr);
1575 if ( OK != rv){return false;}
1576 CatalogTableFK cFk(sysDB_);
1577 rv = cFk.getPkFkFieldInfo(tPkptr,tFkptr,pkFieldList,fkFieldList);
1578 if ( OK != rv){return false;}
1579 int totFld = pkFieldList.size();
1580 Condition *condition = new Condition[totFld];
1581 char *pkFldName = NULL;
1582 char *fkFldName = NULL;
1583 FieldDef *def=NULL;
1584 int i=0;
1585 pkFieldList.resetIter();
1586 fkFieldList.resetIter();
1587 void *val=NULL;
1588 while((pkFldName = pkFieldList.nextFieldName())!= NULL)
1590 fkFldName = fkFieldList.nextFieldName();
1591 FieldIterator fIter = fldList_.getIterator();
1592 while (fIter.hasElement())
1594 def = fIter.nextElement();
1595 if (strcmp(def->fldName_, fkFldName) == 0)
1597 if(NULL == def->bindVal_ && isInsert) { return true; }
1598 if(NULL == def->bindVal_) {
1599 val = (char*)curTuple_+ def->offset_;
1600 } else {
1601 val = def->bindVal_;
1603 if(def->type_==typeString)
1604 condition[i].setTerm(pkFldName,OpEquals,&val);
1605 else
1606 condition[i].setTerm(pkFldName,OpEquals,val);
1607 i++;
1608 break;
1612 pkFieldList.removeAll();
1613 fkFieldList.removeAll();
1614 Condition *cond = NULL;
1615 if(i == 0 && !isInsert)return true;
1616 if( i > 1){
1617 cond = new Condition[i-1];
1618 int totcon = i;
1619 i=0;
1620 int j=0;
1621 for(j=0;j<totcon-1;j++)
1623 if(j==0)
1624 cond[j].setTerm(condition[i++].getPredicate(),OpAnd,condition[i++].getPredicate());
1625 else
1626 cond[j].setTerm(cond[j-1].getPredicate(), OpAnd, condition[i++].getPredicate());
1628 fkTbl->setCondition(&cond[j-1]);
1630 else{
1631 fkTbl->setCondition(&condition[i-1]);
1633 fkTbl->execute();
1634 if(fkTbl->fetch()){
1635 fkTbl->closeScan();
1636 delete[] cond;
1637 delete[] condition;
1638 return true;
1640 delete[] cond;
1641 delete[] condition;
1642 return false;
1645 bool TableImpl::isFkTableHasRecord(char *pkTableName, TableImpl *fkTbl)
1647 DbRetVal rv=OK;
1648 FieldNameList pkFieldList,fkFieldList;
1649 void *tPkptr =NULL;
1650 void *tFkptr = NULL;
1651 void *chunkPk = NULL;
1652 CatalogTableTABLE cTable(sysDB_);
1653 rv = cTable.getChunkAndTblPtr(getName(), chunkPk, tPkptr);
1654 if ( OK != rv){return false;}
1655 rv = cTable.getChunkAndTblPtr(pkTableName, chunkPk, tFkptr);
1656 if ( OK != rv){return false;}
1657 CatalogTableFK cFk(sysDB_);
1658 rv = cFk.getPkFkFieldInfo(tPkptr,tFkptr,pkFieldList,fkFieldList);
1659 if ( OK != rv){return false;}
1660 int totFld = pkFieldList.size();
1661 Condition *condition = new Condition[totFld];
1662 char *pkFldName = NULL;
1663 char *fkFldName = NULL;
1664 FieldDef *def=NULL;
1665 int i=0;
1666 pkFieldList.resetIter();
1667 fkFieldList.resetIter();
1668 while((pkFldName = pkFieldList.nextFieldName())!= NULL)
1670 fkFldName = fkFieldList.nextFieldName();
1671 FieldIterator fIter = fldList_.getIterator();
1672 while (fIter.hasElement())
1674 def = fIter.nextElement();
1675 void *val = (char*)curTuple_+ def->offset_;
1676 if (strcmp(def->fldName_, pkFldName) == 0)
1678 if(def->type_==typeString)
1679 condition[i].setTerm(fkFldName,OpEquals,&val);//((char*)curTuple_+def->offset_));
1680 else
1681 condition[i].setTerm(fkFldName,OpEquals,val);//((char*)curTuple_+def->offset_));
1682 i++;
1683 break;
1687 pkFieldList.removeAll();
1688 fkFieldList.removeAll();
1689 if(i == 0 )return true;
1690 Condition *cond = new Condition[i-1];
1691 i=0;
1692 int j=0;
1693 for(j=0;j<totFld-1;j++)
1695 if(j==0)
1696 cond[j].setTerm(condition[i++].getPredicate(),OpAnd,condition[i++].getPredicate());
1697 else
1698 cond[j].setTerm(cond[j-1].getPredicate(), OpAnd, condition[i++].getPredicate());
1700 if(totFld==1)
1701 fkTbl->setCondition(&condition[totFld-1]);
1702 else
1703 fkTbl->setCondition(&cond[j-1]);
1704 fkTbl->execute();
1705 if(fkTbl->fetch()){
1706 fkTbl->closeScan();
1707 delete[] cond;
1708 delete[] condition;
1709 return true;
1711 delete[] cond;
1712 delete[] condition;
1713 return false;
1715 DbRetVal TableImpl::compact()
1717 DbRetVal rv=OK;
1718 int ret =((Chunk*)chunkPtr_)->compact(db_->procSlot);
1719 if(ret!=0){
1720 return ErrLockTimeOut;
1722 if (NULL != indexPtr_)
1724 int i;
1725 //it has index
1726 for (i = 0; i < numIndexes_ ; i++)
1728 rv = compactIndexNode(indexPtr_[i]);
1729 if (rv != OK) { printError(rv, "Error in compacting index Node"); break;}
1732 return rv;
1735 DbRetVal TableImpl::compactIndexNode( void *indexPtr)
1737 CINDEX *iptr = (CINDEX*)indexPtr;
1738 int ret1=0;
1739 printDebug(DM_Table, "Inside insertIndexNode type %d", iptr->indexType_);
1740 if( hashIndex == (iptr->indexType_) )
1742 ret1 =((Chunk*)iptr->hashNodeChunk_)->compact(db_->procSlot);
1743 if(ret1!=0){
1744 return ErrLockTimeOut;
1746 }else
1748 ret1 =((Chunk*)iptr->chunkPtr_)->compact(db_->procSlot);
1749 if(ret1!=0){
1750 return ErrLockTimeOut;
1753 return OK;