Merge branch 'master' into 2.3beta-2.5beta
[csql/przemoc.git] / src / storage / TupleIterator.cxx
blobbd139ee8329200627d77d354d145b209bb9b71ab
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::open()
25 PredicateImpl *predImpl = (PredicateImpl*) pred_;
26 if (fullTableScan == scanType_)
28 cIter = new ChunkIterator();
29 *cIter = ((Chunk*)chunkPtr_)->getIterator();
30 }else if (hashIndexScan == scanType_)
32 HashIndexInfo *hIdxInfo = (HashIndexInfo*)info;
33 bool isPtr = false;
34 FieldIterator iter = hIdxInfo->idxFldList.getIterator();
35 char *keyBuffer;
36 int offset = hIdxInfo->fldOffset;
37 keyBuffer = (char*) malloc(hIdxInfo->compLength);
38 void *keyStartBuffer = (void*) keyBuffer, *keyPtr;
39 while(iter.hasElement())
41 FieldDef *def = iter.nextElement();
42 keyPtr = (void*)predImpl->valPtrForIndexField(def->fldName_);
43 AllDataType::copyVal(keyBuffer, keyPtr, def->type_, def->length_);
44 keyBuffer = keyBuffer + def->length_;
46 int bucketNo = 0;
47 if (hIdxInfo->type == typeComposite)
48 bucketNo = HashIndex::computeHashBucket(hIdxInfo->type,
49 (char *)keyStartBuffer, hIdxInfo->noOfBuckets, hIdxInfo->compLength);
50 else bucketNo = HashIndex::computeHashBucket(hIdxInfo->type,
51 keyStartBuffer, hIdxInfo->noOfBuckets, hIdxInfo->compLength);
52 free(keyStartBuffer);
53 Bucket *bucket = &(hIdxInfo->buckets[bucketNo]);
54 int ret = bucket->mutex_.getLock(procSlot);
55 if (ret != 0)
57 printError(ErrLockTimeOut,"Unable to acquire bucket Mutex for bucket %d",bucketNo);
58 return ErrLockTimeOut;
60 HashIndexNode *head = (HashIndexNode*) bucket->bucketList_;
61 if (!head)
63 bucket->mutex_.releaseLock(procSlot);
64 bIter = NULL ;
65 return OK;
67 printDebug(DM_HashIndex, "open:head for bucket %x is :%x", bucket, head);
68 bIter = new BucketIter(head);
69 bucket->mutex_.releaseLock(procSlot);
70 }else if (treeIndexScan == scanType_)
72 HashIndexInfo *hIdxInfo = (HashIndexInfo*)info;
73 bool isPtr = false;
74 FieldIterator iter = hIdxInfo->idxFldList.getIterator();
75 void *keyPtr; ComparisionOp op;
76 if(iter.hasElement())
78 FieldDef *def = iter.nextElement();
79 keyPtr = (void*)predImpl->valPtrForIndexField(def->fldName_);
80 op = predImpl->opForIndexField(def->fldName_);
81 //TODO::remove this predicate term as it is pushed to tree iter
83 CINDEX *iptr = (CINDEX*) hIdxInfo->indexPtr;
84 tIter = new TreeIter((TreeNode*)iptr->hashNodeChunk_);
85 tIter->setSearchKey(keyPtr, op);
86 tIter->setFldOffset(hIdxInfo->fldOffset);
87 tIter->setTypeLength(hIdxInfo->type, hIdxInfo->compLength);
89 if(predImpl) predImpl->setIfNoLeftRight();
90 return OK;
93 //not returing previous tuple for all iterators and for tree iterator.
94 //it just decrements the nodeOffset for tree iterator.
95 void* TupleIterator::prev()
97 PredicateImpl *predImpl = (PredicateImpl*) pred_;
98 void *tuple = NULL;
99 if (treeIndexScan == scanType_)
101 if (NULL == tIter) return NULL;
102 tuple = tIter->prev();
103 predImpl->setTuple(tuple);
104 if(NULL == tuple) {
105 printDebug(DM_HashIndex, "prev::tuple is null");
107 //TODO::evaluate as it is done in next() before returning
109 return tuple;
112 void* TupleIterator::next()
114 PredicateImpl *predImpl = (PredicateImpl*) pred_;
115 void *tuple = NULL;
116 DbRetVal rv = OK;
117 if (fullTableScan == scanType_)
120 if (NULL == pred_)
122 //no predicates
123 return cIter->nextElement();
125 else
127 int offset=0;
128 void *val = predImpl->getValIfPointLookupOnInt(offset);
129 char *tup = NULL;
130 if (val != NULL) {
131 while (true)
133 tup = (char*)cIter->nextElement();
134 if(NULL == tup) return NULL;
135 if (*(int*)val == *((int*)(tup+offset))) break;
137 return tup;
139 val = predImpl->getVal1IfBetweenOnInt(offset);
140 if (val != NULL) {
141 void *val2 = predImpl->getVal2IfBetweenOnInt(offset);
142 while (true)
144 tup = (char*)cIter->nextElement();
145 if(NULL == tup) return NULL;
146 if (*((int*)(tup+offset)) >= *(int*)val &&
147 *((int*)(tup+offset)) <= *(int*)val2) break;
149 return tup;
152 //evaluate till it succeeds
153 bool result = false;
154 while (!result)
156 tuple = cIter->nextElement();
157 if(NULL == tuple) return NULL;
158 //predImpl->setTuple(tuple);
159 printDebug(DM_Table, "Evaluating the predicate from fullTableScan");
160 predImpl->evaluateForTable(result, (char*)tuple);
163 }else if (hashIndexScan == scanType_)
165 if (NULL == bIter)
167 //if there are no nodes in bucket bIter will be null
168 return NULL;
170 //evaluate till it succeeds
171 bool result = false;
172 while (!result)
174 HashIndexNode *node = bIter->next();
175 if (node == NULL) return NULL;
176 printDebug(DM_HashIndex, "next: returned HashIndexNode: %x", node);
177 tuple = node->ptrToTuple_;
178 if(NULL == tuple) {
179 printDebug(DM_HashIndex, "next::tuple is null");
180 return NULL;
183 //if (!predImpl->isSingleTerm()) {
184 printDebug(DM_HashIndex, "next: predicate has more than single term");
185 //predImpl->setTuple(tuple);
186 printDebug(DM_Table, "Evaluating the predicate from hashIndexScan: has more than one term");
187 predImpl->evaluateForTable(result, (char*)tuple);
188 //}
189 //else
190 // return tuple;
193 }else if (treeIndexScan == scanType_)
195 if (NULL == tIter) return NULL;
196 bool result = false;
197 while (!result)
199 tuple = tIter->next();
200 if(NULL == tuple) {
201 printDebug(DM_HashIndex, "next::tuple is null");
202 return NULL;
204 //predImpl->setTuple(tuple);
205 predImpl->evaluateForTable(result, (char*)tuple);
206 if(!result && (isBetInvolved() || isPointLookInvolved())) tIter->nextNode();
209 return tuple;
212 DbRetVal TupleIterator::close()
214 if (scanType_ == fullTableScan)
216 delete cIter;
217 cIter = NULL;
218 } else if (scanType_ == hashIndexScan)
220 delete bIter;
221 bIter = NULL;
222 } else if (scanType_ == treeIndexScan)
224 delete tIter;
225 tIter = NULL;
228 scanType_ = unknownScan;
229 return OK;
232 void TupleIterator::reset()
234 DbRetVal rv = OK;
235 if (scanType_ == fullTableScan) *cIter = ((Chunk*)chunkPtr_)->getIterator();
236 else if (scanType_ == hashIndexScan) if(bIter) bIter->reset();
237 else if (scanType_ == treeIndexScan) if(tIter) tIter->reset();