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>
27 DbRetVal
TableImpl::bindFld(const char *name
, void *val
)
29 //set it in the field list
30 DbRetVal rv
= fldList_
.updateBindVal(name
, val
);
32 printError(ErrNotExists
, "Field %s does not exist", name
);
38 bool TableImpl::isFldNull(const char *name
){
39 int colpos
= fldList_
.getFieldPosition(name
);
42 printError(ErrNotExists
, "Field %s does not exist", name
);
46 return isFldNull(colpos
);
49 bool TableImpl::isFldNull(int colpos
)
51 if (!curTuple_
) return false;
52 if (colpos
<1 || colpos
> numFlds_
) return false;
53 char *nullOffset
= (char*)curTuple_
- 4;
54 if (isIntUsedForNULL
) {
55 int nullVal
= *(int*)((char*)curTuple_
+ (length_
- 4));
56 if (BITSET(nullVal
, colpos
)) return true;
59 char *nullOffset
= (char*)curTuple_
- os::align(numFlds_
);
60 if (nullOffset
[colpos
-1]) return true;
64 void TableImpl::markFldNull(char const* name
)
66 int colpos
= fldList_
.getFieldPosition(name
);
69 printError(ErrNotExists
, "Field %s does not exist", name
);
76 void TableImpl::markFldNull(int fldpos
)
78 if (fldpos
<1 || fldpos
> numFlds_
) return;
79 if (isIntUsedForNULL
) {
80 if (!BITSET(iNotNullInfo
, fldpos
)) SETBIT(iNullInfo
, fldpos
);
83 if (!BITSET(iNotNullInfo
, fldpos
)) cNullInfo
[fldpos
-1] = 1;
87 void TableImpl::clearFldNull(const char *name
)
89 int colpos
= fldList_
.getFieldPosition(name
);
92 printError(ErrNotExists
, "Field %s does not exist", name
);
99 void TableImpl::clearFldNull(int colpos
)
101 if (colpos
<1 || colpos
> numFlds_
) return;
102 if (isIntUsedForNULL
) {
103 CLEARBIT(iNullInfo
, colpos
);
106 cNullInfo
[colpos
-1] = 0;
111 DbRetVal
TableImpl::execute()
115 printError(ErrAlready
,"Scan already open:Close and re execute");
118 //table ptr is set in predicate because it needs to access the
119 //type and length to evaluate
122 PredicateImpl
*pred
= (PredicateImpl
*) pred_
;
123 pred
->setTable(this);
130 printError(ErrSysInternal
,"Unable to create the plan");
131 return ErrSysInternal
;
134 iter
= new TupleIterator(pred_
, scanType_
, idxInfo
[useIndex_
], chunkPtr_
, sysDB_
->procSlot
);
135 else if (scanType_
== fullTableScan
)
136 iter
= new TupleIterator(pred_
, scanType_
, NULL
, chunkPtr_
, sysDB_
->procSlot
);
139 printError(ErrSysFatal
,"Unable to create tuple iterator");//should never happen
145 printError(ErrSysInternal
,"Unable to open the iterator");
146 return ErrSysInternal
;
152 DbRetVal
TableImpl::createPlan()
155 //will do early return here. plan is generated only when setPredicate is called.
156 if (scanType_
== unknownScan
) return ErrSysFatal
; //this should never happen
160 //if there are no predicates then go for full scan
161 //if there are no indexes then go for full scan
162 if (NULL
== pred_
|| NULL
== indexPtr_
)
164 scanType_
= fullTableScan
;
165 isPlanCreated
= true;
168 if (NULL
!= indexPtr_
)
170 PredicateImpl
*pred
= (PredicateImpl
*)pred_
;
171 printDebug(DM_Predicate
, "predicate does not involve NOT , OR operator");
172 if (!pred
->isNotOrInvolved())
174 printDebug(DM_Predicate
, "predicate does not involve NOT , OR operator");
175 for (int i
=0; i
< numIndexes_
; i
++)
177 char *fName
= ((SingleFieldHashIndexInfo
*)idxInfo
[i
])->fldName
;
178 if (pred
->pointLookupInvolved(fName
))
180 printDebug(DM_Predicate
, "point lookup involved for field %s",fName
);
181 scanType_
= hashIndexScan
;
183 isPlanCreated
= true;
189 scanType_
= fullTableScan
;
190 isPlanCreated
= true;
194 void* TableImpl::fetch()
197 if (NULL
== curTuple_
) return curTuple_
;
198 copyValuesToBindBuffer(curTuple_
);
202 void* TableImpl::fetchNoBind()
206 printError(ErrNotOpen
,"Scan not open or Scan is closed\n");
209 curTuple_
= iter
->next();
210 if (NULL
== curTuple_
)
214 DbRetVal lockRet
= OK
;
215 if ((*trans
)->isoLevel_
== READ_REPEATABLE
) {
216 lockRet
= lMgr_
->getSharedLock(curTuple_
, trans
);
219 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
224 else if ((*trans
)->isoLevel_
== READ_COMMITTED
)
226 //if iso level is read committed, operation duration lock is sufficent
227 //so release it here itself.
229 struct timeval timeout
;
230 timeout
.tv_sec
= Conf::config
.getMutexSecs();
231 timeout
.tv_usec
= Conf::config
.getMutexUSecs();
235 lockRet
= lMgr_
->isExclusiveLocked( curTuple_
, trans
, status
);
238 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
243 if (tries
== 0) break;
244 os::select(0, 0, 0, 0, &timeout
);
249 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
257 DbRetVal
TableImpl::insertTuple()
260 void *tptr
= ((Chunk
*)chunkPtr_
)->allocate(db_
, &ret
);
263 printError(ret
, "Unable to allocate from chunk");
267 ret
= lMgr_
->getExclusiveLock(tptr
, trans
);
270 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
271 printError(ret
, "Could not get lock for the insert tuple %x", tptr
);
276 ret
= copyValuesFromBindBuffer(tptr
);
279 printError(ret
, "Unable to copy values from bind buffer");
280 lMgr_
->releaseLock(tptr
);
281 (*trans
)->removeFromHasList(db_
, tptr
);
282 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
290 *(int*)((char*)(tptr
) + (length_
-addSize
)) = iNullInfo
;
294 addSize
= os::align(numFlds_
);
295 os::memcpy(((char*)(tptr
) + (length_
-addSize
)), cNullInfo
, addSize
);
298 //int tupleSize = length_ + addSize;
299 if (NULL
!= indexPtr_
)
303 for (i
= 0; i
< numIndexes_
; i
++)
305 ret
= insertIndexNode(*trans
, indexPtr_
[i
], idxInfo
[i
], tptr
);
306 if (ret
!= OK
) { printError(ret
, "Error in inserting to index"); break;}
308 if (i
!= numIndexes_
)
310 for (int j
= 0; j
< i
; j
++)
311 deleteIndexNode(*trans
, indexPtr_
[j
], idxInfo
[j
], tptr
);
312 lMgr_
->releaseLock(tptr
);
313 (*trans
)->removeFromHasList(db_
, tptr
);
314 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
315 printError(ret
, "Unable to insert index node for tuple %x", tptr
);
320 ret
= (*trans
)->appendUndoLog(sysDB_
, InsertOperation
, tptr
, length_
);
324 DbRetVal
TableImpl::deleteTuple()
326 if (NULL
== curTuple_
)
328 printError(ErrNotOpen
, "Scan not open: No Current tuple");
331 DbRetVal ret
= lMgr_
->getExclusiveLock(curTuple_
, trans
);
334 printError(ret
, "Could not get lock for the delete tuple %x", curTuple_
);
338 if (NULL
!= indexPtr_
)
342 for (i
= 0; i
< numIndexes_
; i
++)
344 ret
= deleteIndexNode(*trans
, indexPtr_
[i
], idxInfo
[i
], curTuple_
);
345 if (ret
!= OK
) break;
347 if (i
!= numIndexes_
)
349 for (int j
= 0; j
< i
; j
++)
350 insertIndexNode(*trans
, indexPtr_
[j
], idxInfo
[j
], curTuple_
);
351 lMgr_
->releaseLock(curTuple_
);
352 (*trans
)->removeFromHasList(db_
, curTuple_
);
353 printError(ret
, "Unable to insert index node for tuple %x", curTuple_
);
357 ((Chunk
*)chunkPtr_
)->free(db_
, curTuple_
);
359 ret
= (*trans
)->appendUndoLog(sysDB_
, DeleteOperation
, curTuple_
, length_
);
363 int TableImpl::deleteWhere()
365 int tuplesDeleted
= 0;
368 if (rv
!=OK
) return (int) rv
;
371 if (NULL
== curTuple_
) break;
374 printError(rv
, "Error: Could only delete %d tuples", tuplesDeleted
);
381 return tuplesDeleted
;
384 int TableImpl::truncate()
386 //take exclusive lock on the table
387 //get the chunk ptr of the table
388 //traverse the tablechunks and free all the pages except the first one
389 //get the chunk ptr of all its indexes
390 //traverse the indexchunks and free all the pages except the first one
395 Predicate
* tmpPred
= pred_
;
397 isPlanCreated
= false;
398 int tuplesDeleted
= deleteWhere();
399 isPlanCreated
= false;
401 return tuplesDeleted
;
404 DbRetVal
TableImpl::updateTuple()
406 if (NULL
== curTuple_
)
408 printError(ErrNotOpen
, "Scan not open: No Current tuple");
411 DbRetVal ret
= lMgr_
->getExclusiveLock(curTuple_
, trans
);
414 printError(ret
, "Could not get lock for the update tuple %x", curTuple_
);
417 if (NULL
!= indexPtr_
)
420 //TODO::If it fails while updating index node, we have to undo all the updates
421 //on other indexes on the table.Currently it will leave the database in an
422 //inconsistent state.
423 for (int i
= 0; i
< numIndexes_
; i
++)
425 ret
= updateIndexNode(*trans
, indexPtr_
[i
], idxInfo
[i
], curTuple_
);
428 lMgr_
->releaseLock(curTuple_
);
429 (*trans
)->removeFromHasList(db_
, curTuple_
);
430 printError(ret
, "Unable to update index node for tuple %x", curTuple_
);
436 ret
= (*trans
)->appendUndoLog(sysDB_
, UpdateOperation
, curTuple_
, length_
);
437 if (ret
!= OK
) return ret
;
438 return copyValuesFromBindBuffer(curTuple_
);
441 void TableImpl::printInfo()
443 printf(" <TableName> %s </TableName>\n", tblName_
);
444 printf(" <TupleCount> %d </TupleCount>\n", numTuples());
445 printf(" <PagesUsed> %d </PagesUsed>\n", pagesUsed());
446 printf(" <SpaceUsed> %d </SpaceUsed>\n", spaceUsed());
447 printf(" <Indexes> %d <Indexes>\n", numIndexes_
);
448 printf(" <TupleLength> %d </TupleLength>\n", length_
);
449 printf(" <Fields> %d </Fields>\n", numFlds_
);
450 printf(" <Indexes>\n");
451 for (int i
=0; i
<numIndexes_
; i
++)
452 printf("<IndexName> %s </IndexName>\n", CatalogTableINDEX::getName(indexPtr_
[i
]));
453 printf(" </Indexes>\n");
457 DbRetVal
TableImpl::copyValuesFromBindBuffer(void *tuplePtr
)
459 //Iterate through the bind list and copy the value here
460 FieldIterator fIter
= fldList_
.getIterator();
461 char *colPtr
= (char*) tuplePtr
;
463 while (fIter
.hasElement())
465 FieldDef def
= fIter
.nextElement();
466 if (def
.isNull_
&& NULL
== def
.bindVal_
)
468 printError(ErrNullViolation
, "NOT NULL constraint violation for field %s\n", def
.fldName_
);
469 return ErrNullViolation
;
474 if (NULL
!= def
.bindVal_
)
476 strcpy((char*)colPtr
, (char*)def
.bindVal_
);
477 *(((char*)colPtr
) + (def
.length_
-1)) = '\0';
479 else if (!def
.isNull_
) setNullBit(fldpos
);
480 colPtr
= colPtr
+ os::align(def
.length_
);
483 if (NULL
!= def
.bindVal_
)
484 os::memcpy((char*)colPtr
, (char*)def
.bindVal_
, def
.length_
);
485 else if (!def
.isNull_
) setNullBit(fldpos
);
486 colPtr
= colPtr
+ os::align(def
.length_
);
489 if (NULL
!= def
.bindVal_
)
490 AllDataType::copyVal(colPtr
, def
.bindVal_
, def
.type_
);
491 else { if (!def
.isNull_
) setNullBit(fldpos
); }
492 colPtr
= colPtr
+ os::align(AllDataType::size(def
.type_
));
499 void TableImpl::setNullBit(int fldpos
)
501 if (isIntUsedForNULL
)
502 SETBIT(iNullInfo
, fldpos
);
504 cNullInfo
[fldpos
-1] = 1;
506 DbRetVal
TableImpl::copyValuesToBindBuffer(void *tuplePtr
)
508 //Iterate through the bind list and copy the value here
509 FieldIterator fIter
= fldList_
.getIterator();
510 char *colPtr
= (char*) tuplePtr
;
511 while (fIter
.hasElement())
513 FieldDef def
= fIter
.nextElement();
517 if (NULL
!= def
.bindVal_
)
518 strcpy((char*)def
.bindVal_
, (char*)colPtr
);
519 colPtr
= colPtr
+ os::align(def
.length_
);
522 if (NULL
!= def
.bindVal_
)
523 os::memcpy((char*)def
.bindVal_
, (char*)colPtr
, def
.length_
);
524 colPtr
= colPtr
+ os::align(def
.length_
);
527 if (NULL
!= def
.bindVal_
)
528 AllDataType::copyVal(def
.bindVal_
, colPtr
, def
.type_
);
529 colPtr
= colPtr
+ os::align(AllDataType::size(def
.type_
));
536 //-1 index not supported
537 DbRetVal
TableImpl::insertIndexNode(Transaction
*tr
, void *indexPtr
, IndexInfo
*info
, void *tuple
)
539 INDEX
*iptr
= (INDEX
*)indexPtr
;
541 printDebug(DM_Table
, "Inside insertIndexNode type %d", iptr
->indexType_
);
542 Index
* idx
= Index::getIndex(iptr
->indexType_
);
543 ret
= idx
->insert(this, tr
, indexPtr
, info
, tuple
,undoFlag
);
547 DbRetVal
TableImpl::deleteIndexNode(Transaction
*tr
, void *indexPtr
, IndexInfo
*info
, void *tuple
)
549 INDEX
*iptr
= (INDEX
*)indexPtr
;
551 Index
* idx
= Index::getIndex(iptr
->indexType_
);
552 ret
= idx
->remove(this, tr
, indexPtr
, info
, tuple
, undoFlag
);
557 DbRetVal
TableImpl::updateIndexNode(Transaction
*tr
, void *indexPtr
, IndexInfo
*info
, void *tuple
)
559 INDEX
*iptr
= (INDEX
*)indexPtr
;
561 Index
* idx
= Index::getIndex(iptr
->indexType_
);
562 //TODO::currently it updates irrespective of whether the key changed or not
563 //because of this commenting the whole index update code. relook at it and uncomment
565 //ret = idx->update(this, tr, indexPtr, info, tuple, undoFlag);
571 void TableImpl::setTableInfo(char *name
, int tblid
, size_t length
,
572 int numFld
, int numIdx
, void *chunk
)
574 strcpy(tblName_
, name
);
578 numIndexes_
= numIdx
;
582 long TableImpl::spaceUsed()
584 Chunk
*chk
= (Chunk
*)chunkPtr_
;
585 long totSize
= chk
->getTotalDataNodes() * chk
->getSize();
586 totSize
= totSize
+ (chk
->totalPages() * sizeof (PageInfo
));
590 int TableImpl::pagesUsed()
592 Chunk
*chk
= (Chunk
*)chunkPtr_
;
593 return chk
->totalPages();
596 long TableImpl::numTuples()
598 return ((Chunk
*)chunkPtr_
)->getTotalDataNodes();
601 List
TableImpl::getFieldNameList()
604 FieldIterator fIter
= fldList_
.getIterator();
605 while (fIter
.hasElement())
607 FieldDef def
= fIter
.nextElement();
608 Identifier
*elem
= new Identifier();
609 strcpy(elem
->name
, def
.fldName_
);
610 fldNameList
.append(elem
);
614 DbRetVal
TableImpl::close()
618 printError(ErrNotOpen
,"Scan not open");
626 DbRetVal
TableImpl::lock(bool shared
)
632 ret = lMgr_->getSharedLock(chunkPtr_, NULL);
634 ret = lMgr_->getExclusiveLock(chunkPtr_, NULL);
637 printError(ret, "Could not exclusive lock on the table %x", chunkPtr_);
639 //do not append for S to X upgrade
640 if (!ProcessManager::hasLockList.exists(chunkPtr_))
641 ProcessManager::hasLockList.append(chunkPtr_);
646 DbRetVal
TableImpl::unlock()
649 if (!ProcessManager::hasLockList.exists(chunkPtr_)) return OK;
650 DbRetVal ret = lMgr_->releaseLock(chunkPtr_);
653 printError(ret, "Could not release exclusive lock on the table %x", chunkPtr_);
656 ProcessManager::hasLockList.remove(chunkPtr_);
662 TableImpl::~TableImpl()
664 if (NULL
!= iter
) { delete iter
; iter
= NULL
; }
665 if (NULL
!= idxInfo
) { delete idxInfo
; idxInfo
= NULL
; }
666 if (NULL
!= indexPtr_
) { delete[] indexPtr_
; indexPtr_
= NULL
; }
669 for (int i
= 0; i
< numIndexes_
; i
++) delete idxInfo
[i
];
673 if (numFlds_
> 31 && cNullInfo
!= NULL
) { free(cNullInfo
); cNullInfo
= NULL
; }
675 fldList_
.removeAll();