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
);
708 printError(ret
, "Unable to insert index node for tuple %x ", tptr
);
713 ret
= (*trans
)->appendUndoLog(sysDB_
, InsertOperation
, tptr
, length_
);
715 printError(ret
, "Unable to create undo log for %x %d", tptr
, *(int*)tptr
);
716 for (int j
= 0; j
< numIndexes_
; j
++) {
717 printError(ErrWarning
, "Deleting index node");
718 deleteIndexNode(*trans
, indexPtr_
[j
], idxInfo
[j
], tptr
);
720 lMgr_
->releaseLock(tptr
);
721 (*trans
)->removeFromHasList(db_
, tptr
);
722 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
727 DbRetVal
TableImpl::deleteTuple()
729 if (NULL
== curTuple_
)
731 printError(ErrNotOpen
, "Scan not open: No Current tuple");
734 DbRetVal ret
= lMgr_
->getExclusiveLock(curTuple_
, trans
);
737 printError(ret
, "Could not get lock for the delete tuple %x", curTuple_
);
738 return ErrLockTimeOut
;
741 if (NULL
!= indexPtr_
)
745 for (i
= 0; i
< numIndexes_
; i
++)
747 ret
= deleteIndexNode(*trans
, indexPtr_
[i
], idxInfo
[i
], curTuple_
);
748 if (ret
!= OK
) break;
750 if (i
!= numIndexes_
)
752 for (int j
= 0; j
< i
; j
++)
753 insertIndexNode(*trans
, indexPtr_
[j
], idxInfo
[j
], curTuple_
);
754 lMgr_
->releaseLock(curTuple_
);
755 (*trans
)->removeFromHasList(db_
, curTuple_
);
756 printError(ret
, "Unable to insert index node for tuple %x", curTuple_
);
760 ((Chunk
*)chunkPtr_
)->free(db_
, curTuple_
);
762 ret
= (*trans
)->appendUndoLog(sysDB_
, DeleteOperation
, curTuple_
, length_
);
767 int TableImpl::deleteWhere()
769 int tuplesDeleted
= 0;
772 if (rv
!=OK
) return (int) rv
;
775 if (rv
!= OK
) { tuplesDeleted
= (int)rv
; break; }
776 if (NULL
== curTuple_
) break;
779 printError(rv
, "Error: Could only delete %d tuples", tuplesDeleted
);
786 return tuplesDeleted
;
789 int TableImpl::truncate()
791 //take exclusive lock on the table
792 //get the chunk ptr of the table
793 //traverse the tablechunks and free all the pages except the first one
794 //get the chunk ptr of all its indexes
795 //traverse the indexchunks and free all the pages except the first one
800 Predicate
* tmpPred
= pred_
;
802 isPlanCreated
= false;
803 int tuplesDeleted
= deleteWhere();
804 isPlanCreated
= false;
806 return tuplesDeleted
;
809 DbRetVal
TableImpl::updateTuple()
811 if (NULL
== curTuple_
)
813 printError(ErrNotOpen
, "Scan not open: No Current tuple");
816 DbRetVal ret
= lMgr_
->getExclusiveLock(curTuple_
, trans
);
819 printError(ret
, "Could not get lock for the update tuple %x", curTuple_
);
820 return ErrLockTimeOut
;
822 if (NULL
!= indexPtr_
)
825 //TODO::If it fails while updating index node, we have to undo all the updates
826 //on other indexes on the table.Currently it will leave the database in an
827 //inconsistent state.
828 for (int i
= 0; i
< numIndexes_
; i
++)
830 ret
= updateIndexNode(*trans
, indexPtr_
[i
], idxInfo
[i
], curTuple_
);
833 lMgr_
->releaseLock(curTuple_
);
834 (*trans
)->removeFromHasList(db_
, curTuple_
);
835 printError(ret
, "Unable to update index node for tuple %x", curTuple_
);
841 ret
= (*trans
)->appendUndoLog(sysDB_
, UpdateOperation
, curTuple_
, length_
);
842 if (ret
!= OK
) return ret
;
844 int iNullVal
=iNullInfo
;
848 iNullInfo
= *(int*)((char*)(curTuple_
) + (length_
- addSize
));
852 *(int*)((char*)(curTuple_
) + (length_
-addSize
)) |= iNullInfo
;
855 DbRetVal rv
= copyValuesFromBindBuffer(curTuple_
, false);
857 lMgr_
->releaseLock(curTuple_
);
858 (*trans
)->removeFromHasList(db_
, curTuple_
);
865 *(int*)((char*)(curTuple_
) + (length_
-addSize
)) = iNullInfo
;
868 else iNullInfo
=iNullVal
;
872 addSize
= os::align(numFlds_
);
873 //TODO::Do not do blind memcpy. It should OR each and every char
874 //os::memcpy(((char*)(curTuple_) + (length_-addSize)), cNullInfo, addSize);
880 void TableImpl::printInfo()
882 printf(" <TableName> %s </TableName>\n", tblName_
);
883 printf(" <TupleCount> %d </TupleCount>\n", numTuples());
884 printf(" <PagesUsed> %d </PagesUsed>\n", pagesUsed());
885 printf(" <SpaceUsed> %d </SpaceUsed>\n", spaceUsed());
886 printf(" <Indexes> %d <Indexes>\n", numIndexes_
);
887 printf(" <TupleLength> %d </TupleLength>\n", length_
);
888 printf(" <Fields> %d </Fields>\n", numFlds_
);
889 printf(" <Indexes>\n");
890 for (int i
=0; i
<numIndexes_
; i
++)
891 printf("<IndexName> %s </IndexName>\n", CatalogTableINDEX::getName(indexPtr_
[i
]));
892 printf(" </Indexes>\n");
896 DbRetVal
TableImpl::copyValuesFromBindBuffer(void *tuplePtr
, bool isInsert
)
898 //Iterate through the bind list and copy the value here
899 FieldIterator fIter
= fldList_
.getIterator();
900 char *colPtr
= (char*) tuplePtr
;
902 while (fIter
.hasElement())
904 FieldDef
*def
= fIter
.nextElement();
905 if(def
->isAutoIncrement_
&& isInsert
)
907 void *dest
= AllDataType::alloc(def
->type_
, def
->length_
);
908 AllDataType::copyVal(dest
,ptrToAuto
, def
->type_
, def
->length_
);
909 if(def
->bindVal_
==NULL
)
911 AllDataType::increment(colPtr
, dest
, def
->type_
);
912 AllDataType::copyVal(ptrToAuto
,colPtr
, def
->type_
, def
->length_
);
913 colPtr
= colPtr
+ def
->length_
;
918 if(AllDataType::compareVal(def
->bindVal_
, dest
, OpGreaterThan
, def
->type_
)){
919 AllDataType::copyVal(ptrToAuto
,def
->bindVal_
, def
->type_
, def
->length_
);
924 if (def
->isNull_
&& !def
->isDefault_
&& NULL
== def
->bindVal_
&& isInsert
)
926 printError(ErrNullViolation
, "NOT NULL constraint violation for field %s\n", def
->fldName_
);
927 return ErrNullViolation
;
929 if (def
->isDefault_
&& NULL
== def
->bindVal_
&& isInsert
)
931 void *dest
= AllDataType::alloc(def
->type_
, def
->length_
);
932 AllDataType::convert(typeString
, def
->defaultValueBuf_
, def
->type_
, dest
, def
->length_
);
933 AllDataType::copyVal(colPtr
, dest
, def
->type_
, def
->length_
);
934 colPtr
= colPtr
+ def
->length_
;
942 if (NULL
!= def
->bindVal_
)
944 if(!isInsert
&& isFldNull(fldpos
)){clearNullBit(fldpos
);}
945 strcpy((char*)colPtr
, (char*)def
->bindVal_
);
946 *(((char*)colPtr
) + (def
->length_
-1)) = '\0';
948 else if (!def
->isNull_
&& !def
->bindVal_
&& isInsert
) setNullBit(fldpos
);
949 colPtr
= colPtr
+ def
->length_
;
952 if (NULL
!= def
->bindVal_
)
954 if(!isInsert
&& isFldNull(fldpos
)){clearNullBit(fldpos
);}
955 DbRetVal rv
= AllDataType::strToValue(colPtr
, (char *) def
->bindVal_
, def
->type_
, def
->length_
);
956 if (rv
!= OK
) return ErrBadArg
;
958 else if (!def
->isNull_
&& isInsert
&& !def
->bindVal_
) setNullBit(fldpos
);
959 colPtr
= colPtr
+ def
->length_
;
962 if (NULL
!= def
->bindVal_
){
963 if(!isInsert
&& isFldNull(fldpos
)){clearNullBit(fldpos
);}
964 AllDataType::copyVal(colPtr
, def
->bindVal_
, def
->type_
);}
965 else { if (!def
->isNull_
&& isInsert
) setNullBit(fldpos
); }
966 colPtr
= colPtr
+ def
->length_
;
973 void TableImpl::clearNullBit(int fldpos
)
975 if (isIntUsedForNULL
){
976 CLEARBIT(iNullInfo
, fldpos
);}
978 cNullInfo
[fldpos
-1] = 0;
980 void TableImpl::setNullBit(int fldpos
)
982 if (isIntUsedForNULL
)
983 SETBIT(iNullInfo
, fldpos
);
985 cNullInfo
[fldpos
-1] = 1;
987 DbRetVal
TableImpl::copyValuesToBindBuffer(void *tuplePtr
)
989 //Iterate through the bind list and copy the value here
990 char *colPtr
= (char*) tuplePtr
;
991 FieldDef
*def
= NULL
;
992 for (int i
= 0; i
< numBindFlds_
; i
++) {
993 def
= (FieldDef
*) bindListArray_
[i
];
994 colPtr
= (char *) tuplePtr
+ def
->offset_
;
995 AllDataType::copyVal(def
->bindVal_
, colPtr
, def
->type_
, def
->length_
);
1000 //-1 index not supported
1001 DbRetVal
TableImpl::insertIndexNode(Transaction
*tr
, void *indexPtr
, IndexInfo
*info
, void *tuple
)
1003 CINDEX
*iptr
= (CINDEX
*)indexPtr
;
1005 printDebug(DM_Table
, "Inside insertIndexNode type %d", iptr
->indexType_
);
1006 Index
* idx
= Index::getIndex(iptr
->indexType_
);
1007 ret
= idx
->insert(this, tr
, indexPtr
, info
, tuple
,undoFlag
);
1011 DbRetVal
TableImpl::deleteIndexNode(Transaction
*tr
, void *indexPtr
, IndexInfo
*info
, void *tuple
)
1013 CINDEX
*iptr
= (CINDEX
*)indexPtr
;
1015 Index
* idx
= Index::getIndex(iptr
->indexType_
);
1016 ret
= idx
->remove(this, tr
, indexPtr
, info
, tuple
, undoFlag
);
1019 void TableImpl::printSQLIndexString()
1021 CatalogTableINDEXFIELD
cIndexField(sysDB_
);
1022 char fName
[IDENTIFIER_LENGTH
];
1023 char *fldName
= fName
;
1024 char idxName
[IDENTIFIER_LENGTH
];
1026 for (int i
= 0; i
< numIndexes_
; i
++)
1028 CINDEX
*iptr
= (CINDEX
*) indexPtr_
[i
];
1029 sprintf(idxName
,"%s_idx_Auto_increment",getName());
1030 if(strcmp(iptr
->indName_
,idxName
)==0){ continue; }
1031 printf("CREATE INDEX %s on %s ( ", iptr
->indName_
, getName());
1033 cIndexField
.getFieldInfo(iptr
, fldList
);
1034 FieldIterator fIter
= fldList
.getIterator();
1035 bool firstFld
= true;
1036 while(fIter
.hasElement())
1038 FieldDef
*def
= fIter
.nextElement();
1039 if (firstFld
) { printf(" %s ", def
->fldName_
); firstFld
= false; }
1040 else printf(" ,%s ", def
->fldName_
);
1043 if (iptr
->indexType_
== hashIndex
) printf(" HASH ");
1044 else printf(" TREE ");
1045 if (((HashIndexInfo
*) idxInfo
[i
])->isUnique
) printf(" UNIQUE");
1046 if(((HashIndexInfo
*) idxInfo
[i
])->noOfBuckets
!= 1009 ) printf(" SIZE %d ",((HashIndexInfo
*) idxInfo
[i
])->noOfBuckets
);
1052 DbRetVal
TableImpl::updateIndexNode(Transaction
*tr
, void *indexPtr
, IndexInfo
*info
, void *tuple
)
1054 CINDEX
*iptr
= (CINDEX
*)indexPtr
;
1056 Index
* idx
= Index::getIndex(iptr
->indexType_
);
1057 //TODO::currently it updates irrespective of whether the key changed or not
1058 //because of this commenting the whole index update code. relook at it and uncomment
1060 ret
= idx
->update(this, tr
, indexPtr
, info
, tuple
, undoFlag
);
1066 void TableImpl::setTableInfo(char *name
, int tblid
, size_t length
,
1067 int numFld
, int numIdx
, void *chunk
)
1069 strcpy(tblName_
, name
);
1073 numIndexes_
= numIdx
;
1077 long TableImpl::spaceUsed()
1079 Chunk
*chk
= (Chunk
*)chunkPtr_
;
1080 long totSize
= chk
->getTotalDataNodes() * chk
->getSize();
1081 totSize
= totSize
+ (chk
->totalPages() * sizeof (PageInfo
));
1085 int TableImpl::pagesUsed()
1087 Chunk
*chk
= (Chunk
*)chunkPtr_
;
1088 return chk
->totalPages();
1091 long TableImpl::numTuples()
1093 return ((Chunk
*)chunkPtr_
)->getTotalDataNodes();
1096 List
TableImpl::getFieldNameList()
1099 FieldIterator fIter
= fldList_
.getIterator();
1100 char fieldName
[IDENTIFIER_LENGTH
];
1101 while (fIter
.hasElement())
1103 FieldDef
*def
= fIter
.nextElement();
1104 Identifier
*elem
= new Identifier();
1105 Table::getFieldNameAlone(def
->fldName_
, fieldName
);
1106 sprintf(elem
->name
, "%s.%s", getName(), fieldName
);
1107 fldNameList
.append(elem
);
1111 DbRetVal
TableImpl::close()
1113 if (iter
) { iter
->close(); delete iter
; iter
= NULL
; }
1114 printDebug(DM_Database
,"Closing table handle: %x", this);
1118 logFinest(logger
, "Closing Table");
1122 DbRetVal
TableImpl::closeScan()
1124 //do not throw scan not open error
1125 //this function will be called by table handle
1128 //PRABA::TEMP::otherwise fails.check with kishor
1134 DbRetVal
TableImpl::lock(bool shared
)
1140 ret = lMgr_->getSharedLock(chunkPtr_, NULL);
1142 ret = lMgr_->getExclusiveLock(chunkPtr_, NULL);
1145 printError(ret, "Could not exclusive lock on the table %x", chunkPtr_);
1147 //do not append for S to X upgrade
1148 if (!ProcessManager::hasLockList.exists(chunkPtr_))
1149 ProcessManager::hasLockList.append(chunkPtr_);
1154 DbRetVal
TableImpl::unlock()
1157 if (!ProcessManager::hasLockList.exists(chunkPtr_)) return OK;
1158 DbRetVal ret = lMgr_->releaseLock(chunkPtr_);
1161 printError(ret, "Could not release exclusive lock on the table %x", chunkPtr_);
1164 ProcessManager::hasLockList.remove(chunkPtr_);
1170 TableImpl::~TableImpl()
1172 if (NULL
!= iter
) { delete iter
; iter
= NULL
; }
1173 if (NULL
!= indexPtr_
) { delete[] indexPtr_
; indexPtr_
= NULL
; }
1174 if (NULL
!= idxInfo
)
1176 for (int i
= 0; i
< numIndexes_
; i
++) delete idxInfo
[i
];
1180 if (numFlds_
> 31 && cNullInfo
!= NULL
) { free(cNullInfo
); cNullInfo
= NULL
; }
1181 if (bindList_
.size()) bindList_
.reset();
1182 if (bindListArray_
) { free (bindListArray_
); bindListArray_
= NULL
; }
1183 fldList_
.removeAll();
1187 void *TableImpl::getBindFldAddr(const char *name
)
1189 return fldList_
.getBindField(name
);
1191 bool TableImpl::isTableInvolved(char *tblName
)
1193 //printf("Table isTableInvolved called for %s with %s\n", tblName, getName());
1194 if (0 == strcmp(getName(), tblName
)) return true; else return false;
1196 bool TableImpl::pushPredicate(Predicate
*pred
)
1199 PredicateImpl
*pImpl
= (PredicateImpl
*) pred
;
1200 char tableName
[IDENTIFIER_LENGTH
];
1201 Table::getTableNameAlone(pImpl
->getFldName1(), tableName
);
1202 //printf("predicate tbl name %s\n", tableName);
1204 //if predicate is of form t1.f1=t2.f1 then do not push here
1205 if (0 != strcmp(pImpl
->getFldName2(),"")) return ret
;
1207 if (0 == strcmp(getName(), tableName
))
1210 //printf("PRABA::pushed predicate in tablehdl %s\n", getName());
1215 void TableImpl::setPredicate(Predicate
*pred
)
1217 if (NULL
== pred_
) { pred_
= pred
; return; }
1218 Predicate
*curPred
= pred_
;
1219 PredicateImpl
*newPred
= new PredicateImpl();
1220 newPred
->setTerm(curPred
, OpAnd
, pred
);
1221 newPred
->setTable(this);
1225 void TableImpl::printPlan(int space
)
1227 char spaceBuf
[IDENTIFIER_LENGTH
];
1228 memset(spaceBuf
, 32, IDENTIFIER_LENGTH
);
1229 spaceBuf
[space
] = '\0';
1230 printf("%s <TABLE-NODE>\n", spaceBuf
);
1231 printf("%s <NAME> %s </NAME>\n", spaceBuf
, getName());
1232 printf("%s <ScanType> %s </ScanType>\n", spaceBuf
, ScanTypeNames
[scanType_
]);
1233 PredicateImpl
*pred
= (PredicateImpl
*)pred_
;
1234 if (pred
) pred
->print(space
+2);
1235 printf("%s </TABLE-NODE>\n", spaceBuf
);