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
)
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
);
60 printError(ErrNotExists
, "Field %s does not exist", fieldName
);
66 bool TableImpl::isFldNull(const char *name
){
67 if (name
[0] == '*') return false;
68 char fieldName
[IDENTIFIER_LENGTH
];
69 getFieldNameAlone((char*)name
, fieldName
);
70 int colpos
= fldList_
.getFieldPosition(fieldName
);
73 printError(ErrNotExists
, "Field %s does not exist", name
);
77 return isFldNull(colpos
);
80 int TableImpl::getFldPos(char *name
)
82 return fldList_
.getFieldPosition(name
);
84 bool TableImpl::isFldNull(int colpos
)
86 if (!curTuple_
) return false;
87 if (colpos
<1 || colpos
> numFlds_
) return false;
88 if (isIntUsedForNULL
) {
89 int nullVal
= *(int*)((char*)curTuple_
+ (length_
- 4));
90 if (BITSET(nullVal
, colpos
)) return true;
93 char *nullOffset
= (char*)curTuple_
- os::align(numFlds_
);
94 if (nullOffset
[colpos
-1]) return true;
98 void TableImpl::resetNullinfo()
100 if (isIntUsedForNULL
) {
105 while(i
< numFlds_
) { cNullInfo
[0] = 0;}
108 DbRetVal
TableImpl::markFldNull(char const* name
)
111 int colpos
= fldList_
.getFieldPosition(name
);
114 printError(ErrNotExists
, "Field %s does not exist", name
);
117 rv
= markFldNull(colpos
);
121 DbRetVal
TableImpl::markFldNull(int fldpos
)
123 if (fldpos
<1 || fldpos
> numFlds_
) return ErrBadArg
;
124 bool isBitSet
= false;
125 if (isIntUsedForNULL
) {
126 if (!BITSET(iNotNullInfo
, fldpos
)) {
127 SETBIT(iNullInfo
, fldpos
);
131 printError(ErrNullViolation
, "NOT NULL constraint violation");
132 return ErrNullViolation
;
136 if (!BITSET(iNotNullInfo
, fldpos
)) cNullInfo
[fldpos
-1] = 1;
138 printError(ErrNullViolation
, "NOT NULL constraint violation");
139 return ErrNullViolation
;
145 void TableImpl::clearFldNull(const char *name
)
147 int colpos
= fldList_
.getFieldPosition(name
);
150 printError(ErrNotExists
, "Field %s does not exist", name
);
154 clearFldNull(colpos
);
157 void TableImpl::clearFldNull(int colpos
)
159 if (colpos
<1 || colpos
> numFlds_
) return;
160 if (isIntUsedForNULL
) {
161 CLEARBIT(iNullInfo
, colpos
);
164 cNullInfo
[colpos
-1] = 0;
168 bool TableImpl::hasIndex(char* fName
)
170 if (NULL
== indexPtr_
) return false;
171 for (int i
=0; i
< numIndexes_
; i
++)
173 HashIndexInfo
* info
= (HashIndexInfo
*) idxInfo
[i
];
174 FieldIterator iter
= info
->idxFldList
.getIterator();
175 if(iter
.hasElement())
177 FieldDef
*def
= iter
.nextElement();
178 if(strcmp(def
->fldName_
, fName
) == 0)
179 if(!iter
.hasElement())//neglet if it is composite index
186 IndexType
TableImpl::getIndexType(char *fName
, int *pos
)
188 if (NULL
== indexPtr_
) return unknownIndex
;
189 for (int i
=0; i
< numIndexes_
; i
++)
191 HashIndexInfo
* info
= (HashIndexInfo
*) idxInfo
[i
];
192 FieldIterator iter
= info
->idxFldList
.getIterator();
193 if(iter
.hasElement())
195 FieldDef
*def
= iter
.nextElement();
196 if(strcmp(def
->fldName_
, fName
) == 0)
197 if(!iter
.hasElement()) {//neglet if it is composite index
199 return info
->indType
;
206 void TableImpl::addPredicate(char *fName
, ComparisionOp op
, void *buf
)
208 char fieldName
[IDENTIFIER_LENGTH
];
209 Table::getFieldNameAlone(fName
, fieldName
);
210 PredicateImpl
*pred
= (PredicateImpl
*) pred_
;
211 PredicateImpl
*newPred
= new PredicateImpl();
212 newPred
->setTerm(fName
, op
, buf
);
213 if (NULL
== pred
) { pred_
= newPred
; return; }
214 if (pred
->isSingleTerm())
216 bool res
= pred
->appendIfSameFld(fName
, op
, buf
);
222 PredicateImpl
*bothPred
= new PredicateImpl();
223 bothPred
->setTerm(pred
, OpAnd
, newPred
);
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();
241 DbRetVal
TableImpl::execute()
245 //printError(ErrAlready,"Scan already open:Close and re execute");
252 printError(ErrSysInternal
,"Unable to create the plan");
253 return ErrSysInternal
;
256 iter
= new TupleIterator(pred_
, scanType_
, idxInfo
[useIndex_
], chunkPtr_
, sysDB_
->procSlot
,isBetween
,isPointLook
);
257 else if (scanType_
== fullTableScan
)
258 iter
= new TupleIterator(pred_
, scanType_
, NULL
, chunkPtr_
, sysDB_
->procSlot
,isBetween
,isPointLook
);
261 printError(ErrSysFatal
,"Unable to create tuple iterator");//should never happen
267 printError(ret
,"Unable to open the iterator");
274 DbRetVal
TableImpl::createPlan()
277 //will do early return here. plan is generated only when setPredicate is called.
278 if (scanType_
== unknownScan
) return ErrSysFatal
; //this should never happen
285 FieldIterator fIter
= fldList_
.getIterator();
286 FieldDef
*def
= NULL
;
287 while ((def
= fIter
.nextElement())!= NULL
) {
288 if (NULL
!= def
->bindVal_
) bindList_
.append(def
);
290 numBindFlds_
= bindList_
.size();
291 bindListArray_
= (void **) malloc(numBindFlds_
* sizeof (void *));
294 ListIterator it
= bindList_
.getIterator();
295 while ((elem
= it
.nextElement()) != NULL
) bindListArray_
[i
++] = elem
;
297 //if there are no predicates then go for full scan
298 //if there are no indexes then go for full scan
299 if (NULL
== pred_
|| NULL
== indexPtr_
)
301 scanType_
= fullTableScan
;
302 isPlanCreated
= true;
305 if (NULL
!= indexPtr_
)
307 PredicateImpl
*pred
= (PredicateImpl
*)pred_
;
308 printDebug(DM_Predicate
, "predicate does not involve NOT , OR operator");
309 if (!pred
->isNotOrInvolved())
311 printDebug(DM_Predicate
, "predicate does not involve NOT , OR operator");
312 for (int i
=0; i
< numIndexes_
; i
++)
314 HashIndexInfo
* info
= (HashIndexInfo
*) idxInfo
[i
];
315 FieldIterator iter
= info
->idxFldList
.getIterator();
316 while(iter
.hasElement())
318 FieldDef
*def
= iter
.nextElement();
319 if (pred
->pointLookupInvolved(def
->fldName_
))
321 printDebug(DM_Predicate
, "point lookup involved for field %s",def
->fldName_
);
322 if(hashIndex
== info
->indType
) scanType_
= hashIndexScan
;
323 else scanType_
= treeIndexScan
;
324 isPlanCreated
= true;
328 else if (pred
->isBetweenInvolved(def
->fldName_
))
330 if (treeIndex
== info
->indType
)
332 scanType_
= treeIndexScan
;
333 isPlanCreated
= true;
336 break; //no composite index for tree index
339 else if (pred
->rangeQueryInvolved(def
->fldName_
))
341 printDebug(DM_Predicate
, "range lookup involved for field %s",def
->fldName_
);
342 if (treeIndex
== info
->indType
)
344 scanType_
= treeIndexScan
;
345 isPlanCreated
= true;
347 break; //no composite index for tree index
353 }//while iter.hasElement()
354 if (useIndex_
!= -1) return OK
;
358 scanType_
= fullTableScan
;
359 isPlanCreated
= true;
363 void* TableImpl::fetch()
366 if (NULL
== curTuple_
) return curTuple_
;
367 copyValuesToBindBuffer(curTuple_
);
370 void* TableImpl::fetch(DbRetVal
&rv
)
373 if (NULL
== curTuple_
) return curTuple_
;
374 copyValuesToBindBuffer(curTuple_
);
378 void* TableImpl::fetchNoBind()
382 printError(ErrNotOpen
,"Scan not open or Scan is closed\n");
385 void *prevTuple
= curTuple_
;
386 curTuple_
= iter
->next();
387 if (NULL
== curTuple_
)
391 DbRetVal lockRet
= OK
;
392 if ((*trans
)->isoLevel_
== READ_COMMITTED
)
394 //if iso level is read committed, operation duration lock is sufficent
395 //so release it here itself.
397 struct timeval timeout
;
398 timeout
.tv_sec
= Conf::config
.getMutexSecs();
399 timeout
.tv_usec
= Conf::config
.getMutexUSecs();
403 lockRet
= lMgr_
->isExclusiveLocked( curTuple_
, trans
, status
);
406 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
407 curTuple_
= prevTuple
;
412 if (tries
== 0) break;
413 os::select(0, 0, 0, 0, &timeout
);
418 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
419 curTuple_
= prevTuple
;
423 else if ((*trans
)->isoLevel_
== READ_REPEATABLE
) {
424 lockRet
= lMgr_
->getSharedLock(curTuple_
, trans
);
427 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
428 curTuple_
= prevTuple
;
436 void* TableImpl::fetchNoBind(DbRetVal
&rv
)
441 printError(ErrNotOpen
,"Scan not open or Scan is closed\n");
445 void *prevTuple
= curTuple_
;
446 curTuple_
= iter
->next();
447 if (NULL
== curTuple_
)
451 DbRetVal lockRet
= OK
;
452 if ((*trans
)->isoLevel_
== READ_REPEATABLE
) {
453 lockRet
= lMgr_
->getSharedLock(curTuple_
, trans
);
456 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
458 curTuple_
= prevTuple
;
463 else if ((*trans
)->isoLevel_
== READ_COMMITTED
)
465 //if iso level is read committed, operation duration lock is sufficent
466 //so release it here itself.
468 struct timeval timeout
;
469 timeout
.tv_sec
= Conf::config
.getMutexSecs();
470 timeout
.tv_usec
= Conf::config
.getMutexUSecs();
474 lockRet
= lMgr_
->isExclusiveLocked( curTuple_
, trans
, status
);
477 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
478 curTuple_
= prevTuple
;
484 if (tries
== 0) break;
485 os::select(0, 0, 0, 0, &timeout
);
490 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
491 curTuple_
= prevTuple
;
498 DbRetVal
TableImpl::fetchAgg(const char * fldName
, AggType aType
, void *buf
)
500 FieldInfo
*info
= new FieldInfo();
501 DbRetVal rv
= getFieldInfo(fldName
, info
);
502 if (OK
!= rv
) return rv
;
504 if (AGG_MIN
== aType
|| AGG_MAX
== aType
) {
506 IndexType iType
= getIndexType((char*)fldName
, &pos
);
507 if(treeIndex
== iType
&& pos
>=0) {
508 if (AGG_MIN
== aType
) {
509 HashIndexInfo
* hInfo
= (HashIndexInfo
*) idxInfo
[pos
];
510 CINDEX
*iptr
= (CINDEX
*) hInfo
->indexPtr
;
511 TreeIter
*iter
= new TreeIter((TreeNode
*)iptr
->hashNodeChunk_
);
512 char *tuple
= (char*) iter
->getFirstElement();
514 AllDataType::copyVal(buf
,(void*)(tuple
+info
->offset
),
515 info
->type
, info
->length
);
521 else if (AGG_MAX
== aType
) {
522 HashIndexInfo
* hInfo
= (HashIndexInfo
*) idxInfo
[pos
];
523 CINDEX
*iptr
= (CINDEX
*) hInfo
->indexPtr
;
524 TreeIter
*iter
= new TreeIter((TreeNode
*)iptr
->hashNodeChunk_
);
525 char *tuple
= (char*) iter
->getLastElement();
527 AllDataType::copyVal(buf
,(void*)(tuple
+info
->offset
),
528 info
->type
, info
->length
);
537 DataType type
= info
->type
;
538 int length
= info
->length
;
539 int offset
= info
->offset
;
541 if (NULL
== pred_
&& typeInt
== type
)
543 ChunkIterator cIter
= ((Chunk
*)chunkPtr_
)->getIterator();
544 char *tuple
=(char*)cIter
.nextElement();
545 if (NULL
== tuple
) return OK
;
547 AllDataType::copyVal(buf
, (void*) (tuple
+offset
), type
, length
);
549 tuple
= (char*)cIter
.nextElement();
550 if (NULL
== tuple
) break;
554 if (*(int*)buf
>= *((int*)(tuple
+offset
)))
555 *(int*)buf
= *((int*)(tuple
+offset
));
560 if (*(int*)buf
<= *((int*)(tuple
+offset
)))
561 *(int*)buf
= *((int*)(tuple
+offset
));
566 *(int*)buf
= *(int*)buf
+ *((int*)(tuple
+offset
));
571 *(int*)buf
= *(int*)buf
+ *((int*)(tuple
+offset
));
582 if( AGG_AVG
== aType
) AllDataType::divVal(buf
, &count
, type
);
583 else if (AGG_COUNT
== aType
) (*(int*)buf
) = count
;
588 char *tuple
= (char*) fetchNoBind(rv
);
589 if ( NULL
== tuple
) return OK
;
591 AllDataType::copyVal(buf
, (void*) (tuple
+offset
), type
, length
);
593 tuple
= (char*) fetchNoBind(rv
);
594 if (NULL
== tuple
) break;
598 res
= AllDataType::compareVal(buf
, (void*) (tuple
+offset
),
601 if (res
) AllDataType::copyVal(buf
, (void*) (tuple
+offset
),
607 res
= AllDataType::compareVal(buf
, (void*) (tuple
+offset
),
610 if (res
) AllDataType::copyVal(buf
, (void*) (tuple
+offset
),
616 AllDataType::addVal(buf
, (void*) (tuple
+offset
),
622 AllDataType::addVal(buf
, (void*) (tuple
+offset
),
637 AllDataType::divVal(buf
, &count
,type
);
642 (*(int*)buf
) = count
;
649 DbRetVal
TableImpl::insertTuple()
652 void *tptr
= ((Chunk
*)chunkPtr_
)->allocate(db_
, &ret
);
655 printError(ret
, "Unable to allocate record from chunk");
658 ret
= lMgr_
->getExclusiveLock(tptr
, trans
);
661 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
662 printError(ret
, "Could not get lock for the insert tuple %x", tptr
);
663 return ErrLockTimeOut
;
668 ret
= copyValuesFromBindBuffer(tptr
);
671 printError(ret
, "Unable to copy values from bind buffer");
672 (*trans
)->removeFromHasList(db_
, tptr
);
673 lMgr_
->releaseLock(tptr
);
674 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
681 *(int*)((char*)(tptr
) + (length_
-addSize
)) = iNullInfo
;
685 addSize
= os::align(numFlds_
);
686 os::memcpy(((char*)(tptr
) + (length_
-addSize
)), cNullInfo
, addSize
);
689 //int tupleSize = length_ + addSize;
690 if (NULL
!= indexPtr_
)
694 for (i
= 0; i
< numIndexes_
; i
++)
696 ret
= insertIndexNode(*trans
, indexPtr_
[i
], idxInfo
[i
], tptr
);
697 if (ret
!= OK
) { printError(ret
, "Error in inserting to index"); break;}
699 if (i
!= numIndexes_
)
701 for (int j
= 0; j
< i
; j
++) {
702 printError(ErrWarning
, "Deleting index node");
703 deleteIndexNode(*trans
, indexPtr_
[j
], idxInfo
[j
], tptr
);
705 lMgr_
->releaseLock(tptr
);
706 (*trans
)->removeFromHasList(db_
, tptr
);
707 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
709 //printError(ret, "Unable to insert index node for tuple %x ", tptr);
710 printError(ret
, "Unable to insert index node for tuple %x %d", tptr
, *(int*)tptr
);
715 ret
= (*trans
)->appendUndoLog(sysDB_
, InsertOperation
, tptr
, length_
);
717 printError(ret
, "Unable to create undo log for %x %d", tptr
, *(int*)tptr
);
718 for (int j
= 0; j
< numIndexes_
; j
++) {
719 printError(ErrWarning
, "Deleting index node");
720 deleteIndexNode(*trans
, indexPtr_
[j
], idxInfo
[j
], tptr
);
722 lMgr_
->releaseLock(tptr
);
723 (*trans
)->removeFromHasList(db_
, tptr
);
724 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
729 DbRetVal
TableImpl::deleteTuple()
731 if (NULL
== curTuple_
)
733 printError(ErrNotOpen
, "Scan not open: No Current tuple");
736 DbRetVal ret
= lMgr_
->getExclusiveLock(curTuple_
, trans
);
739 printError(ret
, "Could not get lock for the delete tuple %x", curTuple_
);
740 return ErrLockTimeOut
;
743 if (NULL
!= indexPtr_
)
747 for (i
= 0; i
< numIndexes_
; i
++)
749 ret
= deleteIndexNode(*trans
, indexPtr_
[i
], idxInfo
[i
], curTuple_
);
750 if (ret
!= OK
) break;
752 if (i
!= numIndexes_
)
754 for (int j
= 0; j
< i
; j
++)
755 insertIndexNode(*trans
, indexPtr_
[j
], idxInfo
[j
], curTuple_
);
756 lMgr_
->releaseLock(curTuple_
);
757 (*trans
)->removeFromHasList(db_
, curTuple_
);
758 printError(ret
, "Unable to insert index node for tuple %x", curTuple_
);
762 ((Chunk
*)chunkPtr_
)->free(db_
, curTuple_
);
764 ret
= (*trans
)->appendUndoLog(sysDB_
, DeleteOperation
, curTuple_
, length_
);
769 int TableImpl::deleteWhere()
771 int tuplesDeleted
= 0;
774 if (rv
!=OK
) return (int) rv
;
777 if (rv
!= OK
) { tuplesDeleted
= (int)rv
; break; }
778 if (NULL
== curTuple_
) break;
781 printError(rv
, "Error: Could only delete %d tuples", tuplesDeleted
);
788 return tuplesDeleted
;
791 int TableImpl::truncate()
793 //take exclusive lock on the table
794 //get the chunk ptr of the table
795 //traverse the tablechunks and free all the pages except the first one
796 //get the chunk ptr of all its indexes
797 //traverse the indexchunks and free all the pages except the first one
802 Predicate
* tmpPred
= pred_
;
804 isPlanCreated
= false;
805 int tuplesDeleted
= deleteWhere();
806 isPlanCreated
= false;
808 return tuplesDeleted
;
811 DbRetVal
TableImpl::updateTuple()
813 if (NULL
== curTuple_
)
815 printError(ErrNotOpen
, "Scan not open: No Current tuple");
818 DbRetVal ret
= lMgr_
->getExclusiveLock(curTuple_
, trans
);
821 printError(ret
, "Could not get lock for the update tuple %x", curTuple_
);
822 return ErrLockTimeOut
;
824 if (NULL
!= indexPtr_
)
827 //TODO::If it fails while updating index node, we have to undo all the updates
828 //on other indexes on the table.Currently it will leave the database in an
829 //inconsistent state.
830 for (int i
= 0; i
< numIndexes_
; i
++)
832 ret
= updateIndexNode(*trans
, indexPtr_
[i
], idxInfo
[i
], curTuple_
);
835 lMgr_
->releaseLock(curTuple_
);
836 (*trans
)->removeFromHasList(db_
, curTuple_
);
837 printError(ret
, "Unable to update index node for tuple %x", curTuple_
);
843 ret
= (*trans
)->appendUndoLog(sysDB_
, UpdateOperation
, curTuple_
, length_
);
844 if (ret
!= OK
) return ret
;
846 int iNullVal
=iNullInfo
;
850 iNullInfo
= *(int*)((char*)(curTuple_
) + (length_
- addSize
));
854 *(int*)((char*)(curTuple_
) + (length_
-addSize
)) |= iNullInfo
;
857 DbRetVal rv
= copyValuesFromBindBuffer(curTuple_
, false);
859 lMgr_
->releaseLock(curTuple_
);
860 (*trans
)->removeFromHasList(db_
, curTuple_
);
867 *(int*)((char*)(curTuple_
) + (length_
-addSize
)) = iNullInfo
;
870 else iNullInfo
=iNullVal
;
874 addSize
= os::align(numFlds_
);
875 //TODO::Do not do blind memcpy. It should OR each and every char
876 //os::memcpy(((char*)(curTuple_) + (length_-addSize)), cNullInfo, addSize);
882 void TableImpl::printInfo()
884 printf(" <TableName> %s </TableName>\n", tblName_
);
885 printf(" <TupleCount> %d </TupleCount>\n", numTuples());
886 printf(" <PagesUsed> %d </PagesUsed>\n", pagesUsed());
887 printf(" <SpaceUsed> %d </SpaceUsed>\n", spaceUsed());
888 printf(" <Indexes> %d <Indexes>\n", numIndexes_
);
889 printf(" <TupleLength> %d </TupleLength>\n", length_
);
890 printf(" <Fields> %d </Fields>\n", numFlds_
);
891 printf(" <Indexes>\n");
892 for (int i
=0; i
<numIndexes_
; i
++)
893 printf("<IndexName> %s </IndexName>\n", CatalogTableINDEX::getName(indexPtr_
[i
]));
894 printf(" </Indexes>\n");
898 DbRetVal
TableImpl::copyValuesFromBindBuffer(void *tuplePtr
, bool isInsert
)
900 //Iterate through the bind list and copy the value here
901 FieldIterator fIter
= fldList_
.getIterator();
902 char *colPtr
= (char*) tuplePtr
;
904 while (fIter
.hasElement())
906 FieldDef
*def
= fIter
.nextElement();
907 if(def
->isAutoIncrement_
&& isInsert
)
909 void *dest
= AllDataType::alloc(def
->type_
, def
->length_
);
910 AllDataType::copyVal(dest
,ptrToAuto
, def
->type_
, def
->length_
);
911 if(def
->bindVal_
==NULL
)
913 AllDataType::increment(colPtr
, dest
, def
->type_
);
914 AllDataType::copyVal(ptrToAuto
,colPtr
, def
->type_
, def
->length_
);
915 colPtr
= colPtr
+ def
->length_
;
920 if(AllDataType::compareVal(def
->bindVal_
, dest
, OpGreaterThan
, def
->type_
)){
921 AllDataType::copyVal(ptrToAuto
,def
->bindVal_
, def
->type_
, def
->length_
);
926 if (def
->isNull_
&& !def
->isDefault_
&& NULL
== def
->bindVal_
&& isInsert
)
928 printError(ErrNullViolation
, "NOT NULL constraint violation for field %s\n", def
->fldName_
);
929 return ErrNullViolation
;
931 if (def
->isDefault_
&& NULL
== def
->bindVal_
&& isInsert
)
933 void *dest
= AllDataType::alloc(def
->type_
, def
->length_
);
934 AllDataType::convert(typeString
, def
->defaultValueBuf_
, def
->type_
, dest
, def
->length_
);
935 AllDataType::copyVal(colPtr
, dest
, def
->type_
, def
->length_
);
936 colPtr
= colPtr
+ def
->length_
;
944 if (NULL
!= def
->bindVal_
)
946 if(!isInsert
&& isFldNull(fldpos
)){clearNullBit(fldpos
);}
947 strcpy((char*)colPtr
, (char*)def
->bindVal_
);
948 *(((char*)colPtr
) + (def
->length_
-1)) = '\0';
950 else if (!def
->isNull_
&& !def
->bindVal_
&& isInsert
) setNullBit(fldpos
);
951 colPtr
= colPtr
+ def
->length_
;
954 if (NULL
!= def
->bindVal_
)
956 if(!isInsert
&& isFldNull(fldpos
)){clearNullBit(fldpos
);}
957 DbRetVal rv
= AllDataType::strToValue(colPtr
, (char *) def
->bindVal_
, def
->type_
, def
->length_
);
958 if (rv
!= OK
) return ErrBadArg
;
960 else if (!def
->isNull_
&& isInsert
&& !def
->bindVal_
) setNullBit(fldpos
);
961 colPtr
= colPtr
+ def
->length_
;
964 if (NULL
!= def
->bindVal_
){
965 if(!isInsert
&& isFldNull(fldpos
)){clearNullBit(fldpos
);}
966 AllDataType::copyVal(colPtr
, def
->bindVal_
, def
->type_
);}
967 else { if (!def
->isNull_
&& isInsert
) setNullBit(fldpos
); }
968 colPtr
= colPtr
+ def
->length_
;
975 void TableImpl::clearNullBit(int fldpos
)
977 if (isIntUsedForNULL
){
978 CLEARBIT(iNullInfo
, fldpos
);}
980 cNullInfo
[fldpos
-1] = 0;
982 void TableImpl::setNullBit(int fldpos
)
984 if (isIntUsedForNULL
)
985 SETBIT(iNullInfo
, fldpos
);
987 cNullInfo
[fldpos
-1] = 1;
989 DbRetVal
TableImpl::copyValuesToBindBuffer(void *tuplePtr
)
991 //Iterate through the bind list and copy the value here
992 char *colPtr
= (char*) tuplePtr
;
993 FieldDef
*def
= NULL
;
994 for (int i
= 0; i
< numBindFlds_
; i
++) {
995 def
= (FieldDef
*) bindListArray_
[i
];
996 colPtr
= (char *) tuplePtr
+ def
->offset_
;
997 AllDataType::copyVal(def
->bindVal_
, colPtr
, def
->type_
, def
->length_
);
1002 //-1 index not supported
1003 DbRetVal
TableImpl::insertIndexNode(Transaction
*tr
, void *indexPtr
, IndexInfo
*info
, void *tuple
)
1005 CINDEX
*iptr
= (CINDEX
*)indexPtr
;
1007 printDebug(DM_Table
, "Inside insertIndexNode type %d", iptr
->indexType_
);
1008 Index
* idx
= Index::getIndex(iptr
->indexType_
);
1009 ret
= idx
->insert(this, tr
, indexPtr
, info
, tuple
,undoFlag
);
1013 DbRetVal
TableImpl::deleteIndexNode(Transaction
*tr
, void *indexPtr
, IndexInfo
*info
, void *tuple
)
1015 CINDEX
*iptr
= (CINDEX
*)indexPtr
;
1017 Index
* idx
= Index::getIndex(iptr
->indexType_
);
1018 ret
= idx
->remove(this, tr
, indexPtr
, info
, tuple
, undoFlag
);
1021 void TableImpl::printSQLIndexString()
1023 CatalogTableINDEXFIELD
cIndexField(sysDB_
);
1024 char fName
[IDENTIFIER_LENGTH
];
1025 char *fldName
= fName
;
1026 char idxName
[IDENTIFIER_LENGTH
];
1028 for (int i
= 0; i
< numIndexes_
; i
++)
1030 CINDEX
*iptr
= (CINDEX
*) indexPtr_
[i
];
1031 sprintf(idxName
,"%s_idx_Auto_increment",getName());
1032 if(strcmp(iptr
->indName_
,idxName
)==0){ continue; }
1033 printf("CREATE INDEX %s on %s ( ", iptr
->indName_
, getName());
1035 cIndexField
.getFieldInfo(iptr
, fldList
);
1036 FieldIterator fIter
= fldList
.getIterator();
1037 bool firstFld
= true;
1038 while(fIter
.hasElement())
1040 FieldDef
*def
= fIter
.nextElement();
1041 if (firstFld
) { printf(" %s ", def
->fldName_
); firstFld
= false; }
1042 else printf(" ,%s ", def
->fldName_
);
1045 if (iptr
->indexType_
== hashIndex
) printf(" HASH ");
1046 else printf(" TREE ");
1047 if (((HashIndexInfo
*) idxInfo
[i
])->isUnique
) printf(" UNIQUE");
1048 if(((HashIndexInfo
*) idxInfo
[i
])->noOfBuckets
!= 1009 ) printf(" SIZE %d ",((HashIndexInfo
*) idxInfo
[i
])->noOfBuckets
);
1054 DbRetVal
TableImpl::updateIndexNode(Transaction
*tr
, void *indexPtr
, IndexInfo
*info
, void *tuple
)
1056 CINDEX
*iptr
= (CINDEX
*)indexPtr
;
1058 Index
* idx
= Index::getIndex(iptr
->indexType_
);
1059 //TODO::currently it updates irrespective of whether the key changed or not
1060 //because of this commenting the whole index update code. relook at it and uncomment
1062 ret
= idx
->update(this, tr
, indexPtr
, info
, tuple
, undoFlag
);
1068 void TableImpl::setTableInfo(char *name
, int tblid
, size_t length
,
1069 int numFld
, int numIdx
, void *chunk
)
1071 strcpy(tblName_
, name
);
1075 numIndexes_
= numIdx
;
1079 long TableImpl::spaceUsed()
1081 Chunk
*chk
= (Chunk
*)chunkPtr_
;
1082 long totSize
= chk
->getTotalDataNodes() * chk
->getSize();
1083 totSize
= totSize
+ (chk
->totalPages() * sizeof (PageInfo
));
1087 int TableImpl::pagesUsed()
1089 Chunk
*chk
= (Chunk
*)chunkPtr_
;
1090 return chk
->totalPages();
1093 long TableImpl::numTuples()
1095 return ((Chunk
*)chunkPtr_
)->getTotalDataNodes();
1098 List
TableImpl::getFieldNameList()
1101 FieldIterator fIter
= fldList_
.getIterator();
1102 char fieldName
[IDENTIFIER_LENGTH
];
1103 while (fIter
.hasElement())
1105 FieldDef
*def
= fIter
.nextElement();
1106 Identifier
*elem
= new Identifier();
1107 Table::getFieldNameAlone(def
->fldName_
, fieldName
);
1108 sprintf(elem
->name
, "%s.%s", getName(), fieldName
);
1109 fldNameList
.append(elem
);
1113 DbRetVal
TableImpl::close()
1115 if (iter
) { iter
->close(); delete iter
; iter
= NULL
; }
1116 printDebug(DM_Database
,"Closing table handle: %x", this);
1120 logFinest(logger
, "Closing Table");
1124 DbRetVal
TableImpl::closeScan()
1126 //do not throw scan not open error
1127 //this function will be called by table handle
1130 //PRABA::TEMP::otherwise fails.check with kishor
1136 DbRetVal
TableImpl::lock(bool shared
)
1142 ret = lMgr_->getSharedLock(chunkPtr_, NULL);
1144 ret = lMgr_->getExclusiveLock(chunkPtr_, NULL);
1147 printError(ret, "Could not exclusive lock on the table %x", chunkPtr_);
1149 //do not append for S to X upgrade
1150 if (!ProcessManager::hasLockList.exists(chunkPtr_))
1151 ProcessManager::hasLockList.append(chunkPtr_);
1156 DbRetVal
TableImpl::unlock()
1159 if (!ProcessManager::hasLockList.exists(chunkPtr_)) return OK;
1160 DbRetVal ret = lMgr_->releaseLock(chunkPtr_);
1163 printError(ret, "Could not release exclusive lock on the table %x", chunkPtr_);
1166 ProcessManager::hasLockList.remove(chunkPtr_);
1172 TableImpl::~TableImpl()
1174 if (NULL
!= iter
) { delete iter
; iter
= NULL
; }
1175 if (NULL
!= indexPtr_
) { delete[] indexPtr_
; indexPtr_
= NULL
; }
1176 if (NULL
!= idxInfo
)
1178 for (int i
= 0; i
< numIndexes_
; i
++) delete idxInfo
[i
];
1182 if (numFlds_
> 31 && cNullInfo
!= NULL
) { free(cNullInfo
); cNullInfo
= NULL
; }
1183 if (bindList_
.size()) bindList_
.reset();
1184 if (bindListArray_
) { free (bindListArray_
); bindListArray_
= NULL
; }
1185 fldList_
.removeAll();
1189 void *TableImpl::getBindFldAddr(const char *name
)
1191 return fldList_
.getBindField(name
);
1193 bool TableImpl::isTableInvolved(char *tblName
)
1195 //printf("Table isTableInvolved called for %s with %s\n", tblName, getName());
1196 if (0 == strcmp(getName(), tblName
)) return true; else return false;
1198 bool TableImpl::pushPredicate(Predicate
*pred
)
1201 PredicateImpl
*pImpl
= (PredicateImpl
*) pred
;
1202 char tableName
[IDENTIFIER_LENGTH
];
1203 Table::getTableNameAlone(pImpl
->getFldName1(), tableName
);
1204 //printf("predicate tbl name %s\n", tableName);
1206 //if predicate is of form t1.f1=t2.f1 then do not push here
1207 if (0 != strcmp(pImpl
->getFldName2(),"")) return ret
;
1209 if (0 == strcmp(getName(), tableName
))
1212 //printf("PRABA::pushed predicate in tablehdl %s\n", getName());
1217 void TableImpl::setPredicate(Predicate
*pred
)
1219 if (NULL
== pred_
) { pred_
= pred
; return; }
1220 Predicate
*curPred
= pred_
;
1221 PredicateImpl
*newPred
= new PredicateImpl();
1222 newPred
->setTerm(curPred
, OpAnd
, pred
);
1223 newPred
->setTable(this);
1227 void TableImpl::printPlan(int space
)
1229 char spaceBuf
[IDENTIFIER_LENGTH
];
1230 memset(spaceBuf
, 32, IDENTIFIER_LENGTH
);
1231 spaceBuf
[space
] = '\0';
1232 printf("%s <TABLE-NODE>\n", spaceBuf
);
1233 printf("%s <NAME> %s </NAME>\n", spaceBuf
, getName());
1234 printf("%s <ScanType> %s </ScanType>\n", spaceBuf
, ScanTypeNames
[scanType_
]);
1235 PredicateImpl
*pred
= (PredicateImpl
*)pred_
;
1236 if (pred
) pred
->print(space
+2);
1237 printf("%s </TABLE-NODE>\n", spaceBuf
);