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
);
37 bool TableImpl::isFldNull(const char *name
){
38 //TODO::find the fldpos and call the other function
42 bool TableImpl::isFldNull(int colpos
)
44 if (!curTuple_
) return false;
45 if (colpos
<0 || colpos
> numFlds_
) return false;
46 char *nullOffset
= (char*)curTuple_
- 4;
47 if (isIntUsedForNULL
) {
48 int nullVal
= *(int*)((char*)curTuple_
+ (length_
- 4));
49 if (BITSET(nullVal
, colpos
)) return true;
52 char *nullOffset
= (char*)curTuple_
- os::align(numFlds_
);
53 if (nullOffset
[colpos
-1]) return true;
57 void TableImpl::markFldNull(char const* name
)
59 //TODO::find the fldpos and call the other function
62 void TableImpl::markFldNull(int fldpos
)
64 if (fldpos
<0 || fldpos
> numFlds_
) return;
65 if (isIntUsedForNULL
) {
66 SETBIT(iNullInfo
, fldpos
);
69 cNullInfo
[fldpos
-1] = 1;
73 void TableImpl::clearFldNull(const char *name
)
75 //TODO::find the fldpos and call the other function
78 void TableImpl::clearFldNull(int colpos
)
80 if (colpos
<0 || colpos
> numFlds_
) return;
81 if (isIntUsedForNULL
) {
82 CLEARBIT(iNullInfo
, colpos
);
85 cNullInfo
[colpos
-1] = 0;
90 DbRetVal
TableImpl::execute()
94 printError(ErrAlready
,"Scan already open:Close and re execute");
97 //table ptr is set in predicate because it needs to access the
98 //type and length to evaluate
101 PredicateImpl
*pred
= (PredicateImpl
*) pred_
;
102 pred
->setTable(this);
109 printError(ErrSysInternal
,"Unable to create the plan");
110 return ErrSysInternal
;
112 iter
= new TupleIterator(pred_
, scanType_
, idxInfo
, chunkPtr_
);
116 printError(ErrSysInternal
,"Unable to open the iterator");
117 return ErrSysInternal
;
123 DbRetVal
TableImpl::createPlan()
126 //if there are no predicates then go for full scan
127 //if there are no indexes then go for full scan
128 if (NULL
== pred_
|| NULL
== indexPtr_
)
130 scanType_
= fullTableScan
;
133 if (NULL
!= indexPtr_
)
135 //Note:numIndexes_ == 0 is handled above. for this case indexPtr_ is null
136 if (numIndexes_
== 1) {
137 //check predicate, whether it has field name and == operator
138 //and does not have OR, NOT operator
139 char *fName
= ((SingleFieldHashIndexInfo
*)idxInfo
)->fldName
;
140 PredicateImpl
*pred
= (PredicateImpl
*)pred_
;
141 if (pred
->pointLookupInvolved(fName
))
143 scanType_
= hashIndexScan
;
149 scanType_
= fullTableScan
;
159 scanType_
= fullTableScan
;
163 void* TableImpl::fetch()
166 if (NULL
== curTuple_
) return curTuple_
;
167 copyValuesToBindBuffer(curTuple_
);
171 void* TableImpl::fetchNoBind()
175 printError(ErrNotOpen
,"Scan not open or Scan is closed\n");
178 curTuple_
= iter
->next();
179 if (NULL
== curTuple_
)
183 DbRetVal lockRet
= OK
;
184 if ((*trans
)->isoLevel_
== READ_REPEATABLE
) {
185 lockRet
= lMgr_
->getSharedLock(curTuple_
, trans
);
188 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
193 else if ((*trans
)->isoLevel_
== READ_COMMITTED
)
195 //if iso level is read committed, operation duration lock is sufficent
196 //so release it here itself.
198 struct timeval timeout
;
199 timeout
.tv_sec
= Conf::config
.getMutexSecs();
200 timeout
.tv_usec
= Conf::config
.getMutexUSecs();
204 lockRet
= lMgr_
->isExclusiveLocked( curTuple_
, trans
, status
);
207 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
212 if (tries
== 0) break;
213 os::select(0, 0, 0, 0, &timeout
);
218 printError(lockRet
, "Unable to get the lock for the tuple %x", curTuple_
);
226 DbRetVal
TableImpl::insertTuple()
228 void *tptr
= ((Chunk
*)chunkPtr_
)->allocate(db_
);
231 printError(ErrNoMemory
, "Unable to allocate memory to store tuple");
234 DbRetVal ret
= lMgr_
->getExclusiveLock(tptr
, trans
);
237 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
238 printError(ret
, "Could not get lock for the insert tuple %x", tptr
);
243 ret
= copyValuesFromBindBuffer(tptr
);
246 printError(ret
, "Unable to copy values from bind buffer");
247 lMgr_
->releaseLock(tptr
);
248 (*trans
)->removeFromHasList(db_
, tptr
);
249 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
257 *(int*)((char*)(tptr
) + (length_
-addSize
)) = iNullInfo
;
261 addSize
= os::align(numFlds_
);
262 os::memcpy(((char*)(tptr
) + (length_
-addSize
)), cNullInfo
, addSize
);
265 //int tupleSize = length_ + addSize;
266 if (NULL
!= indexPtr_
)
270 for (i
= 0; i
< numIndexes_
; i
++)
272 ret
= insertIndexNode(*trans
, indexPtr_
[i
], tptr
);
273 if (ret
!= OK
) break;
275 if (i
!= numIndexes_
)
277 for (int j
= 0; j
< i
; j
++)
278 deleteIndexNode(*trans
, indexPtr_
[j
], tptr
);
279 lMgr_
->releaseLock(tptr
);
280 (*trans
)->removeFromHasList(db_
, tptr
);
281 ((Chunk
*)chunkPtr_
)->free(db_
, tptr
);
282 printError(ret
, "Unable to insert index node for tuple %x", tptr
);
286 (*trans
)->appendUndoLog(sysDB_
, InsertOperation
, tptr
, length_
);
290 DbRetVal
TableImpl::deleteTuple()
292 if (NULL
== curTuple_
)
294 printError(ErrNotOpen
, "Scan not open: No Current tuple");
297 DbRetVal ret
= lMgr_
->getExclusiveLock(curTuple_
, trans
);
300 printError(ret
, "Could not get lock for the delete tuple %x", curTuple_
);
304 if (NULL
!= indexPtr_
)
308 for (i
= 0; i
< numIndexes_
; i
++)
310 ret
= deleteIndexNode(*trans
, indexPtr_
[i
], curTuple_
);
311 if (ret
!= OK
) break;
313 if (i
!= numIndexes_
)
315 for (int j
= 0; j
< i
; j
++)
316 insertIndexNode(*trans
, indexPtr_
[j
], curTuple_
);
317 lMgr_
->releaseLock(curTuple_
);
318 (*trans
)->removeFromHasList(db_
, curTuple_
);
319 printError(ret
, "Unable to insert index node for tuple %x", curTuple_
);
323 ((Chunk
*)chunkPtr_
)->free(db_
, curTuple_
);
324 (*trans
)->appendUndoLog(sysDB_
, DeleteOperation
, curTuple_
, length_
);
328 DbRetVal
TableImpl::updateTuple()
330 if (NULL
== curTuple_
)
332 printError(ErrNotOpen
, "Scan not open: No Current tuple");
335 DbRetVal ret
= lMgr_
->getExclusiveLock(curTuple_
, trans
);
338 printError(ret
, "Could not get lock for the update tuple %x", curTuple_
);
341 if (NULL
!= indexPtr_
)
344 //TODO::If it fails while updating index node, we have to undo all the updates
345 //on other indexes on the table.Currently it will leave the database in an
346 //inconsistent state.
347 for (int i
= 0; i
< numIndexes_
; i
++)
349 ret
= updateIndexNode(*trans
, indexPtr_
[i
], curTuple_
);
352 lMgr_
->releaseLock(curTuple_
);
353 (*trans
)->removeFromHasList(db_
, curTuple_
);
354 printError(ret
, "Unable to update index node for tuple %x", curTuple_
);
359 (*trans
)->appendUndoLog(sysDB_
, UpdateOperation
, curTuple_
, length_
);
360 return copyValuesFromBindBuffer(curTuple_
);
363 DbRetVal
TableImpl::copyValuesFromBindBuffer(void *tuplePtr
)
365 //Iterate through the bind list and copy the value here
366 FieldIterator fIter
= fldList_
.getIterator();
367 char *colPtr
= (char*) tuplePtr
;
368 while (fIter
.hasElement())
370 FieldDef def
= fIter
.nextElement();
374 if (NULL
!= def
.bindVal_
)
376 strcpy((char*)colPtr
, (char*)def
.bindVal_
);
377 *(((char*)colPtr
) + (def
.length_
-1)) = '\0';
379 colPtr
= colPtr
+ os::align(def
.length_
);
382 if (NULL
!= def
.bindVal_
)
383 os::memcpy((char*)colPtr
, (char*)def
.bindVal_
, def
.length_
);
384 colPtr
= colPtr
+ os::align(def
.length_
);
387 if (NULL
!= def
.bindVal_
)
388 AllDataType::copyVal(colPtr
, def
.bindVal_
, def
.type_
);
389 colPtr
= colPtr
+ os::align(AllDataType::size(def
.type_
));
396 DbRetVal
TableImpl::copyValuesToBindBuffer(void *tuplePtr
)
398 //Iterate through the bind list and copy the value here
399 FieldIterator fIter
= fldList_
.getIterator();
400 char *colPtr
= (char*) tuplePtr
;
401 while (fIter
.hasElement())
403 FieldDef def
= fIter
.nextElement();
407 if (NULL
!= def
.bindVal_
)
408 strcpy((char*)def
.bindVal_
, (char*)colPtr
);
409 colPtr
= colPtr
+ os::align(def
.length_
);
412 if (NULL
!= def
.bindVal_
)
413 os::memcpy((char*)def
.bindVal_
, (char*)colPtr
, def
.length_
);
414 colPtr
= colPtr
+ os::align(def
.length_
);
417 if (NULL
!= def
.bindVal_
)
418 AllDataType::copyVal(def
.bindVal_
, colPtr
, def
.type_
);
419 colPtr
= colPtr
+ os::align(AllDataType::size(def
.type_
));
426 //-1 index not supported
427 DbRetVal
TableImpl::insertIndexNode(Transaction
*tr
, void *indexPtr
, void *tuple
)
429 INDEX
*iptr
= (INDEX
*)indexPtr
;
431 Index
* idx
= Index::getIndex(iptr
->indexType_
);
432 if (idx
== NULL
) printf("It is here :PRABA\n");
433 ret
= idx
->insert(this, tr
, indexPtr
, tuple
);
437 DbRetVal
TableImpl::deleteIndexNode(Transaction
*tr
, void *indexPtr
, void *tuple
)
439 INDEX
*iptr
= (INDEX
*)indexPtr
;
441 //CatalogTableINDEX::getMutex(indexPtr);
442 Index
* idx
= Index::getIndex(iptr
->indexType_
);
443 ret
= idx
->remove(this, tr
, indexPtr
, tuple
);
444 //CatalogTableINDEX::releaseMutex(indexPtr);
449 DbRetVal
TableImpl::updateIndexNode(Transaction
*tr
, void *indexPtr
, void *tuple
)
451 INDEX
*iptr
= (INDEX
*)indexPtr
;
453 //CatalogTableINDEX::getMutex(indexPtr);
454 Index
* idx
= Index::getIndex(iptr
->indexType_
);
455 ret
= idx
->update(this, tr
, indexPtr
, tuple
);
456 //CatalogTableINDEX::releaseMutex(indexPtr);
462 DbRetVal
TableImpl::close()
466 printError(ErrNotOpen
,"Scan not open");
475 TableImpl::~TableImpl()
477 if (NULL
!= iter
) { delete iter
; iter
= NULL
; }
478 if (NULL
!= idxInfo
) { delete idxInfo
; idxInfo
= NULL
; }
479 if (NULL
!= indexPtr_
) { delete[] indexPtr_
; indexPtr_
= NULL
; }
480 if (numFlds_
> 31 && cNullInfo
!= NULL
) { free(cNullInfo
); cNullInfo
= NULL
; }
482 fldList_
.removeAll();
485 void TableImpl::setTableInfo(char *name
, int tblid
, size_t length
,
486 int numFld
, int numIdx
, void *chunk
)
488 strcpy(tblName_
, name
);
492 numIndexes_
= numIdx
;
496 long TableImpl::spaceUsed()
498 Chunk
*chk
= (Chunk
*)chunkPtr_
;
499 long totSize
= chk
->getTotalDataNodes() * chk
->getSize();
500 totSize
= totSize
+ (chk
->totalPages() * sizeof (PageInfo
));
504 long TableImpl::numTuples()
506 return ((Chunk
*)chunkPtr_
)->getTotalDataNodes();
509 List
TableImpl::getFieldNameList()
512 FieldIterator fIter
= fldList_
.getIterator();
513 while (fIter
.hasElement())
515 FieldDef def
= fIter
.nextElement();
516 Identifier
*elem
= new Identifier();
517 strcpy(elem
->name
, def
.fldName_
);
518 fldNameList
.append(elem
);