summaryrefslogtreecommitdiff
path: root/storage/heap
diff options
context:
space:
mode:
authorunknown <istruewing@stella.local>2007-09-14 11:40:03 +0200
committerunknown <istruewing@stella.local>2007-09-14 11:40:03 +0200
commit967393a0ba81fd63ea78579467308c71ba65aa1b (patch)
tree00d54aa84c061e5f3e359a420344453a343b8dc2 /storage/heap
parent9e13249a38bd63a6cc6926aaeb51a4561f4ee096 (diff)
parent602c7c8a14f0bb8af8a66e5515ee68625146e1ba (diff)
downloadmariadb-git-967393a0ba81fd63ea78579467308c71ba65aa1b.tar.gz
Merge stella.local:/home/mydev/mysql-5.1-ateam
into stella.local:/home/mydev/mysql-5.1-axmrg
Diffstat (limited to 'storage/heap')
-rw-r--r--storage/heap/hp_delete.c3
-rw-r--r--storage/heap/hp_rfirst.c11
-rw-r--r--storage/heap/hp_rnext.c29
3 files changed, 40 insertions, 3 deletions
diff --git a/storage/heap/hp_delete.c b/storage/heap/hp_delete.c
index 1dd79a42e0b..9e9e28da335 100644
--- a/storage/heap/hp_delete.c
+++ b/storage/heap/hp_delete.c
@@ -72,10 +72,7 @@ int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
int res;
if (flag)
- {
info->last_pos= NULL; /* For heap_rnext/heap_rprev */
- info->lastkey_len= 0;
- }
custom_arg.keyseg= keyinfo->seg;
custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
diff --git a/storage/heap/hp_rfirst.c b/storage/heap/hp_rfirst.c
index 48c1e625bd8..d0d2ec9b506 100644
--- a/storage/heap/hp_rfirst.c
+++ b/storage/heap/hp_rfirst.c
@@ -35,6 +35,17 @@ int heap_rfirst(HP_INFO *info, uchar *record, int inx)
sizeof(uchar*));
info->current_ptr = pos;
memcpy(record, pos, (size_t)share->reclength);
+ /*
+ If we're performing index_first on a table that was taken from
+ table cache, info->lastkey_len is initialized to previous query.
+ Thus we set info->lastkey_len to proper value for subsequent
+ heap_rnext() calls.
+ This is needed for DELETE queries only, otherwise this variable is
+ not used.
+ Note that the same workaround may be needed for heap_rlast(), but
+ for now heap_rlast() is never used for DELETE queries.
+ */
+ info->lastkey_len= 0;
info->update = HA_STATE_AKTIV;
}
else
diff --git a/storage/heap/hp_rnext.c b/storage/heap/hp_rnext.c
index 262754e9e64..3d715f4e6d3 100644
--- a/storage/heap/hp_rnext.c
+++ b/storage/heap/hp_rnext.c
@@ -33,11 +33,40 @@ int heap_rnext(HP_INFO *info, uchar *record)
heap_rb_param custom_arg;
if (info->last_pos)
+ {
+ /*
+ We enter this branch for non-DELETE queries after heap_rkey()
+ or heap_rfirst(). As last key position (info->last_pos) is available,
+ we only need to climb the tree using tree_search_next().
+ */
pos = tree_search_next(&keyinfo->rb_tree, &info->last_pos,
offsetof(TREE_ELEMENT, left),
offsetof(TREE_ELEMENT, right));
+ }
+ else if (!info->lastkey_len)
+ {
+ /*
+ We enter this branch only for DELETE queries after heap_rfirst(). E.g.
+ DELETE FROM t1 WHERE a<10. As last key position is not available
+ (last key is removed by heap_delete()), we must restart search as it
+ is done in heap_rfirst().
+
+ It should be safe to handle this situation without this branch. That is
+ branch below should find smallest element in a tree as lastkey_len is
+ zero. tree_search_edge() is a kind of optimisation here as it should be
+ faster than tree_search_key().
+ */
+ pos= tree_search_edge(&keyinfo->rb_tree, info->parents,
+ &info->last_pos, offsetof(TREE_ELEMENT, left));
+ }
else
{
+ /*
+ We enter this branch only for DELETE queries after heap_rkey(). E.g.
+ DELETE FROM t1 WHERE a=10. As last key position is not available
+ (last key is removed by heap_delete()), we must restart search as it
+ is done in heap_rkey().
+ */
custom_arg.keyseg = keyinfo->seg;
custom_arg.key_length = info->lastkey_len;
custom_arg.search_flag = SEARCH_SAME | SEARCH_FIND;