Minor fixes
[csql.git] / src / server / TableImpl.cxx
blobe3abc934f924cb34680c1255d0593c7767621300
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 return true;
40 bool TableImpl::isFldNull(int colpos)
42 return true;
44 void TableImpl::markFldNull(char const* name)
46 return;
48 void TableImpl::markFldNull(int fldpos)
50 return;
54 void TableImpl::clearFldNull(const char *name)
56 return;
58 void TableImpl::clearFldNull(int colpos)
60 return;
64 DbRetVal TableImpl::execute()
66 if (NULL != iter)
68 printError(ErrAlready,"Scan already open:Close and re execute");
69 return ErrAlready;
71 //table ptr is set in predicate because it needs to access the
72 //type and length to evaluate
73 if( NULL != pred_)
75 PredicateImpl *pred = (PredicateImpl*) pred_;
76 pred->setTable(this);
78 DbRetVal ret = OK;
80 ret = createPlan();
81 if (OK != ret)
83 printError(ErrSysInternal,"Unable to create the plan");
84 return ErrSysInternal;
86 iter = new TupleIterator(pred_, scanType_, idxInfo, chunkPtr_);
87 ret = iter->open();
88 if (OK != ret)
90 printError(ErrSysInternal,"Unable to open the iterator");
91 return ErrSysInternal;
93 return OK;
97 DbRetVal TableImpl::createPlan()
99 useIndex_ = -1;
100 //if there are no predicates then go for full scan
101 //if there are no indexes then go for full scan
102 if (NULL == pred_ || NULL == indexPtr_)
104 scanType_ = fullTableScan;
105 return OK;
107 if (NULL != indexPtr_)
109 //Note:numIndexes_ == 0 is handled above. for this case indexPtr_ is null
110 if (numIndexes_ == 1) {
111 //check predicate, whether it has field name and == operator
112 //and does not have OR, NOT operator
113 char *fName = ((SingleFieldHashIndexInfo*)idxInfo)->fldName;
114 PredicateImpl *pred = (PredicateImpl*)pred_;
115 if (pred->pointLookupInvolved(fName))
117 scanType_ = hashIndexScan;
118 useIndex_ = 0;
119 return OK;
121 else
123 scanType_ = fullTableScan;
124 return OK;
127 else
130 return ErrNotYet;
133 scanType_ = fullTableScan;
134 return OK;
137 void* TableImpl::fetch()
139 fetchNoBind();
140 if (NULL == curTuple_) return curTuple_;
141 copyValuesToBindBuffer(curTuple_);
142 return curTuple_;
145 void* TableImpl::fetchNoBind()
147 if (NULL == iter)
149 printError(ErrNotOpen,"Scan not open or Scan is closed\n");
150 return NULL;
152 curTuple_ = iter->next();
153 if (NULL == curTuple_)
155 return NULL;
157 DbRetVal lockRet = OK;
158 if ((*trans)->isoLevel_ == READ_REPEATABLE) {
159 lockRet = lMgr_->getSharedLock(curTuple_, trans);
160 if (OK != lockRet)
162 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
163 return NULL;
167 else if ((*trans)->isoLevel_ == READ_COMMITTED)
169 //if iso level is read committed, operation duration lock is sufficent
170 //so release it here itself.
171 int tries = 5;
172 struct timeval timeout;
173 timeout.tv_sec = Conf::config.getMutexSecs();
174 timeout.tv_usec = Conf::config.getMutexUSecs();
176 bool status = false;
177 while(true) {
178 lockRet = lMgr_->isExclusiveLocked( curTuple_, trans, status);
179 if (OK != lockRet)
181 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
182 return NULL;
184 if (!status) break;
185 tries--;
186 if (tries == 0) break;
187 os::select(0, 0, 0, 0, &timeout);
190 if (tries == 0)
192 printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_);
193 return NULL;
196 return curTuple_;
199 DbRetVal TableImpl::insertTuple()
201 void *tptr = ((Chunk*)chunkPtr_)->allocate(db_);
202 if (NULL == tptr)
204 printError(ErrNoMemory, "Unable to allocate memory to store tuple");
205 return ErrNoMemory;
207 DbRetVal ret = lMgr_->getExclusiveLock(tptr, trans);
208 if (OK != ret)
210 ((Chunk*)chunkPtr_)->free(db_, tptr);
211 printError(ret, "Could not get lock for the insert tuple %x", tptr);
212 return ret;
214 int tupleSize = fldList_.getTupleSize ();
217 ret = copyValuesFromBindBuffer(tptr);
218 if (ret != OK)
220 printError(ret, "Unable to copy values from bind buffer");
221 lMgr_->releaseLock(tptr);
222 ((Chunk*)chunkPtr_)->free(db_, tptr);
223 return ret;
225 if (NULL != indexPtr_)
227 int i;
228 //it has index
229 for (i = 0; i < numIndexes_ ; i++)
231 ret = insertIndexNode(*trans, indexPtr_[i], tptr);
232 if (ret != OK) break;
234 if (i != numIndexes_ )
236 for (int j = 0; j < i ; j++)
237 deleteIndexNode(*trans, indexPtr_[j], tptr);
238 lMgr_->releaseLock(tptr);
239 ((Chunk*)chunkPtr_)->free(db_, tptr);
240 printError(ret, "Unable to insert index node for tuple %x", tptr);
241 return ret;
245 (*trans)->appendUndoLog(sysDB_, InsertOperation, tptr, tupleSize);
246 return OK;
249 DbRetVal TableImpl::deleteTuple()
251 if (NULL == curTuple_)
253 printError(ErrNotOpen, "Scan not open: No Current tuple");
254 return ErrNotOpen;
256 DbRetVal ret = lMgr_->getExclusiveLock(curTuple_, trans);
257 if (OK != ret)
259 printError(ret, "Could not get lock for the delete tuple %x", curTuple_);
260 return ret;
263 if (NULL != indexPtr_)
265 int i;
266 //it has index
267 for (i = 0; i < numIndexes_ ; i++)
269 ret = deleteIndexNode(*trans, indexPtr_[i], curTuple_);
270 if (ret != OK) break;
272 if (i != numIndexes_ )
274 for (int j = 0; j < i ; j++)
275 insertIndexNode(*trans, indexPtr_[j], curTuple_);
276 lMgr_->releaseLock(curTuple_);
277 printError(ret, "Unable to insert index node for tuple %x", curTuple_);
278 return ret;
281 ((Chunk*)chunkPtr_)->free(db_, curTuple_);
282 (*trans)->appendUndoLog(sysDB_, DeleteOperation, curTuple_, fldList_.getTupleSize());
283 return OK;
286 DbRetVal TableImpl::updateTuple()
288 if (NULL == curTuple_)
290 printError(ErrNotOpen, "Scan not open: No Current tuple");
291 return ErrNotOpen;
293 DbRetVal ret = lMgr_->getExclusiveLock(curTuple_, trans);
294 if (OK != ret)
296 printError(ret, "Could not get lock for the update tuple %x", curTuple_);
297 return ret;
299 if (NULL != indexPtr_)
301 //it has index
302 //TODO::If it fails while updating index node, we have to undo all the updates
303 //on other indexes on the table.Currently it will leave the database in an
304 //inconsistent state.
305 for (int i = 0; i < numIndexes_ ; i++)
307 ret = updateIndexNode(*trans, indexPtr_[i], curTuple_);
308 if (ret != OK)
310 lMgr_->releaseLock(curTuple_);
311 printError(ret, "Unable to update index node for tuple %x", curTuple_);
312 return ret;
316 (*trans)->appendUndoLog(sysDB_, UpdateOperation, curTuple_, fldList_.getTupleSize());
317 return copyValuesFromBindBuffer(curTuple_);
320 DbRetVal TableImpl::copyValuesFromBindBuffer(void *tuplePtr)
322 //Iterate through the bind list and copy the value here
323 FieldIterator fIter = fldList_.getIterator();
324 char *colPtr = (char*) tuplePtr;
325 while (fIter.hasElement())
327 FieldDef def = fIter.nextElement();
328 switch(def.type_)
330 case typeString:
331 if (NULL != def.bindVal_)
333 strcpy((char*)colPtr, (char*)def.bindVal_);
334 *(((char*)colPtr) + (def.length_-1)) = '\0';
336 colPtr = colPtr + os::align(def.length_);
337 break;
338 case typeBinary:
339 if (NULL != def.bindVal_)
340 os::memcpy((char*)colPtr, (char*)def.bindVal_, def.length_);
341 colPtr = colPtr + os::align(def.length_);
342 break;
343 default:
344 if (NULL != def.bindVal_)
345 AllDataType::copyVal(colPtr, def.bindVal_, def.type_);
346 colPtr = colPtr + os::align(AllDataType::size(def.type_));
347 break;
350 return OK;
353 DbRetVal TableImpl::copyValuesToBindBuffer(void *tuplePtr)
355 //Iterate through the bind list and copy the value here
356 FieldIterator fIter = fldList_.getIterator();
357 char *colPtr = (char*) tuplePtr;
358 while (fIter.hasElement())
360 FieldDef def = fIter.nextElement();
361 switch(def.type_)
363 case typeString:
364 if (NULL != def.bindVal_)
365 strcpy((char*)def.bindVal_, (char*)colPtr);
366 colPtr = colPtr + os::align(def.length_);
367 break;
368 case typeBinary:
369 if (NULL != def.bindVal_)
370 os::memcpy((char*)def.bindVal_, (char*)colPtr, def.length_);
371 colPtr = colPtr + os::align(def.length_);
372 break;
373 default:
374 if (NULL != def.bindVal_)
375 AllDataType::copyVal(def.bindVal_, colPtr, def.type_);
376 colPtr = colPtr + os::align(AllDataType::size(def.type_));
377 break;
380 return OK;
383 //-1 index not supported
384 DbRetVal TableImpl::insertIndexNode(Transaction *tr, void *indexPtr, void *tuple)
386 INDEX *iptr = (INDEX*)indexPtr;
387 DbRetVal ret = OK;
388 Index* idx = Index::getIndex(iptr->indexType_);
389 if (idx == NULL) printf("It is here :PRABA\n");
390 ret = idx->insert(this, tr, indexPtr, tuple);
391 return ret;
394 DbRetVal TableImpl::deleteIndexNode(Transaction *tr, void *indexPtr, void *tuple)
396 INDEX *iptr = (INDEX*)indexPtr;
397 DbRetVal ret = OK;
398 //CatalogTableINDEX::getMutex(indexPtr);
399 Index* idx = Index::getIndex(iptr->indexType_);
400 ret = idx->remove(this, tr, indexPtr, tuple);
401 //CatalogTableINDEX::releaseMutex(indexPtr);
402 return ret;
406 DbRetVal TableImpl::updateIndexNode(Transaction *tr, void *indexPtr, void *tuple)
408 INDEX *iptr = (INDEX*)indexPtr;
409 DbRetVal ret = OK;
410 //CatalogTableINDEX::getMutex(indexPtr);
411 Index* idx = Index::getIndex(iptr->indexType_);
412 ret = idx->update(this, tr, indexPtr, tuple);
413 //CatalogTableINDEX::releaseMutex(indexPtr);
414 return ret;
419 DbRetVal TableImpl::close()
421 if (NULL == iter)
423 printError(ErrNotOpen,"Scan not open");
424 return ErrNotOpen;
426 iter->close();
427 delete iter;
428 iter = NULL;
429 return OK;
432 TableImpl::~TableImpl()
434 if (NULL != iter ) { delete iter; iter = NULL; }
435 if (NULL != idxInfo) { delete idxInfo; idxInfo = NULL; }
436 if (NULL != indexPtr_) { delete[] indexPtr_; indexPtr_ = NULL; }
437 fldList_.removeAll();
440 void TableImpl::setTableInfo(char *name, int tblid, size_t length,
441 int numFld, int numIdx, void *chunk)
443 strcpy(tblName_, name);
444 tblID_ = tblid;
445 length_ = length;
446 numFlds_ = numFld;
447 numIndexes_ = numIdx;
448 chunkPtr_ = chunk;
451 long TableImpl::spaceUsed()
453 Chunk *chk = (Chunk*)chunkPtr_;
454 long totSize = chk->getTotalDataNodes() * chk->getSize();
455 totSize = totSize + (chk->totalPages() * sizeof (PageInfo));
456 return totSize;
459 long TableImpl::numTuples()
461 return ((Chunk*)chunkPtr_)->getTotalDataNodes();
464 List TableImpl::getFieldNameList()
466 List fldNameList;
467 FieldIterator fIter = fldList_.getIterator();
468 while (fIter.hasElement())
470 FieldDef def = fIter.nextElement();
471 Identifier *elem = new Identifier();
472 strcpy(elem->name, def.fldName_);
473 fldNameList.append(elem);
475 return fldNameList;