1 /***************************************************************************
2 * Copyright (C) 2007 by www.databasecache.com *
3 * Contact: praba_tuty@databasecache.com *
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. *
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. *
15 ***************************************************************************/
17 #include<CatalogTables.h>
23 #include<PredicateImpl.h>
26 #include<AggTableImpl.h> //for AggType
28 void Table::getFieldNameAlone(char *fname
, char *name
) {
30 char *fullname
= fname
;
31 while(*fullname
!= '\0')
33 if (*fullname
== '.') { dotFound
= true; break; }
36 if (dotFound
) strcpy(name
, ++fullname
); else strcpy(name
, fname
);
39 void Table::getTableNameAlone(char *fname
, char *name
) {
42 bool dotFound
= false;
45 if (*name
== '.') { *name
='\0'; dotFound
= true; break; }
48 if (!dotFound
) strcpy(start
, "");
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
);
60 printError(ErrNotExists
, "Field %s does not exist", fieldName
);
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
);
76 printError(ErrNotExists
, "Field %s does not exist", name
);
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
-1)) return true;
100 char *nullOffset
= (char*)curTuple_
+ (length_
- os::align(numFlds_
));
101 if (nullOffset
[colpos
-1]) return true;
105 void TableImpl::resetNullinfo()
107 if (isIntUsedForNULL
) {
112 while(i
< numFlds_
) { cNullInfo
[i
++] = 0;}
115 DbRetVal
TableImpl::markFldNull(char const* name
)
118 int colpos
= fldList_
.getFieldPosition(name
);
121 printError(ErrNotExists
, "Field %s does not exist", name
);
124 rv
= markFldNull(colpos
);
128 DbRetVal
TableImpl::markFldNull(int fldpos
)
130 if (fldpos
<1 || fldpos
> numFlds_
) return ErrBadArg
;
131 if (isIntUsedForNULL
) {
132 if (!BITSET(iNotNullInfo
, fldpos
-1)) SETBIT(iNullInfo
, fldpos
-1);
134 printError(ErrNullViolation
, "NOT NULL constraint violation");
135 return ErrNullViolation
;
139 if (!cNotNullInfo
[fldpos
-1]) cNullInfo
[fldpos
-1] = 1;
141 printError(ErrNullViolation
, "NOT NULL constraint violation");
142 return ErrNullViolation
;
148 void TableImpl::clearFldNull(const char *name
)
150 int colpos
= fldList_
.getFieldPosition(name
);
153 printError(ErrNotExists
, "Field %s does not exist", name
);
156 clearFldNull(colpos
);
159 void TableImpl::clearFldNull(int colpos
)
161 if (colpos
<1 || colpos
> numFlds_
) return;
162 if (isIntUsedForNULL
) CLEARBIT(iNullInfo
, colpos
-1);
163 else cNullInfo
[colpos
-1] = 0;
167 bool TableImpl::hasIndex(char* fName
)
169 if (NULL
== indexPtr_
) return false;
170 for (int i
=0; i
< numIndexes_
; i
++)
172 HashIndexInfo
* info
= (HashIndexInfo
*) idxInfo
[i
];
173 FieldIterator iter
= info
->idxFldList
.getIterator();
174 if(iter
.hasElement())
176 FieldDef
*def
= iter
.nextElement();
177 if(strcmp(def
->fldName_
, fName
) == 0)
178 if(!iter
.hasElement())//neglet if it is composite index
185 IndexType
TableImpl::getIndexType(char *fName
, int *pos
)
187 if (NULL
== indexPtr_
) return unknownIndex
;
188 for (int i
=0; i
< numIndexes_
; i
++)
190 HashIndexInfo
* info
= (HashIndexInfo
*) idxInfo
[i
];
191 FieldIterator iter
= info
->idxFldList
.getIterator();
192 if(iter
.hasElement())
194 FieldDef
*def
= iter
.nextElement();
195 if(strcmp(def
->fldName_
, fName
) == 0)
196 if(!iter
.hasElement()) {//neglet if it is composite index
198 return info
->indType
;
205 void TableImpl::addPredicate(char *fName
, ComparisionOp op
, void *buf
)
207 char fieldName
[IDENTIFIER_LENGTH
];
208 Table::getFieldNameAlone(fName
, fieldName
);
209 PredicateImpl
*pred
= (PredicateImpl
*) pred_
;
210 PredicateImpl
*newPred
= new PredicateImpl();
211 newPred
->setTerm(fName
, op
, buf
);
212 if (NULL
== pred
) { pred_
= newPred
; predList
.append(newPred
); return; }
213 if (pred
->isSingleTerm())
215 bool res
= pred
->appendIfSameFld(fName
, op
, buf
);
221 PredicateImpl
*bothPred
= new PredicateImpl();
222 bothPred
->setTerm(pred
, OpAnd
, newPred
);
223 predList
.append(bothPred
);
227 DbRetVal
TableImpl::optimize()
229 //table ptr is set in predicate because it needs to access the
230 //type and length to evaluate
233 PredicateImpl
*pred
= (PredicateImpl
*) pred_
;
234 pred
->setTable(this);
235 pred
->setProjectionList(NULL
);
236 pred
->setOffsetAndType();
238 DbRetVal rv
= createPlan();
239 if (rv
!= OK
) return rv
;
240 if (iter
) { iter
->close(); delete iter
; iter
= NULL
; }
242 iter
= new TupleIterator(pred_
, scanType_
, idxInfo
[useIndex_
], chunkPtr_
, sysDB_
->procSlot
,isBetween
,isPointLook
,shouldNullSearch
);
243 else if (scanType_
== fullTableScan
)
244 iter
= new TupleIterator(pred_
, scanType_
, NULL
, chunkPtr_
, sysDB_
->procSlot
,isBetween
,isPointLook
,shouldNullSearch
);
247 printError(ErrSysFatal
,"Unable to create tuple iterator");
248 //should never happen
255 DbRetVal
TableImpl::execute()
257 if (iter
&& !iter
->isIterClosed())
259 //printError(ErrAlready,"Scan already open:Close and re execute");
263 if (!isPlanCreated
) ret
= optimize();
266 printError(ErrSysInternal
,"Unable to create the plan");
267 return ErrSysInternal
;
272 printError(ret
,"Unable to open the iterator");
279 DbRetVal
TableImpl::createPlan()
282 //will do early return here. plan is generated only when setPredicate is called.
283 if (scanType_
== unknownScan
) return ErrSysFatal
; //this should never happen
290 FieldIterator fIter
= fldList_
.getIterator();
291 FieldDef
*def
= NULL
;
292 while ((def
= fIter
.nextElement())!= NULL
) {
293 if (NULL
!= def
->bindVal_
) bindList_
.append(def
);
295 numBindFlds_
= bindList_
.size();
296 if (bindListArray_
) { ::free(bindListArray_
); bindListArray_
= NULL
; }
297 bindListArray_
= (void **) malloc(numBindFlds_
* sizeof (void *));
300 ListIterator it
= bindList_
.getIterator();
301 while ((elem
= it
.nextElement()) != NULL
) bindListArray_
[i
++] = elem
;
302 scanType_
= fullTableScan
;
303 isPlanCreated
= true;
305 //if there are no predicates then go for full scan
306 //if there are no indexes then go for full scan
307 if (NULL
== pred_
|| NULL
== indexPtr_
)
311 if (NULL
!= indexPtr_
)
313 PredicateImpl
*pred
= (PredicateImpl
*)pred_
;
314 //If searching for IS NULL or IS NOT NULL then fullscan
315 if(pred
->isIsNullInvolved())
317 scanType_
= fullTableScan
;
318 shouldNullSearch
=true;
321 printDebug(DM_Predicate
, "predicate does not involve NOT , OR operator");
322 if (!pred
->isNotOrInvolved())
324 printDebug(DM_Predicate
, "predicate does not involve NOT , OR operator");
325 for (int i
=0; i
< numIndexes_
; i
++)
327 bool isAllFldPointLookup
= true;
328 HashIndexInfo
* info
= (HashIndexInfo
*) idxInfo
[i
];
329 FieldIterator iter
= info
->idxFldList
.getIterator();
331 while(iter
.hasElement())
334 FieldDef
*def
= iter
.nextElement();
335 if (pred
->pointLookupInvolved(def
->fldName_
))
337 if (!isAllFldPointLookup
) break;
338 printDebug(DM_Predicate
, "point lookup involved for field %s",def
->fldName_
);
339 if(hashIndex
== info
->indType
)
340 scanType_
= hashIndexScan
;
341 else if (trieIndex
== info
->indType
)
342 scanType_
= trieIndexScan
;
344 scanType_
= treeIndexScan
;
348 else if (pred
->isBetweenInvolved(def
->fldName_
))
350 if (treeIndex
== info
->indType
)
352 scanType_
= treeIndexScan
;
355 break; //no composite index for tree index
356 } else isAllFldPointLookup
= false;
358 else if (pred
->rangeQueryInvolved(def
->fldName_
))
360 printDebug(DM_Predicate
, "range lookup involved for field %s",def
->fldName_
);
361 if (treeIndex
== info
->indType
)
363 scanType_
= treeIndexScan
;
365 break; //no composite index for tree index
366 } else isAllFldPointLookup
=false;
369 isAllFldPointLookup
= false;
372 }//while iter.hasElement()
373 if( noOfIfld
== 1 && useIndex_
!= -1)return OK
;
374 if (!isAllFldPointLookup
&& useIndex_
!= -1) return OK
;
378 scanType_
= fullTableScan
;
382 void* TableImpl::fetch()
385 if (NULL
== curTuple_
) return curTuple_
;
386 copyValuesToBindBuffer(curTuple_
);
389 void* TableImpl::fetch(DbRetVal
&rv
)
392 if (NULL
== curTuple_
) return curTuple_
;
393 copyValuesToBindBuffer(curTuple_
);
397 void* TableImpl::fetchNoBind()
401 printError(ErrNotOpen
,"Scan not open or Scan is closed\n");
404 void *prevTuple
= curTuple_
;
405 curTuple_
= iter
->next();
406 if (NULL
== curTuple_
)
410 DbRetVal lockRet
= OK
;
412 if ((*trans
)->isoLevel_
== READ_COMMITTED
)
414 //if iso level is read committed, operation duration lock is sufficent
415 //so release it here itself.
416 int tries
= Conf::config
.getMutexRetries();
417 struct timeval timeout
, timeval
;
418 timeout
.tv_sec
= Conf::config
.getMutexSecs();
419 timeout
.tv_usec
= Conf::config
.getMutexUSecs();
423 lockRet
= lMgr_
->isExclusiveLocked( curTuple_
, trans
, status
);
426 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
427 curTuple_
= prevTuple
;
432 if (tries
== 0) break;
433 timeval
.tv_sec
= timeout
.tv_sec
;
434 timeval
.tv_usec
= timeout
.tv_usec
;
435 os::select(0, 0, 0, 0, &timeval
);
439 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
440 curTuple_
= prevTuple
;
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
;
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
)
463 if (tries
<=0) break;
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
)
474 if (tries
<=0) break;
479 void* TableImpl::fetchNoBind(DbRetVal
&rv
)
484 printError(ErrNotOpen
,"Scan not open or Scan is closed\n");
488 void *prevTuple
= curTuple_
;
489 curTuple_
= iter
->next();
490 if (NULL
== curTuple_
)
494 DbRetVal lockRet
= OK
;
496 if ((*trans
)->isoLevel_
== READ_REPEATABLE
) {
497 lockRet
= lMgr_
->getSharedLock(curTuple_
, trans
);
500 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
502 curTuple_
= prevTuple
;
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();
518 lockRet
= lMgr_
->isExclusiveLocked( curTuple_
, trans
, status
);
521 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
522 curTuple_
= prevTuple
;
528 if (tries
== 0) break;
529 //os::select(0, 0, 0, 0, &timeout);
533 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
534 curTuple_
= prevTuple
;
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
;
548 if (AGG_MIN
== aType
|| AGG_MAX
== aType
) {
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_
;
558 TreeNode
*start
= (TreeNode
*)*((char**)((char*)fstNode
+ sizeof(TreeNode
)));
559 iter
= new TreeIter(start
,(TreeNode
*)iptr
->hashNodeChunk_
,sysDB_
->procSlot
);
561 iter
= new TreeIter(NULL
,(TreeNode
*)iptr
->hashNodeChunk_
,sysDB_
->procSlot
);
563 char *tuple
= (char*) iter
->getFirstElement();
565 AllDataType::copyVal(buf
,(void*)(tuple
+info
->offset
),
566 info
->type
, info
->length
);
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_
;
578 TreeNode
*start
= (TreeNode
*)*((char**)((char*)fstNode
+ sizeof(TreeNode
)));
579 iter
= new TreeIter(start
,(TreeNode
*)iptr
->hashNodeChunk_
,sysDB_
->procSlot
);
581 iter
= new TreeIter(NULL
,(TreeNode
*)iptr
->hashNodeChunk_
,sysDB_
->procSlot
);
583 char *tuple
= (char*) iter
->getLastElement();
585 AllDataType::copyVal(buf
,(void*)(tuple
+info
->offset
),
586 info
->type
, info
->length
);
587 delete iter
; iter
= NULL
;
590 delete iter
; iter
=NULL
;
593 }else if (AGG_COUNT
== aType
) {
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
) {
606 int nullOffset
= length_
-4;
607 if (aType
== AGG_COUNT
) {
608 length
= sizeof(int);
611 if (NULL
== pred_
&& typeInt
== type
&& aType
!= AGG_AVG
)
613 ChunkIterator cIter
= ((Chunk
*)chunkPtr_
)->getIterator();
614 char *tuple
=(char*)cIter
.nextElement();
622 if (isIntUsedForNULL
) {
623 if (BITSET(*(int*)(tuple
+nullOffset
), colPos
-1)) count
=0;
627 if(isFldNull(colPos
)) count
=0;
630 if (aType
!= AGG_COUNT
)
631 AllDataType::copyVal(buf
, (void*) (tuple
+offset
), type
, length
);
634 cIter
.pageSize
= PAGE_SIZE
;
637 tuple
= (char*)cIter
.nextElementInt();
638 if (NULL
== tuple
) break;
640 if (isIntUsedForNULL
) {
641 if (BITSET(*(int*)(tuple
+nullOffset
), colPos
-1)) continue;
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
));
667 else if (aType
== AGG_COUNT
)
673 if( AGG_AVG
== aType
) AllDataType::divVal(buf
, &count
, type
);
674 else if (AGG_COUNT
== aType
) (*(int*)buf
) = count
;
679 char *tuple
= (char*) fetchNoBind(rv
);
680 if ( NULL
== tuple
) { noRec
= true; return OK
; }
683 while(isFldNull(colPos
)) {
684 tuple
= (char*) fetchNoBind(rv
);
685 if (aType
== AGG_COUNT
) count
++;
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
);
696 tuple
= (char*) fetchNoBind(rv
);
697 if (NULL
== tuple
) break;
699 if (isIntUsedForNULL
) {
700 if (BITSET(*(int*)(tuple
+nullOffset
), colPos
-1)) continue;
704 if(isFldNull(colPos
)) continue;
710 res
= AllDataType::compareVal(buf
, (void*) (tuple
+offset
),
713 if (res
) AllDataType::copyVal(buf
, (void*) (tuple
+offset
),
719 res
= AllDataType::compareVal(buf
, (void*) (tuple
+offset
),
722 if (res
) AllDataType::copyVal(buf
, (void*) (tuple
+offset
),
728 AllDataType::addVal(buf
, (void*) (tuple
+offset
),
735 AllDataType::convertToDouble(&tmpBuf
, (void*) (tuple
+offset
), type
);
736 AllDataType::addVal(buf
, &tmpBuf
, typeDouble
);
750 AllDataType::divVal((double *)buf
, count
, type
);
755 (*(int*)buf
) = count
;
762 DbRetVal
TableImpl::getCheckpointMutex()
766 int totalTries
= Conf::config
.getMutexRetries();
767 struct timeval timeout
, timeval
;
768 timeout
.tv_sec
= Conf::config
.getMutexSecs();
769 timeout
.tv_usec
= Conf::config
.getMutexUSecs();
771 while (tries
< totalTries
)
773 rv
= sysDB_
->getSCheckpointMutex();
775 timeval
.tv_sec
= timeout
.tv_sec
;
776 timeval
.tv_usec
= timeout
.tv_usec
;
777 os::select(0,0,0,0,&timeval
);
780 if (tries
== totalTries
) {
781 printError(ErrLockTimeOut
, "Checkpoint server is running. Retry after sometime.");
782 return ErrLockTimeOut
;
786 DbRetVal
TableImpl::insertTuple()
788 DbRetVal ret
= getCheckpointMutex();
789 if (ret
!=OK
) return ret
;
792 int totalTries
= Conf::config
.getMutexRetries();
793 while (tries
< totalTries
)
796 tptr
= ((Chunk
*)chunkPtr_
)->allocate(db_
, &ret
);
797 if (tptr
!=NULL
) break;
798 if (ret
!= ErrLockTimeOut
)
800 sysDB_
->releaseCheckpointMutex();
801 printError(ret
, "Unable to allocate record from chunk");
808 sysDB_
->releaseCheckpointMutex();
809 printError(ret
, "Unable to allocate record from chunk after %d retries", tries
);
814 TableImpl
*fkTbl
=NULL
;
815 ListIterator tblIter
= tblList
.getIterator();
817 while (tblIter
.hasElement()){
818 fkTbl
= (TableImpl
*) tblIter
.nextElement();
819 bool pkRec
= isPkTableHasRecord(fkTbl
->getName(),fkTbl
,true);
821 printError(ErrForeignKeyInsert
, "Unable to insert into foreign Key table.Check PK table");
822 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
823 sysDB_
->releaseCheckpointMutex();
824 return ErrForeignKeyInsert
;
830 //ret = lMgr_->getExclusiveLock(tptr, trans);
831 if (OK
!= tryExclusiveLock(tptr
, trans
))
833 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
834 printError(ret
, "Could not get lock for the insert tuple %x", tptr
);
835 sysDB_
->releaseCheckpointMutex();
836 return ErrLockTimeOut
;
840 ret
= copyValuesFromBindBuffer(tptr
);
843 printError(ret
, "Unable to copy values from bind buffer");
845 (*trans
)->removeFromHasList(db_
, tptr
);
846 lMgr_
->releaseLock(tptr
);
849 FieldIterator fIter
= fldList_
.getIterator();
850 char *colPtr
= (char*) curTuple_
;
851 while (fIter
.hasElement()) {
852 FieldDef
*def
= fIter
.nextElement();
853 colPtr
= (char *) curTuple_
+ def
->offset_
;
854 if (def
->type_
== typeVarchar
) {
855 char *ptr
= (char *) *(long *) colPtr
;
856 if (ptr
!= 0L) ((Chunk
*) vcChunkPtr_
)->free(db_
, ptr
);
859 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
860 sysDB_
->releaseCheckpointMutex();
867 *(int*)((char*)(tptr
) + (length_
-addSize
)) = iNullInfo
;
871 addSize
= os::align(numFlds_
);
872 os::memcpy(((char*)(tptr
) + (length_
-addSize
)), cNullInfo
, addSize
);
875 //int tupleSize = length_ + addSize;
876 if (NULL
!= indexPtr_
)
880 for (i
= 0; i
< numIndexes_
; i
++)
882 ret
= insertIndexNode(*trans
, indexPtr_
[i
], idxInfo
[i
], tptr
);
883 if (ret
!= OK
) { printError(ret
, "Error in inserting to index %x", tptr
); break;}
887 for (int j
= 0; j
< i
; j
++) {
888 printError(ErrWarning
, "Undo:Deleting index node");
889 deleteIndexNode(*trans
, indexPtr_
[j
], idxInfo
[j
], tptr
);
892 (*trans
)->removeFromHasList(db_
, tptr
);
893 lMgr_
->releaseLock(tptr
);
896 FieldIterator fIter
= fldList_
.getIterator();
897 char *colPtr
= (char*) curTuple_
;
898 while (fIter
.hasElement()) {
899 FieldDef
*def
= fIter
.nextElement();
900 colPtr
= (char *) curTuple_
+ def
->offset_
;
901 if (def
->type_
== typeVarchar
) {
902 char *ptr
= (char *) *(long *) colPtr
;
903 if (ptr
!= 0L) ((Chunk
*) vcChunkPtr_
)->free(db_
, ptr
);
906 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
907 sysDB_
->releaseCheckpointMutex();
912 //TODO: number of varchar fields to be stored as a member in TableImpl
914 FieldIterator fIter
= fldList_
.getIterator();
915 while (fIter
.hasElement()) {
916 FieldDef
*def
= fIter
.nextElement();
917 if (def
->type_
== typeVarchar
) nVarchars
++;
920 // the undo log for insert should contain
921 // tuple ptr + metadata Ptr + no of varchars + ptrs to varchars for insert opearation
922 int size
= (3 + nVarchars
) * sizeof(void *) + sizeof(int);
923 void *data
= malloc(size
);
924 char *ptr
= (char *)data
;
925 *(long *) ptr
= (long) tptr
; ptr
+= sizeof(void *);
926 void *metaData
= db_
->getMetaDataPtr();
927 *(long *) ptr
= (long) metaData
; ptr
+= sizeof(void *);
928 *(int *) ptr
= nVarchars
; ptr
+= sizeof(int);
929 *(long *) ptr
= (long) vcChunkPtr_
; ptr
+= sizeof(void *);
930 fIter
= fldList_
.getIterator();
931 char *colPtr
= (char*) curTuple_
;
932 while (fIter
.hasElement()) {
933 FieldDef
*def
= fIter
.nextElement();
934 colPtr
= (char *) curTuple_
+ def
->offset_
;
935 if (def
->type_
== typeVarchar
) {
936 *(long *) ptr
= (long)colPtr
;
937 ptr
+= sizeof(void *);
940 ret
= (*trans
)->appendUndoLog(sysDB_
, InsertOperation
, data
, size
);
944 printError(ret
, "Unable to create undo log for %x %d", tptr
, *(int*)tptr
);
945 for (int j
= 0; j
< numIndexes_
; j
++) {
946 printError(ErrWarning
, "Deleting index node");
947 deleteIndexNode(*trans
, indexPtr_
[j
], idxInfo
[j
], tptr
);
950 (*trans
)->removeFromHasList(db_
, tptr
);
951 lMgr_
->releaseLock(tptr
);
953 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
955 sysDB_
->releaseCheckpointMutex();
959 DbRetVal
TableImpl::deleteTuple()
961 if (NULL
== curTuple_
)
963 printError(ErrNotOpen
, "Scan not open: No Current tuple");
966 DbRetVal ret
= getCheckpointMutex();
967 if (ret
!= OK
) return ret
;
969 TableImpl
*fkTbl
=NULL
;
970 ListIterator tblIter
= tblFkList
.getIterator();
972 while (tblIter
.hasElement()){
973 fkTbl
= (TableImpl
*) tblIter
.nextElement();
974 bool pkRec
= isFkTableHasRecord(fkTbl
->getName(),fkTbl
);
976 printError(ErrForeignKeyDelete
, "A Relation Exists. Delete from child table first");
977 sysDB_
->releaseCheckpointMutex();
978 return ErrForeignKeyDelete
;
984 //ret = lMgr_->getExclusiveLock(curTuple_, trans);
985 if (OK
!= tryExclusiveLock(curTuple_
, trans
))
987 printError(ret
, "Could not get lock for the delete tuple %x",
989 sysDB_
->releaseCheckpointMutex();
990 return ErrLockTimeOut
;
994 if (NULL
!= indexPtr_
)
998 for (i
= 0; i
< numIndexes_
; i
++)
1000 ret
= deleteIndexNode(*trans
, indexPtr_
[i
], idxInfo
[i
], curTuple_
);
1001 if (ret
!= OK
) break;
1003 if (i
!= numIndexes_
)
1005 printError(ErrWarning
, "Inserting back index node");
1006 for (int j
= 0; j
< i
; j
++)
1007 insertIndexNode(*trans
, indexPtr_
[j
], idxInfo
[j
], curTuple_
);
1009 lMgr_
->releaseLock(curTuple_
);
1010 (*trans
)->removeFromHasList(db_
, curTuple_
);
1012 printError(ret
, "Unable to insert index node for tuple %x", curTuple_
);
1013 sysDB_
->releaseCheckpointMutex();
1018 // the undo log for delete should contain
1019 // tupleptr + metadataPtr + nVarchars + varchar chunk ptr +
1020 // ptrs to varchars + size and value pairs for varchars
1022 //TODO: number of varchar fields to be stored as a member in TableImpl
1023 void *tptr
= curTuple_
;
1024 char *colPtr
= (char *)curTuple_
;
1026 int vcLenValPairSize
= 0;
1027 FieldIterator fIter
= fldList_
.getIterator();
1028 while (fIter
.hasElement()) {
1029 FieldDef
*def
= fIter
.nextElement();
1030 colPtr
= (char *) curTuple_
+ def
->offset_
;
1031 if (def
->type_
== typeVarchar
) {
1033 if (* (long *) colPtr
== 0L)
1034 vcLenValPairSize
= vcLenValPairSize
+ sizeof(int);
1035 else vcLenValPairSize
= vcLenValPairSize
+ sizeof(int) +
1036 + os::align(strlen((char *) *(long *)colPtr
) + 1);
1039 int size
= (3 + nVarchars
) * sizeof(void *) + sizeof(int)
1041 void *data
= malloc(size
);
1042 char *ptr
= (char *)data
;
1043 *(long *) ptr
= (long) tptr
; ptr
+= sizeof(void *);
1044 void *metaData
= db_
->getMetaDataPtr();
1045 *(long *) ptr
= (long) metaData
; ptr
+= sizeof(void *);
1046 *(int *) ptr
= nVarchars
; ptr
+= sizeof(int);
1047 *(long *) ptr
= (long) vcChunkPtr_
; ptr
+= sizeof(void *);
1048 fIter
= fldList_
.getIterator();
1049 colPtr
= (char*) curTuple_
;
1050 char *valLenPairPtr
= ptr
+ nVarchars
* sizeof(void *);
1051 while (fIter
.hasElement()) {
1052 FieldDef
*def
= fIter
.nextElement();
1053 colPtr
= (char *) curTuple_
+ def
->offset_
;
1055 if (def
->type_
== typeVarchar
) {
1056 *(long *) ptr
= (long )colPtr
; ptr
+= sizeof(void *);
1057 if (*(long *) colPtr
== 0L) {
1058 *(int *) valLenPairPtr
= vcStrLen
= 0;
1059 valLenPairPtr
+= sizeof(int);
1061 *(int *) valLenPairPtr
= vcStrLen
=
1062 os::align(strlen((char *)*(long *)colPtr
) + 1);
1063 valLenPairPtr
+= sizeof(int);
1064 strcpy(valLenPairPtr
, (char *)*(long *)colPtr
);
1065 valLenPairPtr
+= vcStrLen
;
1069 ret
= (*trans
)->appendUndoLog(sysDB_
, DeleteOperation
, data
, size
);
1073 printError(ret
, "Unable to create undo log for %x ", curTuple_
);
1074 for (int j
= 0; j
< numIndexes_
; j
++) {
1075 printError(ErrWarning
, "Inserting back index node");
1076 insertIndexNode(*trans
, indexPtr_
[j
], idxInfo
[j
], curTuple_
);
1079 (*trans
)->removeFromHasList(db_
, curTuple_
);
1080 lMgr_
->releaseLock(curTuple_
);
1084 FieldIterator fIter
= fldList_
.getIterator();
1085 char *colPtr
= (char*) curTuple_
;
1086 while (fIter
.hasElement()) {
1087 FieldDef
*def
= fIter
.nextElement();
1088 colPtr
= (char *) curTuple_
+ def
->offset_
;
1089 if (def
->type_
== typeVarchar
) {
1090 if (*(long *) colPtr
!= 0L) {
1091 char *ptr
= (char *) *(long *) colPtr
;
1092 ((Chunk
*) vcChunkPtr_
)->free(db_
, ptr
);
1096 ((Chunk
*)chunkPtr_
)->free(db_
, curTuple_
);
1098 sysDB_
->releaseCheckpointMutex();
1102 int TableImpl::deleteWhere()
1104 DbRetVal ret
= getCheckpointMutex();
1105 if (ret
!=OK
) return ret
;
1107 int tuplesDeleted
= 0;
1111 sysDB_
->releaseCheckpointMutex();
1116 if (rv
!= OK
) { tuplesDeleted
= (int)rv
; break; }
1117 if (NULL
== curTuple_
) break;
1120 printError(rv
, "Error: Could only delete %d tuples", tuplesDeleted
);
1122 sysDB_
->releaseCheckpointMutex();
1128 sysDB_
->releaseCheckpointMutex();
1129 return tuplesDeleted
;
1132 int TableImpl::truncate()
1134 //take exclusive lock on the table
1135 //get the chunk ptr of the table
1136 //traverse the tablechunks and free all the pages except the first one
1137 //get the chunk ptr of all its indexes
1138 //traverse the indexchunks and free all the pages except the first one
1139 //release table lock
1143 Predicate
* tmpPred
= pred_
;
1145 isPlanCreated
= false;
1146 int tuplesDeleted
= deleteWhere();
1147 isPlanCreated
= false;
1149 return tuplesDeleted
;
1152 DbRetVal
TableImpl::updateTuple()
1154 if (NULL
== curTuple_
)
1156 printError(ErrNotOpen
, "Scan not open: No Current tuple");
1159 DbRetVal ret
= getCheckpointMutex();
1160 if (ret
!=OK
) return ret
;
1162 TableImpl
*fkTbl
=NULL
;
1163 ListIterator tblIter
= tblList
.getIterator();
1165 while (tblIter
.hasElement()){
1166 fkTbl
= (TableImpl
*) tblIter
.nextElement();
1167 bool pkRec
= isPkTableHasRecord(fkTbl
->getName(),fkTbl
,false);
1169 printError(ErrForeignKeyInsert
, "Unable to insert into foreign Key table.Check PK table");
1170 sysDB_
->releaseCheckpointMutex();
1171 return ErrForeignKeyInsert
;
1178 //ret = lMgr_->getExclusiveLock(curTuple_, trans);
1179 if (OK
!= tryExclusiveLock(curTuple_
, trans
))
1181 printError(ret
, "Could not get lock for the update tuple %x", curTuple_
);
1182 sysDB_
->releaseCheckpointMutex();
1183 return ErrLockTimeOut
;
1186 if (NULL
!= indexPtr_
)
1189 //TODO::If it fails while updating index node, we have to undo all the updates
1190 //on other indexes on the table.Currently it will leave the database in an
1191 //inconsistent state.
1192 for (int i
= 0; i
< numIndexes_
; i
++)
1194 ret
= updateIndexNode(*trans
, indexPtr_
[i
], idxInfo
[i
], curTuple_
);
1198 lMgr_
->releaseLock(curTuple_
);
1199 (*trans
)->removeFromHasList(db_
, curTuple_
);
1201 printError(ret
, "Unable to update index node for tuple %x", curTuple_
);
1202 sysDB_
->releaseCheckpointMutex();
1209 // the undo log for update should contain
1210 // tupleptr + tuple length + actual tuple + metadataPtr +
1211 // nVarchars + varchar chunk ptr + ptrs to varchars +
1212 // size and value pairs for varchars
1214 //TODO: number of varchar fields to be stored as a member in TableImpl
1215 void *tptr
= curTuple_
;
1216 char *colPtr
= (char *)curTuple_
;
1218 int vcLenValPairSize
= 0;
1219 FieldIterator fIter
= fldList_
.getIterator();
1220 while (fIter
.hasElement()) {
1221 FieldDef
*def
= fIter
.nextElement();
1222 colPtr
= (char *) curTuple_
+ def
->offset_
;
1223 if (def
->type_
== typeVarchar
) {
1225 if (* (long *) colPtr
== 0L)
1226 vcLenValPairSize
= vcLenValPairSize
+ sizeof(int);
1227 else vcLenValPairSize
= vcLenValPairSize
+ sizeof(int) +
1228 + os::align(strlen((char *) *(long *)colPtr
) + 1);
1231 int size
= (3 + nVarchars
) * sizeof(void *) + 2 * sizeof(int) +
1232 vcLenValPairSize
+ length_
;
1233 void *data
= malloc(size
);
1234 char *ptr
= (char *) data
;
1235 *(long *) ptr
= (long) tptr
; ptr
+= sizeof(void *);
1236 *(int *) ptr
= length_
; ptr
+= sizeof(int);
1237 os::memcpy(ptr
, tptr
, length_
); ptr
+= length_
;
1238 void *metaData
= db_
->getMetaDataPtr();
1239 *(long *) ptr
= (long) metaData
; ptr
+= sizeof(void *);
1240 *(int *) ptr
= nVarchars
; ptr
+= sizeof(int);
1241 *(long *) ptr
= (long) vcChunkPtr_
; ptr
+= sizeof(void *);
1242 fIter
= fldList_
.getIterator();
1243 colPtr
= (char*) curTuple_
;
1244 char *valLenPairPtr
= ptr
+ nVarchars
* sizeof(void *);
1245 while (fIter
.hasElement()) {
1246 FieldDef
*def
= fIter
.nextElement();
1247 colPtr
= (char *) curTuple_
+ def
->offset_
;
1249 if (def
->type_
== typeVarchar
) {
1250 *(long *) ptr
= (long)colPtr
; ptr
+= sizeof(void *);
1251 if (*(long *) colPtr
== 0L) {
1252 *(int *) valLenPairPtr
= vcStrLen
= 0;
1253 valLenPairPtr
+= sizeof(int);
1255 *(int *) valLenPairPtr
= vcStrLen
=
1256 os::align(strlen((char *)*(long *)colPtr
) + 1);
1257 valLenPairPtr
+= sizeof(int);
1258 strcpy(valLenPairPtr
, (char *)*(long *)colPtr
);
1259 valLenPairPtr
+= vcStrLen
;
1263 ret
= (*trans
)->appendUndoLog(sysDB_
, UpdateOperation
, data
, size
);
1268 lMgr_
->releaseLock(curTuple_
);
1269 (*trans
)->removeFromHasList(db_
, curTuple_
);
1271 sysDB_
->releaseCheckpointMutex();
1276 int iNullVal
=iNullInfo
;
1277 char *cNullVal
= NULL
;
1278 if (numFlds_
> 32) {
1279 addSize
= os::align(numFlds_
);
1280 cNullVal
= (char *) malloc(addSize
);
1281 os::memcpy(cNullVal
, cNullInfo
, addSize
);
1283 bool nullCharSet
= false;
1284 if (numFlds_
<= 32){
1287 iNullInfo
= *(int*)((char*)(curTuple_
) + (length_
- addSize
));
1289 *(int*)((char*)(curTuple_
) + (length_
-addSize
)) |= iNullInfo
;
1292 while(i
< numFlds_
) {
1293 if(cNullInfo
[i
++]) { nullCharSet
= true; break; }
1295 char *null
=(char*)(curTuple_
) + (length_
-addSize
);
1298 while(i
< numFlds_
) {
1299 if(null
[i
]) cNullInfo
[i
] = null
[i
];
1304 while(i
< numFlds_
) {
1305 if(cNullInfo
[i
]) { null
[i
] |= cNullInfo
[i
]; }
1310 DbRetVal rv
= copyValuesFromBindBuffer(curTuple_
, false);
1311 if (rv
!= OK
&& !loadFlag
) {
1312 lMgr_
->releaseLock(curTuple_
);
1313 (*trans
)->removeFromHasList(db_
, curTuple_
);
1314 sysDB_
->releaseCheckpointMutex();
1317 if (numFlds_
<= 32) {
1319 *(int*)((char*)(curTuple_
) + (length_
-addSize
)) = iNullInfo
;
1321 } else iNullInfo
=iNullVal
;
1324 char *null
=(char*)(curTuple_
) + (length_
-addSize
);
1326 os::memcpy(null
, cNullInfo
, addSize
);
1327 while (i
< numFlds_
) cNullInfo
[i
++] = 0;
1328 } else os::memcpy(cNullInfo
, cNullVal
, addSize
);
1329 free(cNullVal
); cNullVal
= NULL
;
1331 sysDB_
->releaseCheckpointMutex();
1335 void TableImpl::printInfo()
1337 printf(" <TableName> %s </TableName>\n", tblName_
);
1338 printf(" <TupleCount> %d </TupleCount>\n", numTuples());
1339 printf(" <PagesUsed> %d </PagesUsed>\n", pagesUsed());
1340 printf(" <SpaceUsed> %d </SpaceUsed>\n", spaceUsed());
1341 printf(" <Indexes> %d <Indexes>\n", numIndexes_
);
1342 printf(" <TupleLength> %d </TupleLength>\n", length_
);
1343 printf(" <Fields> %d </Fields>\n", numFlds_
);
1344 printf(" <Indexes>\n");
1345 for (int i
=0; i
<numIndexes_
; i
++)
1346 printf("<IndexName> %s </IndexName>\n", CatalogTableINDEX::getName(indexPtr_
[i
]));
1347 printf(" </Indexes>\n");
1350 long long TableImpl::getLastInsertedVal(DbRetVal
&rv
)
1353 return *(long long*)ptrToAuto
;
1355 DbRetVal
TableImpl::copyValuesFromBindBuffer(void *tuplePtr
, bool isInsert
)
1357 //Iterate through the bind list and copy the value here
1358 FieldIterator fIter
= fldList_
.getIterator();
1359 char *colPtr
= (char*) tuplePtr
;
1361 while (fIter
.hasElement())
1363 FieldDef
*def
= fIter
.nextElement();
1364 if(def
->isAutoIncrement_
&& isInsert
)
1366 if (OK
!= takeTableMutex())
1368 printError(ErrLockTimeOut
,
1369 " Unable to take table mutex for increment key");
1370 return ErrLockTimeOut
;
1372 AllDataType::copyVal(&tempAutoVal
,ptrToAuto
, def
->type_
, def
->length_
);
1373 if(def
->bindVal_
==NULL
)
1375 AllDataType::increment(colPtr
, &tempAutoVal
, def
->type_
);
1376 AllDataType::copyVal(ptrToAuto
,colPtr
, def
->type_
,
1378 colPtr
= colPtr
+ def
->length_
;
1381 if(AllDataType::compareVal(def
->bindVal_
, &tempAutoVal
, OpGreaterThan
,
1383 AllDataType::copyVal(ptrToAuto
,def
->bindVal_
, def
->type_
,
1387 releaseTableMutex();
1391 if (def
->isNull_
&& !def
->isDefault_
&& NULL
== def
->bindVal_
&&
1394 printError(ErrNullViolation
,
1395 "NOT NULL constraint violation for field %s", def
->fldName_
);
1396 return ErrNullViolation
;
1398 if (def
->isDefault_
&& NULL
== def
->bindVal_
&& isInsert
)
1400 if (! def
->isNullExplicit_
) {
1401 if (def
->type_
== typeVarchar
) {
1404 ((Chunk
*) vcChunkPtr_
)->allocate(db_
, def
->length_
, &rv
);
1405 *(long *)colPtr
= (long)ptr
;
1406 AllDataType::convert(typeString
, def
->defaultValueBuf_
,
1407 def
->type_
, ptr
, def
->length_
);
1409 void *dest
= AllDataType::alloc(def
->type_
, def
->length_
);
1410 AllDataType::convert(typeString
, def
->defaultValueBuf_
,
1411 def
->type_
, dest
, def
->length_
);
1412 AllDataType::copyVal(colPtr
, dest
, def
->type_
,
1418 *(long *) colPtr
= 0L;
1420 if (def
->type_
!= typeVarchar
) colPtr
= colPtr
+ def
->length_
;
1421 else colPtr
= colPtr
+ sizeof(void *);
1428 if (NULL
!= def
->bindVal_
)
1430 if(!isInsert
&& isFldNull(fldpos
)){clearNullBit(fldpos
);}
1431 // strncpy((char*)colPtr, (char*)def->bindVal_, def->length_);
1432 // *(((char*)colPtr) + (def->length_-1)) = '\0';
1433 strcpy((char*)colPtr
, (char*)def
->bindVal_
);
1435 else if (!def
->isNull_
&& isInsert
) setNullBit(fldpos
);
1436 colPtr
= colPtr
+ def
->length_
;
1439 if (NULL
!= def
->bindVal_
)
1441 if(!isInsert
&& isFldNull(fldpos
)){clearNullBit(fldpos
);}
1442 DbRetVal rv
= AllDataType::strToValue(colPtr
,
1443 (char *) def
->bindVal_
, def
->type_
, def
->length_
);
1444 if (rv
!= OK
) return ErrBadArg
;
1445 } else if (!def
->isNull_
&& isInsert
&& !def
->bindVal_
) {
1448 colPtr
= colPtr
+ def
->length_
;
1451 if (NULL
!= def
->bindVal_
) {
1452 if (!isInsert
&& isFldNull(fldpos
)) {clearNullBit(fldpos
);}
1455 if (*(long *) colPtr
!= 0L)
1456 ((Chunk
*) vcChunkPtr_
)->free(db_
,
1457 (void *)*(long *)colPtr
);
1458 *(long *) colPtr
= 0L;
1460 if (strcmp((char *)def
->bindVal_
,"") != 0) {
1462 ((Chunk
*) vcChunkPtr_
)->allocate(db_
,
1464 if (rv
!= OK
) return ErrBadArg
;
1465 *(long *)colPtr
= (long)ptr
;
1466 strcpy((char *)ptr
, (char *)def
->bindVal_
);
1467 } else { setNullBit(fldpos
); }
1468 } else if (!def
->isNull_
&& isInsert
) setNullBit(fldpos
);
1469 colPtr
= colPtr
+ sizeof(void *);
1472 if (NULL
!= def
->bindVal_
) {
1473 if(!isInsert
&& isFldNull(fldpos
)){clearNullBit(fldpos
);}
1474 AllDataType::copyVal(colPtr
, def
->bindVal_
, def
->type_
);
1475 } else { if (!def
->isNull_
&& isInsert
) setNullBit(fldpos
); }
1476 colPtr
= colPtr
+ def
->length_
;
1484 void TableImpl::clearNullBit(int fldpos
)
1486 if (fldpos
<1 || fldpos
> numFlds_
) return;
1487 if (isIntUsedForNULL
) CLEARBIT(iNullInfo
, fldpos
-1);
1488 else cNullInfo
[fldpos
-1] = 0;
1491 void TableImpl::setNullBit(int fldpos
)
1493 if (fldpos
<1 || fldpos
> numFlds_
) return;
1494 if (isIntUsedForNULL
) SETBIT(iNullInfo
, fldpos
-1);
1495 else cNullInfo
[fldpos
-1] = 1;
1498 DbRetVal
TableImpl::copyValuesToBindBuffer(void *tuplePtr
)
1500 //Iterate through the bind list and copy the value here
1501 char *colPtr
= (char*) tuplePtr
;
1502 FieldDef
*def
= NULL
;
1503 for (int i
= 0; i
< numBindFlds_
; i
++) {
1504 def
= (FieldDef
*) bindListArray_
[i
];
1505 colPtr
= (char *) tuplePtr
+ def
->offset_
;
1506 if (def
->type_
!= typeVarchar
)
1507 AllDataType::copyVal(def
->bindVal_
, colPtr
, def
->type_
,
1510 char *ptr
= (char *) *(long *) colPtr
;
1511 if (ptr
!= NULL
) strcpy((char *)def
->bindVal_
, ptr
);
1517 //-1 index not supported
1518 DbRetVal
TableImpl::insertIndexNode(Transaction
*tr
, void *indexPtr
, IndexInfo
*info
, void *tuple
)
1520 CINDEX
*iptr
= (CINDEX
*)indexPtr
;
1522 printDebug(DM_Table
, "Inside insertIndexNode type %d", iptr
->indexType_
);
1523 Index
* idx
= Index::getIndex(iptr
->indexType_
);
1524 ret
= idx
->insert(this, tr
, indexPtr
, info
, tuple
,loadFlag
);
1528 DbRetVal
TableImpl::deleteIndexNode(Transaction
*tr
, void *indexPtr
, IndexInfo
*info
, void *tuple
)
1530 CINDEX
*iptr
= (CINDEX
*)indexPtr
;
1532 Index
* idx
= Index::getIndex(iptr
->indexType_
);
1533 ret
= idx
->remove(this, tr
, indexPtr
, info
, tuple
, loadFlag
);
1536 void TableImpl::printSQLIndexString(FILE *fp
, int fd
)
1538 if (fp
== NULL
) fp
= stdout
;
1539 CatalogTableINDEXFIELD
cIndexField(sysDB_
);
1540 char fName
[IDENTIFIER_LENGTH
];
1541 char idxName
[IDENTIFIER_LENGTH
];
1542 char *fldName
= fName
;
1544 for (int i
= 0; i
< numIndexes_
; i
++)
1546 CINDEX
*iptr
= (CINDEX
*) indexPtr_
[i
];
1547 sprintf(idxName
,"%s_idx_Auto_increment",getName());
1548 if(strcmp(iptr
->indName_
,idxName
)==0){ continue; }
1549 if (Conf::config
.useDurability()) {
1551 strcpy(obj
.name
, iptr
->indName_
);
1552 if (iptr
->indexType_
== hashIndex
) {
1554 obj
.bucketChunk
= ((Chunk
*)iptr
->chunkPtr_
)->getFirstPage();
1555 obj
.firstPage
= ((Chunk
*)iptr
->hashNodeChunk_
)->getFirstPage();
1556 obj
.curPage
= ((Chunk
*)iptr
->hashNodeChunk_
)->getCurrentPage();
1557 } else if (iptr
->indexType_
== treeIndex
) {
1559 obj
.firstPage
= ((Chunk
*)iptr
->chunkPtr_
)->getFirstPage();
1560 obj
.curPage
= ((Chunk
*)iptr
->chunkPtr_
)->getCurrentPage();
1561 long nodes
= ((Chunk
*)iptr
->chunkPtr_
)->getTotalDataNodes();
1563 ChunkIterator cIter
= ((Chunk
*)iptr
->chunkPtr_
)->getIterator();
1564 obj
.bucketChunk
= cIter
.nextElement();
1565 } else obj
.bucketChunk
= NULL
;
1569 write(fd
, buf
, sizeof(obj
));
1571 fprintf(fp
, "CREATE INDEX %s on %s ( ", iptr
->indName_
, getName());
1573 cIndexField
.getFieldInfo(iptr
, fldList
);
1574 FieldIterator fIter
= fldList
.getIterator();
1575 bool firstFld
= true;
1576 while(fIter
.hasElement())
1578 FieldDef
*def
= fIter
.nextElement();
1579 if (firstFld
) { fprintf(fp
, " %s ", def
->fldName_
); firstFld
= false; }
1580 else fprintf(fp
, " ,%s ", def
->fldName_
);
1582 fldList
.removeAll();
1585 if (iptr
->indexType_
== hashIndex
) fprintf(fp
, " HASH ");
1586 else if (iptr
->indexType_
== treeIndex
) fprintf(fp
, " TREE ");
1587 else fprintf(fp
, " TRIE ");
1589 HashIndexInfo
* hInfo
= (HashIndexInfo
*)idxInfo
[i
];
1590 if (hInfo
->isUnique
) fprintf(fp
, " UNIQUE");
1591 if(hInfo
->noOfBuckets
!= 1009 &&
1592 hInfo
->noOfBuckets
!=0) fprintf(fp
, " SIZE %d ",((HashIndexInfo
*) idxInfo
[i
])->noOfBuckets
);
1598 DbRetVal
TableImpl::updateIndexNode(Transaction
*tr
, void *indexPtr
, IndexInfo
*info
, void *tuple
)
1600 CINDEX
*iptr
= (CINDEX
*)indexPtr
;
1602 Index
* idx
= Index::getIndex(iptr
->indexType_
);
1603 //TODO::currently it updates irrespective of whether the key changed or not
1604 //because of this commenting the whole index update code. relook at it and uncomment
1606 ret
= idx
->update(this, tr
, indexPtr
, info
, tuple
, loadFlag
);
1612 void TableImpl::setTableInfo(char *name
, int tblid
, size_t length
,
1613 int numFld
, int numIdx
, void *chunk
, void *vcchunk
)
1615 strcpy(tblName_
, name
);
1619 numIndexes_
= numIdx
;
1621 vcChunkPtr_
= vcchunk
;
1624 long TableImpl::spaceUsed()
1626 Chunk
*chk
= (Chunk
*)chunkPtr_
;
1627 long totSize
= chk
->getTotalDataNodes() * chk
->getSize();
1628 totSize
= totSize
+ (chk
->totalPages() * sizeof (PageInfo
));
1632 int TableImpl::pagesUsed()
1634 Chunk
*chk
= (Chunk
*)chunkPtr_
;
1635 return chk
->totalPages();
1638 long TableImpl::numTuples()
1640 return ((Chunk
*)chunkPtr_
)->getTotalDataNodes();
1643 List
TableImpl::getFieldNameList()
1646 FieldIterator fIter
= fldList_
.getIterator();
1647 char fieldName
[IDENTIFIER_LENGTH
];
1648 while (fIter
.hasElement())
1650 FieldDef
*def
= fIter
.nextElement();
1651 Identifier
*elem
= new Identifier();
1652 Table::getFieldNameAlone(def
->fldName_
, fieldName
);
1653 sprintf(elem
->name
, "%s.%s", getName(), fieldName
);
1654 fldNameList
.append(elem
);
1658 DbRetVal
TableImpl::close()
1660 if (iter
) { iter
->close(); delete iter
; iter
= NULL
; }
1661 TableImpl
*fkTbl
=NULL
;
1662 ListIterator tblIter
= tblList
.getIterator();
1664 while (tblIter
.hasElement()){
1665 fkTbl
= (TableImpl
*) tblIter
.nextElement();
1669 tblIter
= tblFkList
.getIterator();
1671 while (tblIter
.hasElement()){
1672 fkTbl
= (TableImpl
*) tblIter
.nextElement();
1676 printDebug(DM_Database
,"Closing table handle: %x", this);
1679 ListIterator pIter
= predList
.getIterator();
1680 while (pIter
.hasElement())
1682 PredicateImpl
*pImpl
= (PredicateImpl
*) pIter
.nextElement();
1687 logFinest(Conf::logger
, "Closing Table");
1691 DbRetVal
TableImpl::closeScan()
1693 //do not throw scan not open error
1694 //this function will be called by table handle
1700 DbRetVal
TableImpl::takeTableMutex()
1702 struct timeval timeout
, timeval
;
1703 timeout
.tv_sec
= Conf::config
.getMutexSecs();
1704 timeout
.tv_usec
= Conf::config
.getMutexUSecs();
1706 int totalTries
= Conf::config
.getMutexRetries() *2;
1708 while (tries
< totalTries
)
1710 ret
= sysDB_
->getAllocDatabaseMutex();
1711 if (ret
== 0) break;
1712 timeval
.tv_sec
= timeout
.tv_sec
;
1713 timeval
.tv_usec
= timeout
.tv_usec
;
1714 os::select(0, 0, 0, 0, &timeval
);
1717 if (tries
>= totalTries
) return ErrLockTimeOut
;
1720 DbRetVal
TableImpl::releaseTableMutex()
1722 sysDB_
->releaseAllocDatabaseMutex();
1726 DbRetVal
TableImpl::lock(bool shared
)
1732 ret = lMgr_->getSharedLock(chunkPtr_, NULL);
1734 ret = lMgr_->getExclusiveLock(chunkPtr_, NULL);
1737 printError(ret, "Could not exclusive lock on the table %x", chunkPtr_);
1739 //do not append for S to X upgrade
1740 if (!ProcessManager::hasLockList.exists(chunkPtr_))
1741 ProcessManager::hasLockList.append(chunkPtr_);
1746 DbRetVal
TableImpl::unlock()
1749 if (!ProcessManager::hasLockList.exists(chunkPtr_)) return OK;
1750 DbRetVal ret = lMgr_->releaseLock(chunkPtr_);
1753 printError(ret, "Could not release exclusive lock on the table %x", chunkPtr_);
1756 ProcessManager::hasLockList.remove(chunkPtr_);
1762 TableImpl::~TableImpl()
1764 if (NULL
!= iter
) { delete iter
; iter
= NULL
; }
1765 if (NULL
!= indexPtr_
) { delete[] indexPtr_
; indexPtr_
= NULL
; }
1766 if (NULL
!= idxInfo
)
1768 for (int i
= 0; i
< numIndexes_
; i
++) delete idxInfo
[i
];
1772 if (numFlds_
> 32 && cNullInfo
!= NULL
) {
1773 free(cNullInfo
); cNullInfo
= NULL
;
1775 if (bindList_
.size()) bindList_
.reset();
1776 if (bindListArray_
) { free (bindListArray_
); bindListArray_
= NULL
; }
1777 fldList_
.removeAll();
1781 void *TableImpl::getBindFldAddr(const char *name
)
1783 return fldList_
.getBindField(name
);
1785 bool TableImpl::isTableInvolved(char *tblName
)
1787 //printf("Table isTableInvolved called for %s with %s\n", tblName, getName());
1788 if (0 == strcmp(getName(), tblName
)) return true; else return false;
1790 bool TableImpl::pushPredicate(Predicate
*pred
)
1793 PredicateImpl
*pImpl
= (PredicateImpl
*) pred
;
1794 char tableName
[IDENTIFIER_LENGTH
];
1795 Table::getTableNameAlone(pImpl
->getFldName1(), tableName
);
1796 //printf("predicate tbl name %s\n", tableName);
1798 //if predicate is of form t1.f1=t2.f1 then do not push here
1799 bool isAliasSet
= (0 !=strcmp(getAliasName(),"")) ;
1800 if (0 != strcmp(pImpl
->getFldName2(),"")) return ret
;
1802 if (0 == strcmp(getName(), tableName
) ||(isAliasSet
&& 0 == strcmp(getAliasName(), tableName
)))
1805 //printf("PRABA::pushed predicate in tablehdl %s\n", getName());
1811 void TableImpl::setCondition(Condition
*p
)
1813 isPlanCreated
= false;
1814 ListIterator pIter
= predList
.getIterator();
1815 while (pIter
.hasElement())
1817 PredicateImpl
*pImpl
= (PredicateImpl
*) pIter
.nextElement();
1822 if (p
) pred_
= p
->getPredicate(); else pred_
= NULL
;
1825 void TableImpl::setPredicate(Predicate
*pred
)
1827 if (NULL
== pred_
) { pred_
= pred
; return; }
1829 Predicate
*curPred
= pred_
;
1830 PredicateImpl
*newPred
= new PredicateImpl();
1831 newPred
->setTerm(curPred
, OpAnd
, pred
);
1832 newPred
->setTable(this);
1836 void TableImpl::printPlan(int space
)
1838 char spaceBuf
[IDENTIFIER_LENGTH
];
1839 memset(spaceBuf
, 32, IDENTIFIER_LENGTH
);
1840 spaceBuf
[space
] = '\0';
1841 printf("%s <TABLE-NODE>\n", spaceBuf
);
1842 printf("%s <NAME> %s </NAME>\n", spaceBuf
, getName());
1843 printf("%s <ScanType> %s </ScanType>\n", spaceBuf
, ScanTypeNames
[scanType_
]);
1844 PredicateImpl
*pred
= (PredicateImpl
*)pred_
;
1845 if (pred
) pred
->print(space
+2);
1846 printf("%s </TABLE-NODE>\n", spaceBuf
);
1848 void TableImpl::printSQLForeignString()
1851 FieldNameList pkFieldList
,fkFieldList
;
1853 void *tFkptr
= NULL
;
1854 void *chunkPk
= NULL
;
1855 void *vcchunkPk
= NULL
;
1856 CatalogTableTABLE
cTable(sysDB_
);
1857 TableImpl
*fkTbl
=NULL
;
1858 ListIterator tblIter
= tblList
.getIterator();
1861 while (tblIter
.hasElement()){
1862 fkTbl
= (TableImpl
*) tblIter
.nextElement();
1863 rv
= cTable
.getChunkAndTblPtr(fkTbl
->getName(), chunkPk
, tPkptr
,vcchunkPk
);
1864 if ( OK
!= rv
){return ;}
1865 rv
= cTable
.getChunkAndTblPtr(getName(), chunkPk
, tFkptr
, vcchunkPk
);
1866 if ( OK
!= rv
){return ;}
1867 CatalogTableFK
cFk(sysDB_
);
1868 rv
= cFk
.getPkFkFieldInfo(tPkptr
,tFkptr
,pkFieldList
,fkFieldList
);
1869 if ( OK
!= rv
){return;}
1870 pkFieldList
.resetIter();
1871 fkFieldList
.resetIter();
1872 char *fldName
= NULL
;
1873 bool firstField
=true;
1874 if(!firstFK
) printf(", ");
1875 printf(", FOREIGN KEY ( ");
1876 while((fldName
= fkFieldList
.nextFieldName())!= NULL
)
1879 printf("%s",fldName
);
1883 printf(",%s",fldName
);
1885 printf(" ) REFERENCES %s ( ",fkTbl
->getName());
1887 while((fldName
= pkFieldList
.nextFieldName())!= NULL
)
1890 printf("%s",fldName
);
1894 printf(",%s",fldName
);
1898 pkFieldList
.removeAll();
1899 fkFieldList
.removeAll();
1903 bool TableImpl::isPkTableHasRecord(char *pkTableName
, TableImpl
*fkTbl
,bool isInsert
)
1906 bool isRecExist
=false;
1907 FieldNameList pkFieldList
,fkFieldList
;
1909 void *tFkptr
= NULL
;
1910 void *chunkPk
= NULL
;
1911 void *vcchunkPk
= NULL
;
1912 CatalogTableTABLE
cTable(sysDB_
);
1913 rv
= cTable
.getChunkAndTblPtr(pkTableName
, chunkPk
, tPkptr
, vcchunkPk
);
1914 if ( OK
!= rv
){return false;}
1915 rv
= cTable
.getChunkAndTblPtr(getName(), chunkPk
, tFkptr
, vcchunkPk
);
1916 if ( OK
!= rv
){return false;}
1917 CatalogTableFK
cFk(sysDB_
);
1918 rv
= cFk
.getPkFkFieldInfo(tPkptr
,tFkptr
,pkFieldList
,fkFieldList
);
1919 if ( OK
!= rv
){return false;}
1920 int totFld
= pkFieldList
.size();
1921 Condition
*condition
= new Condition
[totFld
];
1922 char *pkFldName
= NULL
;
1923 char *fkFldName
= NULL
;
1926 pkFieldList
.resetIter();
1927 fkFieldList
.resetIter();
1929 while((pkFldName
= pkFieldList
.nextFieldName())!= NULL
)
1931 fkFldName
= fkFieldList
.nextFieldName();
1932 FieldIterator fIter
= fldList_
.getIterator();
1933 while (fIter
.hasElement())
1935 def
= fIter
.nextElement();
1936 if (strcmp(def
->fldName_
, fkFldName
) == 0)
1938 if(NULL
== def
->bindVal_
&& isInsert
) { return true; }
1939 if(NULL
== def
->bindVal_
) {
1940 if (def
->type_
!= typeVarchar
)
1941 val
= (char*)curTuple_
+ def
->offset_
;
1942 else val
= (void *) *(long *) ((char*)curTuple_
+
1945 val
= def
->bindVal_
;
1947 if(def
->type_
==typeString
)
1948 condition
[i
].setTerm(pkFldName
,OpEquals
,&val
);
1950 condition
[i
].setTerm(pkFldName
,OpEquals
,val
);
1956 pkFieldList
.removeAll();
1957 fkFieldList
.removeAll();
1958 Condition
*cond
= NULL
;
1959 if(i
== 0 && !isInsert
)return true;
1961 cond
= new Condition
[i
-1];
1965 for(j
=0;j
<totcon
-1;j
++)
1968 cond
[j
].setTerm(condition
[i
++].getPredicate(),OpAnd
,condition
[i
++].getPredicate());
1970 cond
[j
].setTerm(cond
[j
-1].getPredicate(), OpAnd
, condition
[i
++].getPredicate());
1972 fkTbl
->setCondition(&cond
[j
-1]);
1975 fkTbl
->setCondition(&condition
[i
-1]);
1989 bool TableImpl::isFkTableHasRecord(char *pkTableName
, TableImpl
*fkTbl
)
1992 FieldNameList pkFieldList
,fkFieldList
;
1994 void *tFkptr
= NULL
;
1995 void *chunkPk
= NULL
;
1996 void *vcchunkPk
= NULL
;
1997 CatalogTableTABLE
cTable(sysDB_
);
1998 rv
= cTable
.getChunkAndTblPtr(getName(), chunkPk
, tPkptr
, vcchunkPk
);
1999 if ( OK
!= rv
){return false;}
2000 rv
= cTable
.getChunkAndTblPtr(pkTableName
, chunkPk
, tFkptr
, vcchunkPk
);
2001 if ( OK
!= rv
){return false;}
2002 CatalogTableFK
cFk(sysDB_
);
2003 rv
= cFk
.getPkFkFieldInfo(tPkptr
,tFkptr
,pkFieldList
,fkFieldList
);
2004 if ( OK
!= rv
){return false;}
2005 int totFld
= pkFieldList
.size();
2006 Condition
*condition
= new Condition
[totFld
];
2007 char *pkFldName
= NULL
;
2008 char *fkFldName
= NULL
;
2011 pkFieldList
.resetIter();
2012 fkFieldList
.resetIter();
2013 while((pkFldName
= pkFieldList
.nextFieldName())!= NULL
)
2015 fkFldName
= fkFieldList
.nextFieldName();
2016 FieldIterator fIter
= fldList_
.getIterator();
2017 while (fIter
.hasElement())
2019 def
= fIter
.nextElement();
2021 if (def
->type_
!= typeVarchar
)
2022 val
= (char*)curTuple_
+ def
->offset_
;
2023 else val
= (void *) *(long *) ((char*)curTuple_
+ def
->offset_
);
2024 if (strcmp(def
->fldName_
, pkFldName
) == 0)
2026 if(def
->type_
==typeString
)
2027 condition
[i
].setTerm(fkFldName
,OpEquals
,&val
);//((char*)curTuple_+def->offset_));
2029 condition
[i
].setTerm(fkFldName
,OpEquals
,val
);//((char*)curTuple_+def->offset_));
2035 pkFieldList
.removeAll();
2036 fkFieldList
.removeAll();
2037 if(i
== 0 )return true;
2038 Condition
*cond
= new Condition
[i
-1];
2041 for(j
=0;j
<totFld
-1;j
++)
2044 cond
[j
].setTerm(condition
[i
++].getPredicate(),OpAnd
,condition
[i
++].getPredicate());
2046 cond
[j
].setTerm(cond
[j
-1].getPredicate(), OpAnd
, condition
[i
++].getPredicate());
2049 fkTbl
->setCondition(&condition
[totFld
-1]);
2051 fkTbl
->setCondition(&cond
[j
-1]);
2063 DbRetVal
TableImpl::compact()
2066 int ret
=((Chunk
*)chunkPtr_
)->compact(db_
->procSlot
);
2067 if(ret
!=0) return ErrLockTimeOut
;
2069 if (NULL
!= vcChunkPtr_
) {
2070 ret
= ((Chunk
*)vcChunkPtr_
)->compact(db_
->procSlot
);
2071 if(ret
!=0) return ErrLockTimeOut
;
2074 if (NULL
!= indexPtr_
)
2078 for (i
= 0; i
< numIndexes_
; i
++)
2080 rv
= compactIndexNode(indexPtr_
[i
]);
2082 printError(rv
, "Error in compacting index Node");
2090 DbRetVal
TableImpl::compactIndexNode( void *indexPtr
)
2092 CINDEX
*iptr
= (CINDEX
*)indexPtr
;
2094 printDebug(DM_Table
, "Inside insertIndexNode type %d", iptr
->indexType_
);
2095 if( hashIndex
== (iptr
->indexType_
) )
2097 ret1
=((Chunk
*)iptr
->hashNodeChunk_
)->compact(db_
->procSlot
);
2099 return ErrLockTimeOut
;
2101 }else if (treeIndex
== (iptr
->indexType_
))
2103 ret1
=((Chunk
*)iptr
->chunkPtr_
)->compact(db_
->procSlot
);
2105 return ErrLockTimeOut
;
2107 } else if ( trieIndex
== (iptr
->indexType_
))
2109 ret1
=((Chunk
*)iptr
->chunkPtr_
)->compact(db_
->procSlot
);
2111 return ErrLockTimeOut
;
2113 ret1
=((Chunk
*)iptr
->hashNodeChunk_
)->compact(db_
->procSlot
);
2115 return ErrLockTimeOut
;