1
/* Copyright (C) 2003 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
#define DBTUX_SEARCH_CPP
20
* Search for entry to add.
22
* Similar to searchToRemove (see below).
25
Dbtux::searchToAdd(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos)
27
const TreeHead& tree = frag.m_tree;
28
const unsigned numAttrs = frag.m_numAttrs;
29
NodeHandle currNode(frag);
30
currNode.m_loc = tree.m_root;
31
if (currNode.m_loc == NullTupLoc) {
36
NodeHandle glbNode(frag); // potential g.l.b of final node
38
* In order to not (yet) change old behaviour, a position between
39
* 2 nodes returns the one at the bottom of the tree.
41
NodeHandle bottomNode(frag);
44
selectNode(currNode, currNode.m_loc);
48
ret = cmpSearchKey(frag, start, searchKey, currNode.getPref(), tree.m_prefSize);
49
if (ret == NdbSqlUtil::CmpUnknown) {
51
// read and compare remaining attributes
52
ndbrequire(start < numAttrs);
53
readKeyAttrs(frag, currNode.getMinMax(0), start, c_entryKey);
54
ret = cmpSearchKey(frag, start, searchKey, c_entryKey);
55
ndbrequire(ret != NdbSqlUtil::CmpUnknown);
59
// keys are equal, compare entry values
60
ret = searchEnt.cmp(currNode.getMinMax(0));
64
const TupLoc loc = currNode.getLink(0);
65
if (loc != NullTupLoc) {
67
// continue to left subtree
71
if (! glbNode.isNull()) {
73
// move up to the g.l.b but remember the bottom node
74
bottomNode = currNode;
79
const TupLoc loc = currNode.getLink(1);
80
if (loc != NullTupLoc) {
82
// save potential g.l.b
84
// continue to right subtree
90
treePos.m_loc = currNode.m_loc;
92
// entry found - error
98
treePos.m_loc = currNode.m_loc;
101
int hi = currNode.getOccup();
105
// hi - lo > 1 implies lo < j < hi
106
int j = (hi + lo) / 2;
107
// read and compare attributes
109
readKeyAttrs(frag, currNode.getEnt(j), start, c_entryKey);
110
ret = cmpSearchKey(frag, start, searchKey, c_entryKey);
111
ndbrequire(ret != NdbSqlUtil::CmpUnknown);
114
// keys are equal, compare entry values
115
ret = searchEnt.cmp(currNode.getEnt(j));
123
// entry found - error
134
if ((uint) hi < currNode.getOccup()) {
139
if (bottomNode.isNull()) {
145
// backwards compatible for now
146
treePos.m_loc = bottomNode.m_loc;
152
* Search for entry to remove.
154
* Compares search key to each node min. A move to right subtree can
155
* overshoot target node. The last such node is saved. The final node
156
* is a semi-leaf or leaf. If search key is less than final node min
157
* then the saved node is the g.l.b of the final node and we move back
161
Dbtux::searchToRemove(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos)
163
const TreeHead& tree = frag.m_tree;
164
const unsigned numAttrs = frag.m_numAttrs;
165
NodeHandle currNode(frag);
166
currNode.m_loc = tree.m_root;
167
if (currNode.m_loc == NullTupLoc) {
168
// empty tree - failed
172
NodeHandle glbNode(frag); // potential g.l.b of final node
175
selectNode(currNode, currNode.m_loc);
179
ret = cmpSearchKey(frag, start, searchKey, currNode.getPref(), tree.m_prefSize);
180
if (ret == NdbSqlUtil::CmpUnknown) {
182
// read and compare remaining attributes
183
ndbrequire(start < numAttrs);
184
readKeyAttrs(frag, currNode.getMinMax(0), start, c_entryKey);
185
ret = cmpSearchKey(frag, start, searchKey, c_entryKey);
186
ndbrequire(ret != NdbSqlUtil::CmpUnknown);
190
// keys are equal, compare entry values
191
ret = searchEnt.cmp(currNode.getMinMax(0));
195
const TupLoc loc = currNode.getLink(0);
196
if (loc != NullTupLoc) {
198
// continue to left subtree
199
currNode.m_loc = loc;
202
if (! glbNode.isNull()) {
204
// move up to the g.l.b
207
} else if (ret > 0) {
209
const TupLoc loc = currNode.getLink(1);
210
if (loc != NullTupLoc) {
212
// save potential g.l.b
214
// continue to right subtree
215
currNode.m_loc = loc;
220
treePos.m_loc = currNode.m_loc;
227
treePos.m_loc = currNode.m_loc;
228
// pos 0 was handled above
229
for (unsigned j = 1, occup = currNode.getOccup(); j < occup; j++) {
231
// compare only the entry
232
if (searchEnt.eq(currNode.getEnt(j))) {
238
treePos.m_pos = currNode.getOccup();
239
// not found - failed
244
* Search for scan start position.
246
* Similar to searchToAdd. The routines differ somewhat depending on
247
* scan direction and are done by separate methods.
250
Dbtux::searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, bool descending, TreePos& treePos)
252
const TreeHead& tree = frag.m_tree;
253
if (tree.m_root != NullTupLoc) {
255
searchToScanAscending(frag, boundInfo, boundCount, treePos);
257
searchToScanDescending(frag, boundInfo, boundCount, treePos);
264
Dbtux::searchToScanAscending(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos)
266
const TreeHead& tree = frag.m_tree;
267
NodeHandle currNode(frag);
268
currNode.m_loc = tree.m_root;
269
NodeHandle glbNode(frag); // potential g.l.b of final node
270
NodeHandle bottomNode(frag);
273
selectNode(currNode, currNode.m_loc);
276
ret = cmpScanBound(frag, 0, boundInfo, boundCount, currNode.getPref(), tree.m_prefSize);
277
if (ret == NdbSqlUtil::CmpUnknown) {
279
// read and compare all attributes
280
readKeyAttrs(frag, currNode.getMinMax(0), 0, c_entryKey);
281
ret = cmpScanBound(frag, 0, boundInfo, boundCount, c_entryKey);
282
ndbrequire(ret != NdbSqlUtil::CmpUnknown);
285
// bound is left of this node
287
const TupLoc loc = currNode.getLink(0);
288
if (loc != NullTupLoc) {
290
// continue to left subtree
291
currNode.m_loc = loc;
294
if (! glbNode.isNull()) {
296
// move up to the g.l.b but remember the bottom node
297
bottomNode = currNode;
300
// start scanning this node
301
treePos.m_loc = currNode.m_loc;
307
// bound is at or right of this node
309
const TupLoc loc = currNode.getLink(1);
310
if (loc != NullTupLoc) {
312
// save potential g.l.b
314
// continue to right subtree
315
currNode.m_loc = loc;
321
for (unsigned j = 0, occup = currNode.getOccup(); j < occup; j++) {
324
// read and compare attributes
325
readKeyAttrs(frag, currNode.getEnt(j), 0, c_entryKey);
326
ret = cmpScanBound(frag, 0, boundInfo, boundCount, c_entryKey);
327
ndbrequire(ret != NdbSqlUtil::CmpUnknown);
329
// found first entry satisfying the bound
330
treePos.m_loc = currNode.m_loc;
336
// bound is to right of this node
337
if (! bottomNode.isNull()) {
339
// start scanning the l.u.b
340
treePos.m_loc = bottomNode.m_loc;
345
// start scanning upwards (pretend we came from right child)
346
treePos.m_loc = currNode.m_loc;
351
Dbtux::searchToScanDescending(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos)
353
const TreeHead& tree = frag.m_tree;
354
NodeHandle currNode(frag);
355
currNode.m_loc = tree.m_root;
356
NodeHandle glbNode(frag); // potential g.l.b of final node
357
NodeHandle bottomNode(frag);
360
selectNode(currNode, currNode.m_loc);
363
ret = cmpScanBound(frag, 1, boundInfo, boundCount, currNode.getPref(), tree.m_prefSize);
364
if (ret == NdbSqlUtil::CmpUnknown) {
366
// read and compare all attributes
367
readKeyAttrs(frag, currNode.getMinMax(0), 0, c_entryKey);
368
ret = cmpScanBound(frag, 1, boundInfo, boundCount, c_entryKey);
369
ndbrequire(ret != NdbSqlUtil::CmpUnknown);
372
// bound is left of this node
374
const TupLoc loc = currNode.getLink(0);
375
if (loc != NullTupLoc) {
377
// continue to left subtree
378
currNode.m_loc = loc;
381
if (! glbNode.isNull()) {
383
// move up to the g.l.b but remember the bottom node
384
bottomNode = currNode;
391
// bound is at or right of this node
393
const TupLoc loc = currNode.getLink(1);
394
if (loc != NullTupLoc) {
396
// save potential g.l.b
398
// continue to right subtree
399
currNode.m_loc = loc;
405
for (unsigned j = 0, occup = currNode.getOccup(); j < occup; j++) {
408
// read and compare attributes
409
readKeyAttrs(frag, currNode.getEnt(j), 0, c_entryKey);
410
ret = cmpScanBound(frag, 1, boundInfo, boundCount, c_entryKey);
411
ndbrequire(ret != NdbSqlUtil::CmpUnknown);
414
// start scanning from previous entry
415
treePos.m_loc = currNode.m_loc;
416
treePos.m_pos = j - 1;
420
// start scanning upwards (pretend we came from left child)
421
treePos.m_loc = currNode.m_loc;
427
// start scanning this node
428
treePos.m_loc = currNode.m_loc;
429
treePos.m_pos = currNode.getOccup() - 1;