autoinc and tree index predicate fix
[csql.git] / src / storage / TupleIterator.cxx
blob3faec2159b126ff1b97b808000bd2cbd4771fb60
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<Table.h>
17 #include<Index.h>
18 #include<CatalogTables.h>
19 #include<Lock.h>
20 #include<Debug.h>
21 #include<TableImpl.h>
22 #include<PredicateImpl.h>
23 DbRetVal TupleIterator::setPlan()
25 PredicateImpl *predImpl = (PredicateImpl*) pred_;
26 if (treeIndexScan == scanType_)
28 HashIndexInfo *hIdxInfo = (HashIndexInfo*)info;
29 FieldIterator iter = hIdxInfo->idxFldList.getIterator();
30 if(iter.hasElement())
32 FieldDef *def = iter.nextElement();
33 keyPtr = (char*)predImpl->opAndValPtrForIndexField(def->fldName_, hIdxInfo->isUnique,op);
35 CINDEX *iptr = (CINDEX*) hIdxInfo->indexPtr;
36 TreeNode *fstNode=(TreeNode *)iptr->hashNodeChunk_;
37 if(fstNode!=NULL){
38 TreeNode *start = (TreeNode *)*((char**)((char*)fstNode + sizeof(TreeNode)));
39 tIter->set(start,(TreeNode*)iptr->hashNodeChunk_,procSlot);
40 }else{
41 tIter->set(NULL,(TreeNode*)iptr->hashNodeChunk_,procSlot);
43 tIter->setSearchKey(keyPtr, op);
44 if (hIdxInfo->isUnique) tIter->setUnique();
45 tIter->setFldOffset(hIdxInfo->fldOffset);
46 tIter->setTypeLength(hIdxInfo->type, hIdxInfo->compLength);
48 if(predImpl) predImpl->setIfNoLeftRight();
49 return OK;
51 DbRetVal TupleIterator::open()
53 PredicateImpl *predImpl = (PredicateImpl*) pred_;
54 if (fullTableScan == scanType_)
56 *cIter = ((Chunk*)chunkPtr_)->getIterator();
57 }else if (hashIndexScan == scanType_)
59 HashIndexInfo *hIdxInfo = (HashIndexInfo*)info;
60 FieldIterator iter = hIdxInfo->idxFldList.getIterator();
61 int offset = hIdxInfo->fldOffset;
62 if(!keyBuffer) keyBuffer = (char*) malloc(hIdxInfo->compLength);
63 void *keyPtr = NULL;
64 char *keyBufferIter = keyBuffer;
65 while(iter.hasElement())
67 FieldDef *def = iter.nextElement();
68 //keyPtr = (void*)predImpl->valPtrForIndexField(def->fldName_,hIdxInfo->isUnique);
69 //TODO::PRABA::the below opt should be done for hash also
70 keyPtr = (void*)predImpl->valPtrForIndexField(def->fldName_,false);
71 if (NULL == keyPtr) {
72 printError(ErrSysFatal, "Fatal: Should not come here");
73 continue;
75 AllDataType::copyVal(keyBufferIter, keyPtr, def->type_, def->length_);
76 keyBufferIter = keyBufferIter + def->length_;
78 int bucketNo = HashIndex::computeHashBucket(hIdxInfo->type,
79 keyBuffer, hIdxInfo->noOfBuckets, hIdxInfo->compLength);
80 Bucket *bucket = &(hIdxInfo->buckets[bucketNo]);
81 IndexNode *head = (IndexNode*) bucket->bucketList_;
82 if (!head)
84 bIter->setHead(head);
85 return OK;
87 printDebug(DM_HashIndex, "open:head for bucket %x is :%x", bucket, head);
88 bIter->setHead(head);
89 }else if (trieIndexScan == scanType_)
91 HashIndexInfo *indInfo = (HashIndexInfo*)info;
92 char hashValue[TRIE_MAX_LENGTH];
93 FieldIterator iter = indInfo->idxFldList.getIterator();
94 FieldDef *def = iter.nextElement();
95 void* keyPtr = (void*)predImpl->valPtrForIndexField(def->fldName_,false);
96 if (NULL == keyPtr) {
97 printError(ErrSysFatal, "Fatal: Should not come here");
99 TrieIndex::computeHashValues(indInfo->type, keyPtr, hashValue, indInfo->compLength);
100 TrieNode* start = (TrieNode*)indInfo->buckets;
101 if (NULL == start)
103 bIter->setHead(NULL);
104 return OK;
106 char **next = NULL;
107 int cnt = 0;
108 while(-1 != hashValue[cnt+1]) {
109 next = (char**)&(start->next_[hashValue[cnt]]);
110 if (! *next)
112 printError(ErrNotFound, "No trie node found \n");
113 return ErrNotFound;
115 //traverse till the end
116 start = (TrieNode*) *next;
117 cnt++;
119 void **ptr = (void**)&(start->head_[hashValue[cnt]]);
120 IndexNode *head = (IndexNode*) *ptr;
121 if (!head)
123 bIter->setHead(head);
124 return OK;
126 bIter->setHead(head);
128 }else if (treeIndexScan == scanType_)
130 HashIndexInfo *hIdxInfo = (HashIndexInfo*)info;
131 CINDEX *iptr = (CINDEX*) hIdxInfo->indexPtr;
132 TreeNode *fstNode=(TreeNode *)iptr->hashNodeChunk_;
133 if(fstNode!=NULL){
134 TreeNode *start = (TreeNode *)*((char**)((char*)fstNode + sizeof(TreeNode)));
135 tIter->set(start,(TreeNode*)iptr->hashNodeChunk_,procSlot);
136 }else{
137 tIter->set(NULL,(TreeNode*)iptr->hashNodeChunk_,procSlot);
139 if (hIdxInfo->isUnique) tIter->setUnique();
141 isClosed = false;
142 return OK;
145 //not returing previous tuple for all iterators and for tree iterator.
146 //it just decrements the nodeOffset for tree iterator.
147 void* TupleIterator::prev()
149 PredicateImpl *predImpl = (PredicateImpl*) pred_;
150 void *tuple = NULL;
151 if (treeIndexScan == scanType_)
153 if (NULL == tIter) return NULL;
154 tuple = tIter->prev();
155 predImpl->setTuple(tuple);
156 if(NULL == tuple) {
157 printDebug(DM_HashIndex, "prev::tuple is null");
159 //TODO::evaluate as it is done in next() before returning
161 return tuple;
164 void* TupleIterator::next()
166 PredicateImpl *predImpl = (PredicateImpl*) pred_;
167 void *tuple = NULL;
168 DbRetVal rv = OK;
169 if (fullTableScan == scanType_)
171 if (NULL == pred_)
173 //no predicates
174 return cIter->nextElement();
176 else
178 int offset=0;
179 bool isLargeSizeAllocator = cIter->isLargeSize();
180 void *val = predImpl->getValIfPointLookupOnInt(offset);
181 char *tup = NULL;
182 if (val != NULL) {
183 int value = *(int*)val;
184 if (isLargeSizeAllocator) {
185 while (true)
187 tup = (char*)cIter->nextElement();
188 if(NULL == tup) return NULL;
189 if (value == *((int*)(tup+offset))) break;
191 return tup;
192 }else {
193 tup = (char*)cIter->nextElementIntMatch(value, offset);
194 return tup;
197 val = predImpl->getVal1IfBetweenOnInt(offset);
198 if (val != NULL) {
199 void *val2 = predImpl->getVal2IfBetweenOnInt(offset);
200 int value1 = *(int*)val;
201 int value2 = *(int*)val2;
202 while (true)
204 if(isLargeSizeAllocator)
205 tup = (char*)cIter->nextElement();
206 else
207 tup = (char*)cIter->nextElementInt();
208 if(NULL == tup) return NULL;
209 if (*((int*)(tup+offset)) >= value1 &&
210 *((int*)(tup+offset)) <= value2) break;
212 return tup;
215 //evaluate till it succeeds
216 bool result = false;
217 while (!result)
219 if(isLargeSizeAllocator)
220 tuple = cIter->nextElement();
221 else
222 tuple = cIter->nextElementInt();
223 if(NULL == tuple) return NULL;
224 //predImpl->setTuple(tuple);
225 printDebug(DM_Table, "Evaluating the predicate from fullTableScan");
226 predImpl->evaluateForTable(result, (char*)tuple);
229 }else if (hashIndexScan == scanType_ || trieIndexScan == scanType_)
231 //evaluate till it succeeds
232 bool result = false;
233 while (!result)
235 IndexNode *node = bIter->next();
236 if (node == NULL) return NULL;
237 printDebug(DM_HashIndex, "next: returned IndexNode: %x", node);
238 tuple = node->ptrToTuple_;
239 if(NULL == tuple) {
240 printDebug(DM_HashIndex, "next::tuple is null");
241 return NULL;
244 //if (!predImpl->isSingleTerm()) {
245 printDebug(DM_HashIndex, "next: predicate has more than single term");
246 //predImpl->setTuple(tuple);
247 printDebug(DM_Table, "Evaluating the predicate from hashIndexScan: has more than one term");
248 predImpl->evaluateForTable(result, (char*)tuple);
249 //}
250 //else
251 // return tuple;
254 }else if (treeIndexScan == scanType_)
256 if (NULL == tIter) return NULL;
257 bool result = false;
258 while (!result)
260 tuple = tIter->next();
261 if(NULL == tuple) {
262 printDebug(DM_HashIndex, "next::tuple is null");
263 return NULL;
265 //predImpl->setTuple(tuple);
266 predImpl->evaluateForTable(result, (char*)tuple);
267 if(!result && (isBetween || isPointLook)) tIter->nextNode();
270 return tuple;
273 DbRetVal TupleIterator::close()
275 if (isClosed) return OK;
276 reset();
277 isClosed = true;
278 return OK;
281 void TupleIterator::reset()
283 DbRetVal rv = OK;
284 if (scanType_ == fullTableScan) {
285 if (cIter) *cIter = ((Chunk*)chunkPtr_)->getIterator();
287 else if (scanType_ == hashIndexScan) {
288 if(bIter) bIter->reset();
290 else if (scanType_ == treeIndexScan) { if(tIter) tIter->reset(); }