#At file:///home/anurag/mysqlsrc/mysql-5.1-bugteam/ based on revid:patrick.crews@stripped
2768 Anurag Shekhar 2009-02-04
Bug#30590 delete from memory table with composite btree primary key
While evaluating self join with delete server uses two instance of handler
(with both holding reference to same file). During query evaluation last_pos
is cached in handler to improve search performance. But in the mean while
second handler is used to delete the node last_pos is holding. This makes
the last_pos an invalid and when accessed results in segmentation fault.
To fix this I have introduced a new variable in HP_INFO structure (deleted)
which remembers the number of deleted (initialized while opening the file)
nodes since last_pos is updated. If this value differs from the value of
deleted nodes in shared structure last_pos is invalidated (set to zero).
modified:
include/heap.h
mysql-test/r/heap_btree.result
mysql-test/t/heap_btree.test
storage/heap/hp_open.c
storage/heap/hp_rnext.c
per-file messages:
include/heap.h
Added new field in HP_INFO to remember number of deleted nodes since last_pos was last updated.
mysql-test/r/heap_btree.result
Updated result for newly introduced test.
mysql-test/t/heap_btree.test
Added new case to test self join with delete.
storage/heap/hp_open.c
Initializes HP_INFO's deleted field to shared->deleted (value while opening the file)
storage/heap/hp_rnext.c
Introduced new test to check if any more node has been deleted since last_pos was updated. If it has then invalidate last_pos (by setting it to zero).
=== modified file 'include/heap.h'
--- a/include/heap.h 2007-07-24 22:58:12 +0000
+++ b/include/heap.h 2009-02-04 08:28:11 +0000
@@ -179,6 +179,9 @@ typedef struct st_heap_info
THR_LOCK_DATA lock;
#endif
LIST open_list;
+ int deleted; /* Record number of deleted keys in tree
+ If this value isn't same as s->deleted
+ last_pos should be reinitialized */
} HP_INFO;
=== modified file 'mysql-test/r/heap_btree.result'
--- a/mysql-test/r/heap_btree.result 2007-10-19 20:12:14 +0000
+++ b/mysql-test/r/heap_btree.result 2009-02-04 08:28:11 +0000
@@ -337,3 +337,7 @@ NULL NULL
NULL 1
drop table t1;
End of 5.0 tests
+CREATE TABLE t1(a INT, KEY USING BTREE (a)) ENGINE=MEMORY;
+INSERT INTO t1 VALUES(1),(1);
+DELETE a1 FROM t1 AS a1, t1 AS a2 WHERE a1.a=a2.a;
+DROP TABLE t1;
=== modified file 'mysql-test/t/heap_btree.test'
--- a/mysql-test/t/heap_btree.test 2007-10-19 20:12:14 +0000
+++ b/mysql-test/t/heap_btree.test 2009-02-04 08:28:11 +0000
@@ -255,3 +255,11 @@ drop table t1;
--echo End of 5.0 tests
+#
+# bug#39918 - memory (heap) engine crashing while executing self join with delete
+#
+
+CREATE TABLE t1(a INT, KEY USING BTREE (a)) ENGINE=MEMORY;
+INSERT INTO t1 VALUES(1),(1);
+DELETE a1 FROM t1 AS a1, t1 AS a2 WHERE a1.a=a2.a;
+DROP TABLE t1;
=== modified file 'storage/heap/hp_open.c'
--- a/storage/heap/hp_open.c 2007-07-24 22:58:12 +0000
+++ b/storage/heap/hp_open.c 2009-02-04 08:28:11 +0000
@@ -106,6 +106,10 @@ HP_INFO *heap_open(const char *name, int
info->open_list.data= (void*) info;
heap_open_list= list_add(heap_open_list,&info->open_list);
}
+ /*
+ Remember the number of deleted records while opening the file.
+ */
+ info->deleted= share->deleted;
pthread_mutex_unlock(&THR_LOCK_heap);
DBUG_RETURN(info);
}
=== modified file 'storage/heap/hp_rnext.c'
--- a/storage/heap/hp_rnext.c 2007-09-13 12:12:46 +0000
+++ b/storage/heap/hp_rnext.c 2009-02-04 08:28:11 +0000
@@ -32,6 +32,17 @@ int heap_rnext(HP_INFO *info, uchar *rec
{
heap_rb_param custom_arg;
+ /*
+ Check if any key is deleted in tree since last_pos was
+ updated. If it has then last_pos might be holding a invalid
+ address. Invalidate last_pos and remember the current count
+ of deleted keys.
+ */
+ if (info->deleted != share->deleted)
+ {
+ info->last_pos= 0;
+ info->deleted= share->deleted;
+ }
if (info->last_pos)
{
/*
Thread |
---|
• bzr commit into mysql-5.1-bugteam branch (anurag.shekhar:2768)Bug#30590 | Anurag Shekhar | 4 Feb |