*** empty log message ***
[csql.git] / src / relational / table / TupleIterator.cxx
blobc3170ecee44b31e8e67d42ea0d40a56791ef79d8
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;
52 DbRetVal TupleIterator::open()
54 PredicateImpl *predImpl = (PredicateImpl*) pred_;
55 if (fullTableScan == scanType_)
57 *cIter = ((Chunk*)chunkPtr_)->getIterator();
58 }else if (hashIndexScan == scanType_)
60 HashIndexInfo *hIdxInfo = (HashIndexInfo*)info;
61 FieldIterator iter = hIdxInfo->idxFldList.getIterator();
62 int offset = hIdxInfo->fldOffset;
63 if(!keyBuffer) keyBuffer = (char*) malloc(hIdxInfo->compLength);
64 void *keyPtr = NULL;
65 char *keyBufferIter = keyBuffer;
66 while(iter.hasElement())
68 FieldDef *def = iter.nextElement();
69 //keyPtr = (void*)predImpl->valPtrForIndexField(def->fldName_,hIdxInfo->isUnique);
70 //TODO::PRABA::the below opt should be done for hash also
71 keyPtr = (void*)predImpl->valPtrForIndexField(def->fldName_,false);
72 if (NULL == keyPtr) {
73 printError(ErrSysFatal, "Fatal: Should not come here");
74 continue;
76 AllDataType::copyVal(keyBufferIter, keyPtr, def->type_, def->length_);
77 keyBufferIter = keyBufferIter + def->length_;
79 int bucketNo = HashIndex::computeHashBucket(hIdxInfo->type,
80 keyBuffer, hIdxInfo->noOfBuckets, hIdxInfo->compLength);
81 Bucket *bucket = &(hIdxInfo->buckets[bucketNo]);
82 IndexNode *head = (IndexNode*) bucket->bucketList_;
83 if (!head)
85 bIter->setHead(head);
86 return OK;
88 printDebug(DM_HashIndex, "open:head for bucket %x is :%x", bucket, head);
89 bIter->setHead(head);
90 }else if (trieIndexScan == scanType_)
92 HashIndexInfo *indInfo = (HashIndexInfo*)info;
93 char hashValue[TRIE_MAX_LENGTH];
94 FieldIterator iter = indInfo->idxFldList.getIterator();
95 FieldDef *def = iter.nextElement();
96 void* keyPtr = (void*)predImpl->valPtrForIndexField(def->fldName_,false);
97 if (NULL == keyPtr) {
98 printError(ErrSysFatal, "Fatal: Should not come here");
100 TrieIndex::computeHashValues(indInfo->type, keyPtr, hashValue, indInfo->compLength);
101 TrieNode* start = (TrieNode*)indInfo->buckets;
102 if (NULL == start)
104 bIter->setHead(NULL);
105 return OK;
107 char **next = NULL;
108 int cnt = 0;
109 while(-1 != hashValue[cnt+1]) {
110 next = (char**)&(start->next_[hashValue[cnt]]);
111 if (! *next)
113 printError(ErrNotFound, "No trie node found \n");
114 return ErrNotFound;
116 //traverse till the end
117 start = (TrieNode*) *next;
118 cnt++;
120 void **ptr = (void**)&(start->head_[hashValue[cnt]]);
121 IndexNode *head = (IndexNode*) *ptr;
122 if (!head)
124 bIter->setHead(head);
125 return OK;
127 bIter->setHead(head);
129 }else if (treeIndexScan == scanType_)
131 HashIndexInfo *hIdxInfo = (HashIndexInfo*)info;
132 CINDEX *iptr = (CINDEX*) hIdxInfo->indexPtr;
133 TreeNode *fstNode=(TreeNode *)iptr->hashNodeChunk_;
134 if(fstNode!=NULL){
135 TreeNode *start = (TreeNode *)*((char**)((char*)fstNode + sizeof(TreeNode)));
136 tIter->set(start,(TreeNode*)iptr->hashNodeChunk_,procSlot);
137 }else{
138 tIter->set(NULL,(TreeNode*)iptr->hashNodeChunk_,procSlot);
140 if (hIdxInfo->isUnique) tIter->setUnique();
142 isClosed = false;
143 return OK;
146 //not returing previous tuple for all iterators and for tree iterator.
147 //it just decrements the nodeOffset for tree iterator.
148 void* TupleIterator::prev()
150 PredicateImpl *predImpl = (PredicateImpl*) pred_;
151 void *tuple = NULL;
152 if (treeIndexScan == scanType_)
154 if (NULL == tIter) return NULL;
155 tuple = tIter->prev();
156 predImpl->setTuple(tuple);
157 if(NULL == tuple) {
158 printDebug(DM_HashIndex, "prev::tuple is null");
160 //TODO::evaluate as it is done in next() before returning
162 return tuple;
165 void* TupleIterator::next()
167 PredicateImpl *predImpl = (PredicateImpl*) pred_;
168 void *tuple = NULL;
169 DbRetVal rv = OK;
170 if (fullTableScan == scanType_)
172 if (NULL == pred_)
174 //no predicates
175 return cIter->nextElement();
177 else
179 int offset=0;
180 bool isLargeSizeAllocator = cIter->isLargeSize();
181 void *val = predImpl->getValIfPointLookupOnInt(offset);
182 char *tup = NULL;
183 if (val != NULL) {
184 int value = *(int*)val;
185 if (isLargeSizeAllocator) {
186 while (true)
188 tup = (char*)cIter->nextElement();
189 if(NULL == tup) return NULL;
190 if (value == *((int*)(tup+offset))) break;
192 return tup;
193 }else {
194 tup = (char*)cIter->nextElementIntMatch(value, offset);
195 return tup;
198 val = predImpl->getVal1IfBetweenOnInt(offset);
199 if (val != NULL) {
200 void *val2 = predImpl->getVal2IfBetweenOnInt(offset);
201 int value1 = *(int*)val;
202 int value2 = *(int*)val2;
203 while (true)
205 if(isLargeSizeAllocator)
206 tup = (char*)cIter->nextElement();
207 else
208 tup = (char*)cIter->nextElementInt();
209 if(NULL == tup) return NULL;
210 if (*((int*)(tup+offset)) >= value1 &&
211 *((int*)(tup+offset)) <= value2) break;
213 return tup;
216 //evaluate till it succeeds
217 bool result = false;
218 while (!result)
220 if(isLargeSizeAllocator)
221 tuple = cIter->nextElement();
222 else
223 tuple = cIter->nextElementInt();
224 if(NULL == tuple) return NULL;
225 //predImpl->setTuple(tuple);
226 printDebug(DM_Table, "Evaluating the predicate from fullTableScan");
227 predImpl->evaluateForTable(result, (char*)tuple);
230 }else if (hashIndexScan == scanType_ || trieIndexScan == scanType_)
232 //evaluate till it succeeds
233 bool result = false;
234 while (!result)
236 IndexNode *node = bIter->next();
237 if (node == NULL) return NULL;
238 printDebug(DM_HashIndex, "next: returned IndexNode: %x", node);
239 tuple = node->ptrToTuple_;
240 if(NULL == tuple) {
241 printDebug(DM_HashIndex, "next::tuple is null");
242 return NULL;
245 //if (!predImpl->isSingleTerm()) {
246 printDebug(DM_HashIndex, "next: predicate has more than single term");
247 //predImpl->setTuple(tuple);
248 printDebug(DM_Table, "Evaluating the predicate from hashIndexScan: has more than one term");
249 predImpl->evaluateForTable(result, (char*)tuple);
250 //}
251 //else
252 // return tuple;
255 }else if (treeIndexScan == scanType_)
257 if (NULL == tIter) return NULL;
258 bool result = false;
259 while (!result)
261 tuple = tIter->next();
262 if(NULL == tuple) {
263 printDebug(DM_HashIndex, "next::tuple is null");
264 return NULL;
266 //predImpl->setTuple(tuple);
267 predImpl->evaluateForTable(result, (char*)tuple);
268 if(!result && (isBetween || isPointLook)) tIter->nextNode();
271 return tuple;
274 DbRetVal TupleIterator::close()
276 if (isClosed) return OK;
277 reset();
278 isClosed = true;
279 return OK;
282 void TupleIterator::reset()
284 DbRetVal rv = OK;
285 if (scanType_ == fullTableScan) {
286 if (cIter) *cIter = ((Chunk*)chunkPtr_)->getIterator();
288 else if (scanType_ == hashIndexScan) {
289 if(bIter) bIter->reset();
291 else if (scanType_ == treeIndexScan) { if(tIter) tIter->reset(); }