Though select fails, it return the tuple. This is because curTuple_ is not set in...
[csql.git] / src / server / TableImpl.cxx
blobe2fad665c35a243d330f0776fb586deb0cccbb80
1 /***************************************************************************
2 * Copyright (C) 2007 by www.databasecache.com *
3 * Contact: praba_tuty@databasecache.com *
4 * *
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. *
9 * *
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. *
14 * *
15 ***************************************************************************/
16 #include<Index.h>
17 #include<CatalogTables.h>
18 #include<Lock.h>
19 #include<Debug.h>
20 #include<Table.h>
21 #include<TableImpl.h>
22 #include<Predicate.h>
23 #include<PredicateImpl.h>
24 #include<Index.h>
25 #include<Config.h>
27 DbRetVal TableImpl::bindFld(const char *name, void *val)
29 //set it in the field list
30 DbRetVal rv = fldList_.updateBindVal(name, val);
31 if (OK != rv) {
32 printError(ErrNotExists, "Field %s does not exist", name);
33 return rv;
35 return OK;
37 bool TableImpl::isFldNull(const char *name){
38 //TODO::find the fldpos and call the other function
39 return true;
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;
51 else {
52 char *nullOffset = (char*)curTuple_ - os::align(numFlds_);
53 if (nullOffset[colpos-1]) return true;
55 return false;
57 void TableImpl::markFldNull(char const* name)
59 //TODO::find the fldpos and call the other function
60 return;
62 void TableImpl::markFldNull(int fldpos)
64 if (fldpos <0 || fldpos > numFlds_) return;
65 if (isIntUsedForNULL) {
66 SETBIT(iNullInfo, fldpos);
68 else
69 cNullInfo[fldpos-1] = 1;
70 return;
73 void TableImpl::clearFldNull(const char *name)
75 //TODO::find the fldpos and call the other function
76 return;
78 void TableImpl::clearFldNull(int colpos)
80 if (colpos <0 || colpos > numFlds_) return;
81 if (isIntUsedForNULL) {
82 CLEARBIT(iNullInfo, colpos);
84 else
85 cNullInfo[colpos-1] = 0;
86 return;
90 DbRetVal TableImpl::execute()
92 if (NULL != iter)
94 printError(ErrAlready,"Scan already open:Close and re execute");
95 return ErrAlready;
97 //table ptr is set in predicate because it needs to access the
98 //type and length to evaluate
99 if( NULL != pred_)
101 PredicateImpl *pred = (PredicateImpl*) pred_;
102 pred->setTable(this);
104 DbRetVal ret = OK;
106 ret = createPlan();
107 if (OK != ret)
109 printError(ErrSysInternal,"Unable to create the plan");
110 return ErrSysInternal;
112 iter = new TupleIterator(pred_, scanType_, idxInfo, chunkPtr_);
113 ret = iter->open();
114 if (OK != ret)
116 printError(ErrSysInternal,"Unable to open the iterator");
117 return ErrSysInternal;
119 return OK;
123 DbRetVal TableImpl::createPlan()
125 useIndex_ = -1;
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;
131 return OK;
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;
144 useIndex_ = 0;
145 return OK;
147 else
149 scanType_ = fullTableScan;
150 return OK;
153 else
156 return ErrNotYet;
159 scanType_ = fullTableScan;
160 return OK;
163 void* TableImpl::fetch()
165 fetchNoBind();
166 if (NULL == curTuple_) return curTuple_;
167 copyValuesToBindBuffer(curTuple_);
168 return curTuple_;
171 void* TableImpl::fetchNoBind()
173 if (NULL == iter)
175 printError(ErrNotOpen,"Scan not open or Scan is closed\n");
176 return NULL;
178 curTuple_ = iter->next();
179 if (NULL == curTuple_)
181 return NULL;
183 DbRetVal lockRet = OK;
184 if ((*trans)->isoLevel_ == READ_REPEATABLE) {
185 lockRet = lMgr_->getSharedLock(curTuple_, trans);
186 if (OK != lockRet)
188 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
189 return NULL;
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.
197 int tries = 5;
198 struct timeval timeout;
199 timeout.tv_sec = Conf::config.getMutexSecs();
200 timeout.tv_usec = Conf::config.getMutexUSecs();
202 bool status = false;
203 while(true) {
204 lockRet = lMgr_->isExclusiveLocked( curTuple_, trans, status);
205 if (OK != lockRet)
207 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
208 return NULL;
210 if (!status) break;
211 tries--;
212 if (tries == 0) break;
213 os::select(0, 0, 0, 0, &timeout);
216 if (tries == 0)
218 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
219 curTuple_ = NULL;
220 return NULL;
223 return curTuple_;
226 DbRetVal TableImpl::insertTuple()
228 void *tptr = ((Chunk*)chunkPtr_)->allocate(db_);
229 if (NULL == tptr)
231 printError(ErrNoMemory, "Unable to allocate memory to store tuple");
232 return ErrNoMemory;
234 DbRetVal ret = lMgr_->getExclusiveLock(tptr, trans);
235 if (OK != ret)
237 ((Chunk*)chunkPtr_)->free(db_, tptr);
238 printError(ret, "Could not get lock for the insert tuple %x", tptr);
239 return ret;
243 ret = copyValuesFromBindBuffer(tptr);
244 if (ret != OK)
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);
250 return ret;
253 int addSize = 0;
254 if (numFlds_ > 31)
256 addSize = 4;
257 *(int*)((char*)(tptr) + (length_-addSize)) = iNullInfo;
259 else
261 addSize = os::align(numFlds_);
262 os::memcpy(((char*)(tptr) + (length_-addSize)), cNullInfo, addSize);
265 //int tupleSize = length_ + addSize;
266 if (NULL != indexPtr_)
268 int i;
269 //it has index
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);
283 return ret;
286 (*trans)->appendUndoLog(sysDB_, InsertOperation, tptr, length_);
287 return OK;
290 DbRetVal TableImpl::deleteTuple()
292 if (NULL == curTuple_)
294 printError(ErrNotOpen, "Scan not open: No Current tuple");
295 return ErrNotOpen;
297 DbRetVal ret = lMgr_->getExclusiveLock(curTuple_, trans);
298 if (OK != ret)
300 printError(ret, "Could not get lock for the delete tuple %x", curTuple_);
301 return ret;
304 if (NULL != indexPtr_)
306 int i;
307 //it has index
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_);
320 return ret;
323 ((Chunk*)chunkPtr_)->free(db_, curTuple_);
324 (*trans)->appendUndoLog(sysDB_, DeleteOperation, curTuple_, length_);
325 return OK;
328 DbRetVal TableImpl::updateTuple()
330 if (NULL == curTuple_)
332 printError(ErrNotOpen, "Scan not open: No Current tuple");
333 return ErrNotOpen;
335 DbRetVal ret = lMgr_->getExclusiveLock(curTuple_, trans);
336 if (OK != ret)
338 printError(ret, "Could not get lock for the update tuple %x", curTuple_);
339 return ret;
341 if (NULL != indexPtr_)
343 //it has index
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_);
350 if (ret != OK)
352 lMgr_->releaseLock(curTuple_);
353 (*trans)->removeFromHasList(db_, curTuple_);
354 printError(ret, "Unable to update index node for tuple %x", curTuple_);
355 return ret;
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();
371 switch(def.type_)
373 case typeString:
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_);
380 break;
381 case typeBinary:
382 if (NULL != def.bindVal_)
383 os::memcpy((char*)colPtr, (char*)def.bindVal_, def.length_);
384 colPtr = colPtr + os::align(def.length_);
385 break;
386 default:
387 if (NULL != def.bindVal_)
388 AllDataType::copyVal(colPtr, def.bindVal_, def.type_);
389 colPtr = colPtr + os::align(AllDataType::size(def.type_));
390 break;
393 return OK;
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();
404 switch(def.type_)
406 case typeString:
407 if (NULL != def.bindVal_)
408 strcpy((char*)def.bindVal_, (char*)colPtr);
409 colPtr = colPtr + os::align(def.length_);
410 break;
411 case typeBinary:
412 if (NULL != def.bindVal_)
413 os::memcpy((char*)def.bindVal_, (char*)colPtr, def.length_);
414 colPtr = colPtr + os::align(def.length_);
415 break;
416 default:
417 if (NULL != def.bindVal_)
418 AllDataType::copyVal(def.bindVal_, colPtr, def.type_);
419 colPtr = colPtr + os::align(AllDataType::size(def.type_));
420 break;
423 return OK;
426 //-1 index not supported
427 DbRetVal TableImpl::insertIndexNode(Transaction *tr, void *indexPtr, void *tuple)
429 INDEX *iptr = (INDEX*)indexPtr;
430 DbRetVal ret = OK;
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);
434 return ret;
437 DbRetVal TableImpl::deleteIndexNode(Transaction *tr, void *indexPtr, void *tuple)
439 INDEX *iptr = (INDEX*)indexPtr;
440 DbRetVal ret = OK;
441 //CatalogTableINDEX::getMutex(indexPtr);
442 Index* idx = Index::getIndex(iptr->indexType_);
443 ret = idx->remove(this, tr, indexPtr, tuple);
444 //CatalogTableINDEX::releaseMutex(indexPtr);
445 return ret;
449 DbRetVal TableImpl::updateIndexNode(Transaction *tr, void *indexPtr, void *tuple)
451 INDEX *iptr = (INDEX*)indexPtr;
452 DbRetVal ret = OK;
453 //CatalogTableINDEX::getMutex(indexPtr);
454 Index* idx = Index::getIndex(iptr->indexType_);
455 ret = idx->update(this, tr, indexPtr, tuple);
456 //CatalogTableINDEX::releaseMutex(indexPtr);
457 return ret;
462 DbRetVal TableImpl::close()
464 if (NULL == iter)
466 printError(ErrNotOpen,"Scan not open");
467 return ErrNotOpen;
469 iter->close();
470 delete iter;
471 iter = NULL;
472 return OK;
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);
489 tblID_ = tblid;
490 length_ = length;
491 numFlds_ = numFld;
492 numIndexes_ = numIdx;
493 chunkPtr_ = chunk;
496 long TableImpl::spaceUsed()
498 Chunk *chk = (Chunk*)chunkPtr_;
499 long totSize = chk->getTotalDataNodes() * chk->getSize();
500 totSize = totSize + (chk->totalPages() * sizeof (PageInfo));
501 return totSize;
504 long TableImpl::numTuples()
506 return ((Chunk*)chunkPtr_)->getTotalDataNodes();
509 List TableImpl::getFieldNameList()
511 List fldNameList;
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);
520 return fldNameList;