summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <pappa@c-5608e253.1238-1-64736c10.cust.bredbandsbolaget.se>2005-11-08 00:26:37 -0500
committerunknown <pappa@c-5608e253.1238-1-64736c10.cust.bredbandsbolaget.se>2005-11-08 00:26:37 -0500
commitbba73a091031e9c324fedd6ad1bb26bcd4e635f9 (patch)
treec9d5aa727d72266be0ab83ff53f139f4209b6e51
parent0e878d7e541983757bc0b31e7caa8a16a5fd2896 (diff)
downloadmariadb-git-bba73a091031e9c324fedd6ad1bb26bcd4e635f9.tar.gz
Bug #12796: Record lost in HEAP table
Two handler objects were present, one was used for an insert and the other for a select The state of the statistics was local to the handler object and thus the other handler object didn't notice the insert. Fix included: 1) Add a new variable key_stat_version added to whenever statistics was considered in need of update (previously key_stats_ok= FALSE in those places) 2) Add a new handler variable key_stat_version assigned whenever key_stats_ok= TRUE was set previously 3) Fix records_in_range to return records if records <= 1 4) Fix records_in_range to add 2 to rec_per_key to ensure we don't specify 0 or 1 when it isn't and thus invoking incorrect optimisations. 5) Fix unique key handling for HEAP table in records_in_range
-rw-r--r--heap/hp_create.c1
-rw-r--r--include/heap.h1
-rw-r--r--mysql-test/r/heap.result12
-rw-r--r--mysql-test/t/heap.test11
-rw-r--r--mysql-test/t/test_heap.test20
-rw-r--r--sql/ha_heap.cc38
-rw-r--r--sql/ha_heap.h4
7 files changed, 71 insertions, 16 deletions
diff --git a/heap/hp_create.c b/heap/hp_create.c
index 2b811dac89b..acd4447fe5c 100644
--- a/heap/hp_create.c
+++ b/heap/hp_create.c
@@ -104,6 +104,7 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
DBUG_RETURN(1);
}
share->keydef= (HP_KEYDEF*) (share + 1);
+ share->key_stat_version= 1;
keyseg= (HA_KEYSEG*) (share->keydef + keys);
init_block(&share->block, reclength + 1, min_records, max_records);
/* Fix keys */
diff --git a/include/heap.h b/include/heap.h
index badec9ce2ef..cfbb6113f86 100644
--- a/include/heap.h
+++ b/include/heap.h
@@ -136,6 +136,7 @@ typedef struct st_heap_share
HP_KEYDEF *keydef;
ulong min_records,max_records; /* Params to open */
ulong data_length,index_length,max_table_size;
+ uint key_stat_version; /* version to indicate insert/delete */
uint records; /* records */
uint blength; /* records rounded up to 2^n */
uint deleted; /* Deleted records in database */
diff --git a/mysql-test/r/heap.result b/mysql-test/r/heap.result
index 53dec294ef8..e3b9f7db984 100644
--- a/mysql-test/r/heap.result
+++ b/mysql-test/r/heap.result
@@ -182,7 +182,7 @@ SELECT * FROM t1 WHERE a=NULL;
a b
explain SELECT * FROM t1 WHERE a IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a a 5 const 1 Using where
+1 SIMPLE t1 ref a a 5 const 2 Using where
SELECT * FROM t1 WHERE a<=>NULL;
a b
NULL 99
@@ -296,3 +296,13 @@ insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd
insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
ERROR 23000: Duplicate entry 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl' for key 1
drop table t1;
+CREATE TABLE t1 (a int, key(a)) engine=heap;
+insert delayed into t1 values (0);
+delete from t1;
+select * from t1;
+a
+insert delayed into t1 values (0), (1);
+select * from t1 where a = 0;
+a
+0
+drop table t1;
diff --git a/mysql-test/t/heap.test b/mysql-test/t/heap.test
index 270b8a1df6f..a8128b79e3b 100644
--- a/mysql-test/t/heap.test
+++ b/mysql-test/t/heap.test
@@ -234,4 +234,15 @@ insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd
insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
drop table t1;
+#
+# Bug 12796: Record doesn't show when selecting through index
+#
+CREATE TABLE t1 (a int, key(a)) engine=heap;
+insert delayed into t1 values (0);
+delete from t1;
+select * from t1;
+insert delayed into t1 values (0), (1);
+select * from t1 where a = 0;
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/test_heap.test b/mysql-test/t/test_heap.test
new file mode 100644
index 00000000000..851c376ba38
--- /dev/null
+++ b/mysql-test/t/test_heap.test
@@ -0,0 +1,20 @@
+#
+# Test of heap tables.
+#
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+#
+# Bug 12796: Record doesn't show when selecting through index
+#
+CREATE TABLE t1 (a int, key(a)) engine=heap;
+insert delayed into t1 values (0);
+delete from t1;
+select * from t1;
+insert delayed into t1 values (0), (1);
+select * from t1 where a = 0;
+drop table t1;
+
+# End of 4.1 tests
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index f8c2e6cc338..61e5ce89693 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -68,7 +68,7 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked)
ha_heap::info(), which is always called before key statistics are
used.
*/
- key_stats_ok= FALSE;
+ key_stat_version= file->s->key_stat_version-1;
}
return (file ? 0 : 1);
}
@@ -114,14 +114,21 @@ void ha_heap::update_key_stats()
continue;
if (key->algorithm != HA_KEY_ALG_BTREE)
{
- ha_rows hash_buckets= file->s->keydef[i].hash_buckets;
- key->rec_per_key[key->key_parts-1]=
- hash_buckets ? file->s->records/hash_buckets : 0;
+ if (key->flags & HA_NOSAME)
+ key->rec_per_key[key->key_parts-1]= 1;
+ else
+ {
+ ha_rows hash_buckets= file->s->keydef[i].hash_buckets;
+ uint no_records= hash_buckets ? file->s->records/hash_buckets : 2;
+ if (no_records < 2)
+ no_records= 2;
+ key->rec_per_key[key->key_parts-1]= no_records;
+ }
}
}
records_changed= 0;
/* At the end of update_key_stats() we can proudly claim they are OK. */
- key_stats_ok= TRUE;
+ key_stat_version= file->s->key_stat_version;
}
int ha_heap::write_row(byte * buf)
@@ -135,7 +142,7 @@ int ha_heap::write_row(byte * buf)
res= heap_write(file,buf);
if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
file->s->records)
- key_stats_ok= FALSE;
+ file->s->key_stat_version++;
return res;
}
@@ -148,7 +155,7 @@ int ha_heap::update_row(const byte * old_data, byte * new_data)
res= heap_update(file,old_data,new_data);
if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
file->s->records)
- key_stats_ok= FALSE;
+ file->s->key_stat_version++;
return res;
}
@@ -159,7 +166,7 @@ int ha_heap::delete_row(const byte * buf)
res= heap_delete(file,buf);
if (!res && table->tmp_table == NO_TMP_TABLE &&
++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records)
- key_stats_ok= FALSE;
+ file->s->key_stat_version++;
return res;
}
@@ -277,7 +284,7 @@ void ha_heap::info(uint flag)
have to update the key statistics. Hoping that a table lock is now
in place.
*/
- if (! key_stats_ok)
+ if (key_stat_version != file->s->key_stat_version)
update_key_stats();
}
@@ -290,7 +297,7 @@ int ha_heap::delete_all_rows()
{
heap_clear(file);
if (table->tmp_table == NO_TMP_TABLE)
- key_stats_ok= FALSE;
+ file->s->key_stat_version++;
return 0;
}
@@ -451,9 +458,14 @@ ha_rows ha_heap::records_in_range(uint inx, key_range *min_key,
return HA_POS_ERROR; // Can only use exact keys
else
{
- /* Assert that info() did run. We need current statistics here. */
- DBUG_ASSERT(key_stats_ok);
- return key->rec_per_key[key->key_parts-1];
+ if (records <= 1)
+ return records;
+ else
+ {
+ /* Assert that info() did run. We need current statistics here. */
+ DBUG_ASSERT(key_stat_version == file->s->key_stat_version);
+ return key->rec_per_key[key->key_parts-1];
+ }
}
}
diff --git a/sql/ha_heap.h b/sql/ha_heap.h
index cbe2474492d..0a087fde1b0 100644
--- a/sql/ha_heap.h
+++ b/sql/ha_heap.h
@@ -29,10 +29,10 @@ class ha_heap: public handler
key_map btree_keys;
/* number of records changed since last statistics update */
uint records_changed;
- bool key_stats_ok;
+ uint key_stat_version;
public:
ha_heap(TABLE *table): handler(table), file(0), records_changed(0),
- key_stats_ok(0) {}
+ key_stat_version(0) {}
~ha_heap() {}
const char *table_type() const { return "HEAP"; }
const char *index_type(uint inx)