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
)) 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 bool isBitSet
= false;
132 if (isIntUsedForNULL
) {
133 if (!BITSET(iNotNullInfo
, fldpos
)) {
134 SETBIT(iNullInfo
, fldpos
);
138 printError(ErrNullViolation
, "NOT NULL constraint violation");
139 return ErrNullViolation
;
143 if (!cNotNullInfo
[fldpos
-1]) cNullInfo
[fldpos
-1] = 1;
145 printError(ErrNullViolation
, "NOT NULL constraint violation");
146 return ErrNullViolation
;
152 void TableImpl::clearFldNull(const char *name
)
154 int colpos
= fldList_
.getFieldPosition(name
);
157 printError(ErrNotExists
, "Field %s does not exist", name
);
160 clearFldNull(colpos
);
163 void TableImpl::clearFldNull(int colpos
)
165 if (colpos
<1 || colpos
> numFlds_
) return;
166 if (isIntUsedForNULL
) {
167 CLEARBIT(iNullInfo
, colpos
);
170 cNullInfo
[colpos
-1] = 0;
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
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
205 return info
->indType
;
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
);
228 PredicateImpl
*bothPred
= new PredicateImpl();
229 bothPred
->setTerm(pred
, OpAnd
, newPred
);
230 predList
.append(bothPred
);
234 DbRetVal
TableImpl::optimize()
236 //table ptr is set in predicate because it needs to access the
237 //type and length to evaluate
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
; }
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
);
254 printError(ErrSysFatal
,"Unable to create tuple iterator");
255 //should never happen
262 DbRetVal
TableImpl::execute()
264 if (iter
&& !iter
->isIterClosed())
266 //printError(ErrAlready,"Scan already open:Close and re execute");
270 if (!isPlanCreated
) ret
= optimize();
273 printError(ErrSysInternal
,"Unable to create the plan");
274 return ErrSysInternal
;
279 printError(ret
,"Unable to open the iterator");
286 DbRetVal
TableImpl::createPlan()
289 //will do early return here. plan is generated only when setPredicate is called.
290 if (scanType_
== unknownScan
) return ErrSysFatal
; //this should never happen
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 *));
307 ListIterator it
= bindList_
.getIterator();
308 while ((elem
= it
.nextElement()) != NULL
) bindListArray_
[i
++] = elem
;
309 scanType_
= fullTableScan
;
310 isPlanCreated
= true;
312 //if there are no predicates then go for full scan
313 //if there are no indexes then go for full scan
314 if (NULL
== pred_
|| NULL
== indexPtr_
)
318 if (NULL
!= indexPtr_
)
320 PredicateImpl
*pred
= (PredicateImpl
*)pred_
;
321 //If searching for IS NULL or IS NOT NULL then fullscan
322 if(pred
->isIsNullInvolved())
324 scanType_
= fullTableScan
;
325 shouldNullSearch
=true;
328 printDebug(DM_Predicate
, "predicate does not involve NOT , OR operator");
329 if (!pred
->isNotOrInvolved())
331 printDebug(DM_Predicate
, "predicate does not involve NOT , OR operator");
332 for (int i
=0; i
< numIndexes_
; i
++)
334 bool isAllFldPointLookup
= true;
335 HashIndexInfo
* info
= (HashIndexInfo
*) idxInfo
[i
];
336 FieldIterator iter
= info
->idxFldList
.getIterator();
338 while(iter
.hasElement())
341 FieldDef
*def
= iter
.nextElement();
342 if (pred
->pointLookupInvolved(def
->fldName_
))
344 if (!isAllFldPointLookup
) break;
345 printDebug(DM_Predicate
, "point lookup involved for field %s",def
->fldName_
);
346 if(hashIndex
== info
->indType
) scanType_
= hashIndexScan
;
347 else scanType_
= treeIndexScan
;
351 else if (pred
->isBetweenInvolved(def
->fldName_
))
353 if (treeIndex
== info
->indType
)
355 scanType_
= treeIndexScan
;
358 break; //no composite index for tree index
359 } else isAllFldPointLookup
= false;
361 else if (pred
->rangeQueryInvolved(def
->fldName_
))
363 printDebug(DM_Predicate
, "range lookup involved for field %s",def
->fldName_
);
364 if (treeIndex
== info
->indType
)
366 scanType_
= treeIndexScan
;
368 break; //no composite index for tree index
369 } else isAllFldPointLookup
=false;
372 isAllFldPointLookup
= false;
375 }//while iter.hasElement()
376 if( noOfIfld
== 1 && useIndex_
!= -1)return OK
;
377 if (!isAllFldPointLookup
&& useIndex_
!= -1) return OK
;
381 scanType_
= fullTableScan
;
385 void* TableImpl::fetch()
388 if (NULL
== curTuple_
) return curTuple_
;
389 copyValuesToBindBuffer(curTuple_
);
392 void* TableImpl::fetch(DbRetVal
&rv
)
395 if (NULL
== curTuple_
) return curTuple_
;
396 copyValuesToBindBuffer(curTuple_
);
400 void* TableImpl::fetchNoBind()
404 printError(ErrNotOpen
,"Scan not open or Scan is closed\n");
407 void *prevTuple
= curTuple_
;
408 curTuple_
= iter
->next();
409 if (NULL
== curTuple_
)
413 DbRetVal lockRet
= OK
;
415 if ((*trans
)->isoLevel_
== READ_COMMITTED
)
417 //if iso level is read committed, operation duration lock is sufficent
418 //so release it here itself.
419 int tries
= Conf::config
.getMutexRetries();
420 struct timeval timeout
, timeval
;
421 timeout
.tv_sec
= Conf::config
.getMutexSecs();
422 timeout
.tv_usec
= Conf::config
.getMutexUSecs();
426 lockRet
= lMgr_
->isExclusiveLocked( curTuple_
, trans
, status
);
429 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
430 curTuple_
= prevTuple
;
435 if (tries
== 0) break;
436 timeval
.tv_sec
= timeout
.tv_sec
;
437 timeval
.tv_usec
= timeout
.tv_usec
;
438 os::select(0, 0, 0, 0, &timeval
);
442 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
443 curTuple_
= prevTuple
;
447 else if ((*trans
)->isoLevel_
== READ_REPEATABLE
) {
448 if (OK
!= trySharedLock(curTuple_
, trans
))
450 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
451 curTuple_
= prevTuple
;
459 DbRetVal
TableImpl::trySharedLock(void *curTuple
, Transaction
**trans
)
461 DbRetVal lockRet
= OK
;
462 int tries
= Conf::config
.getMutexRetries();
463 while((lockRet
= lMgr_
->getSharedLock(curTuple_
, trans
)) == ErrLockTimeOut
)
466 if (tries
<=0) break;
470 DbRetVal
TableImpl::tryExclusiveLock(void *curTuple
, Transaction
**trans
)
472 DbRetVal lockRet
= OK
;
473 int tries
= Conf::config
.getMutexRetries();
474 while((lockRet
= lMgr_
->getExclusiveLock(curTuple_
, trans
)) == ErrLockTimeOut
)
477 if (tries
<=0) break;
482 void* TableImpl::fetchNoBind(DbRetVal
&rv
)
487 printError(ErrNotOpen
,"Scan not open or Scan is closed\n");
491 void *prevTuple
= curTuple_
;
492 curTuple_
= iter
->next();
493 if (NULL
== curTuple_
)
497 DbRetVal lockRet
= OK
;
499 if ((*trans
)->isoLevel_
== READ_REPEATABLE
) {
500 lockRet
= lMgr_
->getSharedLock(curTuple_
, trans
);
503 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
505 curTuple_
= prevTuple
;
510 else if ((*trans
)->isoLevel_
== READ_COMMITTED
)
512 //if iso level is read committed, operation duration lock is sufficent
513 //so release it here itself.
514 int tries
= Conf::config
.getMutexRetries();
515 //struct timeval timeout;
516 //timeout.tv_sec = Conf::config.getMutexSecs();
517 //timeout.tv_usec = Conf::config.getMutexUSecs();
521 lockRet
= lMgr_
->isExclusiveLocked( curTuple_
, trans
, status
);
524 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
525 curTuple_
= prevTuple
;
531 if (tries
== 0) break;
532 //os::select(0, 0, 0, 0, &timeout);
536 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
537 curTuple_
= prevTuple
;
545 DbRetVal
TableImpl::fetchAgg(const char * fldName
, AggType aType
, void *buf
, bool &noRec
)
547 FieldInfo
*info
= new FieldInfo();
548 DbRetVal rv
= getFieldInfo(fldName
, info
);
549 if (OK
!= rv
) return rv
;
551 if (AGG_MIN
== aType
|| AGG_MAX
== aType
) {
553 IndexType iType
= getIndexType((char*)fldName
, &pos
);
554 if(treeIndex
== iType
&& pos
>=0) {
555 if (AGG_MIN
== aType
) {
556 HashIndexInfo
* hInfo
= (HashIndexInfo
*) idxInfo
[pos
];
557 CINDEX
*iptr
= (CINDEX
*) hInfo
->indexPtr
;
558 TreeNode
*fstNode
=(TreeNode
*)iptr
->hashNodeChunk_
;
561 TreeNode
*start
= (TreeNode
*)*((char**)((char*)fstNode
+ sizeof(TreeNode
)));
562 iter
= new TreeIter(start
,(TreeNode
*)iptr
->hashNodeChunk_
,sysDB_
->procSlot
);
564 iter
= new TreeIter(NULL
,(TreeNode
*)iptr
->hashNodeChunk_
,sysDB_
->procSlot
);
566 char *tuple
= (char*) iter
->getFirstElement();
568 AllDataType::copyVal(buf
,(void*)(tuple
+info
->offset
),
569 info
->type
, info
->length
);
573 delete iter
; iter
= NULL
;
575 else if (AGG_MAX
== aType
) {
576 HashIndexInfo
* hInfo
= (HashIndexInfo
*) idxInfo
[pos
];
577 CINDEX
*iptr
= (CINDEX
*) hInfo
->indexPtr
;
578 TreeNode
*fstNode
=(TreeNode
*)iptr
->hashNodeChunk_
;
581 TreeNode
*start
= (TreeNode
*)*((char**)((char*)fstNode
+ sizeof(TreeNode
)));
582 iter
= new TreeIter(start
,(TreeNode
*)iptr
->hashNodeChunk_
,sysDB_
->procSlot
);
584 iter
= new TreeIter(NULL
,(TreeNode
*)iptr
->hashNodeChunk_
,sysDB_
->procSlot
);
586 char *tuple
= (char*) iter
->getLastElement();
588 AllDataType::copyVal(buf
,(void*)(tuple
+info
->offset
),
589 info
->type
, info
->length
);
590 delete iter
; iter
= NULL
;
593 delete iter
; iter
=NULL
;
596 }else if (AGG_COUNT
== aType
) {
601 DataType type
= info
->type
;
602 int length
= info
->length
;
603 int offset
= info
->offset
;
604 int colPos
= fldList_
.getFieldPosition(fldName
);
605 bool isNullable
= true;
606 if (info
->isNull
|| info
->isPrimary
|| info
->isDefault
|| info
->isAutoIncrement
) {
609 int nullOffset
= length_
-4;
610 if (aType
== AGG_COUNT
) {
611 length
= sizeof(int);
614 if (NULL
== pred_
&& typeInt
== type
&& aType
!= AGG_AVG
)
616 ChunkIterator cIter
= ((Chunk
*)chunkPtr_
)->getIterator();
617 char *tuple
=(char*)cIter
.nextElement();
625 if (isIntUsedForNULL
) {
626 if (BITSET(*(int*)(tuple
+nullOffset
), colPos
)) count
=0;
630 if(isFldNull(colPos
)) count
=0;
633 if (aType
!= AGG_COUNT
)
634 AllDataType::copyVal(buf
, (void*) (tuple
+offset
), type
, length
);
637 cIter
.pageSize
= PAGE_SIZE
;
640 tuple
= (char*)cIter
.nextElementInt();
641 if (NULL
== tuple
) break;
643 if (isIntUsedForNULL
) {
644 if (BITSET(*(int*)(tuple
+nullOffset
), colPos
)) continue;
648 if(isFldNull(colPos
)) continue;
651 if (aType
== AGG_MIN
)
653 if (*(int*)buf
>= *((int*)(tuple
+offset
)))
654 *(int*)buf
= *((int*)(tuple
+offset
));
656 else if (aType
== AGG_MAX
)
658 if (*(int*)buf
<= *((int*)(tuple
+offset
)))
659 *(int*)buf
= *((int*)(tuple
+offset
));
661 else if (aType
== AGG_SUM
)
663 *(int*)buf
+= *((int*)(tuple
+offset
));
665 else if (aType
== AGG_AVG
)
667 *(int*)buf
= *(int*)buf
+ *((int*)(tuple
+offset
));
670 else if (aType
== AGG_COUNT
)
676 if( AGG_AVG
== aType
) AllDataType::divVal(buf
, &count
, type
);
677 else if (AGG_COUNT
== aType
) (*(int*)buf
) = count
;
682 char *tuple
= (char*) fetchNoBind(rv
);
683 if ( NULL
== tuple
) { noRec
= true; return OK
; }
686 while(isFldNull(colPos
)) {
687 tuple
= (char*) fetchNoBind(rv
);
688 if (aType
== AGG_COUNT
) count
++;
691 if ( NULL
== tuple
) { noRec
= true; return OK
; }
693 if (aType
== AGG_AVG
) {
694 AllDataType::convertToDouble(buf
, (void*) (tuple
+offset
), type
);
695 } else if (aType
!= AGG_COUNT
) {
696 AllDataType::copyVal(buf
, (void*) (tuple
+offset
), type
, length
);
699 tuple
= (char*) fetchNoBind(rv
);
700 if (NULL
== tuple
) break;
702 if (isIntUsedForNULL
) {
703 if (BITSET(*(int*)(tuple
+nullOffset
), colPos
)) continue;
707 if(isFldNull(colPos
)) continue;
713 res
= AllDataType::compareVal(buf
, (void*) (tuple
+offset
),
716 if (res
) AllDataType::copyVal(buf
, (void*) (tuple
+offset
),
722 res
= AllDataType::compareVal(buf
, (void*) (tuple
+offset
),
725 if (res
) AllDataType::copyVal(buf
, (void*) (tuple
+offset
),
731 AllDataType::addVal(buf
, (void*) (tuple
+offset
),
738 AllDataType::convertToDouble(&tmpBuf
, (void*) (tuple
+offset
), type
);
739 AllDataType::addVal(buf
, &tmpBuf
, typeDouble
);
753 AllDataType::divVal((double *)buf
, count
, type
);
758 (*(int*)buf
) = count
;
765 DbRetVal
TableImpl::getCheckpointMutex()
769 int totalTries
= Conf::config
.getMutexRetries();
770 struct timeval timeout
, timeval
;
771 timeout
.tv_sec
= Conf::config
.getMutexSecs();
772 timeout
.tv_usec
= Conf::config
.getMutexUSecs();
774 while (tries
< totalTries
)
776 rv
= sysDB_
->getSCheckpointMutex();
778 timeval
.tv_sec
= timeout
.tv_sec
;
779 timeval
.tv_usec
= timeout
.tv_usec
;
780 os::select(0,0,0,0,&timeval
);
783 if (tries
== totalTries
) {
784 printError(ErrLockTimeOut
, "Checkpoint server is running. Retry after sometime.");
785 return ErrLockTimeOut
;
789 DbRetVal
TableImpl::insertTuple()
791 DbRetVal ret
= getCheckpointMutex();
792 if (ret
!=OK
) return ret
;
795 int totalTries
= Conf::config
.getMutexRetries();
796 while (tries
< totalTries
)
799 tptr
= ((Chunk
*)chunkPtr_
)->allocate(db_
, &ret
);
800 if (tptr
!=NULL
) break;
801 if (ret
!= ErrLockTimeOut
)
803 sysDB_
->releaseCheckpointMutex();
804 printError(ret
, "Unable to allocate record from chunk");
811 sysDB_
->releaseCheckpointMutex();
812 printError(ret
, "Unable to allocate record from chunk after %d retries", tries
);
817 TableImpl
*fkTbl
=NULL
;
818 ListIterator tblIter
= tblList
.getIterator();
820 while (tblIter
.hasElement()){
821 fkTbl
= (TableImpl
*) tblIter
.nextElement();
822 bool pkRec
= isPkTableHasRecord(fkTbl
->getName(),fkTbl
,true);
824 printError(ErrForeignKeyInsert
, "Unable to insert into foreign Key table.Check PK table");
825 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
826 sysDB_
->releaseCheckpointMutex();
827 return ErrForeignKeyInsert
;
833 //ret = lMgr_->getExclusiveLock(tptr, trans);
834 if (OK
!= tryExclusiveLock(tptr
, trans
))
836 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
837 printError(ret
, "Could not get lock for the insert tuple %x", tptr
);
838 sysDB_
->releaseCheckpointMutex();
839 return ErrLockTimeOut
;
843 ret
= copyValuesFromBindBuffer(tptr
);
846 printError(ret
, "Unable to copy values from bind buffer");
848 (*trans
)->removeFromHasList(db_
, tptr
);
849 lMgr_
->releaseLock(tptr
);
852 FieldIterator fIter
= fldList_
.getIterator();
853 char *colPtr
= (char*) curTuple_
;
854 while (fIter
.hasElement()) {
855 FieldDef
*def
= fIter
.nextElement();
856 colPtr
= (char *) curTuple_
+ def
->offset_
;
857 if (def
->type_
== typeVarchar
) {
858 char *ptr
= (char *) *(long *) colPtr
;
859 if (ptr
!= 0L) ((Chunk
*) vcChunkPtr_
)->free(db_
, ptr
);
862 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
863 sysDB_
->releaseCheckpointMutex();
870 *(int*)((char*)(tptr
) + (length_
-addSize
)) = iNullInfo
;
874 addSize
= os::align(numFlds_
);
875 os::memcpy(((char*)(tptr
) + (length_
-addSize
)), cNullInfo
, addSize
);
878 //int tupleSize = length_ + addSize;
879 if (NULL
!= indexPtr_
)
883 for (i
= 0; i
< numIndexes_
; i
++)
885 ret
= insertIndexNode(*trans
, indexPtr_
[i
], idxInfo
[i
], tptr
);
886 if (ret
!= OK
) { printError(ret
, "Error in inserting to index %x", tptr
); break;}
890 for (int j
= 0; j
< i
; j
++) {
891 printError(ErrWarning
, "Undo:Deleting index node");
892 deleteIndexNode(*trans
, indexPtr_
[j
], idxInfo
[j
], tptr
);
895 (*trans
)->removeFromHasList(db_
, tptr
);
896 lMgr_
->releaseLock(tptr
);
899 FieldIterator fIter
= fldList_
.getIterator();
900 char *colPtr
= (char*) curTuple_
;
901 while (fIter
.hasElement()) {
902 FieldDef
*def
= fIter
.nextElement();
903 colPtr
= (char *) curTuple_
+ def
->offset_
;
904 if (def
->type_
== typeVarchar
) {
905 char *ptr
= (char *) *(long *) colPtr
;
906 if (ptr
!= 0L) ((Chunk
*) vcChunkPtr_
)->free(db_
, ptr
);
909 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
910 sysDB_
->releaseCheckpointMutex();
915 //TODO: number of varchar fields to be stored as a member in TableImpl
917 FieldIterator fIter
= fldList_
.getIterator();
918 while (fIter
.hasElement()) {
919 FieldDef
*def
= fIter
.nextElement();
920 if (def
->type_
== typeVarchar
) nVarchars
++;
923 // the undo log for insert should contain
924 // tuple ptr + metadata Ptr + no of varchars + ptrs to varchars for insert opearation
925 int size
= (3 + nVarchars
) * sizeof(void *) + sizeof(int);
926 void *data
= malloc(size
);
927 char *ptr
= (char *)data
;
928 *(long *) ptr
= (long) tptr
; ptr
+= sizeof(void *);
929 void *metaData
= db_
->getMetaDataPtr();
930 *(long *) ptr
= (long) metaData
; ptr
+= sizeof(void *);
931 *(int *) ptr
= nVarchars
; ptr
+= sizeof(int);
932 *(long *) ptr
= (long) vcChunkPtr_
; ptr
+= sizeof(void *);
933 fIter
= fldList_
.getIterator();
934 char *colPtr
= (char*) curTuple_
;
935 while (fIter
.hasElement()) {
936 FieldDef
*def
= fIter
.nextElement();
937 colPtr
= (char *) curTuple_
+ def
->offset_
;
938 if (def
->type_
== typeVarchar
) {
939 *(long *) ptr
= (long)colPtr
;
940 ptr
+= sizeof(void *);
943 ret
= (*trans
)->appendUndoLog(sysDB_
, InsertOperation
, data
, size
);
947 printError(ret
, "Unable to create undo log for %x %d", tptr
, *(int*)tptr
);
948 for (int j
= 0; j
< numIndexes_
; j
++) {
949 printError(ErrWarning
, "Deleting index node");
950 deleteIndexNode(*trans
, indexPtr_
[j
], idxInfo
[j
], tptr
);
953 (*trans
)->removeFromHasList(db_
, tptr
);
954 lMgr_
->releaseLock(tptr
);
956 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
958 sysDB_
->releaseCheckpointMutex();
962 DbRetVal
TableImpl::deleteTuple()
964 if (NULL
== curTuple_
)
966 printError(ErrNotOpen
, "Scan not open: No Current tuple");
969 DbRetVal ret
= getCheckpointMutex();
970 if (ret
!= OK
) return ret
;
972 TableImpl
*fkTbl
=NULL
;
973 ListIterator tblIter
= tblFkList
.getIterator();
975 while (tblIter
.hasElement()){
976 fkTbl
= (TableImpl
*) tblIter
.nextElement();
977 bool pkRec
= isFkTableHasRecord(fkTbl
->getName(),fkTbl
);
979 printError(ErrForeignKeyDelete
, "A Relation Exists. Delete from child table first");
980 sysDB_
->releaseCheckpointMutex();
981 return ErrForeignKeyDelete
;
987 //ret = lMgr_->getExclusiveLock(curTuple_, trans);
988 if (OK
!= tryExclusiveLock(curTuple_
, trans
))
990 printError(ret
, "Could not get lock for the delete tuple %x",
992 sysDB_
->releaseCheckpointMutex();
993 return ErrLockTimeOut
;
997 if (NULL
!= indexPtr_
)
1001 for (i
= 0; i
< numIndexes_
; i
++)
1003 ret
= deleteIndexNode(*trans
, indexPtr_
[i
], idxInfo
[i
], curTuple_
);
1004 if (ret
!= OK
) break;
1006 if (i
!= numIndexes_
)
1008 printError(ErrWarning
, "Inserting back index node");
1009 for (int j
= 0; j
< i
; j
++)
1010 insertIndexNode(*trans
, indexPtr_
[j
], idxInfo
[j
], curTuple_
);
1012 lMgr_
->releaseLock(curTuple_
);
1013 (*trans
)->removeFromHasList(db_
, curTuple_
);
1015 printError(ret
, "Unable to insert index node for tuple %x", curTuple_
);
1016 sysDB_
->releaseCheckpointMutex();
1021 // the undo log for delete should contain
1022 // tupleptr + metadataPtr + nVarchars + varchar chunk ptr +
1023 // ptrs to varchars + size and value pairs for varchars
1025 //TODO: number of varchar fields to be stored as a member in TableImpl
1026 void *tptr
= curTuple_
;
1027 char *colPtr
= (char *)curTuple_
;
1029 int vcLenValPairSize
= 0;
1030 FieldIterator fIter
= fldList_
.getIterator();
1031 while (fIter
.hasElement()) {
1032 FieldDef
*def
= fIter
.nextElement();
1033 colPtr
= (char *) curTuple_
+ def
->offset_
;
1034 if (def
->type_
== typeVarchar
) {
1036 if (* (long *) colPtr
== 0L)
1037 vcLenValPairSize
= vcLenValPairSize
+ sizeof(int);
1038 else vcLenValPairSize
= vcLenValPairSize
+ sizeof(int) +
1039 + os::align(strlen((char *) *(long *)colPtr
) + 1);
1042 int size
= (3 + nVarchars
) * sizeof(void *) + sizeof(int)
1044 void *data
= malloc(size
);
1045 char *ptr
= (char *)data
;
1046 *(long *) ptr
= (long) tptr
; ptr
+= sizeof(void *);
1047 void *metaData
= db_
->getMetaDataPtr();
1048 *(long *) ptr
= (long) metaData
; ptr
+= sizeof(void *);
1049 *(int *) ptr
= nVarchars
; ptr
+= sizeof(int);
1050 *(long *) ptr
= (long) vcChunkPtr_
; ptr
+= sizeof(void *);
1051 fIter
= fldList_
.getIterator();
1052 colPtr
= (char*) curTuple_
;
1053 char *valLenPairPtr
= ptr
+ nVarchars
* sizeof(void *);
1054 while (fIter
.hasElement()) {
1055 FieldDef
*def
= fIter
.nextElement();
1056 colPtr
= (char *) curTuple_
+ def
->offset_
;
1058 if (def
->type_
== typeVarchar
) {
1059 *(long *) ptr
= (long )colPtr
; ptr
+= sizeof(void *);
1060 if (*(long *) colPtr
== 0L) {
1061 *(int *) valLenPairPtr
= vcStrLen
= 0;
1062 valLenPairPtr
+= sizeof(int);
1064 *(int *) valLenPairPtr
= vcStrLen
=
1065 os::align(strlen((char *)*(long *)colPtr
) + 1);
1066 valLenPairPtr
+= sizeof(int);
1067 strcpy(valLenPairPtr
, (char *)*(long *)colPtr
);
1068 valLenPairPtr
+= vcStrLen
;
1072 ret
= (*trans
)->appendUndoLog(sysDB_
, DeleteOperation
, data
, size
);
1076 printError(ret
, "Unable to create undo log for %x ", curTuple_
);
1077 for (int j
= 0; j
< numIndexes_
; j
++) {
1078 printError(ErrWarning
, "Inserting back index node");
1079 insertIndexNode(*trans
, indexPtr_
[j
], idxInfo
[j
], curTuple_
);
1082 (*trans
)->removeFromHasList(db_
, curTuple_
);
1083 lMgr_
->releaseLock(curTuple_
);
1087 FieldIterator fIter
= fldList_
.getIterator();
1088 char *colPtr
= (char*) curTuple_
;
1089 while (fIter
.hasElement()) {
1090 FieldDef
*def
= fIter
.nextElement();
1091 colPtr
= (char *) curTuple_
+ def
->offset_
;
1092 if (def
->type_
== typeVarchar
) {
1093 if (*(long *) colPtr
!= 0L) {
1094 char *ptr
= (char *) *(long *) colPtr
;
1095 ((Chunk
*) vcChunkPtr_
)->free(db_
, ptr
);
1099 ((Chunk
*)chunkPtr_
)->free(db_
, curTuple_
);
1101 sysDB_
->releaseCheckpointMutex();
1105 int TableImpl::deleteWhere()
1107 DbRetVal ret
= getCheckpointMutex();
1108 if (ret
!=OK
) return ret
;
1110 int tuplesDeleted
= 0;
1114 sysDB_
->releaseCheckpointMutex();
1119 if (rv
!= OK
) { tuplesDeleted
= (int)rv
; break; }
1120 if (NULL
== curTuple_
) break;
1123 printError(rv
, "Error: Could only delete %d tuples", tuplesDeleted
);
1125 sysDB_
->releaseCheckpointMutex();
1131 sysDB_
->releaseCheckpointMutex();
1132 return tuplesDeleted
;
1135 int TableImpl::truncate()
1137 //take exclusive lock on the table
1138 //get the chunk ptr of the table
1139 //traverse the tablechunks and free all the pages except the first one
1140 //get the chunk ptr of all its indexes
1141 //traverse the indexchunks and free all the pages except the first one
1142 //release table lock
1146 Predicate
* tmpPred
= pred_
;
1148 isPlanCreated
= false;
1149 int tuplesDeleted
= deleteWhere();
1150 isPlanCreated
= false;
1152 return tuplesDeleted
;
1155 DbRetVal
TableImpl::updateTuple()
1157 if (NULL
== curTuple_
)
1159 printError(ErrNotOpen
, "Scan not open: No Current tuple");
1162 DbRetVal ret
= getCheckpointMutex();
1163 if (ret
!=OK
) return ret
;
1165 TableImpl
*fkTbl
=NULL
;
1166 ListIterator tblIter
= tblList
.getIterator();
1168 while (tblIter
.hasElement()){
1169 fkTbl
= (TableImpl
*) tblIter
.nextElement();
1170 bool pkRec
= isPkTableHasRecord(fkTbl
->getName(),fkTbl
,false);
1172 printError(ErrForeignKeyInsert
, "Unable to insert into foreign Key table.Check PK table");
1173 sysDB_
->releaseCheckpointMutex();
1174 return ErrForeignKeyInsert
;
1181 //ret = lMgr_->getExclusiveLock(curTuple_, trans);
1182 if (OK
!= tryExclusiveLock(curTuple_
, trans
))
1184 printError(ret
, "Could not get lock for the update tuple %x", curTuple_
);
1185 sysDB_
->releaseCheckpointMutex();
1186 return ErrLockTimeOut
;
1189 if (NULL
!= indexPtr_
)
1192 //TODO::If it fails while updating index node, we have to undo all the updates
1193 //on other indexes on the table.Currently it will leave the database in an
1194 //inconsistent state.
1195 for (int i
= 0; i
< numIndexes_
; i
++)
1197 ret
= updateIndexNode(*trans
, indexPtr_
[i
], idxInfo
[i
], curTuple_
);
1201 lMgr_
->releaseLock(curTuple_
);
1202 (*trans
)->removeFromHasList(db_
, curTuple_
);
1204 printError(ret
, "Unable to update index node for tuple %x", curTuple_
);
1205 sysDB_
->releaseCheckpointMutex();
1212 // the undo log for update should contain
1213 // tupleptr + tuple length + actual tuple + metadataPtr +
1214 // nVarchars + varchar chunk ptr + ptrs to varchars +
1215 // size and value pairs for varchars
1217 //TODO: number of varchar fields to be stored as a member in TableImpl
1218 void *tptr
= curTuple_
;
1219 char *colPtr
= (char *)curTuple_
;
1221 int vcLenValPairSize
= 0;
1222 FieldIterator fIter
= fldList_
.getIterator();
1223 while (fIter
.hasElement()) {
1224 FieldDef
*def
= fIter
.nextElement();
1225 colPtr
= (char *) curTuple_
+ def
->offset_
;
1226 if (def
->type_
== typeVarchar
) {
1228 if (* (long *) colPtr
== 0L)
1229 vcLenValPairSize
= vcLenValPairSize
+ sizeof(int);
1230 else vcLenValPairSize
= vcLenValPairSize
+ sizeof(int) +
1231 + os::align(strlen((char *) *(long *)colPtr
) + 1);
1234 int size
= (3 + nVarchars
) * sizeof(void *) + 2 * sizeof(int) +
1235 vcLenValPairSize
+ length_
;
1236 void *data
= malloc(size
);
1237 char *ptr
= (char *) data
;
1238 *(long *) ptr
= (long) tptr
; ptr
+= sizeof(void *);
1239 *(int *) ptr
= length_
; ptr
+= sizeof(int);
1240 os::memcpy(ptr
, tptr
, length_
); ptr
+= length_
;
1241 void *metaData
= db_
->getMetaDataPtr();
1242 *(long *) ptr
= (long) metaData
; ptr
+= sizeof(void *);
1243 *(int *) ptr
= nVarchars
; ptr
+= sizeof(int);
1244 *(long *) ptr
= (long) vcChunkPtr_
; ptr
+= sizeof(void *);
1245 fIter
= fldList_
.getIterator();
1246 colPtr
= (char*) curTuple_
;
1247 char *valLenPairPtr
= ptr
+ nVarchars
* sizeof(void *);
1248 while (fIter
.hasElement()) {
1249 FieldDef
*def
= fIter
.nextElement();
1250 colPtr
= (char *) curTuple_
+ def
->offset_
;
1252 if (def
->type_
== typeVarchar
) {
1253 *(long *) ptr
= (long)colPtr
; ptr
+= sizeof(void *);
1254 if (*(long *) colPtr
== 0L) {
1255 *(int *) valLenPairPtr
= vcStrLen
= 0;
1256 valLenPairPtr
+= sizeof(int);
1258 *(int *) valLenPairPtr
= vcStrLen
=
1259 os::align(strlen((char *)*(long *)colPtr
) + 1);
1260 valLenPairPtr
+= sizeof(int);
1261 strcpy(valLenPairPtr
, (char *)*(long *)colPtr
);
1262 valLenPairPtr
+= vcStrLen
;
1266 ret
= (*trans
)->appendUndoLog(sysDB_
, UpdateOperation
, data
, size
);
1271 lMgr_
->releaseLock(curTuple_
);
1272 (*trans
)->removeFromHasList(db_
, curTuple_
);
1274 sysDB_
->releaseCheckpointMutex();
1279 int iNullVal
=iNullInfo
;
1283 iNullInfo
= *(int*)((char*)(curTuple_
) + (length_
- addSize
));
1287 *(int*)((char*)(curTuple_
) + (length_
-addSize
)) |= iNullInfo
;
1290 DbRetVal rv
= copyValuesFromBindBuffer(curTuple_
, false);
1291 if (rv
!= OK
&& !loadFlag
) {
1292 lMgr_
->releaseLock(curTuple_
);
1293 (*trans
)->removeFromHasList(db_
, curTuple_
);
1294 sysDB_
->releaseCheckpointMutex();
1301 *(int*)((char*)(curTuple_
) + (length_
-addSize
)) = iNullInfo
;
1304 else iNullInfo
=iNullVal
;
1308 addSize
= os::align(numFlds_
);
1309 //TODO::Do not do blind memcpy. It should OR each and every char
1311 char *null
=(char*)(curTuple_
) + (length_
-addSize
);
1312 while(i
< numFlds_
) {
1313 if(cNullInfo
[i
]) null
[i
] |= cNullInfo
[i
];
1316 //os::memcpy(((char*)(curTuple_) + (length_-addSize)), cNullInfo, addSize);
1318 sysDB_
->releaseCheckpointMutex();
1322 void TableImpl::printInfo()
1324 printf(" <TableName> %s </TableName>\n", tblName_
);
1325 printf(" <TupleCount> %d </TupleCount>\n", numTuples());
1326 printf(" <PagesUsed> %d </PagesUsed>\n", pagesUsed());
1327 printf(" <SpaceUsed> %d </SpaceUsed>\n", spaceUsed());
1328 printf(" <Indexes> %d <Indexes>\n", numIndexes_
);
1329 printf(" <TupleLength> %d </TupleLength>\n", length_
);
1330 printf(" <Fields> %d </Fields>\n", numFlds_
);
1331 printf(" <Indexes>\n");
1332 for (int i
=0; i
<numIndexes_
; i
++)
1333 printf("<IndexName> %s </IndexName>\n", CatalogTableINDEX::getName(indexPtr_
[i
]));
1334 printf(" </Indexes>\n");
1337 long long TableImpl::getLastInsertedVal(DbRetVal
&rv
)
1340 return *(long long*)ptrToAuto
;
1342 DbRetVal
TableImpl::copyValuesFromBindBuffer(void *tuplePtr
, bool isInsert
)
1344 //Iterate through the bind list and copy the value here
1345 FieldIterator fIter
= fldList_
.getIterator();
1346 char *colPtr
= (char*) tuplePtr
;
1348 while (fIter
.hasElement())
1350 FieldDef
*def
= fIter
.nextElement();
1351 if(def
->isAutoIncrement_
&& isInsert
)
1353 void *dest
= AllDataType::alloc(def
->type_
, def
->length_
);
1354 AllDataType::copyVal(dest
,ptrToAuto
, def
->type_
, def
->length_
);
1355 if(def
->bindVal_
==NULL
)
1357 AllDataType::increment(colPtr
, dest
, def
->type_
);
1358 AllDataType::copyVal(ptrToAuto
,colPtr
, def
->type_
,
1360 colPtr
= colPtr
+ def
->length_
;
1365 if(AllDataType::compareVal(def
->bindVal_
, dest
, OpGreaterThan
,
1367 AllDataType::copyVal(ptrToAuto
,def
->bindVal_
, def
->type_
,
1373 if (def
->isNull_
&& !def
->isDefault_
&& NULL
== def
->bindVal_
&&
1376 printError(ErrNullViolation
,
1377 "NOT NULL constraint violation for field %s", def
->fldName_
);
1378 return ErrNullViolation
;
1380 if (def
->isDefault_
&& NULL
== def
->bindVal_
&& isInsert
)
1382 if (! def
->isNullExplicit_
) {
1383 if (def
->type_
== typeVarchar
) {
1386 ((Chunk
*) vcChunkPtr_
)->allocate(db_
, def
->length_
, &rv
);
1387 *(long *)colPtr
= (long)ptr
;
1388 AllDataType::convert(typeString
, def
->defaultValueBuf_
,
1389 def
->type_
, ptr
, def
->length_
);
1391 void *dest
= AllDataType::alloc(def
->type_
, def
->length_
);
1392 AllDataType::convert(typeString
, def
->defaultValueBuf_
,
1393 def
->type_
, dest
, def
->length_
);
1394 AllDataType::copyVal(colPtr
, dest
, def
->type_
,
1400 *(long *) colPtr
= 0L;
1402 if (def
->type_
!= typeVarchar
) colPtr
= colPtr
+ def
->length_
;
1403 else colPtr
= colPtr
+ sizeof(void *);
1410 if (NULL
!= def
->bindVal_
)
1412 if(!isInsert
&& isFldNull(fldpos
)){clearNullBit(fldpos
);}
1413 strncpy((char*)colPtr
, (char*)def
->bindVal_
, def
->length_
);
1414 *(((char*)colPtr
) + (def
->length_
-1)) = '\0';
1415 } else if (!def
->isNull_
&& !def
->bindVal_
&& isInsert
) {
1418 colPtr
= colPtr
+ def
->length_
;
1421 if (NULL
!= def
->bindVal_
)
1423 if(!isInsert
&& isFldNull(fldpos
)){clearNullBit(fldpos
);}
1424 DbRetVal rv
= AllDataType::strToValue(colPtr
,
1425 (char *) def
->bindVal_
, def
->type_
, def
->length_
);
1426 if (rv
!= OK
) return ErrBadArg
;
1427 } else if (!def
->isNull_
&& isInsert
&& !def
->bindVal_
) {
1430 colPtr
= colPtr
+ def
->length_
;
1433 if (NULL
!= def
->bindVal_
) {
1434 if (!isInsert
&& isFldNull(fldpos
)) {clearNullBit(fldpos
);}
1437 if (*(long *) colPtr
!= 0L)
1438 ((Chunk
*) vcChunkPtr_
)->free(db_
,
1439 (void *)*(long *)colPtr
);
1440 *(long *) colPtr
= 0L;
1442 if (strcmp((char *)def
->bindVal_
,"") != 0) {
1444 ((Chunk
*) vcChunkPtr_
)->allocate(db_
,
1446 if (rv
!= OK
) return ErrBadArg
;
1447 *(long *)colPtr
= (long)ptr
;
1448 strcpy((char *)ptr
, (char *)def
->bindVal_
);
1449 } else { setNullBit(fldpos
); }
1450 } else if (!def
->isNull_
&& isInsert
&& !def
->bindVal_
) {
1453 colPtr
= colPtr
+ sizeof(void *);
1456 if (NULL
!= def
->bindVal_
) {
1457 if(!isInsert
&& isFldNull(fldpos
)){clearNullBit(fldpos
);}
1458 AllDataType::copyVal(colPtr
, def
->bindVal_
, def
->type_
);
1459 } else { if (!def
->isNull_
&& isInsert
) setNullBit(fldpos
); }
1460 colPtr
= colPtr
+ def
->length_
;
1467 void TableImpl::clearNullBit(int fldpos
)
1469 if (isIntUsedForNULL
){
1470 CLEARBIT(iNullInfo
, fldpos
);}
1472 cNullInfo
[fldpos
-1] = 0;
1474 void TableImpl::setNullBit(int fldpos
)
1476 if (isIntUsedForNULL
)
1477 SETBIT(iNullInfo
, fldpos
);
1479 cNullInfo
[fldpos
-1] = 1;
1481 DbRetVal
TableImpl::copyValuesToBindBuffer(void *tuplePtr
)
1483 //Iterate through the bind list and copy the value here
1484 char *colPtr
= (char*) tuplePtr
;
1485 FieldDef
*def
= NULL
;
1486 for (int i
= 0; i
< numBindFlds_
; i
++) {
1487 def
= (FieldDef
*) bindListArray_
[i
];
1488 colPtr
= (char *) tuplePtr
+ def
->offset_
;
1489 if (def
->type_
!= typeVarchar
)
1490 AllDataType::copyVal(def
->bindVal_
, colPtr
, def
->type_
,
1493 char *ptr
= (char *) *(long *) colPtr
;
1494 if (ptr
!= NULL
) strcpy((char *)def
->bindVal_
, ptr
);
1500 //-1 index not supported
1501 DbRetVal
TableImpl::insertIndexNode(Transaction
*tr
, void *indexPtr
, IndexInfo
*info
, void *tuple
)
1503 CINDEX
*iptr
= (CINDEX
*)indexPtr
;
1505 printDebug(DM_Table
, "Inside insertIndexNode type %d", iptr
->indexType_
);
1506 Index
* idx
= Index::getIndex(iptr
->indexType_
);
1507 ret
= idx
->insert(this, tr
, indexPtr
, info
, tuple
,loadFlag
);
1511 DbRetVal
TableImpl::deleteIndexNode(Transaction
*tr
, void *indexPtr
, IndexInfo
*info
, void *tuple
)
1513 CINDEX
*iptr
= (CINDEX
*)indexPtr
;
1515 Index
* idx
= Index::getIndex(iptr
->indexType_
);
1516 ret
= idx
->remove(this, tr
, indexPtr
, info
, tuple
, loadFlag
);
1519 void TableImpl::printSQLIndexString(FILE *fp
, int fd
)
1521 if (fp
== NULL
) fp
= stdout
;
1522 CatalogTableINDEXFIELD
cIndexField(sysDB_
);
1523 char fName
[IDENTIFIER_LENGTH
];
1524 char idxName
[IDENTIFIER_LENGTH
];
1525 char *fldName
= fName
;
1527 for (int i
= 0; i
< numIndexes_
; i
++)
1529 CINDEX
*iptr
= (CINDEX
*) indexPtr_
[i
];
1530 sprintf(idxName
,"%s_idx_Auto_increment",getName());
1531 if(strcmp(iptr
->indName_
,idxName
)==0){ continue; }
1532 if (Conf::config
.useDurability()) {
1534 strcpy(obj
.name
, iptr
->indName_
);
1535 if (iptr
->indexType_
== hashIndex
) {
1537 obj
.bucketChunk
= ((Chunk
*)iptr
->chunkPtr_
)->getFirstPage();
1538 obj
.firstPage
= ((Chunk
*)iptr
->hashNodeChunk_
)->getFirstPage();
1539 obj
.curPage
= ((Chunk
*)iptr
->hashNodeChunk_
)->getCurrentPage();
1540 } else if (iptr
->indexType_
== treeIndex
) {
1542 obj
.firstPage
= ((Chunk
*)iptr
->chunkPtr_
)->getFirstPage();
1543 obj
.curPage
= ((Chunk
*)iptr
->chunkPtr_
)->getCurrentPage();
1544 long nodes
= ((Chunk
*)iptr
->chunkPtr_
)->getTotalDataNodes();
1546 ChunkIterator cIter
= ((Chunk
*)iptr
->chunkPtr_
)->getIterator();
1547 obj
.bucketChunk
= cIter
.nextElement();
1548 } else obj
.bucketChunk
= NULL
;
1551 write(fd
, buf
, sizeof(obj
));
1553 fprintf(fp
, "CREATE INDEX %s on %s ( ", iptr
->indName_
, getName());
1555 cIndexField
.getFieldInfo(iptr
, fldList
);
1556 FieldIterator fIter
= fldList
.getIterator();
1557 bool firstFld
= true;
1558 while(fIter
.hasElement())
1560 FieldDef
*def
= fIter
.nextElement();
1561 if (firstFld
) { fprintf(fp
, " %s ", def
->fldName_
); firstFld
= false; }
1562 else fprintf(fp
, " ,%s ", def
->fldName_
);
1564 fldList
.removeAll();
1566 if (iptr
->indexType_
== hashIndex
) fprintf(fp
, " HASH ");
1567 else fprintf(fp
, " TREE ");
1568 if (((HashIndexInfo
*) idxInfo
[i
])->isUnique
) fprintf(fp
, " UNIQUE");
1569 if(((HashIndexInfo
*) idxInfo
[i
])->noOfBuckets
!= 1009 ) fprintf(fp
, " SIZE %d ",((HashIndexInfo
*) idxInfo
[i
])->noOfBuckets
);
1575 DbRetVal
TableImpl::updateIndexNode(Transaction
*tr
, void *indexPtr
, IndexInfo
*info
, void *tuple
)
1577 CINDEX
*iptr
= (CINDEX
*)indexPtr
;
1579 Index
* idx
= Index::getIndex(iptr
->indexType_
);
1580 //TODO::currently it updates irrespective of whether the key changed or not
1581 //because of this commenting the whole index update code. relook at it and uncomment
1583 ret
= idx
->update(this, tr
, indexPtr
, info
, tuple
, loadFlag
);
1589 void TableImpl::setTableInfo(char *name
, int tblid
, size_t length
,
1590 int numFld
, int numIdx
, void *chunk
, void *vcchunk
)
1592 strcpy(tblName_
, name
);
1596 numIndexes_
= numIdx
;
1598 vcChunkPtr_
= vcchunk
;
1601 long TableImpl::spaceUsed()
1603 Chunk
*chk
= (Chunk
*)chunkPtr_
;
1604 long totSize
= chk
->getTotalDataNodes() * chk
->getSize();
1605 totSize
= totSize
+ (chk
->totalPages() * sizeof (PageInfo
));
1609 int TableImpl::pagesUsed()
1611 Chunk
*chk
= (Chunk
*)chunkPtr_
;
1612 return chk
->totalPages();
1615 long TableImpl::numTuples()
1617 return ((Chunk
*)chunkPtr_
)->getTotalDataNodes();
1620 List
TableImpl::getFieldNameList()
1623 FieldIterator fIter
= fldList_
.getIterator();
1624 char fieldName
[IDENTIFIER_LENGTH
];
1625 while (fIter
.hasElement())
1627 FieldDef
*def
= fIter
.nextElement();
1628 Identifier
*elem
= new Identifier();
1629 Table::getFieldNameAlone(def
->fldName_
, fieldName
);
1630 sprintf(elem
->name
, "%s.%s", getName(), fieldName
);
1631 fldNameList
.append(elem
);
1635 DbRetVal
TableImpl::close()
1637 if (iter
) { iter
->close(); delete iter
; iter
= NULL
; }
1638 TableImpl
*fkTbl
=NULL
;
1639 ListIterator tblIter
= tblList
.getIterator();
1641 while (tblIter
.hasElement()){
1642 fkTbl
= (TableImpl
*) tblIter
.nextElement();
1646 tblIter
= tblFkList
.getIterator();
1648 while (tblIter
.hasElement()){
1649 fkTbl
= (TableImpl
*) tblIter
.nextElement();
1653 printDebug(DM_Database
,"Closing table handle: %x", this);
1656 ListIterator pIter
= predList
.getIterator();
1657 while (pIter
.hasElement())
1659 PredicateImpl
*pImpl
= (PredicateImpl
*) pIter
.nextElement();
1664 logFinest(Conf::logger
, "Closing Table");
1668 DbRetVal
TableImpl::closeScan()
1670 //do not throw scan not open error
1671 //this function will be called by table handle
1677 DbRetVal
TableImpl::lock(bool shared
)
1683 ret = lMgr_->getSharedLock(chunkPtr_, NULL);
1685 ret = lMgr_->getExclusiveLock(chunkPtr_, NULL);
1688 printError(ret, "Could not exclusive lock on the table %x", chunkPtr_);
1690 //do not append for S to X upgrade
1691 if (!ProcessManager::hasLockList.exists(chunkPtr_))
1692 ProcessManager::hasLockList.append(chunkPtr_);
1697 DbRetVal
TableImpl::unlock()
1700 if (!ProcessManager::hasLockList.exists(chunkPtr_)) return OK;
1701 DbRetVal ret = lMgr_->releaseLock(chunkPtr_);
1704 printError(ret, "Could not release exclusive lock on the table %x", chunkPtr_);
1707 ProcessManager::hasLockList.remove(chunkPtr_);
1713 TableImpl::~TableImpl()
1715 if (NULL
!= iter
) { delete iter
; iter
= NULL
; }
1716 if (NULL
!= indexPtr_
) { delete[] indexPtr_
; indexPtr_
= NULL
; }
1717 if (NULL
!= idxInfo
)
1719 for (int i
= 0; i
< numIndexes_
; i
++) delete idxInfo
[i
];
1723 if (numFlds_
> 31 && cNullInfo
!= NULL
) { free(cNullInfo
); cNullInfo
= NULL
; }
1724 if (bindList_
.size()) bindList_
.reset();
1725 if (bindListArray_
) { free (bindListArray_
); bindListArray_
= NULL
; }
1726 fldList_
.removeAll();
1730 void *TableImpl::getBindFldAddr(const char *name
)
1732 return fldList_
.getBindField(name
);
1734 bool TableImpl::isTableInvolved(char *tblName
)
1736 //printf("Table isTableInvolved called for %s with %s\n", tblName, getName());
1737 if (0 == strcmp(getName(), tblName
)) return true; else return false;
1739 bool TableImpl::pushPredicate(Predicate
*pred
)
1742 PredicateImpl
*pImpl
= (PredicateImpl
*) pred
;
1743 char tableName
[IDENTIFIER_LENGTH
];
1744 Table::getTableNameAlone(pImpl
->getFldName1(), tableName
);
1745 //printf("predicate tbl name %s\n", tableName);
1747 //if predicate is of form t1.f1=t2.f1 then do not push here
1748 bool isAliasSet
= (0 !=strcmp(getAliasName(),"")) ;
1749 if (0 != strcmp(pImpl
->getFldName2(),"")) return ret
;
1751 if (0 == strcmp(getName(), tableName
) ||(isAliasSet
&& 0 == strcmp(getAliasName(), tableName
)))
1754 //printf("PRABA::pushed predicate in tablehdl %s\n", getName());
1760 void TableImpl::setCondition(Condition
*p
)
1762 isPlanCreated
= false;
1763 ListIterator pIter
= predList
.getIterator();
1764 while (pIter
.hasElement())
1766 PredicateImpl
*pImpl
= (PredicateImpl
*) pIter
.nextElement();
1771 if (p
) pred_
= p
->getPredicate(); else pred_
= NULL
;
1774 void TableImpl::setPredicate(Predicate
*pred
)
1776 if (NULL
== pred_
) { pred_
= pred
; return; }
1778 Predicate
*curPred
= pred_
;
1779 PredicateImpl
*newPred
= new PredicateImpl();
1780 newPred
->setTerm(curPred
, OpAnd
, pred
);
1781 newPred
->setTable(this);
1785 void TableImpl::printPlan(int space
)
1787 char spaceBuf
[IDENTIFIER_LENGTH
];
1788 memset(spaceBuf
, 32, IDENTIFIER_LENGTH
);
1789 spaceBuf
[space
] = '\0';
1790 printf("%s <TABLE-NODE>\n", spaceBuf
);
1791 printf("%s <NAME> %s </NAME>\n", spaceBuf
, getName());
1792 printf("%s <ScanType> %s </ScanType>\n", spaceBuf
, ScanTypeNames
[scanType_
]);
1793 PredicateImpl
*pred
= (PredicateImpl
*)pred_
;
1794 if (pred
) pred
->print(space
+2);
1795 printf("%s </TABLE-NODE>\n", spaceBuf
);
1797 void TableImpl::printSQLForeignString()
1800 FieldNameList pkFieldList
,fkFieldList
;
1802 void *tFkptr
= NULL
;
1803 void *chunkPk
= NULL
;
1804 void *vcchunkPk
= NULL
;
1805 CatalogTableTABLE
cTable(sysDB_
);
1806 TableImpl
*fkTbl
=NULL
;
1807 ListIterator tblIter
= tblList
.getIterator();
1810 while (tblIter
.hasElement()){
1811 fkTbl
= (TableImpl
*) tblIter
.nextElement();
1812 rv
= cTable
.getChunkAndTblPtr(fkTbl
->getName(), chunkPk
, tPkptr
,vcchunkPk
);
1813 if ( OK
!= rv
){return ;}
1814 rv
= cTable
.getChunkAndTblPtr(getName(), chunkPk
, tFkptr
, vcchunkPk
);
1815 if ( OK
!= rv
){return ;}
1816 CatalogTableFK
cFk(sysDB_
);
1817 rv
= cFk
.getPkFkFieldInfo(tPkptr
,tFkptr
,pkFieldList
,fkFieldList
);
1818 if ( OK
!= rv
){return;}
1819 pkFieldList
.resetIter();
1820 fkFieldList
.resetIter();
1821 char *fldName
= NULL
;
1822 bool firstField
=true;
1823 if(!firstFK
) printf(", ");
1824 printf(", FOREIGN KEY ( ");
1825 while((fldName
= fkFieldList
.nextFieldName())!= NULL
)
1828 printf("%s",fldName
);
1832 printf(",%s",fldName
);
1834 printf(" ) REFERENCES %s ( ",fkTbl
->getName());
1836 while((fldName
= pkFieldList
.nextFieldName())!= NULL
)
1839 printf("%s",fldName
);
1843 printf(",%s",fldName
);
1847 pkFieldList
.removeAll();
1848 fkFieldList
.removeAll();
1852 bool TableImpl::isPkTableHasRecord(char *pkTableName
, TableImpl
*fkTbl
,bool isInsert
)
1855 bool isRecExist
=false;
1856 FieldNameList pkFieldList
,fkFieldList
;
1858 void *tFkptr
= NULL
;
1859 void *chunkPk
= NULL
;
1860 void *vcchunkPk
= NULL
;
1861 CatalogTableTABLE
cTable(sysDB_
);
1862 rv
= cTable
.getChunkAndTblPtr(pkTableName
, chunkPk
, tPkptr
, vcchunkPk
);
1863 if ( OK
!= rv
){return false;}
1864 rv
= cTable
.getChunkAndTblPtr(getName(), chunkPk
, tFkptr
, vcchunkPk
);
1865 if ( OK
!= rv
){return false;}
1866 CatalogTableFK
cFk(sysDB_
);
1867 rv
= cFk
.getPkFkFieldInfo(tPkptr
,tFkptr
,pkFieldList
,fkFieldList
);
1868 if ( OK
!= rv
){return false;}
1869 int totFld
= pkFieldList
.size();
1870 Condition
*condition
= new Condition
[totFld
];
1871 char *pkFldName
= NULL
;
1872 char *fkFldName
= NULL
;
1875 pkFieldList
.resetIter();
1876 fkFieldList
.resetIter();
1878 while((pkFldName
= pkFieldList
.nextFieldName())!= NULL
)
1880 fkFldName
= fkFieldList
.nextFieldName();
1881 FieldIterator fIter
= fldList_
.getIterator();
1882 while (fIter
.hasElement())
1884 def
= fIter
.nextElement();
1885 if (strcmp(def
->fldName_
, fkFldName
) == 0)
1887 if(NULL
== def
->bindVal_
&& isInsert
) { return true; }
1888 if(NULL
== def
->bindVal_
) {
1889 if (def
->type_
!= typeVarchar
)
1890 val
= (char*)curTuple_
+ def
->offset_
;
1891 else val
= (void *) *(long *) ((char*)curTuple_
+
1894 val
= def
->bindVal_
;
1896 if(def
->type_
==typeString
)
1897 condition
[i
].setTerm(pkFldName
,OpEquals
,&val
);
1899 condition
[i
].setTerm(pkFldName
,OpEquals
,val
);
1905 pkFieldList
.removeAll();
1906 fkFieldList
.removeAll();
1907 Condition
*cond
= NULL
;
1908 if(i
== 0 && !isInsert
)return true;
1910 cond
= new Condition
[i
-1];
1914 for(j
=0;j
<totcon
-1;j
++)
1917 cond
[j
].setTerm(condition
[i
++].getPredicate(),OpAnd
,condition
[i
++].getPredicate());
1919 cond
[j
].setTerm(cond
[j
-1].getPredicate(), OpAnd
, condition
[i
++].getPredicate());
1921 fkTbl
->setCondition(&cond
[j
-1]);
1924 fkTbl
->setCondition(&condition
[i
-1]);
1938 bool TableImpl::isFkTableHasRecord(char *pkTableName
, TableImpl
*fkTbl
)
1941 FieldNameList pkFieldList
,fkFieldList
;
1943 void *tFkptr
= NULL
;
1944 void *chunkPk
= NULL
;
1945 void *vcchunkPk
= NULL
;
1946 CatalogTableTABLE
cTable(sysDB_
);
1947 rv
= cTable
.getChunkAndTblPtr(getName(), chunkPk
, tPkptr
, vcchunkPk
);
1948 if ( OK
!= rv
){return false;}
1949 rv
= cTable
.getChunkAndTblPtr(pkTableName
, chunkPk
, tFkptr
, vcchunkPk
);
1950 if ( OK
!= rv
){return false;}
1951 CatalogTableFK
cFk(sysDB_
);
1952 rv
= cFk
.getPkFkFieldInfo(tPkptr
,tFkptr
,pkFieldList
,fkFieldList
);
1953 if ( OK
!= rv
){return false;}
1954 int totFld
= pkFieldList
.size();
1955 Condition
*condition
= new Condition
[totFld
];
1956 char *pkFldName
= NULL
;
1957 char *fkFldName
= NULL
;
1960 pkFieldList
.resetIter();
1961 fkFieldList
.resetIter();
1962 while((pkFldName
= pkFieldList
.nextFieldName())!= NULL
)
1964 fkFldName
= fkFieldList
.nextFieldName();
1965 FieldIterator fIter
= fldList_
.getIterator();
1966 while (fIter
.hasElement())
1968 def
= fIter
.nextElement();
1970 if (def
->type_
!= typeVarchar
)
1971 val
= (char*)curTuple_
+ def
->offset_
;
1972 else val
= (void *) *(long *) ((char*)curTuple_
+ def
->offset_
);
1973 if (strcmp(def
->fldName_
, pkFldName
) == 0)
1975 if(def
->type_
==typeString
)
1976 condition
[i
].setTerm(fkFldName
,OpEquals
,&val
);//((char*)curTuple_+def->offset_));
1978 condition
[i
].setTerm(fkFldName
,OpEquals
,val
);//((char*)curTuple_+def->offset_));
1984 pkFieldList
.removeAll();
1985 fkFieldList
.removeAll();
1986 if(i
== 0 )return true;
1987 Condition
*cond
= new Condition
[i
-1];
1990 for(j
=0;j
<totFld
-1;j
++)
1993 cond
[j
].setTerm(condition
[i
++].getPredicate(),OpAnd
,condition
[i
++].getPredicate());
1995 cond
[j
].setTerm(cond
[j
-1].getPredicate(), OpAnd
, condition
[i
++].getPredicate());
1998 fkTbl
->setCondition(&condition
[totFld
-1]);
2000 fkTbl
->setCondition(&cond
[j
-1]);
2012 DbRetVal
TableImpl::compact()
2015 int ret
=((Chunk
*)chunkPtr_
)->compact(db_
->procSlot
);
2016 if(ret
!=0) return ErrLockTimeOut
;
2017 ret
= ((Chunk
*)vcChunkPtr_
)->compact(db_
->procSlot
);
2018 if(ret
!=0) return ErrLockTimeOut
;
2019 if (NULL
!= indexPtr_
)
2023 for (i
= 0; i
< numIndexes_
; i
++)
2025 rv
= compactIndexNode(indexPtr_
[i
]);
2026 if (rv
!= OK
) { printError(rv
, "Error in compacting index Node"); break;}
2032 DbRetVal
TableImpl::compactIndexNode( void *indexPtr
)
2034 CINDEX
*iptr
= (CINDEX
*)indexPtr
;
2036 printDebug(DM_Table
, "Inside insertIndexNode type %d", iptr
->indexType_
);
2037 if( hashIndex
== (iptr
->indexType_
) )
2039 ret1
=((Chunk
*)iptr
->hashNodeChunk_
)->compact(db_
->procSlot
);
2041 return ErrLockTimeOut
;
2045 ret1
=((Chunk
*)iptr
->chunkPtr_
)->compact(db_
->procSlot
);
2047 return ErrLockTimeOut
;