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
->isNull_
&& !def
->isDefault_
&& NULL
== def
->bindVal_
&& isInsert
)
909 printError(ErrNullViolation
, "NOT NULL constraint violation for field %s\n", def
->fldName_
);
910 return ErrNullViolation
;
912 if (def
->isDefault_
&& NULL
== def
->bindVal_
&& isInsert
)
914 void *dest
= AllDataType::alloc(def
->type_
, def
->length_
);
915 AllDataType::convert(typeString
, def
->defaultValueBuf_
, def
->type_
, dest
, def
->length_
);
916 AllDataType::copyVal(colPtr
, dest
, def
->type_
, def
->length_
);
917 colPtr
= colPtr
+ def
->length_
;
925 if (NULL
!= def
->bindVal_
)
927 if(!isInsert
&& isFldNull(fldpos
)){clearNullBit(fldpos
);}
928 strcpy((char*)colPtr
, (char*)def
->bindVal_
);
929 *(((char*)colPtr
) + (def
->length_
-1)) = '\0';
931 else if (!def
->isNull_
&& !def
->bindVal_
&& isInsert
) setNullBit(fldpos
);
932 colPtr
= colPtr
+ def
->length_
;
935 if (NULL
!= def
->bindVal_
)
937 if(!isInsert
&& isFldNull(fldpos
)){clearNullBit(fldpos
);}
938 DbRetVal rv
= AllDataType::strToValue(colPtr
, (char *) def
->bindVal_
, def
->type_
, def
->length_
);
939 if (rv
!= OK
) return ErrBadArg
;
941 else if (!def
->isNull_
&& isInsert
&& !def
->bindVal_
) setNullBit(fldpos
);
942 colPtr
= colPtr
+ def
->length_
;
945 if (NULL
!= def
->bindVal_
){
946 if(!isInsert
&& isFldNull(fldpos
)){clearNullBit(fldpos
);}
947 AllDataType::copyVal(colPtr
, def
->bindVal_
, def
->type_
);}
948 else { if (!def
->isNull_
&& isInsert
) setNullBit(fldpos
); }
949 colPtr
= colPtr
+ def
->length_
;
956 void TableImpl::clearNullBit(int fldpos
)
958 if (isIntUsedForNULL
){
959 CLEARBIT(iNullInfo
, fldpos
);}
961 cNullInfo
[fldpos
-1] = 0;
963 void TableImpl::setNullBit(int fldpos
)
965 if (isIntUsedForNULL
)
966 SETBIT(iNullInfo
, fldpos
);
968 cNullInfo
[fldpos
-1] = 1;
970 DbRetVal
TableImpl::copyValuesToBindBuffer(void *tuplePtr
)
972 //Iterate through the bind list and copy the value here
973 char *colPtr
= (char*) tuplePtr
;
974 FieldDef
*def
= NULL
;
975 for (int i
= 0; i
< numBindFlds_
; i
++) {
976 def
= (FieldDef
*) bindListArray_
[i
];
977 colPtr
= (char *) tuplePtr
+ def
->offset_
;
978 AllDataType::copyVal(def
->bindVal_
, colPtr
, def
->type_
, def
->length_
);
983 //-1 index not supported
984 DbRetVal
TableImpl::insertIndexNode(Transaction
*tr
, void *indexPtr
, IndexInfo
*info
, void *tuple
)
986 CINDEX
*iptr
= (CINDEX
*)indexPtr
;
988 printDebug(DM_Table
, "Inside insertIndexNode type %d", iptr
->indexType_
);
989 Index
* idx
= Index::getIndex(iptr
->indexType_
);
990 ret
= idx
->insert(this, tr
, indexPtr
, info
, tuple
,undoFlag
);
994 DbRetVal
TableImpl::deleteIndexNode(Transaction
*tr
, void *indexPtr
, IndexInfo
*info
, void *tuple
)
996 CINDEX
*iptr
= (CINDEX
*)indexPtr
;
998 Index
* idx
= Index::getIndex(iptr
->indexType_
);
999 ret
= idx
->remove(this, tr
, indexPtr
, info
, tuple
, undoFlag
);
1002 void TableImpl::printSQLIndexString()
1004 CatalogTableINDEXFIELD
cIndexField(sysDB_
);
1005 char fName
[IDENTIFIER_LENGTH
];
1006 char *fldName
= fName
;
1008 for (int i
= 0; i
< numIndexes_
; i
++)
1010 CINDEX
*iptr
= (CINDEX
*) indexPtr_
[i
];
1011 printf("CREATE INDEX %s on %s ( ", iptr
->indName_
, getName());
1013 cIndexField
.getFieldInfo(iptr
, fldList
);
1014 FieldIterator fIter
= fldList
.getIterator();
1015 bool firstFld
= true;
1016 while(fIter
.hasElement())
1018 FieldDef
*def
= fIter
.nextElement();
1019 if (firstFld
) { printf(" %s ", def
->fldName_
); firstFld
= false; }
1020 else printf(" ,%s ", def
->fldName_
);
1023 if (iptr
->indexType_
== hashIndex
) printf(" HASH ");
1024 else printf(" TREE ");
1025 if (((HashIndexInfo
*) idxInfo
[i
])->isUnique
) printf(" UNIQUE;\n"); else printf(";\n");
1030 DbRetVal
TableImpl::updateIndexNode(Transaction
*tr
, void *indexPtr
, IndexInfo
*info
, void *tuple
)
1032 CINDEX
*iptr
= (CINDEX
*)indexPtr
;
1034 Index
* idx
= Index::getIndex(iptr
->indexType_
);
1035 //TODO::currently it updates irrespective of whether the key changed or not
1036 //because of this commenting the whole index update code. relook at it and uncomment
1038 ret
= idx
->update(this, tr
, indexPtr
, info
, tuple
, undoFlag
);
1044 void TableImpl::setTableInfo(char *name
, int tblid
, size_t length
,
1045 int numFld
, int numIdx
, void *chunk
)
1047 strcpy(tblName_
, name
);
1051 numIndexes_
= numIdx
;
1055 long TableImpl::spaceUsed()
1057 Chunk
*chk
= (Chunk
*)chunkPtr_
;
1058 long totSize
= chk
->getTotalDataNodes() * chk
->getSize();
1059 totSize
= totSize
+ (chk
->totalPages() * sizeof (PageInfo
));
1063 int TableImpl::pagesUsed()
1065 Chunk
*chk
= (Chunk
*)chunkPtr_
;
1066 return chk
->totalPages();
1069 long TableImpl::numTuples()
1071 return ((Chunk
*)chunkPtr_
)->getTotalDataNodes();
1074 List
TableImpl::getFieldNameList()
1077 FieldIterator fIter
= fldList_
.getIterator();
1078 char fieldName
[IDENTIFIER_LENGTH
];
1079 while (fIter
.hasElement())
1081 FieldDef
*def
= fIter
.nextElement();
1082 Identifier
*elem
= new Identifier();
1083 Table::getFieldNameAlone(def
->fldName_
, fieldName
);
1084 sprintf(elem
->name
, "%s.%s", getName(), fieldName
);
1085 fldNameList
.append(elem
);
1089 DbRetVal
TableImpl::close()
1091 if (iter
) { iter
->close(); delete iter
; iter
= NULL
; }
1092 printDebug(DM_Database
,"Closing table handle: %x", this);
1096 logFinest(logger
, "Closing Table");
1100 DbRetVal
TableImpl::closeScan()
1102 //do not throw scan not open error
1103 //this function will be called by table handle
1106 //PRABA::TEMP::otherwise fails.check with kishor
1112 DbRetVal
TableImpl::lock(bool shared
)
1118 ret = lMgr_->getSharedLock(chunkPtr_, NULL);
1120 ret = lMgr_->getExclusiveLock(chunkPtr_, NULL);
1123 printError(ret, "Could not exclusive lock on the table %x", chunkPtr_);
1125 //do not append for S to X upgrade
1126 if (!ProcessManager::hasLockList.exists(chunkPtr_))
1127 ProcessManager::hasLockList.append(chunkPtr_);
1132 DbRetVal
TableImpl::unlock()
1135 if (!ProcessManager::hasLockList.exists(chunkPtr_)) return OK;
1136 DbRetVal ret = lMgr_->releaseLock(chunkPtr_);
1139 printError(ret, "Could not release exclusive lock on the table %x", chunkPtr_);
1142 ProcessManager::hasLockList.remove(chunkPtr_);
1148 TableImpl::~TableImpl()
1150 if (NULL
!= iter
) { delete iter
; iter
= NULL
; }
1151 if (NULL
!= indexPtr_
) { delete[] indexPtr_
; indexPtr_
= NULL
; }
1152 if (NULL
!= idxInfo
)
1154 for (int i
= 0; i
< numIndexes_
; i
++) delete idxInfo
[i
];
1158 if (numFlds_
> 31 && cNullInfo
!= NULL
) { free(cNullInfo
); cNullInfo
= NULL
; }
1159 if (bindList_
.size()) bindList_
.reset();
1160 if (bindListArray_
) { free (bindListArray_
); bindListArray_
= NULL
; }
1161 fldList_
.removeAll();
1165 void *TableImpl::getBindFldAddr(const char *name
)
1167 return fldList_
.getBindField(name
);
1169 bool TableImpl::isTableInvolved(char *tblName
)
1171 //printf("Table isTableInvolved called for %s with %s\n", tblName, getName());
1172 if (0 == strcmp(getName(), tblName
)) return true; else return false;
1174 bool TableImpl::pushPredicate(Predicate
*pred
)
1177 PredicateImpl
*pImpl
= (PredicateImpl
*) pred
;
1178 char tableName
[IDENTIFIER_LENGTH
];
1179 Table::getTableNameAlone(pImpl
->getFldName1(), tableName
);
1180 //printf("predicate tbl name %s\n", tableName);
1182 //if predicate is of form t1.f1=t2.f1 then do not push here
1183 if (0 != strcmp(pImpl
->getFldName2(),"")) return ret
;
1185 if (0 == strcmp(getName(), tableName
))
1188 //printf("PRABA::pushed predicate in tablehdl %s\n", getName());
1193 void TableImpl::setPredicate(Predicate
*pred
)
1195 if (NULL
== pred_
) { pred_
= pred
; return; }
1196 Predicate
*curPred
= pred_
;
1197 PredicateImpl
*newPred
= new PredicateImpl();
1198 newPred
->setTerm(curPred
, OpAnd
, pred
);
1199 newPred
->setTable(this);
1203 void TableImpl::printPlan(int space
)
1205 char spaceBuf
[IDENTIFIER_LENGTH
];
1206 memset(spaceBuf
, 32, IDENTIFIER_LENGTH
);
1207 spaceBuf
[space
] = '\0';
1208 printf("%s <TABLE-NODE>\n", spaceBuf
);
1209 printf("%s <NAME> %s </NAME>\n", spaceBuf
, getName());
1210 printf("%s <ScanType> %s </ScanType>\n", spaceBuf
, ScanTypeNames
[scanType_
]);
1211 PredicateImpl
*pred
= (PredicateImpl
*)pred_
;
1212 if (pred
) pred
->print(space
+2);
1213 printf("%s </TABLE-NODE>\n", spaceBuf
);