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 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
;
310 //if there are no predicates then go for full scan
311 //if there are no indexes then go for full scan
312 if (NULL
== pred_
|| NULL
== indexPtr_
)
314 scanType_
= fullTableScan
;
315 isPlanCreated
= true;
318 //If serching for IS NULL or IS NOT NULL then fullscan
319 if (NULL
!= indexPtr_
)
321 PredicateImpl
*pred
= (PredicateImpl
*)pred_
;
322 if(pred
->isIsNullInvolved())
324 scanType_
= fullTableScan
;
325 isPlanCreated
= true;
326 shouldNullSearch
=true;
329 printDebug(DM_Predicate
, "predicate does not involve NOT , OR operator");
330 if (!pred
->isNotOrInvolved())
332 printDebug(DM_Predicate
, "predicate does not involve NOT , OR operator");
333 for (int i
=0; i
< numIndexes_
; i
++)
335 HashIndexInfo
* info
= (HashIndexInfo
*) idxInfo
[i
];
336 FieldIterator iter
= info
->idxFldList
.getIterator();
337 while(iter
.hasElement())
339 FieldDef
*def
= iter
.nextElement();
340 if (pred
->pointLookupInvolved(def
->fldName_
))
342 printDebug(DM_Predicate
, "point lookup involved for field %s",def
->fldName_
);
343 if(hashIndex
== info
->indType
) scanType_
= hashIndexScan
;
344 else scanType_
= treeIndexScan
;
345 isPlanCreated
= true;
349 else if (pred
->isBetweenInvolved(def
->fldName_
))
351 if (treeIndex
== info
->indType
)
353 scanType_
= treeIndexScan
;
354 isPlanCreated
= true;
357 break; //no composite index for tree index
360 else if (pred
->rangeQueryInvolved(def
->fldName_
))
362 printDebug(DM_Predicate
, "range lookup involved for field %s",def
->fldName_
);
363 if (treeIndex
== info
->indType
)
365 scanType_
= treeIndexScan
;
366 isPlanCreated
= true;
368 break; //no composite index for tree index
374 }//while iter.hasElement()
375 if (useIndex_
!= -1) return OK
;
379 scanType_
= fullTableScan
;
380 isPlanCreated
= true;
384 void* TableImpl::fetch()
387 if (NULL
== curTuple_
) return curTuple_
;
388 copyValuesToBindBuffer(curTuple_
);
391 void* TableImpl::fetch(DbRetVal
&rv
)
394 if (NULL
== curTuple_
) return curTuple_
;
395 copyValuesToBindBuffer(curTuple_
);
399 void* TableImpl::fetchNoBind()
403 printError(ErrNotOpen
,"Scan not open or Scan is closed\n");
406 void *prevTuple
= curTuple_
;
407 curTuple_
= iter
->next();
408 if (NULL
== curTuple_
)
412 DbRetVal lockRet
= OK
;
414 if ((*trans
)->isoLevel_
== READ_COMMITTED
)
416 //if iso level is read committed, operation duration lock is sufficent
417 //so release it here itself.
418 int tries
= Conf::config
.getMutexRetries();
419 struct timeval timeout
;
420 timeout
.tv_sec
= Conf::config
.getMutexSecs();
421 timeout
.tv_usec
= Conf::config
.getMutexUSecs();
425 lockRet
= lMgr_
->isExclusiveLocked( curTuple_
, trans
, status
);
428 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
429 curTuple_
= prevTuple
;
434 if (tries
== 0) break;
435 os::select(0, 0, 0, 0, &timeout
);
439 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
440 curTuple_
= prevTuple
;
444 else if ((*trans
)->isoLevel_
== READ_REPEATABLE
) {
445 if (OK
!= trySharedLock(curTuple_
, trans
))
447 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
448 curTuple_
= prevTuple
;
456 DbRetVal
TableImpl::trySharedLock(void *curTuple
, Transaction
**trans
)
458 DbRetVal lockRet
= OK
;
459 int tries
= Conf::config
.getMutexRetries();
460 while((lockRet
= lMgr_
->getSharedLock(curTuple_
, trans
)) == ErrLockTimeOut
)
463 if (tries
<=0) break;
467 DbRetVal
TableImpl::tryExclusiveLock(void *curTuple
, Transaction
**trans
)
469 DbRetVal lockRet
= OK
;
470 int tries
= Conf::config
.getMutexRetries();
471 while((lockRet
= lMgr_
->getExclusiveLock(curTuple_
, trans
)) == ErrLockTimeOut
)
474 if (tries
<=0) break;
479 void* TableImpl::fetchNoBind(DbRetVal
&rv
)
484 printError(ErrNotOpen
,"Scan not open or Scan is closed\n");
488 void *prevTuple
= curTuple_
;
489 curTuple_
= iter
->next();
490 if (NULL
== curTuple_
)
494 DbRetVal lockRet
= OK
;
496 if ((*trans
)->isoLevel_
== READ_REPEATABLE
) {
497 lockRet
= lMgr_
->getSharedLock(curTuple_
, trans
);
500 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
502 curTuple_
= prevTuple
;
507 else if ((*trans
)->isoLevel_
== READ_COMMITTED
)
509 //if iso level is read committed, operation duration lock is sufficent
510 //so release it here itself.
511 int tries
= Conf::config
.getMutexRetries();
512 //struct timeval timeout;
513 //timeout.tv_sec = Conf::config.getMutexSecs();
514 //timeout.tv_usec = Conf::config.getMutexUSecs();
518 lockRet
= lMgr_
->isExclusiveLocked( curTuple_
, trans
, status
);
521 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
522 curTuple_
= prevTuple
;
528 if (tries
== 0) break;
529 //os::select(0, 0, 0, 0, &timeout);
533 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
534 curTuple_
= prevTuple
;
542 DbRetVal
TableImpl::fetchAgg(const char * fldName
, AggType aType
, void *buf
, bool &noRec
)
544 FieldInfo
*info
= new FieldInfo();
545 DbRetVal rv
= getFieldInfo(fldName
, info
);
546 if (OK
!= rv
) return rv
;
548 if (AGG_MIN
== aType
|| AGG_MAX
== aType
) {
550 IndexType iType
= getIndexType((char*)fldName
, &pos
);
551 if(treeIndex
== iType
&& pos
>=0) {
552 if (AGG_MIN
== aType
) {
553 HashIndexInfo
* hInfo
= (HashIndexInfo
*) idxInfo
[pos
];
554 CINDEX
*iptr
= (CINDEX
*) hInfo
->indexPtr
;
555 TreeNode
*fstNode
=(TreeNode
*)iptr
->hashNodeChunk_
;
558 TreeNode
*start
= (TreeNode
*)*((char**)((char*)fstNode
+ sizeof(TreeNode
)));
559 iter
= new TreeIter(start
,(TreeNode
*)iptr
->hashNodeChunk_
,sysDB_
->procSlot
);
561 iter
= new TreeIter(NULL
,(TreeNode
*)iptr
->hashNodeChunk_
,sysDB_
->procSlot
);
563 char *tuple
= (char*) iter
->getFirstElement();
565 AllDataType::copyVal(buf
,(void*)(tuple
+info
->offset
),
566 info
->type
, info
->length
);
570 delete iter
; iter
= NULL
;
572 else if (AGG_MAX
== aType
) {
573 HashIndexInfo
* hInfo
= (HashIndexInfo
*) idxInfo
[pos
];
574 CINDEX
*iptr
= (CINDEX
*) hInfo
->indexPtr
;
575 TreeNode
*fstNode
=(TreeNode
*)iptr
->hashNodeChunk_
;
578 TreeNode
*start
= (TreeNode
*)*((char**)((char*)fstNode
+ sizeof(TreeNode
)));
579 iter
= new TreeIter(start
,(TreeNode
*)iptr
->hashNodeChunk_
,sysDB_
->procSlot
);
581 iter
= new TreeIter(NULL
,(TreeNode
*)iptr
->hashNodeChunk_
,sysDB_
->procSlot
);
583 char *tuple
= (char*) iter
->getLastElement();
585 AllDataType::copyVal(buf
,(void*)(tuple
+info
->offset
),
586 info
->type
, info
->length
);
587 delete iter
; iter
= NULL
;
590 delete iter
; iter
=NULL
;
593 }else if (AGG_COUNT
== aType
) {
598 DataType type
= info
->type
;
599 int length
= info
->length
;
600 int offset
= info
->offset
;
601 int colPos
= fldList_
.getFieldPosition(fldName
);
602 bool isNullable
= true;
603 if (info
->isNull
|| info
->isPrimary
|| info
->isDefault
|| info
->isAutoIncrement
) {
606 int nullOffset
= length_
-4;
607 if (aType
== AGG_COUNT
) {
608 length
= sizeof(int);
611 if (NULL
== pred_
&& typeInt
== type
&& aType
!= AGG_AVG
)
613 ChunkIterator cIter
= ((Chunk
*)chunkPtr_
)->getIterator();
614 char *tuple
=(char*)cIter
.nextElement();
622 if (isIntUsedForNULL
) {
623 if (BITSET(*(int*)(tuple
+nullOffset
), colPos
)) count
=0;
627 if(isFldNull(colPos
)) count
=0;
630 if (aType
!= AGG_COUNT
)
631 AllDataType::copyVal(buf
, (void*) (tuple
+offset
), type
, length
);
634 cIter
.pageSize
= PAGE_SIZE
;
637 tuple
= (char*)cIter
.nextElementInt();
638 if (NULL
== tuple
) break;
640 if (isIntUsedForNULL
) {
641 if (BITSET(*(int*)(tuple
+nullOffset
), colPos
)) continue;
645 if(isFldNull(colPos
)) continue;
648 if (aType
== AGG_MIN
)
650 if (*(int*)buf
>= *((int*)(tuple
+offset
)))
651 *(int*)buf
= *((int*)(tuple
+offset
));
653 else if (aType
== AGG_MAX
)
655 if (*(int*)buf
<= *((int*)(tuple
+offset
)))
656 *(int*)buf
= *((int*)(tuple
+offset
));
658 else if (aType
== AGG_SUM
)
660 *(int*)buf
+= *((int*)(tuple
+offset
));
662 else if (aType
== AGG_AVG
)
664 *(int*)buf
= *(int*)buf
+ *((int*)(tuple
+offset
));
667 else if (aType
== AGG_COUNT
)
673 if( AGG_AVG
== aType
) AllDataType::divVal(buf
, &count
, type
);
674 else if (AGG_COUNT
== aType
) (*(int*)buf
) = count
;
679 char *tuple
= (char*) fetchNoBind(rv
);
680 if ( NULL
== tuple
) { noRec
= true; return OK
; }
683 while(isFldNull(colPos
)) {
684 tuple
= (char*) fetchNoBind(rv
);
685 if (aType
== AGG_COUNT
) count
++;
688 if ( NULL
== tuple
) { noRec
= true; return OK
; }
690 if (aType
== AGG_AVG
) {
691 AllDataType::convertToDouble(buf
, (void*) (tuple
+offset
), type
);
692 } else if (aType
!= AGG_COUNT
) {
693 AllDataType::copyVal(buf
, (void*) (tuple
+offset
), type
, length
);
696 tuple
= (char*) fetchNoBind(rv
);
697 if (NULL
== tuple
) break;
699 if (isIntUsedForNULL
) {
700 if (BITSET(*(int*)(tuple
+nullOffset
), colPos
)) continue;
704 if(isFldNull(colPos
)) continue;
710 res
= AllDataType::compareVal(buf
, (void*) (tuple
+offset
),
713 if (res
) AllDataType::copyVal(buf
, (void*) (tuple
+offset
),
719 res
= AllDataType::compareVal(buf
, (void*) (tuple
+offset
),
722 if (res
) AllDataType::copyVal(buf
, (void*) (tuple
+offset
),
728 AllDataType::addVal(buf
, (void*) (tuple
+offset
),
735 AllDataType::convertToDouble(&tmpBuf
, (void*) (tuple
+offset
), type
);
736 AllDataType::addVal(buf
, &tmpBuf
, typeDouble
);
750 AllDataType::divVal((double *)buf
, count
, type
);
755 (*(int*)buf
) = count
;
762 DbRetVal
TableImpl::insertTuple()
765 void *tptr
= NULL
;// ((Chunk*)chunkPtr_)->allocate(db_, &ret);
767 int totalTries
= Conf::config
.getMutexRetries();
768 while (tries
< totalTries
)
771 tptr
= ((Chunk
*)chunkPtr_
)->allocate(db_
, &ret
);
772 if (tptr
!=NULL
) break;
773 if (ret
!= ErrLockTimeOut
)
775 printError(ret
, "Unable to allocate record from chunk");
782 printError(ret
, "Unable to allocate record from chunk after %d retries", tries
);
787 TableImpl
*fkTbl
=NULL
;
788 ListIterator tblIter
= tblList
.getIterator();
790 while (tblIter
.hasElement()){
791 fkTbl
= (TableImpl
*) tblIter
.nextElement();
792 bool pkRec
= isPkTableHasRecord(fkTbl
->getName(),fkTbl
,true);
794 printError(ErrForeignKeyInsert
, "Unable to insert into foreign Key table.Check PK table");
795 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
796 return ErrForeignKeyInsert
;
802 //ret = lMgr_->getExclusiveLock(tptr, trans);
803 if (OK
!= tryExclusiveLock(tptr
, trans
))
805 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
806 printError(ret
, "Could not get lock for the insert tuple %x", tptr
);
807 return ErrLockTimeOut
;
811 ret
= copyValuesFromBindBuffer(tptr
);
814 printError(ret
, "Unable to copy values from bind buffer");
816 (*trans
)->removeFromHasList(db_
, tptr
);
817 lMgr_
->releaseLock(tptr
);
819 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
826 *(int*)((char*)(tptr
) + (length_
-addSize
)) = iNullInfo
;
830 addSize
= os::align(numFlds_
);
831 os::memcpy(((char*)(tptr
) + (length_
-addSize
)), cNullInfo
, addSize
);
834 //int tupleSize = length_ + addSize;
835 if (NULL
!= indexPtr_
)
839 for (i
= 0; i
< numIndexes_
; i
++)
841 ret
= insertIndexNode(*trans
, indexPtr_
[i
], idxInfo
[i
], tptr
);
842 if (ret
!= OK
) { printError(ret
, "Error in inserting to index %x", tptr
); break;}
846 for (int j
= 0; j
< i
; j
++) {
847 printError(ErrWarning
, "Undo:Deleting index node");
848 deleteIndexNode(*trans
, indexPtr_
[j
], idxInfo
[j
], tptr
);
851 (*trans
)->removeFromHasList(db_
, tptr
);
852 lMgr_
->releaseLock(tptr
);
854 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
859 ret
= (*trans
)->appendUndoLog(sysDB_
, InsertOperation
, tptr
, length_
);
861 printError(ret
, "Unable to create undo log for %x %d", tptr
, *(int*)tptr
);
862 for (int j
= 0; j
< numIndexes_
; j
++) {
863 printError(ErrWarning
, "Deleting index node");
864 deleteIndexNode(*trans
, indexPtr_
[j
], idxInfo
[j
], tptr
);
867 (*trans
)->removeFromHasList(db_
, tptr
);
868 lMgr_
->releaseLock(tptr
);
870 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
875 DbRetVal
TableImpl::deleteTuple()
877 if (NULL
== curTuple_
)
879 printError(ErrNotOpen
, "Scan not open: No Current tuple");
883 TableImpl
*fkTbl
=NULL
;
884 ListIterator tblIter
= tblFkList
.getIterator();
886 while (tblIter
.hasElement()){
887 fkTbl
= (TableImpl
*) tblIter
.nextElement();
888 bool pkRec
= isFkTableHasRecord(fkTbl
->getName(),fkTbl
);
890 printError(ErrForeignKeyDelete
, "A Relation Exists. Delete from child table first");
891 return ErrForeignKeyDelete
;
898 //ret = lMgr_->getExclusiveLock(curTuple_, trans);
899 if (OK
!= tryExclusiveLock(curTuple_
, trans
))
901 printError(ret
, "Could not get lock for the delete tuple %x",
903 return ErrLockTimeOut
;
907 if (NULL
!= indexPtr_
)
911 for (i
= 0; i
< numIndexes_
; i
++)
913 ret
= deleteIndexNode(*trans
, indexPtr_
[i
], idxInfo
[i
], curTuple_
);
914 if (ret
!= OK
) break;
916 if (i
!= numIndexes_
)
918 printError(ErrWarning
, "Inserting back index node");
919 for (int j
= 0; j
< i
; j
++)
920 insertIndexNode(*trans
, indexPtr_
[j
], idxInfo
[j
], curTuple_
);
922 lMgr_
->releaseLock(curTuple_
);
923 (*trans
)->removeFromHasList(db_
, curTuple_
);
925 printError(ret
, "Unable to insert index node for tuple %x", curTuple_
);
930 ret
= (*trans
)->appendUndoLog(sysDB_
, DeleteOperation
, curTuple_
, 0);
932 printError(ret
, "Unable to create undo log for %x ", curTuple_
);
933 for (int j
= 0; j
< numIndexes_
; j
++) {
934 printError(ErrWarning
, "Inserting back index node");
935 insertIndexNode(*trans
, indexPtr_
[j
], idxInfo
[j
], curTuple_
);
938 (*trans
)->removeFromHasList(db_
, curTuple_
);
939 lMgr_
->releaseLock(curTuple_
);
942 ((Chunk
*)chunkPtr_
)->free(db_
, curTuple_
);
948 int TableImpl::deleteWhere()
950 int tuplesDeleted
= 0;
953 if (rv
!=OK
) return (int) rv
;
956 if (rv
!= OK
) { tuplesDeleted
= (int)rv
; break; }
957 if (NULL
== curTuple_
) break;
960 printError(rv
, "Error: Could only delete %d tuples", tuplesDeleted
);
967 return tuplesDeleted
;
970 int TableImpl::truncate()
972 //take exclusive lock on the table
973 //get the chunk ptr of the table
974 //traverse the tablechunks and free all the pages except the first one
975 //get the chunk ptr of all its indexes
976 //traverse the indexchunks and free all the pages except the first one
981 Predicate
* tmpPred
= pred_
;
983 isPlanCreated
= false;
984 int tuplesDeleted
= deleteWhere();
985 isPlanCreated
= false;
987 return tuplesDeleted
;
990 DbRetVal
TableImpl::updateTuple()
992 if (NULL
== curTuple_
)
994 printError(ErrNotOpen
, "Scan not open: No Current tuple");
998 TableImpl
*fkTbl
=NULL
;
999 ListIterator tblIter
= tblList
.getIterator();
1001 while (tblIter
.hasElement()){
1002 fkTbl
= (TableImpl
*) tblIter
.nextElement();
1003 bool pkRec
= isPkTableHasRecord(fkTbl
->getName(),fkTbl
,false);
1005 printError(ErrForeignKeyInsert
, "Unable to insert into foreign Key table.Check PK table");
1006 return ErrForeignKeyInsert
;
1014 //ret = lMgr_->getExclusiveLock(curTuple_, trans);
1015 if (OK
!= tryExclusiveLock(curTuple_
, trans
))
1017 printError(ret
, "Could not get lock for the update tuple %x", curTuple_
);
1018 return ErrLockTimeOut
;
1021 if (NULL
!= indexPtr_
)
1024 //TODO::If it fails while updating index node, we have to undo all the updates
1025 //on other indexes on the table.Currently it will leave the database in an
1026 //inconsistent state.
1027 for (int i
= 0; i
< numIndexes_
; i
++)
1029 ret
= updateIndexNode(*trans
, indexPtr_
[i
], idxInfo
[i
], curTuple_
);
1033 lMgr_
->releaseLock(curTuple_
);
1034 (*trans
)->removeFromHasList(db_
, curTuple_
);
1036 printError(ret
, "Unable to update index node for tuple %x", curTuple_
);
1042 ret
= (*trans
)->appendUndoLog(sysDB_
, UpdateOperation
, curTuple_
, length_
);
1045 lMgr_
->releaseLock(curTuple_
);
1046 (*trans
)->removeFromHasList(db_
, curTuple_
);
1051 int iNullVal
=iNullInfo
;
1055 iNullInfo
= *(int*)((char*)(curTuple_
) + (length_
- addSize
));
1059 *(int*)((char*)(curTuple_
) + (length_
-addSize
)) |= iNullInfo
;
1062 DbRetVal rv
= copyValuesFromBindBuffer(curTuple_
, false);
1063 if (rv
!= OK
&& !loadFlag
) {
1064 lMgr_
->releaseLock(curTuple_
);
1065 (*trans
)->removeFromHasList(db_
, curTuple_
);
1072 *(int*)((char*)(curTuple_
) + (length_
-addSize
)) = iNullInfo
;
1075 else iNullInfo
=iNullVal
;
1079 addSize
= os::align(numFlds_
);
1080 //TODO::Do not do blind memcpy. It should OR each and every char
1082 char *null
=(char*)(curTuple_
) + (length_
-addSize
);
1083 while(i
< numFlds_
) {
1084 if(cNullInfo
[i
]) null
[i
] |= cNullInfo
[i
];
1087 //os::memcpy(((char*)(curTuple_) + (length_-addSize)), cNullInfo, addSize);
1094 void TableImpl::printInfo()
1096 printf(" <TableName> %s </TableName>\n", tblName_
);
1097 printf(" <TupleCount> %d </TupleCount>\n", numTuples());
1098 printf(" <PagesUsed> %d </PagesUsed>\n", pagesUsed());
1099 printf(" <SpaceUsed> %d </SpaceUsed>\n", spaceUsed());
1100 printf(" <Indexes> %d <Indexes>\n", numIndexes_
);
1101 printf(" <TupleLength> %d </TupleLength>\n", length_
);
1102 printf(" <Fields> %d </Fields>\n", numFlds_
);
1103 printf(" <Indexes>\n");
1104 for (int i
=0; i
<numIndexes_
; i
++)
1105 printf("<IndexName> %s </IndexName>\n", CatalogTableINDEX::getName(indexPtr_
[i
]));
1106 printf(" </Indexes>\n");
1110 DbRetVal
TableImpl::copyValuesFromBindBuffer(void *tuplePtr
, bool isInsert
)
1112 //Iterate through the bind list and copy the value here
1113 FieldIterator fIter
= fldList_
.getIterator();
1114 char *colPtr
= (char*) tuplePtr
;
1116 while (fIter
.hasElement())
1118 FieldDef
*def
= fIter
.nextElement();
1119 if(def
->isAutoIncrement_
&& isInsert
)
1121 void *dest
= AllDataType::alloc(def
->type_
, def
->length_
);
1122 AllDataType::copyVal(dest
,ptrToAuto
, def
->type_
, def
->length_
);
1123 if(def
->bindVal_
==NULL
)
1125 AllDataType::increment(colPtr
, dest
, def
->type_
);
1126 AllDataType::copyVal(ptrToAuto
,colPtr
, def
->type_
, def
->length_
);
1127 colPtr
= colPtr
+ def
->length_
;
1132 if(AllDataType::compareVal(def
->bindVal_
, dest
, OpGreaterThan
, def
->type_
)){
1133 AllDataType::copyVal(ptrToAuto
,def
->bindVal_
, def
->type_
, def
->length_
);
1138 if (def
->isNull_
&& !def
->isDefault_
&& NULL
== def
->bindVal_
&& isInsert
)
1140 printError(ErrNullViolation
, "NOT NULL constraint violation for field %s", def
->fldName_
);
1141 return ErrNullViolation
;
1143 if (def
->isDefault_
&& NULL
== def
->bindVal_
&& isInsert
)
1145 void *dest
= AllDataType::alloc(def
->type_
, def
->length_
);
1146 AllDataType::convert(typeString
, def
->defaultValueBuf_
, def
->type_
, dest
, def
->length_
);
1147 AllDataType::copyVal(colPtr
, dest
, def
->type_
, def
->length_
);
1148 colPtr
= colPtr
+ def
->length_
;
1156 if (NULL
!= def
->bindVal_
)
1158 if(!isInsert
&& isFldNull(fldpos
)){clearNullBit(fldpos
);}
1159 strncpy((char*)colPtr
, (char*)def
->bindVal_
, def
->length_
);
1160 *(((char*)colPtr
) + (def
->length_
-1)) = '\0';
1162 else if (!def
->isNull_
&& !def
->bindVal_
&& isInsert
) setNullBit(fldpos
);
1163 colPtr
= colPtr
+ def
->length_
;
1166 if (NULL
!= def
->bindVal_
)
1168 if(!isInsert
&& isFldNull(fldpos
)){clearNullBit(fldpos
);}
1169 DbRetVal rv
= AllDataType::strToValue(colPtr
, (char *) def
->bindVal_
, def
->type_
, def
->length_
);
1170 if (rv
!= OK
) return ErrBadArg
;
1172 else if (!def
->isNull_
&& isInsert
&& !def
->bindVal_
) setNullBit(fldpos
);
1173 colPtr
= colPtr
+ def
->length_
;
1176 if (NULL
!= def
->bindVal_
){
1177 if(!isInsert
&& isFldNull(fldpos
)){clearNullBit(fldpos
);}
1178 AllDataType::copyVal(colPtr
, def
->bindVal_
, def
->type_
);}
1179 else { if (!def
->isNull_
&& isInsert
) setNullBit(fldpos
); }
1180 colPtr
= colPtr
+ def
->length_
;
1187 void TableImpl::clearNullBit(int fldpos
)
1189 if (isIntUsedForNULL
){
1190 CLEARBIT(iNullInfo
, fldpos
);}
1192 cNullInfo
[fldpos
-1] = 0;
1194 void TableImpl::setNullBit(int fldpos
)
1196 if (isIntUsedForNULL
)
1197 SETBIT(iNullInfo
, fldpos
);
1199 cNullInfo
[fldpos
-1] = 1;
1201 DbRetVal
TableImpl::copyValuesToBindBuffer(void *tuplePtr
)
1203 //Iterate through the bind list and copy the value here
1204 char *colPtr
= (char*) tuplePtr
;
1205 FieldDef
*def
= NULL
;
1206 for (int i
= 0; i
< numBindFlds_
; i
++) {
1207 def
= (FieldDef
*) bindListArray_
[i
];
1208 colPtr
= (char *) tuplePtr
+ def
->offset_
;
1209 AllDataType::copyVal(def
->bindVal_
, colPtr
, def
->type_
, def
->length_
);
1214 //-1 index not supported
1215 DbRetVal
TableImpl::insertIndexNode(Transaction
*tr
, void *indexPtr
, IndexInfo
*info
, void *tuple
)
1217 CINDEX
*iptr
= (CINDEX
*)indexPtr
;
1219 printDebug(DM_Table
, "Inside insertIndexNode type %d", iptr
->indexType_
);
1220 Index
* idx
= Index::getIndex(iptr
->indexType_
);
1221 ret
= idx
->insert(this, tr
, indexPtr
, info
, tuple
,loadFlag
);
1225 DbRetVal
TableImpl::deleteIndexNode(Transaction
*tr
, void *indexPtr
, IndexInfo
*info
, void *tuple
)
1227 CINDEX
*iptr
= (CINDEX
*)indexPtr
;
1229 Index
* idx
= Index::getIndex(iptr
->indexType_
);
1230 ret
= idx
->remove(this, tr
, indexPtr
, info
, tuple
, loadFlag
);
1233 void TableImpl::printSQLIndexString(FILE *fp
, int fd
)
1235 if (fp
== NULL
) fp
= stdout
;
1236 CatalogTableINDEXFIELD
cIndexField(sysDB_
);
1237 char fName
[IDENTIFIER_LENGTH
];
1238 char idxName
[IDENTIFIER_LENGTH
];
1239 char *fldName
= fName
;
1241 for (int i
= 0; i
< numIndexes_
; i
++)
1243 CINDEX
*iptr
= (CINDEX
*) indexPtr_
[i
];
1244 sprintf(idxName
,"%s_idx_Auto_increment",getName());
1245 if(strcmp(iptr
->indName_
,idxName
)==0){ continue; }
1246 if (Conf::config
.useDurability()) {
1248 strcpy(obj
.name
, iptr
->indName_
);
1249 if (iptr
->indexType_
== hashIndex
) {
1251 obj
.bucketChunk
= ((Chunk
*)iptr
->chunkPtr_
)->getFirstPage();
1252 obj
.firstPage
= ((Chunk
*)iptr
->hashNodeChunk_
)->getFirstPage();
1253 obj
.curPage
= ((Chunk
*)iptr
->hashNodeChunk_
)->getCurrentPage();
1254 } else if (iptr
->indexType_
== treeIndex
) {
1256 obj
.firstPage
= ((Chunk
*)iptr
->chunkPtr_
)->getFirstPage();
1257 obj
.curPage
= ((Chunk
*)iptr
->chunkPtr_
)->getCurrentPage();
1258 long nodes
= ((Chunk
*)iptr
->chunkPtr_
)->getTotalDataNodes();
1260 ChunkIterator cIter
= ((Chunk
*)iptr
->chunkPtr_
)->getIterator();
1261 obj
.bucketChunk
= cIter
.nextElement();
1262 } else obj
.bucketChunk
= NULL
;
1265 write(fd
, buf
, sizeof(obj
));
1267 fprintf(fp
, "CREATE INDEX %s on %s ( ", iptr
->indName_
, getName());
1269 cIndexField
.getFieldInfo(iptr
, fldList
);
1270 FieldIterator fIter
= fldList
.getIterator();
1271 bool firstFld
= true;
1272 while(fIter
.hasElement())
1274 FieldDef
*def
= fIter
.nextElement();
1275 if (firstFld
) { fprintf(fp
, " %s ", def
->fldName_
); firstFld
= false; }
1276 else fprintf(fp
, " ,%s ", def
->fldName_
);
1278 fldList
.removeAll();
1280 if (iptr
->indexType_
== hashIndex
) fprintf(fp
, " HASH ");
1281 else fprintf(fp
, " TREE ");
1282 if (((HashIndexInfo
*) idxInfo
[i
])->isUnique
) fprintf(fp
, " UNIQUE");
1283 if(((HashIndexInfo
*) idxInfo
[i
])->noOfBuckets
!= 1009 ) fprintf(fp
, " SIZE %d ",((HashIndexInfo
*) idxInfo
[i
])->noOfBuckets
);
1289 DbRetVal
TableImpl::updateIndexNode(Transaction
*tr
, void *indexPtr
, IndexInfo
*info
, void *tuple
)
1291 CINDEX
*iptr
= (CINDEX
*)indexPtr
;
1293 Index
* idx
= Index::getIndex(iptr
->indexType_
);
1294 //TODO::currently it updates irrespective of whether the key changed or not
1295 //because of this commenting the whole index update code. relook at it and uncomment
1297 ret
= idx
->update(this, tr
, indexPtr
, info
, tuple
, loadFlag
);
1303 void TableImpl::setTableInfo(char *name
, int tblid
, size_t length
,
1304 int numFld
, int numIdx
, void *chunk
)
1306 strcpy(tblName_
, name
);
1310 numIndexes_
= numIdx
;
1314 long TableImpl::spaceUsed()
1316 Chunk
*chk
= (Chunk
*)chunkPtr_
;
1317 long totSize
= chk
->getTotalDataNodes() * chk
->getSize();
1318 totSize
= totSize
+ (chk
->totalPages() * sizeof (PageInfo
));
1322 int TableImpl::pagesUsed()
1324 Chunk
*chk
= (Chunk
*)chunkPtr_
;
1325 return chk
->totalPages();
1328 long TableImpl::numTuples()
1330 return ((Chunk
*)chunkPtr_
)->getTotalDataNodes();
1333 List
TableImpl::getFieldNameList()
1336 FieldIterator fIter
= fldList_
.getIterator();
1337 char fieldName
[IDENTIFIER_LENGTH
];
1338 while (fIter
.hasElement())
1340 FieldDef
*def
= fIter
.nextElement();
1341 Identifier
*elem
= new Identifier();
1342 Table::getFieldNameAlone(def
->fldName_
, fieldName
);
1343 sprintf(elem
->name
, "%s.%s", getName(), fieldName
);
1344 fldNameList
.append(elem
);
1348 DbRetVal
TableImpl::close()
1350 if (iter
) { iter
->close(); delete iter
; iter
= NULL
; }
1351 TableImpl
*fkTbl
=NULL
;
1352 ListIterator tblIter
= tblList
.getIterator();
1354 while (tblIter
.hasElement()){
1355 fkTbl
= (TableImpl
*) tblIter
.nextElement();
1359 tblIter
= tblFkList
.getIterator();
1361 while (tblIter
.hasElement()){
1362 fkTbl
= (TableImpl
*) tblIter
.nextElement();
1366 printDebug(DM_Database
,"Closing table handle: %x", this);
1369 ListIterator pIter
= predList
.getIterator();
1370 while (pIter
.hasElement())
1372 PredicateImpl
*pImpl
= (PredicateImpl
*) pIter
.nextElement();
1377 logFinest(Conf::logger
, "Closing Table");
1381 DbRetVal
TableImpl::closeScan()
1383 //do not throw scan not open error
1384 //this function will be called by table handle
1390 DbRetVal
TableImpl::lock(bool shared
)
1396 ret = lMgr_->getSharedLock(chunkPtr_, NULL);
1398 ret = lMgr_->getExclusiveLock(chunkPtr_, NULL);
1401 printError(ret, "Could not exclusive lock on the table %x", chunkPtr_);
1403 //do not append for S to X upgrade
1404 if (!ProcessManager::hasLockList.exists(chunkPtr_))
1405 ProcessManager::hasLockList.append(chunkPtr_);
1410 DbRetVal
TableImpl::unlock()
1413 if (!ProcessManager::hasLockList.exists(chunkPtr_)) return OK;
1414 DbRetVal ret = lMgr_->releaseLock(chunkPtr_);
1417 printError(ret, "Could not release exclusive lock on the table %x", chunkPtr_);
1420 ProcessManager::hasLockList.remove(chunkPtr_);
1426 TableImpl::~TableImpl()
1428 if (NULL
!= iter
) { delete iter
; iter
= NULL
; }
1429 if (NULL
!= indexPtr_
) { delete[] indexPtr_
; indexPtr_
= NULL
; }
1430 if (NULL
!= idxInfo
)
1432 for (int i
= 0; i
< numIndexes_
; i
++) delete idxInfo
[i
];
1436 if (numFlds_
> 31 && cNullInfo
!= NULL
) { free(cNullInfo
); cNullInfo
= NULL
; }
1437 if (bindList_
.size()) bindList_
.reset();
1438 if (bindListArray_
) { free (bindListArray_
); bindListArray_
= NULL
; }
1439 fldList_
.removeAll();
1443 void *TableImpl::getBindFldAddr(const char *name
)
1445 return fldList_
.getBindField(name
);
1447 bool TableImpl::isTableInvolved(char *tblName
)
1449 //printf("Table isTableInvolved called for %s with %s\n", tblName, getName());
1450 if (0 == strcmp(getName(), tblName
)) return true; else return false;
1452 bool TableImpl::pushPredicate(Predicate
*pred
)
1455 PredicateImpl
*pImpl
= (PredicateImpl
*) pred
;
1456 char tableName
[IDENTIFIER_LENGTH
];
1457 Table::getTableNameAlone(pImpl
->getFldName1(), tableName
);
1458 //printf("predicate tbl name %s\n", tableName);
1460 //if predicate is of form t1.f1=t2.f1 then do not push here
1461 if (0 != strcmp(pImpl
->getFldName2(),"")) return ret
;
1463 if (0 == strcmp(getName(), tableName
))
1466 //printf("PRABA::pushed predicate in tablehdl %s\n", getName());
1472 void TableImpl::setCondition(Condition
*p
)
1474 isPlanCreated
= false;
1475 ListIterator pIter
= predList
.getIterator();
1476 while (pIter
.hasElement())
1478 PredicateImpl
*pImpl
= (PredicateImpl
*) pIter
.nextElement();
1483 if (p
) pred_
= p
->getPredicate(); else pred_
= NULL
;
1486 void TableImpl::setPredicate(Predicate
*pred
)
1488 if (NULL
== pred_
) { pred_
= pred
; return; }
1490 Predicate
*curPred
= pred_
;
1491 PredicateImpl
*newPred
= new PredicateImpl();
1492 newPred
->setTerm(curPred
, OpAnd
, pred
);
1493 newPred
->setTable(this);
1497 void TableImpl::printPlan(int space
)
1499 char spaceBuf
[IDENTIFIER_LENGTH
];
1500 memset(spaceBuf
, 32, IDENTIFIER_LENGTH
);
1501 spaceBuf
[space
] = '\0';
1502 printf("%s <TABLE-NODE>\n", spaceBuf
);
1503 printf("%s <NAME> %s </NAME>\n", spaceBuf
, getName());
1504 printf("%s <ScanType> %s </ScanType>\n", spaceBuf
, ScanTypeNames
[scanType_
]);
1505 PredicateImpl
*pred
= (PredicateImpl
*)pred_
;
1506 if (pred
) pred
->print(space
+2);
1507 printf("%s </TABLE-NODE>\n", spaceBuf
);
1509 void TableImpl::printSQLForeignString()
1512 FieldNameList pkFieldList
,fkFieldList
;
1514 void *tFkptr
= NULL
;
1515 void *chunkPk
= NULL
;
1516 CatalogTableTABLE
cTable(sysDB_
);
1517 TableImpl
*fkTbl
=NULL
;
1518 ListIterator tblIter
= tblList
.getIterator();
1521 while (tblIter
.hasElement()){
1522 fkTbl
= (TableImpl
*) tblIter
.nextElement();
1523 rv
= cTable
.getChunkAndTblPtr(fkTbl
->getName(), chunkPk
, tPkptr
);
1524 if ( OK
!= rv
){return ;}
1525 rv
= cTable
.getChunkAndTblPtr(getName(), chunkPk
, tFkptr
);
1526 if ( OK
!= rv
){return ;}
1527 CatalogTableFK
cFk(sysDB_
);
1528 rv
= cFk
.getPkFkFieldInfo(tPkptr
,tFkptr
,pkFieldList
,fkFieldList
);
1529 if ( OK
!= rv
){return;}
1530 pkFieldList
.resetIter();
1531 fkFieldList
.resetIter();
1532 char *fldName
= NULL
;
1533 bool firstField
=true;
1534 if(!firstFK
) printf(", ");
1535 printf(", FOREIGN KEY ( ");
1536 while((fldName
= fkFieldList
.nextFieldName())!= NULL
)
1539 printf("%s",fldName
);
1543 printf(",%s",fldName
);
1545 printf(" ) REFERENCES %s ( ",fkTbl
->getName());
1547 while((fldName
= pkFieldList
.nextFieldName())!= NULL
)
1550 printf("%s",fldName
);
1554 printf(",%s",fldName
);
1558 pkFieldList
.removeAll();
1559 fkFieldList
.removeAll();
1563 bool TableImpl::isPkTableHasRecord(char *pkTableName
, TableImpl
*fkTbl
,bool isInsert
)
1566 bool isRecExist
=false;
1567 FieldNameList pkFieldList
,fkFieldList
;
1569 void *tFkptr
= NULL
;
1570 void *chunkPk
= NULL
;
1571 CatalogTableTABLE
cTable(sysDB_
);
1572 rv
= cTable
.getChunkAndTblPtr(pkTableName
, chunkPk
, tPkptr
);
1573 if ( OK
!= rv
){return false;}
1574 rv
= cTable
.getChunkAndTblPtr(getName(), chunkPk
, tFkptr
);
1575 if ( OK
!= rv
){return false;}
1576 CatalogTableFK
cFk(sysDB_
);
1577 rv
= cFk
.getPkFkFieldInfo(tPkptr
,tFkptr
,pkFieldList
,fkFieldList
);
1578 if ( OK
!= rv
){return false;}
1579 int totFld
= pkFieldList
.size();
1580 Condition
*condition
= new Condition
[totFld
];
1581 char *pkFldName
= NULL
;
1582 char *fkFldName
= NULL
;
1585 pkFieldList
.resetIter();
1586 fkFieldList
.resetIter();
1588 while((pkFldName
= pkFieldList
.nextFieldName())!= NULL
)
1590 fkFldName
= fkFieldList
.nextFieldName();
1591 FieldIterator fIter
= fldList_
.getIterator();
1592 while (fIter
.hasElement())
1594 def
= fIter
.nextElement();
1595 if (strcmp(def
->fldName_
, fkFldName
) == 0)
1597 if(NULL
== def
->bindVal_
&& isInsert
) { return true; }
1598 if(NULL
== def
->bindVal_
) {
1599 val
= (char*)curTuple_
+ def
->offset_
;
1601 val
= def
->bindVal_
;
1603 if(def
->type_
==typeString
)
1604 condition
[i
].setTerm(pkFldName
,OpEquals
,&val
);
1606 condition
[i
].setTerm(pkFldName
,OpEquals
,val
);
1612 pkFieldList
.removeAll();
1613 fkFieldList
.removeAll();
1614 Condition
*cond
= NULL
;
1615 if(i
== 0 && !isInsert
)return true;
1617 cond
= new Condition
[i
-1];
1621 for(j
=0;j
<totcon
-1;j
++)
1624 cond
[j
].setTerm(condition
[i
++].getPredicate(),OpAnd
,condition
[i
++].getPredicate());
1626 cond
[j
].setTerm(cond
[j
-1].getPredicate(), OpAnd
, condition
[i
++].getPredicate());
1628 fkTbl
->setCondition(&cond
[j
-1]);
1631 fkTbl
->setCondition(&condition
[i
-1]);
1645 bool TableImpl::isFkTableHasRecord(char *pkTableName
, TableImpl
*fkTbl
)
1648 FieldNameList pkFieldList
,fkFieldList
;
1650 void *tFkptr
= NULL
;
1651 void *chunkPk
= NULL
;
1652 CatalogTableTABLE
cTable(sysDB_
);
1653 rv
= cTable
.getChunkAndTblPtr(getName(), chunkPk
, tPkptr
);
1654 if ( OK
!= rv
){return false;}
1655 rv
= cTable
.getChunkAndTblPtr(pkTableName
, chunkPk
, tFkptr
);
1656 if ( OK
!= rv
){return false;}
1657 CatalogTableFK
cFk(sysDB_
);
1658 rv
= cFk
.getPkFkFieldInfo(tPkptr
,tFkptr
,pkFieldList
,fkFieldList
);
1659 if ( OK
!= rv
){return false;}
1660 int totFld
= pkFieldList
.size();
1661 Condition
*condition
= new Condition
[totFld
];
1662 char *pkFldName
= NULL
;
1663 char *fkFldName
= NULL
;
1666 pkFieldList
.resetIter();
1667 fkFieldList
.resetIter();
1668 while((pkFldName
= pkFieldList
.nextFieldName())!= NULL
)
1670 fkFldName
= fkFieldList
.nextFieldName();
1671 FieldIterator fIter
= fldList_
.getIterator();
1672 while (fIter
.hasElement())
1674 def
= fIter
.nextElement();
1675 void *val
= (char*)curTuple_
+ def
->offset_
;
1676 if (strcmp(def
->fldName_
, pkFldName
) == 0)
1678 if(def
->type_
==typeString
)
1679 condition
[i
].setTerm(fkFldName
,OpEquals
,&val
);//((char*)curTuple_+def->offset_));
1681 condition
[i
].setTerm(fkFldName
,OpEquals
,val
);//((char*)curTuple_+def->offset_));
1687 pkFieldList
.removeAll();
1688 fkFieldList
.removeAll();
1689 if(i
== 0 )return true;
1690 Condition
*cond
= new Condition
[i
-1];
1693 for(j
=0;j
<totFld
-1;j
++)
1696 cond
[j
].setTerm(condition
[i
++].getPredicate(),OpAnd
,condition
[i
++].getPredicate());
1698 cond
[j
].setTerm(cond
[j
-1].getPredicate(), OpAnd
, condition
[i
++].getPredicate());
1701 fkTbl
->setCondition(&condition
[totFld
-1]);
1703 fkTbl
->setCondition(&cond
[j
-1]);
1715 DbRetVal
TableImpl::compact()
1718 int ret
=((Chunk
*)chunkPtr_
)->compact(db_
->procSlot
);
1720 return ErrLockTimeOut
;
1722 if (NULL
!= indexPtr_
)
1726 for (i
= 0; i
< numIndexes_
; i
++)
1728 rv
= compactIndexNode(indexPtr_
[i
]);
1729 if (rv
!= OK
) { printError(rv
, "Error in compacting index Node"); break;}
1735 DbRetVal
TableImpl::compactIndexNode( void *indexPtr
)
1737 CINDEX
*iptr
= (CINDEX
*)indexPtr
;
1739 printDebug(DM_Table
, "Inside insertIndexNode type %d", iptr
->indexType_
);
1740 if( hashIndex
== (iptr
->indexType_
) )
1742 ret1
=((Chunk
*)iptr
->hashNodeChunk_
)->compact(db_
->procSlot
);
1744 return ErrLockTimeOut
;
1748 ret1
=((Chunk
*)iptr
->chunkPtr_
)->compact(db_
->procSlot
);
1750 return ErrLockTimeOut
;