From f0f9ab69c7c75241ce0a28a33132e504c39f4a6d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 19 Nov 2010 12:17:57 +0100 Subject: [PATCH 01/27] Mbug#677407 / MySQL Bug#48883: Stale data from INNODB_LOCKS table. The logic for how to check when to update the table cache for INNODB_LOCKS with real data was flawed. This could result in both not updating the cache often enough (when the table is queried repeatedly with less than 100 milliseconds in-between) resulting in stale data; as well as updating too often (when multiple queries against the table start at around the same time). This caused occasional test failures in innodb_information_schema. Fix by updating the "last updated" timestamp in the right place, when the cache is updated, not when it is read. --- storage/innodb_plugin/trx/trx0i_s.c | 33 +++++++++-------------------- storage/xtradb/trx/trx0i_s.c | 33 +++++++++-------------------- 2 files changed, 20 insertions(+), 46 deletions(-) diff --git a/storage/innodb_plugin/trx/trx0i_s.c b/storage/innodb_plugin/trx/trx0i_s.c index 5bc8302d0c0..c0b9a73a68c 100644 --- a/storage/innodb_plugin/trx/trx0i_s.c +++ b/storage/innodb_plugin/trx/trx0i_s.c @@ -157,10 +157,6 @@ struct trx_i_s_cache_struct { ullint last_read; /*!< last time the cache was read; measured in microseconds since epoch */ - mutex_t last_read_mutex;/*!< mutex protecting the - last_read member - it is updated - inside a shared lock of the - rw_lock member */ i_s_table_cache_t innodb_trx; /*!< innodb_trx table */ i_s_table_cache_t innodb_locks; /*!< innodb_locks table */ i_s_table_cache_t innodb_lock_waits;/*!< innodb_lock_waits table */ @@ -1101,13 +1097,6 @@ can_cache_be_updated( { ullint now; - /* Here we read cache->last_read without acquiring its mutex - because last_read is only updated when a shared rw lock on the - whole cache is being held (see trx_i_s_cache_end_read()) and - we are currently holding an exclusive rw lock on the cache. - So it is not possible for last_read to be updated while we are - reading it. */ - #ifdef UNIV_SYNC_DEBUG ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_EX)); #endif @@ -1205,6 +1194,12 @@ trx_i_s_possibly_fetch_data_into_cache( /*===================================*/ trx_i_s_cache_t* cache) /*!< in/out: cache */ { + ullint now; + +#ifdef UNIV_SYNC_DEBUG + ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_EX)); +#endif + if (!can_cache_be_updated(cache)) { return(1); @@ -1217,6 +1212,10 @@ trx_i_s_possibly_fetch_data_into_cache( mutex_exit(&kernel_mutex); + /* update cache last read time */ + now = ut_time_us(NULL); + cache->last_read = now; + return(0); } @@ -1247,16 +1246,12 @@ trx_i_s_cache_init( release kernel_mutex release trx_i_s_cache_t::rw_lock acquire trx_i_s_cache_t::rw_lock, S - acquire trx_i_s_cache_t::last_read_mutex - release trx_i_s_cache_t::last_read_mutex release trx_i_s_cache_t::rw_lock */ rw_lock_create(&cache->rw_lock, SYNC_TRX_I_S_RWLOCK); cache->last_read = 0; - mutex_create(&cache->last_read_mutex, SYNC_TRX_I_S_LAST_READ); - table_cache_init(&cache->innodb_trx, sizeof(i_s_trx_row_t)); table_cache_init(&cache->innodb_locks, sizeof(i_s_locks_row_t)); table_cache_init(&cache->innodb_lock_waits, @@ -1307,18 +1302,10 @@ trx_i_s_cache_end_read( /*===================*/ trx_i_s_cache_t* cache) /*!< in: cache */ { - ullint now; - #ifdef UNIV_SYNC_DEBUG ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_SHARED)); #endif - /* update cache last read time */ - now = ut_time_us(NULL); - mutex_enter(&cache->last_read_mutex); - cache->last_read = now; - mutex_exit(&cache->last_read_mutex); - rw_lock_s_unlock(&cache->rw_lock); } diff --git a/storage/xtradb/trx/trx0i_s.c b/storage/xtradb/trx/trx0i_s.c index 5bc8302d0c0..c0b9a73a68c 100644 --- a/storage/xtradb/trx/trx0i_s.c +++ b/storage/xtradb/trx/trx0i_s.c @@ -157,10 +157,6 @@ struct trx_i_s_cache_struct { ullint last_read; /*!< last time the cache was read; measured in microseconds since epoch */ - mutex_t last_read_mutex;/*!< mutex protecting the - last_read member - it is updated - inside a shared lock of the - rw_lock member */ i_s_table_cache_t innodb_trx; /*!< innodb_trx table */ i_s_table_cache_t innodb_locks; /*!< innodb_locks table */ i_s_table_cache_t innodb_lock_waits;/*!< innodb_lock_waits table */ @@ -1101,13 +1097,6 @@ can_cache_be_updated( { ullint now; - /* Here we read cache->last_read without acquiring its mutex - because last_read is only updated when a shared rw lock on the - whole cache is being held (see trx_i_s_cache_end_read()) and - we are currently holding an exclusive rw lock on the cache. - So it is not possible for last_read to be updated while we are - reading it. */ - #ifdef UNIV_SYNC_DEBUG ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_EX)); #endif @@ -1205,6 +1194,12 @@ trx_i_s_possibly_fetch_data_into_cache( /*===================================*/ trx_i_s_cache_t* cache) /*!< in/out: cache */ { + ullint now; + +#ifdef UNIV_SYNC_DEBUG + ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_EX)); +#endif + if (!can_cache_be_updated(cache)) { return(1); @@ -1217,6 +1212,10 @@ trx_i_s_possibly_fetch_data_into_cache( mutex_exit(&kernel_mutex); + /* update cache last read time */ + now = ut_time_us(NULL); + cache->last_read = now; + return(0); } @@ -1247,16 +1246,12 @@ trx_i_s_cache_init( release kernel_mutex release trx_i_s_cache_t::rw_lock acquire trx_i_s_cache_t::rw_lock, S - acquire trx_i_s_cache_t::last_read_mutex - release trx_i_s_cache_t::last_read_mutex release trx_i_s_cache_t::rw_lock */ rw_lock_create(&cache->rw_lock, SYNC_TRX_I_S_RWLOCK); cache->last_read = 0; - mutex_create(&cache->last_read_mutex, SYNC_TRX_I_S_LAST_READ); - table_cache_init(&cache->innodb_trx, sizeof(i_s_trx_row_t)); table_cache_init(&cache->innodb_locks, sizeof(i_s_locks_row_t)); table_cache_init(&cache->innodb_lock_waits, @@ -1307,18 +1302,10 @@ trx_i_s_cache_end_read( /*===================*/ trx_i_s_cache_t* cache) /*!< in: cache */ { - ullint now; - #ifdef UNIV_SYNC_DEBUG ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_SHARED)); #endif - /* update cache last read time */ - now = ut_time_us(NULL); - mutex_enter(&cache->last_read_mutex); - cache->last_read = now; - mutex_exit(&cache->last_read_mutex); - rw_lock_s_unlock(&cache->rw_lock); } From adb9fd9578f61a73ae224ede3bcb7adef863c1e3 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Tue, 7 Dec 2010 14:48:04 -0800 Subject: [PATCH 02/27] Made sure that SELECT from the test case for bug BUG#56862/64041 uses the same execution plan that is in the output of the corresponding EXPLAIN. --- mysql-test/r/index_merge_innodb.result | 2 +- mysql-test/t/index_merge_innodb.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/index_merge_innodb.result b/mysql-test/r/index_merge_innodb.result index 4c561da6420..fdc5b57a2e3 100644 --- a/mysql-test/r/index_merge_innodb.result +++ b/mysql-test/r/index_merge_innodb.result @@ -692,7 +692,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away 2 DERIVED t1 index_merge PRIMARY,idx idx,PRIMARY 5,4 NULL 11419 Using sort_union(idx,PRIMARY); Using where SELECT COUNT(*) FROM -(SELECT * FROM t1 +(SELECT * FROM t1 FORCE INDEX(primary,idx) WHERE a BETWEEN 2 AND 7 OR pk=1000000) AS t; COUNT(*) 6145 diff --git a/mysql-test/t/index_merge_innodb.test b/mysql-test/t/index_merge_innodb.test index 7c6ffaace4f..04f8c5a659b 100644 --- a/mysql-test/t/index_merge_innodb.test +++ b/mysql-test/t/index_merge_innodb.test @@ -71,7 +71,7 @@ SELECT COUNT(*) FROM (SELECT * FROM t1 FORCE INDEX(primary,idx) WHERE a BETWEEN 2 AND 7 OR pk=1000000) AS t; SELECT COUNT(*) FROM - (SELECT * FROM t1 + (SELECT * FROM t1 FORCE INDEX(primary,idx) WHERE a BETWEEN 2 AND 7 OR pk=1000000) AS t; --replace_column 9 # From 1bbb55a2603f3571585cc085f05149d3d9cdbdba Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 8 Dec 2010 14:34:08 +0100 Subject: [PATCH 03/27] MBug#687320: Fix sporadic test failures in innodb_mysql.test and partition_innodb_semi_consistent.test Problem is that these tests run with --innodb-lock-wait-timeout=2 in .opt (and this is necessary as built-in innodb does not allow to change this dynamically). This cases another part of the test to occasionally time out an UPDATE, which subsequently caused the test case to timeout due to waiting for a condition (successful UPDATE) that never occurs. Fixed by re-trying the update in case of timeout. Tested by inserting a sleep() in the connection that the UPDATE is waiting for, and checking that the retry loops a couple of times until the other connection is done and COMMITs. --- mysql-test/include/mix1.inc | 12 +++++++++++- mysql-test/r/partition_innodb_semi_consistent.result | 10 ++++++++++ mysql-test/suite/innodb/r/innodb_mysql.result | 10 ++++++++++ mysql-test/suite/innodb_plugin/r/innodb_mysql.result | 10 ++++++++++ mysql-test/t/partition_innodb_semi_consistent.test | 12 +++++++++++- 5 files changed, 52 insertions(+), 2 deletions(-) diff --git a/mysql-test/include/mix1.inc b/mysql-test/include/mix1.inc index 194d9e41108..7ef8adf8e08 100644 --- a/mysql-test/include/mix1.inc +++ b/mysql-test/include/mix1.inc @@ -1359,7 +1359,17 @@ INSERT INTO t1 VALUES (1,'init'); DELIMITER |; CREATE PROCEDURE p1() BEGIN - UPDATE t1 SET b = CONCAT(b, '+con2') WHERE a = 1; + # retry the UPDATE in case it times out the lock before con1 has time + # to COMMIT. + DECLARE do_retry INT DEFAULT 0; + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET do_retry = 1; + retry_loop:LOOP + UPDATE t1 SET b = CONCAT(b, '+con2') WHERE a = 1; + IF do_retry = 0 THEN + LEAVE retry_loop; + END IF; + SET do_retry = 0; + END LOOP; INSERT INTO t2 VALUES (); END| DELIMITER ;| diff --git a/mysql-test/r/partition_innodb_semi_consistent.result b/mysql-test/r/partition_innodb_semi_consistent.result index 471da4c1c2e..fbdd70528c5 100644 --- a/mysql-test/r/partition_innodb_semi_consistent.result +++ b/mysql-test/r/partition_innodb_semi_consistent.result @@ -75,7 +75,17 @@ TRUNCATE t1; INSERT INTO t1 VALUES (1,'init'); CREATE PROCEDURE p1() BEGIN +# retry the UPDATE in case it times out the lock before con1 has time +# to COMMIT. +DECLARE do_retry INT DEFAULT 0; +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET do_retry = 1; +retry_loop:LOOP UPDATE t1 SET b = CONCAT(b, '+con2') WHERE a = 1; +IF do_retry = 0 THEN +LEAVE retry_loop; +END IF; +SET do_retry = 0; +END LOOP; INSERT INTO t2 VALUES (); END| BEGIN; diff --git a/mysql-test/suite/innodb/r/innodb_mysql.result b/mysql-test/suite/innodb/r/innodb_mysql.result index 5d90a96f61c..86a51b337ff 100644 --- a/mysql-test/suite/innodb/r/innodb_mysql.result +++ b/mysql-test/suite/innodb/r/innodb_mysql.result @@ -1594,7 +1594,17 @@ TRUNCATE t1; INSERT INTO t1 VALUES (1,'init'); CREATE PROCEDURE p1() BEGIN +# retry the UPDATE in case it times out the lock before con1 has time +# to COMMIT. +DECLARE do_retry INT DEFAULT 0; +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET do_retry = 1; +retry_loop:LOOP UPDATE t1 SET b = CONCAT(b, '+con2') WHERE a = 1; +IF do_retry = 0 THEN +LEAVE retry_loop; +END IF; +SET do_retry = 0; +END LOOP; INSERT INTO t2 VALUES (); END| BEGIN; diff --git a/mysql-test/suite/innodb_plugin/r/innodb_mysql.result b/mysql-test/suite/innodb_plugin/r/innodb_mysql.result index 32ee3c21946..1aee85b5288 100644 --- a/mysql-test/suite/innodb_plugin/r/innodb_mysql.result +++ b/mysql-test/suite/innodb_plugin/r/innodb_mysql.result @@ -1594,7 +1594,17 @@ TRUNCATE t1; INSERT INTO t1 VALUES (1,'init'); CREATE PROCEDURE p1() BEGIN +# retry the UPDATE in case it times out the lock before con1 has time +# to COMMIT. +DECLARE do_retry INT DEFAULT 0; +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET do_retry = 1; +retry_loop:LOOP UPDATE t1 SET b = CONCAT(b, '+con2') WHERE a = 1; +IF do_retry = 0 THEN +LEAVE retry_loop; +END IF; +SET do_retry = 0; +END LOOP; INSERT INTO t2 VALUES (); END| BEGIN; diff --git a/mysql-test/t/partition_innodb_semi_consistent.test b/mysql-test/t/partition_innodb_semi_consistent.test index 2711d79f194..9d3e2570256 100644 --- a/mysql-test/t/partition_innodb_semi_consistent.test +++ b/mysql-test/t/partition_innodb_semi_consistent.test @@ -117,7 +117,17 @@ INSERT INTO t1 VALUES (1,'init'); DELIMITER |; CREATE PROCEDURE p1() BEGIN - UPDATE t1 SET b = CONCAT(b, '+con2') WHERE a = 1; + # retry the UPDATE in case it times out the lock before con1 has time + # to COMMIT. + DECLARE do_retry INT DEFAULT 0; + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET do_retry = 1; + retry_loop:LOOP + UPDATE t1 SET b = CONCAT(b, '+con2') WHERE a = 1; + IF do_retry = 0 THEN + LEAVE retry_loop; + END IF; + SET do_retry = 0; + END LOOP; INSERT INTO t2 VALUES (); END| DELIMITER ;| From b78f6240448c3e53ae60549483eb78225a5edc34 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 10 Dec 2010 09:51:34 +0100 Subject: [PATCH 04/27] Fix wrong merge of patch for Bug#46639. --- sql/ha_partition.cc | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index e7de3fb5289..e2ad4b4462c 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -4640,19 +4640,6 @@ int ha_partition::handle_unordered_scan_next_partition(uchar * buf) break; case partition_index_first: DBUG_PRINT("info", ("index_first on partition %d", i)); - /* - MyISAM engine can fail if we call index_first() when indexes disabled - that happens if the table is empty. - Here we use file->stats.records instead of file->records() because - file->records() is supposed to return an EXACT count, and it can be - possibly slow. We don't need an exact number, an approximate one- from - the last ::info() call - is sufficient. - */ - if (file->stats.records == 0) - { - error= HA_ERR_END_OF_FILE; - break; - } error= file->ha_index_first(buf); break; case partition_index_first_unordered: @@ -4740,36 +4727,10 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order) m_start_key.flag); break; case partition_index_first: - /* - MyISAM engine can fail if we call index_first() when indexes disabled - that happens if the table is empty. - Here we use file->stats.records instead of file->records() because - file->records() is supposed to return an EXACT count, and it can be - possibly slow. We don't need an exact number, an approximate one- from - the last ::info() call - is sufficient. - */ - if (file->stats.records == 0) - { - error= HA_ERR_END_OF_FILE; - break; - } error= file->ha_index_first(rec_buf_ptr); reverse_order= FALSE; break; case partition_index_last: - /* - MyISAM engine can fail if we call index_last() when indexes disabled - that happens if the table is empty. - Here we use file->stats.records instead of file->records() because - file->records() is supposed to return an EXACT count, and it can be - possibly slow. We don't need an exact number, an approximate one- from - the last ::info() call - is sufficient. - */ - if (file->stats.records == 0) - { - error= HA_ERR_END_OF_FILE; - break; - } error= file->ha_index_last(rec_buf_ptr); reverse_order= TRUE; break; From 84edaac4f14b2fbaf57fef8fbaeb45966b1feda3 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Fri, 10 Dec 2010 17:04:09 +0200 Subject: [PATCH 05/27] Better warning message if lock test fails Made archive.test a bit more safe mysql-test/r/archive.result: Added removal of files to make rerun of failed test work mysql-test/t/archive.test: Added removal of files to make rerun of failed test work mysys/thr_lock.c: Better warning message if lock test fails --- mysql-test/r/archive.result | 1 + mysql-test/t/archive.test | 5 +++++ mysys/thr_lock.c | 10 ++++------ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/archive.result b/mysql-test/r/archive.result index 5a731e6476c..ae79e237ade 100644 --- a/mysql-test/r/archive.result +++ b/mysql-test/r/archive.result @@ -12717,6 +12717,7 @@ COUNT(t1.a) 729 DROP TABLE t1; SET @@join_buffer_size= @save_join_buffer_size; +flush tables; SHOW CREATE TABLE t1; ERROR HY000: Table upgrade required. Please do "REPAIR TABLE `t1`" or dump/reload to fix it! SELECT * FROM t1; diff --git a/mysql-test/t/archive.test b/mysql-test/t/archive.test index 7478c7dcdce..c966b51d861 100644 --- a/mysql-test/t/archive.test +++ b/mysql-test/t/archive.test @@ -1630,6 +1630,11 @@ SET @@join_buffer_size= @save_join_buffer_size; # BUG#47012 archive tables are not upgradeable, and server crashes on any access # let $MYSQLD_DATADIR= `SELECT @@datadir`; + +# Remove files to handle possible restart of test +flush tables; +remove_files_wildcard $MYSQLD_DATADIR/test t1.*; + copy_file std_data/bug47012.frm $MYSQLD_DATADIR/test/t1.frm; copy_file std_data/bug47012.ARZ $MYSQLD_DATADIR/test/t1.ARZ; copy_file std_data/bug47012.ARM $MYSQLD_DATADIR/test/t1.ARM; diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index 341b2f0058e..60214c9af08 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -158,15 +158,13 @@ static int check_lock(struct st_lock_list *list, const char* lock_type, { THR_LOCK_DATA *data,**prev; uint count=0; - THR_LOCK_OWNER *UNINIT_VAR(first_owner); prev= &list->data; if (list->data) { - enum thr_lock_type last_lock_type=list->data->type; + enum thr_lock_type last_lock_type= list->data->type; + THR_LOCK_OWNER first_owner= list->data->owner; - if (same_owner && list->data) - first_owner= list->data->owner; for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next) { if (data->type != last_lock_type) @@ -184,8 +182,8 @@ static int check_lock(struct st_lock_list *list, const char* lock_type, last_lock_type != TL_WRITE_CONCURRENT_INSERT) { fprintf(stderr, - "Warning: Found locks from different threads in %s: %s\n", - lock_type,where); + "Warning: Found locks from different threads in %s at '%s'. org_lock_type: %d last_lock_type: %d new_lock_type: %d\n", + lock_type, where, list->data->type, last_lock_type, data->type); return 1; } if (no_cond && data->cond) From bd2034dbee16bc90217d44df5059d837d60a6110 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Fri, 10 Dec 2010 17:15:18 +0200 Subject: [PATCH 06/27] Fix for Lbug:#686010 maria.optimize corrupts stack around alloca() call storage/maria/ma_check.c: Allocate also memory for nodflag and transid's storage/maria/ma_write.c: Allow nodflag and transid as part of key. (This has nothing to do with the bug report, but it's a safer check). storage/maria/maria_def.h: Define MARIA_MAX_POINTER_LENGTH (length of pointer to node) Added node pointer length to MARIA_INDEX_OVERHEAD_SIZE, as this is part of the key. (Safety fix) --- storage/maria/ma_check.c | 3 ++- storage/maria/ma_write.c | 6 ++---- storage/maria/maria_def.h | 4 +++- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index fcf01385e97..1cb14567804 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -3133,7 +3133,8 @@ static int sort_one_index(HA_CHECK *param, MARIA_HA *info, key.keyinfo= keyinfo; if (!(buff= (uchar*) my_alloca((uint) keyinfo->block_length + - keyinfo->maxlength))) + keyinfo->maxlength + + MARIA_INDEX_OVERHEAD_SIZE))) { _ma_check_print_error(param,"Not enough memory for key block"); DBUG_RETURN(-1); diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c index 02eeec754ee..49f86fe291b 100644 --- a/storage/maria/ma_write.c +++ b/storage/maria/ma_write.c @@ -22,8 +22,6 @@ #include "ma_key_recover.h" #include "ma_blockrec.h" -#define MAX_POINTER_LENGTH 8 - /* Functions declared in this file */ static int w_search(MARIA_HA *info, uint32 comp_flag, @@ -802,7 +800,7 @@ int _ma_insert(register MARIA_HA *info, MARIA_KEY *key, #endif if (t_length > 0) { - if (t_length >= keyinfo->maxlength*2+MAX_POINTER_LENGTH) + if (t_length >= keyinfo->maxlength*2+MARIA_INDEX_OVERHEAD_SIZE) { my_errno=HA_ERR_CRASHED; DBUG_RETURN(-1); @@ -811,7 +809,7 @@ int _ma_insert(register MARIA_HA *info, MARIA_KEY *key, } else { - if (-t_length >= keyinfo->maxlength*2+MAX_POINTER_LENGTH) + if (-t_length >= keyinfo->maxlength*2+MARIA_INDEX_OVERHEAD_SIZE) { my_errno=HA_ERR_CRASHED; DBUG_RETURN(-1); diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index b998ac4f3a0..85696d04858 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -152,11 +152,13 @@ typedef struct st_maria_state_info #define MARIA_COLUMNDEF_SIZE (2*7+1+1+4) #define MARIA_BASE_INFO_SIZE (MY_UUID_SIZE + 5*8 + 6*4 + 11*2 + 6 + 5*2 + 1 + 16) #define MARIA_INDEX_BLOCK_MARGIN 16 /* Safety margin for .MYI tables */ +#define MARIA_MAX_POINTER_LENGTH 7 /* Node pointer */ /* Internal management bytes needed to store 2 transid/key on an index page */ #define MARIA_MAX_PACK_TRANSID_SIZE (TRANSID_SIZE+1) #define MARIA_TRANSID_PACK_OFFSET (256- TRANSID_SIZE - 1) #define MARIA_MIN_TRANSID_PACK_OFFSET (MARIA_TRANSID_PACK_OFFSET-TRANSID_SIZE) -#define MARIA_INDEX_OVERHEAD_SIZE (MARIA_MAX_PACK_TRANSID_SIZE * 2) +#define MARIA_INDEX_OVERHEAD_SIZE (MARIA_MAX_PACK_TRANSID_SIZE * 2 + \ + MARIA_MAX_POINTER_LENGTH) #define MARIA_DELETE_KEY_NR 255 /* keynr for deleted blocks */ /* From ffb0cd6146662705491e1461a7727c9627f9bd15 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Mon, 13 Dec 2010 15:05:57 +0200 Subject: [PATCH 07/27] When compiling with valgrind, change my_alloca() to use my_malloc() - This allows us to detect missing my_afree() calls and also find overruns (when running with valgrind) to alloca() areas. - Added missing my_afree() calls - Fixed wrong call to my_afree() include/my_sys.h: When compiling with valgrind, change my_alloca() to use my_malloc() mysql-test/suite/innodb/t/innodb_bug57255.test: Speed up taste case (patch from Stewart Smith) mysql-test/suite/innodb_plugin/t/innodb_bug57255.test: Speed up taste case (patch from Stewart Smith) sql/ha_partition.cc: Removed casts from my_afree() sql/opt_range.cc: Add missing my_afree() calls. storage/maria/ma_rt_split.c: Fixed wrong parameter to my_afree() --- include/my_sys.h | 2 +- mysql-test/suite/innodb/t/innodb_bug57255.test | 2 ++ mysql-test/suite/innodb_plugin/t/innodb_bug57255.test | 2 ++ sql/ha_partition.cc | 4 ++-- sql/opt_range.cc | 2 ++ storage/maria/ma_rt_split.c | 3 +-- 6 files changed, 10 insertions(+), 5 deletions(-) diff --git a/include/my_sys.h b/include/my_sys.h index 309cb9c59b9..f5e38c5858e 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -197,7 +197,7 @@ extern void my_large_free(uchar * ptr, myf my_flags); #define my_large_free(A,B) my_free_lock((A),(B)) #endif /* HAVE_LARGE_PAGES */ -#ifdef HAVE_ALLOCA +#if defined(HAVE_ALLOCA) && !defined(HAVE_valgrind) #if defined(_AIX) && !defined(__GNUC__) && !defined(_AIX43) #pragma alloca #endif /* _AIX */ diff --git a/mysql-test/suite/innodb/t/innodb_bug57255.test b/mysql-test/suite/innodb/t/innodb_bug57255.test index 2b37a0a6092..0bf686578b2 100644 --- a/mysql-test/suite/innodb/t/innodb_bug57255.test +++ b/mysql-test/suite/innodb/t/innodb_bug57255.test @@ -12,6 +12,7 @@ create table C(id int not null auto_increment primary key, f1 int not null, fore insert into A values(1), (2); --disable_query_log +begin; let $i=257; while ($i) { @@ -24,6 +25,7 @@ while ($i) insert into C(f1) values(2); dec $i; } +commit; --enable_query_log # Following Deletes should not report error diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug57255.test b/mysql-test/suite/innodb_plugin/t/innodb_bug57255.test index 96184c355b6..e5056d3e23c 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb_bug57255.test +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug57255.test @@ -12,6 +12,7 @@ create table C(id int not null auto_increment primary key, f1 int not null, fore insert into A values(1), (2); --disable_query_log +begin; let $i=257; while ($i) { @@ -24,6 +25,7 @@ while ($i) insert into C(f1) values(2); dec $i; } +commit; --enable_query_log # Following Deletes should not report error diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index e2ad4b4462c..1e462130a32 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -2432,7 +2432,7 @@ bool ha_partition::get_from_handler_file(const char *name, MEM_ROOT *mem_root) for (i= 0; i < m_tot_parts; i++) m_engine_array[i]= ha_lock_engine(NULL, engine_array[i]); - my_afree((gptr) engine_array); + my_afree(engine_array); if (!m_file && create_handlers(mem_root)) { @@ -2442,7 +2442,7 @@ bool ha_partition::get_from_handler_file(const char *name, MEM_ROOT *mem_root) DBUG_RETURN(FALSE); err3: - my_afree((gptr) engine_array); + my_afree(engine_array); err2: my_free(file_buffer, MYF(0)); err1: diff --git a/sql/opt_range.cc b/sql/opt_range.cc index caacec164d2..5b4aa53bb91 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -11058,6 +11058,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min_in_range() /* Compare the found key with max_key. */ int cmp_res= key_cmp(index_info->key_part, max_key, real_prefix_len + min_max_arg_len); + my_afree(max_key); /* The key is outside of the range if: the interval is open and the key is equal to the maximum boundry @@ -11183,6 +11184,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range() /* Compare the found key with min_key. */ int cmp_res= key_cmp(index_info->key_part, min_key, real_prefix_len + min_max_arg_len); + my_afree(min_key); /* The key is outside of the range if: the interval is open and the key is equal to the minimum boundry diff --git a/storage/maria/ma_rt_split.c b/storage/maria/ma_rt_split.c index 856edc60490..6f32a60c073 100644 --- a/storage/maria/ma_rt_split.c +++ b/storage/maria/ma_rt_split.c @@ -544,8 +544,7 @@ int maria_rtree_split_page(const MARIA_KEY *key, MARIA_PAGE *page, } DBUG_PRINT("rtree", ("split new block: %lu", (ulong) *new_page_offs)); - my_afree(new_page); - + my_afree(new_page_buff); split_err: my_afree(coord_buf); DBUG_RETURN(err_code); From 0b20943e9d7e22332ccc14b30b49a78a780cc23d Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Mon, 13 Dec 2010 15:27:13 +0200 Subject: [PATCH 08/27] Fixed typo that caused compile failure in thr_lock.c mysys/thr_lock.c: Fixed typo that caused compile failure --- mysys/thr_lock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index 60214c9af08..68a3caf6da7 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -163,7 +163,7 @@ static int check_lock(struct st_lock_list *list, const char* lock_type, if (list->data) { enum thr_lock_type last_lock_type= list->data->type; - THR_LOCK_OWNER first_owner= list->data->owner; + THR_LOCK_OWNER *first_owner= list->data->owner; for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next) { From 970e67b5e3c459d0a6b8a0e4ce4a3bf602362fba Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 17 Dec 2010 08:33:36 +0100 Subject: [PATCH 09/27] MBug#691437: storage/sphinx/plug.in missing from source tarball. It was missing from EXTRA_DIST in Makefile.am. --- storage/sphinx/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/sphinx/Makefile.am b/storage/sphinx/Makefile.am index ce4324ae5cb..67d01d08484 100644 --- a/storage/sphinx/Makefile.am +++ b/storage/sphinx/Makefile.am @@ -49,6 +49,6 @@ libsphinx_la_CXXFLAGS = $(AM_CXXFLAGS) libsphinx_la_CFLAGS = $(AM_CFLAGS) libsphinx_la_SOURCES= ha_sphinx.cc -EXTRA_DIST = CMakeLists.txt +EXTRA_DIST = CMakeLists.txt plug.in # Don't update the files from bitkeeper %::SCCS/s.% From 6c958d6e80f681c207f4298b754c8b18170d3224 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 20 Dec 2010 19:19:24 +0100 Subject: [PATCH 10/27] bug#683112 Maria 5.2 incorrectly reports "(using password: NO)" even when password is specified set thd->password appropriately also for cases when a user was not found. --- mysql-test/r/connect.result | 4 ++++ mysql-test/t/connect.test | 13 +++++++++++++ sql/sql_acl.cc | 17 ++++++++++------- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/connect.result b/mysql-test/r/connect.result index 690a6fb3bc3..00602093425 100644 --- a/mysql-test/r/connect.result +++ b/mysql-test/r/connect.result @@ -237,5 +237,9 @@ ERROR 28000: Access denied for user 'mysqltest_up2'@'localhost' (using password: select user(), current_user(); user() current_user() mysqltest_up2@localhost mysqltest_up2@% +connect(localhost,mysqltest_nouser,newpw,test,MASTER_PORT,MASTER_SOCKET); +ERROR 28000: Access denied for user 'mysqltest_nouser'@'localhost' (using password: YES) +connect(localhost,mysqltest_nouser,,test,MASTER_PORT,MASTER_SOCKET); +ERROR 28000: Access denied for user 'mysqltest_nouser'@'localhost' (using password: NO) DROP USER mysqltest_up1@'%'; DROP USER mysqltest_up2@'%'; diff --git a/mysql-test/t/connect.test b/mysql-test/t/connect.test index a8c8b659c3c..8fbdd709364 100644 --- a/mysql-test/t/connect.test +++ b/mysql-test/t/connect.test @@ -352,6 +352,19 @@ connection pcon4; select user(), current_user(); disconnect pcon4; +# +# lpbug#683112 Maria 5.2 incorrectly reports "(using password: NO)" +# even when password is specified +# +# test "access denied" error for nonexisting user with and without a password +# +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error ER_ACCESS_DENIED_ERROR +connect(pcon5,localhost,mysqltest_nouser,newpw,,$MASTER_MYPORT,); +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error ER_ACCESS_DENIED_ERROR +connect(pcon5,localhost,mysqltest_nouser,,,$MASTER_MYPORT,); + connection default; DROP USER mysqltest_up1@'%'; DROP USER mysqltest_up2@'%'; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 87e27d68b98..9b1d0df4251 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -6980,16 +6980,16 @@ struct MPVIO_EXT : public MYSQL_PLUGIN_VIO a helper function to report an access denied error in all the proper places */ -static void login_failed_error(THD *thd, bool passwd_used) +static void login_failed_error(THD *thd) { my_error(ER_ACCESS_DENIED_ERROR, MYF(0), thd->main_security_ctx.user, thd->main_security_ctx.host_or_ip, - passwd_used ? ER(ER_YES) : ER(ER_NO)); + thd->password ? ER(ER_YES) : ER(ER_NO)); general_log_print(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR), thd->main_security_ctx.user, thd->main_security_ctx.host_or_ip, - passwd_used ? ER(ER_YES) : ER(ER_NO)); + thd->password ? ER(ER_YES) : ER(ER_NO)); status_var_increment(thd->status_var.access_denied_errors); /* Log access denied messages to the error log when log-warnings = 2 @@ -7001,7 +7001,7 @@ static void login_failed_error(THD *thd, bool passwd_used) sql_print_warning(ER(ER_ACCESS_DENIED_ERROR), thd->main_security_ctx.user, thd->main_security_ctx.host_or_ip, - passwd_used ? ER(ER_YES) : ER(ER_NO)); + thd->password ? ER(ER_YES) : ER(ER_NO)); } } @@ -7266,7 +7266,7 @@ static bool find_mpvio_user(MPVIO_EXT *mpvio, Security_context *sctx) if (!mpvio->acl_user) { - login_failed_error(mpvio->thd, 0); + login_failed_error(mpvio->thd); return 1; } @@ -7583,8 +7583,11 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, return packet_error; } + thd->password= passwd_len > 0; if (find_mpvio_user(mpvio, sctx)) + { return packet_error; + } if (thd->client_capabilities & CLIENT_PLUGIN_AUTH) { @@ -8072,7 +8075,7 @@ bool acl_authenticate(THD *thd, uint connect_errors, uint com_change_user_pkt_le DBUG_ASSERT(mpvio.status == MPVIO_EXT::FAILURE); if (!thd->is_error()) - login_failed_error(thd, thd->password); + login_failed_error(thd); DBUG_RETURN(1); } @@ -8092,7 +8095,7 @@ bool acl_authenticate(THD *thd, uint connect_errors, uint com_change_user_pkt_le */ if (acl_check_ssl(thd, acl_user)) { - login_failed_error(thd, thd->password); + login_failed_error(thd); DBUG_RETURN(1); } From 865685dc0c0d7dec7415b82bf93ad63ca26cbacc Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Tue, 21 Dec 2010 19:22:20 +0200 Subject: [PATCH 11/27] Fixed bug in Aria that caused REPAIR to find old deleted rows. BUILD/compile-pentium64: Added --with-zlib-dir=bundled when doing static build. mysql-test/suite/maria/r/maria.result: Added test case mysql-test/suite/maria/t/maria.test: Added test case storage/maria/ma_blockrec.c: We need to flush blob pages to disk to ensure they overwrite any reused head/tail pages. If not, REPAIR will find rows that was previously deleted. --- BUILD/compile-pentium64 | 5 ++++- mysql-test/suite/maria/r/maria.result | 16 ++++++++++++++++ mysql-test/suite/maria/t/maria.test | 18 ++++++++++++++++++ storage/maria/ma_blockrec.c | 2 +- 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/BUILD/compile-pentium64 b/BUILD/compile-pentium64 index 3a8fad51fea..01eb2adf88b 100755 --- a/BUILD/compile-pentium64 +++ b/BUILD/compile-pentium64 @@ -4,7 +4,10 @@ path=`dirname $0` . "$path/SETUP.sh" extra_flags="$pentium64_cflags $fast_cflags" -extra_configs="$pentium_configs $static_link" +# On CentOS/Fedora Core 10 amd64, there is system libz.so but not +# libz.a, so need to use bundled zlib when building static +# binary. Hence we use --with-zlib-dir=bundled +extra_configs="$pentium_configs $static_link --with-zlib-dir=bundled" CC="$CC --pipe" strip=yes diff --git a/mysql-test/suite/maria/r/maria.result b/mysql-test/suite/maria/r/maria.result index 46ae485b678..9f34f60ca24 100644 --- a/mysql-test/suite/maria/r/maria.result +++ b/mysql-test/suite/maria/r/maria.result @@ -2624,3 +2624,19 @@ KEY (v3) INSERT INTO t1 ( f1 , f2 , f3 , f4 ) SELECT f1 , f4 , f1 , f4 FROM t1; DELETE FROM t1; drop table t1; +create table t1 (a int not null primary key, b blob) engine=maria transactional=1; +insert into t1 values(1,repeat('a',8000)); +insert into t1 values(2,repeat('b',8000)); +insert into t1 values(3,repeat('c',8000)); +flush tables; +delete from t1 where a>1; +insert into t1 values(1,repeat('d',8000*3)); +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +flush tables; +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +repair table t1 extended; +Table Op Msg_type Msg_text +test.t1 repair status OK +drop table t1; diff --git a/mysql-test/suite/maria/t/maria.test b/mysql-test/suite/maria/t/maria.test index 4dde6364bb1..fe2bd43988e 100644 --- a/mysql-test/suite/maria/t/maria.test +++ b/mysql-test/suite/maria/t/maria.test @@ -1910,6 +1910,24 @@ INSERT INTO t1 ( f1 , f2 , f3 , f4 ) SELECT f1 , f4 , f1 , f4 FROM t1; DELETE FROM t1; drop table t1; +# +# Test of problem where REPAIR finds old deleted rows. +# + +create table t1 (a int not null primary key, b blob) engine=maria transactional=1; +insert into t1 values(1,repeat('a',8000)); +insert into t1 values(2,repeat('b',8000)); +insert into t1 values(3,repeat('c',8000)); +flush tables; +delete from t1 where a>1; +--error 1062 +insert into t1 values(1,repeat('d',8000*3)); +flush tables; +check table t1; +# This failed by finding 2 extra rows. +repair table t1 extended; +drop table t1; + # # End of test # diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index fd02e2ac0ec..2c3ff43c6ec 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -2506,7 +2506,7 @@ static my_bool free_full_page_range(MARIA_HA *info, pgcache_page_no_t page, } if (delete_count && pagecache_delete_pages(share->pagecache, &info->dfile, - page, delete_count, PAGECACHE_LOCK_WRITE, 0)) + page, delete_count, PAGECACHE_LOCK_WRITE, 1)) res= 1; if (share->now_transactional) From 46c7fb2722d3e0088c2a05acd202e4ebb48b44c0 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Tue, 21 Dec 2010 19:23:50 +0200 Subject: [PATCH 12/27] Increased version number to 5.1.54 --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index ebb705fc48e..fdcad1db195 100644 --- a/configure.in +++ b/configure.in @@ -12,7 +12,7 @@ dnl dnl When changing the major version number please also check the switch dnl statement in mysqlbinlog::check_master_version(). You may also need dnl to update version.c in ndb. -AC_INIT([MariaDB Server], [5.1.53-MariaDB], [], [mysql]) +AC_INIT([MariaDB Server], [5.1.54-MariaDB], [], [mysql]) AC_CONFIG_SRCDIR([sql/mysqld.cc]) AC_CANONICAL_SYSTEM From efbb3c6c90279f2bed8dda9c48dbaaf8b09a8cae Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Fri, 24 Dec 2010 15:30:23 -0800 Subject: [PATCH 13/27] Fixed LP bug #639935 (bug #58727). When the optimizer creates items out of other items it does not have to call the fix_fields method. Usually in these cases it calls quick_fix_field() that just marks the created item as fixed. If the created item is an Item_func object then calling quick_fix_field() works fine if the arguments of the created functional item are already fixed. Otherwise some unfixed nodes remain in the item tree and it triggers an assertion failure whenever the item is evaluated. Fixed the problem by making the method quick_fix_field virtual and providing an implementation for the class Item_func objects that recursively calls the method for unfixed arguments of any functional item. --- mysql-test/r/subselect.result | 11 +++++++++++ mysql-test/t/subselect.test | 15 +++++++++++++++ sql/item.h | 11 +++++++++-- sql/item_func.cc | 15 +++++++++++++++ sql/item_func.h | 1 + 5 files changed, 51 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 6d8cb7f5b9a..6710b8fc941 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4749,4 +4749,15 @@ sum(a) sub 1 3 deallocate prepare stmt1; drop table t1,t2; +# +# Bug LP#693935/#58727: Assertion failure with +# a single row subquery returning more than one row +# +create table t1 (a char(1) charset utf8); +insert into t1 values ('a'), ('b'); +create table t2 (a binary(1)); +insert into t2 values ('x'), ('y'); +select * from t2 where a=(select a from t1) and a='x'; +ERROR 21000: Subquery returns more than 1 row +drop table t1,t2; End of 5.1 tests diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index bd333d5a649..9bacaaaf6ec 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3759,4 +3759,19 @@ deallocate prepare stmt1; drop table t1,t2; +--echo # +--echo # Bug LP#693935/#58727: Assertion failure with +--echo # a single row subquery returning more than one row +--echo # + +create table t1 (a char(1) charset utf8); +insert into t1 values ('a'), ('b'); +create table t2 (a binary(1)); +insert into t2 values ('x'), ('y'); + +-- error ER_SUBQUERY_NO_1_ROW +select * from t2 where a=(select a from t1) and a='x'; + +drop table t1,t2; + --echo End of 5.1 tests diff --git a/sql/item.h b/sql/item.h index f66892a76cc..4bee370642e 100644 --- a/sql/item.h +++ b/sql/item.h @@ -556,10 +556,17 @@ public: Field *make_string_field(TABLE *table); virtual bool fix_fields(THD *, Item **); /* - should be used in case where we are sure that we do not need + This method should be used in case where we are sure that we do not need complete fix_fields() procedure. + Usually this method is used by the optimizer when it has to create a new + item out of other already fixed items. For example, if the optimizer has + to create a new Item_func for an inferred equality whose left and right + parts are already fixed items. In some cases the optimizer cannot use + directly fixed items as the arguments of the created functional item, + but rather uses intermediate type conversion items. Then the method is + supposed to be applied recursively. */ - inline void quick_fix_field() { fixed= 1; } + virtual inline void quick_fix_field() { fixed= 1; } /* Function returns 1 on overflow and -1 on fatal errors */ int save_in_field_no_warnings(Field *field, bool no_conversions); virtual int save_in_field(Field *field, bool no_conversions); diff --git a/sql/item_func.cc b/sql/item_func.cc index c35db7ad1cb..ab84303101c 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -202,6 +202,21 @@ Item_func::fix_fields(THD *thd, Item **ref) return FALSE; } +void +Item_func::quick_fix_field() +{ + Item **arg,**arg_end; + if (arg_count) + { + for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++) + { + if (!(*arg)->fixed) + (*arg)->quick_fix_field(); + } + } + fixed= 1; +} + bool Item_func::walk(Item_processor processor, bool walk_subquery, uchar *argument) diff --git a/sql/item_func.h b/sql/item_func.h index e45638472e4..3d2cb709ce3 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -117,6 +117,7 @@ public: // Constructor used for Item_cond_and/or (see Item comment) Item_func(THD *thd, Item_func *item); bool fix_fields(THD *, Item **ref); + void quick_fix_field(); table_map used_tables() const; table_map not_null_tables() const; void update_used_tables(); From fda18d8fa26d10dee034756b276fe4f46f477f3a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 27 Dec 2010 10:53:02 +0100 Subject: [PATCH 14/27] lpbug#665028 SHOW STORAGE ENGINES shows incorrect Transaction support for Aria don't fill in handlerton::commit member, as it's not used and makes MySQL believe that Aria is transactional. Fix the TRANSACTIONAL=1 warning. --- mysql-test/suite/maria/r/maria.result | 2 +- mysql-test/suite/maria/r/maria3.result | 2 +- sql/sql_table.cc | 16 ++++++++++------ storage/maria/ha_maria.cc | 3 +++ 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/mysql-test/suite/maria/r/maria.result b/mysql-test/suite/maria/r/maria.result index e7f40ca10ed..2eb3546fc96 100644 --- a/mysql-test/suite/maria/r/maria.result +++ b/mysql-test/suite/maria/r/maria.result @@ -1,6 +1,6 @@ select * from INFORMATION_SCHEMA.ENGINES where ENGINE="ARIA"; ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS -Aria YES Crash-safe tables with MyISAM heritage YES NO NO +Aria YES Crash-safe tables with MyISAM heritage NO NO NO set global storage_engine=aria; set session storage_engine=aria; set global aria_page_checksum=0; diff --git a/mysql-test/suite/maria/r/maria3.result b/mysql-test/suite/maria/r/maria3.result index 2311669640b..490059587ad 100644 --- a/mysql-test/suite/maria/r/maria3.result +++ b/mysql-test/suite/maria/r/maria3.result @@ -1,6 +1,6 @@ select * from INFORMATION_SCHEMA.ENGINES where ENGINE="ARIA"; ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS -Aria YES Crash-safe tables with MyISAM heritage YES NO NO +Aria YES Crash-safe tables with MyISAM heritage NO NO NO set global storage_engine=aria; set session storage_engine=aria; set global aria_page_checksum=0; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index d702e83aefd..1d56fd53327 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3929,12 +3929,16 @@ bool mysql_create_table_no_lock(THD *thd, } /* Give warnings for not supported table options */ - if (create_info->transactional && !file->ht->commit) - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, - ER_ILLEGAL_HA_CREATE_OPTION, - ER(ER_ILLEGAL_HA_CREATE_OPTION), - file->engine_name()->str, - "TRANSACTIONAL=1"); +#if defined(WITH_ARIA_STORAGE_ENGINE) + extern handlerton *maria_hton; + if (file->ht != maria_hton) +#endif + if (create_info->transactional) + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_ILLEGAL_HA_CREATE_OPTION, + ER(ER_ILLEGAL_HA_CREATE_OPTION), + file->engine_name()->str, + "TRANSACTIONAL=1"); VOID(pthread_mutex_lock(&LOCK_open)); if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE)) diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 306728edb64..256455d4531 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -3302,6 +3302,9 @@ static int ha_maria_init(void *p) maria_hton->panic= maria_hton_panic; maria_hton->commit= maria_commit; maria_hton->rollback= maria_rollback; +#ifdef MARIA_CANNOT_ROLLBACK + maria_hton->commit= 0; +#endif maria_hton->flush_logs= maria_flush_logs; maria_hton->show_status= maria_show_status; /* TODO: decide if we support Maria being used for log tables */ From 31a78529bc5c4431865eba06762e6cc66359f759 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 31 Dec 2010 10:39:14 +0100 Subject: [PATCH 15/27] virtual columns: * move a capability from a virtual handler method to table_flags() * rephrase error messages to avoid hard-coded English parts * admit in test cases that they need xtradb, not innodb mysql-test/suite/vcol/t/rpl_vcol.test: this test needs xtradb, it will fail with innodb mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_innodb.test: this test needs xtradb, it will fail with innodb mysql-test/suite/vcol/t/vcol_column_def_options_innodb.test: this test needs xtradb, it will fail with innodb mysql-test/suite/vcol/t/vcol_handler_innodb.test: this test needs xtradb, it will fail with innodb mysql-test/suite/vcol/t/vcol_ins_upd_innodb.test: this test needs xtradb, it will fail with innodb mysql-test/suite/vcol/t/vcol_keys_innodb.test: this test needs xtradb, it will fail with innodb mysql-test/suite/vcol/t/vcol_non_stored_columns_innodb.test: this test needs xtradb, it will fail with innodb mysql-test/suite/vcol/t/vcol_partition_innodb.test: this test needs xtradb, it will fail with innodb mysql-test/suite/vcol/t/vcol_select_innodb.test: this test needs xtradb, it will fail with innodb mysql-test/suite/vcol/t/vcol_supported_sql_funcs_innodb.test: this test needs xtradb, it will fail with innodb mysql-test/suite/vcol/t/vcol_trigger_sp_innodb.test: this test needs xtradb, it will fail with innodb mysql-test/suite/vcol/t/vcol_view_innodb.test: this test needs xtradb, it will fail with innodb sql/ha_partition.h: check_if_supported_virtual_columns() -> HA_CAN_VIRTUAL_COLUMNS sql/handler.h: check_if_supported_virtual_columns() -> HA_CAN_VIRTUAL_COLUMNS sql/share/errmsg.txt: no hard-coded english parts in the error messages (ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN) sql/sql_table.cc: no hard-coded english parts in the error messages sql/table.cc: * check_if_supported_virtual_columns() -> HA_CAN_VIRTUAL_COLUMNS * no "csv workaround" is needed * no hard-coded english parts in the error messages storage/maria/ha_maria.cc: check_if_supported_virtual_columns() -> HA_CAN_VIRTUAL_COLUMNS storage/maria/ha_maria.h: check_if_supported_virtual_columns() -> HA_CAN_VIRTUAL_COLUMNS storage/myisam/ha_myisam.cc: check_if_supported_virtual_columns() -> HA_CAN_VIRTUAL_COLUMNS storage/myisam/ha_myisam.h: check_if_supported_virtual_columns() -> HA_CAN_VIRTUAL_COLUMNS storage/xtradb/handler/ha_innodb.cc: check_if_supported_virtual_columns() -> HA_CAN_VIRTUAL_COLUMNS storage/xtradb/handler/ha_innodb.h: check_if_supported_virtual_columns() -> HA_CAN_VIRTUAL_COLUMNS --- mysql-test/include/have_xtradb.inc | 9 ++-- mysql-test/include/have_xtradb.opt | 2 + mysql-test/r/log_tables.result | 8 ++-- mysql-test/r/plugin.result | 6 +-- mysql-test/r/table_options.result | 46 +++++++++---------- .../inc/vcol_unsupported_storage_engines.inc | 6 +-- mysql-test/suite/vcol/r/vcol_archive.result | 6 +-- mysql-test/suite/vcol/r/vcol_blackhole.result | 6 +-- mysql-test/suite/vcol/r/vcol_csv.result | 4 +- mysql-test/suite/vcol/r/vcol_memory.result | 6 +-- mysql-test/suite/vcol/r/vcol_merge.result | 2 +- .../r/vcol_non_stored_columns_innodb.result | 4 +- .../r/vcol_non_stored_columns_myisam.result | 4 +- mysql-test/suite/vcol/t/rpl_vcol.test | 2 +- .../vcol/t/vcol_blocked_sql_funcs_innodb.test | 2 +- .../t/vcol_column_def_options_innodb.test | 2 +- mysql-test/suite/vcol/t/vcol_csv.test | 8 +--- .../suite/vcol/t/vcol_handler_innodb.test | 2 +- .../suite/vcol/t/vcol_ins_upd_innodb.test | 2 +- mysql-test/suite/vcol/t/vcol_keys_innodb.test | 2 +- mysql-test/suite/vcol/t/vcol_merge.test | 2 +- .../t/vcol_non_stored_columns_innodb.test | 2 +- .../suite/vcol/t/vcol_partition_innodb.test | 2 +- .../suite/vcol/t/vcol_select_innodb.test | 2 +- .../t/vcol_supported_sql_funcs_innodb.test | 2 +- .../suite/vcol/t/vcol_trigger_sp_innodb.test | 2 +- mysql-test/suite/vcol/t/vcol_view_innodb.test | 2 +- sql/ha_partition.h | 1 - sql/handler.h | 12 +---- sql/share/errmsg.txt | 6 ++- sql/sql_table.cc | 4 +- sql/table.cc | 11 ++--- storage/maria/ha_maria.cc | 2 +- storage/maria/ha_maria.h | 1 - storage/myisam/ha_myisam.cc | 1 + storage/myisam/ha_myisam.h | 1 - storage/xtradb/handler/ha_innodb.cc | 2 +- storage/xtradb/handler/ha_innodb.h | 1 - 38 files changed, 83 insertions(+), 102 deletions(-) create mode 100644 mysql-test/include/have_xtradb.opt diff --git a/mysql-test/include/have_xtradb.inc b/mysql-test/include/have_xtradb.inc index 6c2fc5155a9..3f3893e5642 100644 --- a/mysql-test/include/have_xtradb.inc +++ b/mysql-test/include/have_xtradb.inc @@ -1,4 +1,5 @@ -disable_query_log; ---require r/true.require -SELECT (plugin_description LIKE '%xtradb%') AS `TRUE` FROM information_schema.plugins WHERE LOWER(plugin_name) = 'innodb' AND LOWER(plugin_status) = 'active'; -enable_query_log; +if (!`SELECT count(*) FROM information_schema.plugins WHERE + plugin_name = 'innodb' AND plugin_status = 'active' AND + plugin_description LIKE '%xtradb%'`){ + skip Need XtraDB engine; +} diff --git a/mysql-test/include/have_xtradb.opt b/mysql-test/include/have_xtradb.opt new file mode 100644 index 00000000000..4fb96229a7b --- /dev/null +++ b/mysql-test/include/have_xtradb.opt @@ -0,0 +1,2 @@ +--loose-innodb +--plugin-load=$HA_XTRADB_SO diff --git a/mysql-test/r/log_tables.result b/mysql-test/r/log_tables.result index f8321520880..cee912ffb2e 100644 --- a/mysql-test/r/log_tables.result +++ b/mysql-test/r/log_tables.result @@ -248,13 +248,13 @@ set global slow_query_log='OFF'; set @save_storage_engine= @@session.storage_engine; set storage_engine= MEMORY; alter table mysql.slow_log engine=ndb; -ERROR HY000: This storage engine cannot be used for log tables" +ERROR HY000: This storage engine cannot be used for log tables alter table mysql.slow_log engine=innodb; -ERROR HY000: This storage engine cannot be used for log tables" +ERROR HY000: This storage engine cannot be used for log tables alter table mysql.slow_log engine=archive; -ERROR HY000: This storage engine cannot be used for log tables" +ERROR HY000: This storage engine cannot be used for log tables alter table mysql.slow_log engine=blackhole; -ERROR HY000: This storage engine cannot be used for log tables" +ERROR HY000: This storage engine cannot be used for log tables set storage_engine= @save_storage_engine; drop table mysql.slow_log; drop table mysql.general_log; diff --git a/mysql-test/r/plugin.result b/mysql-test/r/plugin.result index ec9d804d6da..98be0326ef0 100644 --- a/mysql-test/r/plugin.result +++ b/mysql-test/r/plugin.result @@ -75,9 +75,9 @@ SET SQL_MODE='IGNORE_BAD_TABLE_OPTIONS'; #illegal value fixed CREATE TABLE t1 (a int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS; Warnings: -Warning 1652 Incorrect value '10000000000000000000' for option 'ULL' -Warning 1652 Incorrect value 'ttt' for option 'one_or_two' -Warning 1652 Incorrect value 'SSS' for option 'YESNO' +Warning 1653 Incorrect value '10000000000000000000' for option 'ULL' +Warning 1653 Incorrect value 'ttt' for option 'one_or_two' +Warning 1653 Incorrect value 'SSS' for option 'YESNO' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( diff --git a/mysql-test/r/table_options.result b/mysql-test/r/table_options.result index ed6fe4fb3de..ddb7bd13c03 100644 --- a/mysql-test/r/table_options.result +++ b/mysql-test/r/table_options.result @@ -3,9 +3,9 @@ SET @OLD_SQL_MODE=@@SQL_MODE; SET SQL_MODE='IGNORE_BAD_TABLE_OPTIONS'; create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1='1v1'; Warnings: -Warning 1651 Unknown option 'fkey' -Warning 1651 Unknown option 'dff' -Warning 1651 Unknown option 'tkey1' +Warning 1652 Unknown option 'fkey' +Warning 1652 Unknown option 'dff' +Warning 1652 Unknown option 'tkey1' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -16,10 +16,10 @@ drop table t1; #reassiginig options in the same line create table t1 (a int fkey=vvv, key akey (a) dff=vvv) tkey1=1v1 TKEY1=DEFAULT tkey1=1v2 tkey2=2v1; Warnings: -Warning 1651 Unknown option 'fkey' -Warning 1651 Unknown option 'dff' -Warning 1651 Unknown option 'tkey1' -Warning 1651 Unknown option 'tkey2' +Warning 1652 Unknown option 'fkey' +Warning 1652 Unknown option 'dff' +Warning 1652 Unknown option 'tkey1' +Warning 1652 Unknown option 'tkey2' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -29,7 +29,7 @@ t1 CREATE TABLE `t1` ( #add option alter table t1 tkey4=4v1; Warnings: -Warning 1651 Unknown option 'tkey4' +Warning 1652 Unknown option 'tkey4' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -39,8 +39,8 @@ t1 CREATE TABLE `t1` ( #remove options alter table t1 tkey3=DEFAULT tkey4=DEFAULT; Warnings: -Warning 1651 Unknown option 'tkey3' -Warning 1651 Unknown option 'tkey4' +Warning 1652 Unknown option 'tkey3' +Warning 1652 Unknown option 'tkey4' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -50,11 +50,11 @@ t1 CREATE TABLE `t1` ( drop table t1; create table t1 (a int fkey1=v1, key akey (a) kkey1=v1) tkey1=1v1 tkey1=1v2 TKEY1=DEFAULT tkey2=2v1 tkey3=3v1; Warnings: -Warning 1651 Unknown option 'fkey1' -Warning 1651 Unknown option 'kkey1' -Warning 1651 Unknown option 'TKEY1' -Warning 1651 Unknown option 'tkey2' -Warning 1651 Unknown option 'tkey3' +Warning 1652 Unknown option 'fkey1' +Warning 1652 Unknown option 'kkey1' +Warning 1652 Unknown option 'TKEY1' +Warning 1652 Unknown option 'tkey2' +Warning 1652 Unknown option 'tkey3' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -64,7 +64,7 @@ t1 CREATE TABLE `t1` ( #change field with option with the same value alter table t1 change a a int `FKEY1`='v1'; Warnings: -Warning 1651 Unknown option 'FKEY1' +Warning 1652 Unknown option 'FKEY1' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -74,7 +74,7 @@ t1 CREATE TABLE `t1` ( #change field with option with a different value alter table t1 change a a int fkey1=v2; Warnings: -Warning 1651 Unknown option 'fkey1' +Warning 1652 Unknown option 'fkey1' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -93,7 +93,7 @@ t1 CREATE TABLE `t1` ( #new key with options alter table t1 add key bkey (b) kkey2=v1; Warnings: -Warning 1651 Unknown option 'kkey2' +Warning 1652 Unknown option 'kkey2' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -105,8 +105,8 @@ t1 CREATE TABLE `t1` ( #new column with options alter table t1 add column c int fkey1=v1 fkey2=v2; Warnings: -Warning 1651 Unknown option 'fkey1' -Warning 1651 Unknown option 'fkey2' +Warning 1652 Unknown option 'fkey1' +Warning 1652 Unknown option 'fkey2' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -141,7 +141,7 @@ t1 CREATE TABLE `t1` ( #add column with options after delete alter table t1 add column b int fkey2=v1; Warnings: -Warning 1651 Unknown option 'fkey2' +Warning 1652 Unknown option 'fkey2' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -154,7 +154,7 @@ t1 CREATE TABLE `t1` ( #add key alter table t1 add key bkey (b) kkey2=v2; Warnings: -Warning 1651 Unknown option 'kkey2' +Warning 1652 Unknown option 'kkey2' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -168,7 +168,7 @@ t1 CREATE TABLE `t1` ( drop table t1; create table t1 (a int) tkey1=100; Warnings: -Warning 1651 Unknown option 'tkey1' +Warning 1652 Unknown option 'tkey1' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( diff --git a/mysql-test/suite/vcol/inc/vcol_unsupported_storage_engines.inc b/mysql-test/suite/vcol/inc/vcol_unsupported_storage_engines.inc index 681ed77fb3c..4ec98ebf3f4 100644 --- a/mysql-test/suite/vcol/inc/vcol_unsupported_storage_engines.inc +++ b/mysql-test/suite/vcol/inc/vcol_unsupported_storage_engines.inc @@ -13,9 +13,9 @@ # Change: Syntax changed ################################################################################ ---error ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN +--error ER_UNSUPPORTED_ENGINE_FOR_VIRTUAL_COLUMNS create table t1 (a int, b int as (a+1)); -create table t1 (a int); ---error ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN +create table t1 (a int not null); +--error ER_UNSUPPORTED_ENGINE_FOR_VIRTUAL_COLUMNS alter table t1 add column b int as (a+1); drop table t1; diff --git a/mysql-test/suite/vcol/r/vcol_archive.result b/mysql-test/suite/vcol/r/vcol_archive.result index 83fb78a5592..5ed2f3768ca 100644 --- a/mysql-test/suite/vcol/r/vcol_archive.result +++ b/mysql-test/suite/vcol/r/vcol_archive.result @@ -1,7 +1,7 @@ SET @@session.storage_engine = 'archive'; create table t1 (a int, b int as (a+1)); -ERROR HY000: 'Specified storage engine' is not yet supported for computed columns -create table t1 (a int); +ERROR HY000: ARCHIVE storage engine does not support computed columns +create table t1 (a int not null); alter table t1 add column b int as (a+1); -ERROR HY000: 'Specified storage engine' is not yet supported for computed columns +ERROR HY000: ARCHIVE storage engine does not support computed columns drop table t1; diff --git a/mysql-test/suite/vcol/r/vcol_blackhole.result b/mysql-test/suite/vcol/r/vcol_blackhole.result index 15e7505aebb..2d33937a2f1 100644 --- a/mysql-test/suite/vcol/r/vcol_blackhole.result +++ b/mysql-test/suite/vcol/r/vcol_blackhole.result @@ -1,7 +1,7 @@ SET @@session.storage_engine = 'blackhole'; create table t1 (a int, b int as (a+1)); -ERROR HY000: 'Specified storage engine' is not yet supported for computed columns -create table t1 (a int); +ERROR HY000: BLACKHOLE storage engine does not support computed columns +create table t1 (a int not null); alter table t1 add column b int as (a+1); -ERROR HY000: 'Specified storage engine' is not yet supported for computed columns +ERROR HY000: BLACKHOLE storage engine does not support computed columns drop table t1; diff --git a/mysql-test/suite/vcol/r/vcol_csv.result b/mysql-test/suite/vcol/r/vcol_csv.result index 97977505696..920e614c0b1 100644 --- a/mysql-test/suite/vcol/r/vcol_csv.result +++ b/mysql-test/suite/vcol/r/vcol_csv.result @@ -1,7 +1,7 @@ SET @@session.storage_engine = 'CSV'; create table t1 (a int, b int as (a+1)); -ERROR HY000: 'Specified storage engine' is not yet supported for computed columns +ERROR HY000: CSV storage engine does not support computed columns create table t1 (a int not null); alter table t1 add column b int as (a+1); -ERROR HY000: 'Specified storage engine' is not yet supported for computed columns +ERROR HY000: CSV storage engine does not support computed columns drop table t1; diff --git a/mysql-test/suite/vcol/r/vcol_memory.result b/mysql-test/suite/vcol/r/vcol_memory.result index 30b6bd4a4bf..4503c51e39a 100644 --- a/mysql-test/suite/vcol/r/vcol_memory.result +++ b/mysql-test/suite/vcol/r/vcol_memory.result @@ -1,7 +1,7 @@ SET @@session.storage_engine = 'memory'; create table t1 (a int, b int as (a+1)); -ERROR HY000: 'Specified storage engine' is not yet supported for computed columns -create table t1 (a int); +ERROR HY000: MEMORY storage engine does not support computed columns +create table t1 (a int not null); alter table t1 add column b int as (a+1); -ERROR HY000: 'Specified storage engine' is not yet supported for computed columns +ERROR HY000: MEMORY storage engine does not support computed columns drop table t1; diff --git a/mysql-test/suite/vcol/r/vcol_merge.result b/mysql-test/suite/vcol/r/vcol_merge.result index 03a1e151c2e..4b5ed838c3a 100644 --- a/mysql-test/suite/vcol/r/vcol_merge.result +++ b/mysql-test/suite/vcol/r/vcol_merge.result @@ -4,5 +4,5 @@ create table t2 (a int, b int as (a % 10)); insert into t1 values (1,default); insert into t2 values (2,default); create table t3 (a int, b int as (a % 10)) engine=MERGE UNION=(t1,t2); -ERROR HY000: 'Specified storage engine' is not yet supported for computed columns +ERROR HY000: MRG_MYISAM storage engine does not support computed columns drop table t1,t2; diff --git a/mysql-test/suite/vcol/r/vcol_non_stored_columns_innodb.result b/mysql-test/suite/vcol/r/vcol_non_stored_columns_innodb.result index c638ced4f41..0379a71922d 100644 --- a/mysql-test/suite/vcol/r/vcol_non_stored_columns_innodb.result +++ b/mysql-test/suite/vcol/r/vcol_non_stored_columns_innodb.result @@ -76,7 +76,7 @@ drop table t1; # Case 7. ALTER. Modify virtual stored -> virtual non-stored create table t1 (a int, b int as (a % 2) persistent); alter table t1 modify b int as (a % 2); -ERROR HY000: 'Changing the STORED status' is not yet supported for computed columns +ERROR HY000: This is not yet supported for computed columns show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -87,7 +87,7 @@ drop table t1; # Case 8. ALTER. Modify virtual non-stored -> virtual stored create table t1 (a int, b int as (a % 2)); alter table t1 modify b int as (a % 2) persistent; -ERROR HY000: 'Changing the STORED status' is not yet supported for computed columns +ERROR HY000: This is not yet supported for computed columns show create table t1; Table Create Table t1 CREATE TABLE `t1` ( diff --git a/mysql-test/suite/vcol/r/vcol_non_stored_columns_myisam.result b/mysql-test/suite/vcol/r/vcol_non_stored_columns_myisam.result index be42b8b76c4..de9a962ac2c 100644 --- a/mysql-test/suite/vcol/r/vcol_non_stored_columns_myisam.result +++ b/mysql-test/suite/vcol/r/vcol_non_stored_columns_myisam.result @@ -76,7 +76,7 @@ drop table t1; # Case 7. ALTER. Modify virtual stored -> virtual non-stored create table t1 (a int, b int as (a % 2) persistent); alter table t1 modify b int as (a % 2); -ERROR HY000: 'Changing the STORED status' is not yet supported for computed columns +ERROR HY000: This is not yet supported for computed columns show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -87,7 +87,7 @@ drop table t1; # Case 8. ALTER. Modify virtual non-stored -> virtual stored create table t1 (a int, b int as (a % 2)); alter table t1 modify b int as (a % 2) persistent; -ERROR HY000: 'Changing the STORED status' is not yet supported for computed columns +ERROR HY000: This is not yet supported for computed columns show create table t1; Table Create Table t1 CREATE TABLE `t1` ( diff --git a/mysql-test/suite/vcol/t/rpl_vcol.test b/mysql-test/suite/vcol/t/rpl_vcol.test index 2ac31f5ba35..df07b3aed2d 100644 --- a/mysql-test/suite/vcol/t/rpl_vcol.test +++ b/mysql-test/suite/vcol/t/rpl_vcol.test @@ -27,7 +27,7 @@ ##### Storage engine to be tested # Set the session storage engine ---source include/have_innodb.inc +--source include/have_xtradb.inc SET @@session.storage_engine = 'InnoDB'; #------------------------------------------------------------------------------# diff --git a/mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_innodb.test b/mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_innodb.test index 516e121a2aa..baefddc0fd1 100644 --- a/mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_innodb.test +++ b/mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_innodb.test @@ -32,7 +32,7 @@ ##### Storage engine to be tested # Set the session storage engine ---source include/have_innodb.inc +--source include/have_xtradb.inc eval SET @@session.storage_engine = 'InnoDB'; let $skip_full_text_checks = 1; diff --git a/mysql-test/suite/vcol/t/vcol_column_def_options_innodb.test b/mysql-test/suite/vcol/t/vcol_column_def_options_innodb.test index 38baa2b3024..e11618163cc 100644 --- a/mysql-test/suite/vcol/t/vcol_column_def_options_innodb.test +++ b/mysql-test/suite/vcol/t/vcol_column_def_options_innodb.test @@ -33,7 +33,7 @@ ##### Storage engine to be tested # Set the session storage engine ---source include/have_innodb.inc +--source include/have_xtradb.inc eval SET @@session.storage_engine = 'InnoDB'; ##### Workarounds for known open engine specific bugs diff --git a/mysql-test/suite/vcol/t/vcol_csv.test b/mysql-test/suite/vcol/t/vcol_csv.test index b8342e24e07..75ddf819818 100644 --- a/mysql-test/suite/vcol/t/vcol_csv.test +++ b/mysql-test/suite/vcol/t/vcol_csv.test @@ -41,13 +41,7 @@ SET @@session.storage_engine = 'CSV'; # Execute the tests to be applied to all storage engines #------------------------------------------------------------------------------# -# Execute storage engine specific tests ---error ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN -create table t1 (a int, b int as (a+1)); -create table t1 (a int not null); ---error ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN -alter table t1 add column b int as (a+1); -drop table t1; +--source suite/vcol/inc/vcol_unsupported_storage_engines.inc #------------------------------------------------------------------------------# # Cleanup diff --git a/mysql-test/suite/vcol/t/vcol_handler_innodb.test b/mysql-test/suite/vcol/t/vcol_handler_innodb.test index bf443c6bbd3..1a50aeaaa86 100644 --- a/mysql-test/suite/vcol/t/vcol_handler_innodb.test +++ b/mysql-test/suite/vcol/t/vcol_handler_innodb.test @@ -33,7 +33,7 @@ ##### Storage engine to be tested # Set the session storage engine ---source include/have_innodb.inc +--source include/have_xtradb.inc eval SET @@session.storage_engine = 'InnoDB'; ##### Workarounds for known open engine specific bugs diff --git a/mysql-test/suite/vcol/t/vcol_ins_upd_innodb.test b/mysql-test/suite/vcol/t/vcol_ins_upd_innodb.test index 5d9ac12e930..3b83c7f4565 100644 --- a/mysql-test/suite/vcol/t/vcol_ins_upd_innodb.test +++ b/mysql-test/suite/vcol/t/vcol_ins_upd_innodb.test @@ -33,7 +33,7 @@ ##### Storage engine to be tested # Set the session storage engine ---source include/have_innodb.inc +--source include/have_xtradb.inc eval SET @@session.storage_engine = 'InnoDB'; ##### Workarounds for known open engine specific bugs diff --git a/mysql-test/suite/vcol/t/vcol_keys_innodb.test b/mysql-test/suite/vcol/t/vcol_keys_innodb.test index e408672ac07..d44d2f701cf 100644 --- a/mysql-test/suite/vcol/t/vcol_keys_innodb.test +++ b/mysql-test/suite/vcol/t/vcol_keys_innodb.test @@ -33,7 +33,7 @@ ##### Storage engine to be tested # Set the session storage engine ---source include/have_innodb.inc +--source include/have_xtradb.inc eval SET @@session.storage_engine = 'InnoDB'; ##### Workarounds for known open engine specific bugs diff --git a/mysql-test/suite/vcol/t/vcol_merge.test b/mysql-test/suite/vcol/t/vcol_merge.test index 7ba72441bf5..a1d3c628c8e 100644 --- a/mysql-test/suite/vcol/t/vcol_merge.test +++ b/mysql-test/suite/vcol/t/vcol_merge.test @@ -48,7 +48,7 @@ create table t1 (a int, b int as (a % 10)); create table t2 (a int, b int as (a % 10)); insert into t1 values (1,default); insert into t2 values (2,default); ---error ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN +--error ER_UNSUPPORTED_ENGINE_FOR_VIRTUAL_COLUMNS create table t3 (a int, b int as (a % 10)) engine=MERGE UNION=(t1,t2); drop table t1,t2; diff --git a/mysql-test/suite/vcol/t/vcol_non_stored_columns_innodb.test b/mysql-test/suite/vcol/t/vcol_non_stored_columns_innodb.test index 88ed6157294..42834d5c0bb 100644 --- a/mysql-test/suite/vcol/t/vcol_non_stored_columns_innodb.test +++ b/mysql-test/suite/vcol/t/vcol_non_stored_columns_innodb.test @@ -35,7 +35,7 @@ ##### Storage engine to be tested # Set the session storage engine ---source include/have_innodb.inc +--source include/have_xtradb.inc eval SET @@session.storage_engine = 'InnoDB'; ##### Workarounds for known open engine specific bugs diff --git a/mysql-test/suite/vcol/t/vcol_partition_innodb.test b/mysql-test/suite/vcol/t/vcol_partition_innodb.test index 01230120ef9..47f1581fc96 100644 --- a/mysql-test/suite/vcol/t/vcol_partition_innodb.test +++ b/mysql-test/suite/vcol/t/vcol_partition_innodb.test @@ -34,7 +34,7 @@ ##### Storage engine to be tested # Set the session storage engine ---source include/have_innodb.inc +--source include/have_xtradb.inc eval SET @@session.storage_engine = 'InnoDB'; ##### Workarounds for known open engine specific bugs diff --git a/mysql-test/suite/vcol/t/vcol_select_innodb.test b/mysql-test/suite/vcol/t/vcol_select_innodb.test index 314aecb75b9..787f5fe77a7 100644 --- a/mysql-test/suite/vcol/t/vcol_select_innodb.test +++ b/mysql-test/suite/vcol/t/vcol_select_innodb.test @@ -33,7 +33,7 @@ ##### Storage engine to be tested # Set the session storage engine ---source include/have_innodb.inc +--source include/have_xtradb.inc eval SET @@session.storage_engine = 'InnoDB'; ##### Workarounds for known open engine specific bugs diff --git a/mysql-test/suite/vcol/t/vcol_supported_sql_funcs_innodb.test b/mysql-test/suite/vcol/t/vcol_supported_sql_funcs_innodb.test index 53826a460a7..32e2600c2fc 100644 --- a/mysql-test/suite/vcol/t/vcol_supported_sql_funcs_innodb.test +++ b/mysql-test/suite/vcol/t/vcol_supported_sql_funcs_innodb.test @@ -32,7 +32,7 @@ ##### Storage engine to be tested # Set the session storage engine ---source include/have_innodb.inc +--source include/have_xtradb.inc SET @@session.storage_engine = 'InnoDB'; ##### Workarounds for known open engine specific bugs diff --git a/mysql-test/suite/vcol/t/vcol_trigger_sp_innodb.test b/mysql-test/suite/vcol/t/vcol_trigger_sp_innodb.test index 5a36fb1c06d..57655d6d3fe 100644 --- a/mysql-test/suite/vcol/t/vcol_trigger_sp_innodb.test +++ b/mysql-test/suite/vcol/t/vcol_trigger_sp_innodb.test @@ -34,7 +34,7 @@ ##### Storage engine to be tested # Set the session storage engine ---source include/have_innodb.inc +--source include/have_xtradb.inc eval SET @@session.storage_engine = 'InnoDB'; ##### Workarounds for known open engine specific bugs diff --git a/mysql-test/suite/vcol/t/vcol_view_innodb.test b/mysql-test/suite/vcol/t/vcol_view_innodb.test index 01fced8e4c3..322fb122436 100644 --- a/mysql-test/suite/vcol/t/vcol_view_innodb.test +++ b/mysql-test/suite/vcol/t/vcol_view_innodb.test @@ -33,7 +33,7 @@ ##### Storage engine to be tested # Set the session storage engine ---source include/have_innodb.inc +--source include/have_xtradb.inc eval SET @@session.storage_engine = 'InnoDB'; ##### Workarounds for known open engine specific bugs diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 1489ead8b5a..0cf1713ed13 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -253,7 +253,6 @@ public: DBUG_RETURN(0); } virtual void change_table_ptr(TABLE *table_arg, TABLE_SHARE *share); - bool check_if_supported_virtual_columns(void) { return TRUE;} virtual bool check_if_incompatible_data(HA_CREATE_INFO *create_info, uint table_changes); private: diff --git a/sql/handler.h b/sql/handler.h index 33f935cce39..7e39ead5029 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -137,6 +137,7 @@ #define HA_BINLOG_STMT_CAPABLE (LL(1) << 35) /* Has automatic checksums and uses the new checksum format */ #define HA_HAS_NEW_CHECKSUM (LL(1) << 36) +#define HA_CAN_VIRTUAL_COLUMNS (LL(1) << 37) /* Set of all binlog flags. Currently only contain the capabilities @@ -1955,17 +1956,6 @@ public: LEX_STRING *engine_name() { return hton_name(ht); } - /* - @brief - Check whether the engine supports virtual columns - - @retval - FALSE if the engine does not support virtual columns - @retval - TRUE if the engine supports virtual columns - */ - virtual bool check_if_supported_virtual_columns(void) { return FALSE;} - protected: /* deprecated, don't use in new engines */ inline void ha_statistic_increment(ulong SSV::*offset) const { } diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 54061931d5f..a872fa1f1e9 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -6017,7 +6017,7 @@ ER_ONLY_INTEGERS_ALLOWED eng "Only integers allowed as number here" ger "An dieser Stelle sind nur Ganzzahlen zulässig" ER_UNSUPORTED_LOG_ENGINE - eng "This storage engine cannot be used for log tables"" + eng "This storage engine cannot be used for log tables" ger "Diese Speicher-Engine kann für Logtabellen nicht verwendet werden" ER_BAD_LOG_STATEMENT eng "You cannot '%s' a log table if logging is enabled" @@ -6236,13 +6236,15 @@ ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN eng "The value specified for computed column '%s' in table '%s' ignored" ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN - eng "'%s' is not yet supported for computed columns" + eng "This is not yet supported for computed columns" ER_CONST_EXPR_IN_VCOL eng "Constant expression in computed column function is not allowed" ER_ROW_EXPR_FOR_VCOL eng "Expression for computed column cannot return a row" +ER_UNSUPPORTED_ENGINE_FOR_VIRTUAL_COLUMNS + eng "%s storage engine does not support computed columns" ER_UNKNOWN_OPTION eng "Unknown option '%-.64s'" ER_BAD_OPTION_VALUE diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 1d56fd53327..a9ed2a79df4 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6280,9 +6280,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, def->field=field; if (field->stored_in_db != def->stored_in_db) { - my_error(ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN, - MYF(0), - "Changing the STORED status"); + my_error(ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN, MYF(0)); goto err; } if (!def->after) diff --git a/sql/table.cc b/sql/table.cc index af842937491..5f448e48d80 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2337,14 +2337,11 @@ partititon_err: /* Check virtual columns against table's storage engine. */ if (share->vfields && - ((outparam->file && - !outparam->file->check_if_supported_virtual_columns()) || - (!outparam->file && share->db_type() && - share->db_type()->db_type == DB_TYPE_CSV_DB))) // Workaround for CSV + !(outparam->file && + (outparam->file->ha_table_flags() & HA_CAN_VIRTUAL_COLUMNS))) { - my_error(ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN, - MYF(0), - "Specified storage engine"); + my_error(ER_UNSUPPORTED_ENGINE_FOR_VIRTUAL_COLUMNS, MYF(0), + plugin_name(share->db_plugin)->str); error_reported= TRUE; goto err; } diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 256455d4531..2b6e7c1b3a6 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -821,7 +821,7 @@ int_table_flags(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER | HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE | HA_DUPLICATE_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY | HA_FILE_BASED | HA_CAN_GEOMETRY | CANNOT_ROLLBACK_FLAG | - HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS | + HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS | HA_CAN_VIRTUAL_COLUMNS | HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT), can_enable_indexes(1), bulk_insert_single_undo(BULK_INSERT_NONE) {} diff --git a/storage/maria/ha_maria.h b/storage/maria/ha_maria.h index 251e4069d59..39307e5efdd 100644 --- a/storage/maria/ha_maria.h +++ b/storage/maria/ha_maria.h @@ -143,7 +143,6 @@ public: int assign_to_keycache(THD * thd, HA_CHECK_OPT * check_opt); int preload_keys(THD * thd, HA_CHECK_OPT * check_opt); bool check_if_incompatible_data(HA_CREATE_INFO * info, uint table_changes); - bool check_if_supported_virtual_columns(void) { return TRUE;} #ifdef HAVE_REPLICATION int dump(THD * thd, int fd); int net_read_dump(NET * net); diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index d3d073d2fbe..09a20383937 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -545,6 +545,7 @@ ha_myisam::ha_myisam(handlerton *hton, TABLE_SHARE *table_arg) :handler(hton, table_arg), file(0), int_table_flags(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER | HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE | + HA_CAN_VIRTUAL_COLUMNS | HA_DUPLICATE_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY | HA_FILE_BASED | HA_CAN_GEOMETRY | HA_NO_TRANSACTIONS | HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS | diff --git a/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h index 0cb89b64c3c..d8f307c4aa7 100644 --- a/storage/myisam/ha_myisam.h +++ b/storage/myisam/ha_myisam.h @@ -133,7 +133,6 @@ class ha_myisam: public handler int assign_to_keycache(THD* thd, HA_CHECK_OPT* check_opt); int preload_keys(THD* thd, HA_CHECK_OPT* check_opt); bool check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes); - bool check_if_supported_virtual_columns(void) { return TRUE;} #ifdef HAVE_REPLICATION int dump(THD* thd, int fd); int net_read_dump(NET* net); diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 42e9c99b95c..ee060f61c75 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -1471,7 +1471,7 @@ UNIV_INTERN ha_innobase::ha_innobase(handlerton *hton, TABLE_SHARE *table_arg) :handler(hton, table_arg), int_table_flags(HA_REC_NOT_IN_SEQ | - HA_NULL_IN_KEY | + HA_NULL_IN_KEY | HA_CAN_VIRTUAL_COLUMNS | HA_CAN_INDEX_BLOBS | HA_CAN_SQL_HANDLER | HA_PRIMARY_KEY_REQUIRED_FOR_POSITION | diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h index deb72307df0..c60a5eae19e 100644 --- a/storage/xtradb/handler/ha_innodb.h +++ b/storage/xtradb/handler/ha_innodb.h @@ -222,7 +222,6 @@ class ha_innobase: public handler /** @} */ bool check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes); - bool check_if_supported_virtual_columns(void) { return TRUE; } }; /* Some accessor functions which the InnoDB plugin needs, but which From 92fc42638661bf574009c4a3cd6a812d948db8e9 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 3 Jan 2011 15:33:39 +0100 Subject: [PATCH 16/27] Speed up `mtr --parallel=` by scheduling some slow tests earlier. The patch also fixes a race in rpl_stop_slave.test. On machines with lots of CPU and memory, something like `mtr --parallel=10` can speed up the test suite enormously. However, we have a few test cases that run for long (several minutes), and if we are unlucky and happen to schedule those towards the end of the test suite, we end up with most workers idle while waiting for the last slow test to end, significantly delaying the finish of the entire suite. Improve this by marking the offending tests as taking "long", and trying to schedule those tests early. This reduces the time towards the end of the test suite run where some workers are waiting with nothing to do for the remaining workers each to finish their last test. Also, the rpl_stop_slave test had a race which could cause it to take a 300 seconds debug_sync timeout; this is fixed. Testing on a 4-core 8GB machine, this patch speeds up the test suite with around 30% for --parallel=10 (debug build), allowing to run the entire suite in 5 minutes. --- .../extra/rpl_tests/rpl_stop_slave.test | 1 + mysql-test/include/long_test.inc | 4 ++++ mysql-test/lib/mtr_cases.pm | 19 ++++++++++++++++--- mysql-test/mysql-test-run.pl | 8 +++++--- .../suite/federated/federated_debug.test | 1 + .../maria/t/maria-recovery-rtree-ft.test | 1 + .../parts/t/partition_alter2_1_myisam.test | 2 ++ .../parts/t/partition_alter2_2_myisam.test | 2 ++ .../suite/parts/t/partition_basic_innodb.test | 2 ++ .../parts/t/partition_decimal_myisam.test | 2 ++ .../suite/parts/t/partition_float_myisam.test | 2 ++ .../suite/parts/t/partition_int_myisam.test | 2 ++ mysql-test/suite/rpl/r/rpl_stop_slave.result | 4 ++++ .../suite/rpl/t/rpl_deadlock_innodb.test | 1 + mysql-test/suite/rpl/t/rpl_row_sp003.test | 1 + mysql-test/t/join_outer.test | 2 ++ mysql-test/t/multi_update2.test | 2 ++ mysql-test/t/pool_of_threads.test | 1 + mysql-test/t/query_cache.test | 1 + sql/sql_parse.cc | 11 ++++++++--- 20 files changed, 60 insertions(+), 9 deletions(-) create mode 100644 mysql-test/include/long_test.inc diff --git a/mysql-test/extra/rpl_tests/rpl_stop_slave.test b/mysql-test/extra/rpl_tests/rpl_stop_slave.test index 7c88afe3532..5adfc99d59e 100644 --- a/mysql-test/extra/rpl_tests/rpl_stop_slave.test +++ b/mysql-test/extra/rpl_tests/rpl_stop_slave.test @@ -42,6 +42,7 @@ send STOP SLAVE SQL_THREAD; connection slave1; --echo # To resume slave SQL thread SET DEBUG_SYNC= 'now SIGNAL signal.continue'; +SET DEBUG_SYNC= 'now WAIT_FOR signal.continued'; SET DEBUG_SYNC= 'RESET'; --echo diff --git a/mysql-test/include/long_test.inc b/mysql-test/include/long_test.inc new file mode 100644 index 00000000000..d9a3b338229 --- /dev/null +++ b/mysql-test/include/long_test.inc @@ -0,0 +1,4 @@ +# We use this --source include to mark a test as taking long to run. +# We can use this to schedule such test early (to not be left with +# only one or two long tests running, and rests of works idle), or to +# run a quick test skipping long-running test cases. diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index 3ed2f072e9e..39a4e28823b 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -89,6 +89,20 @@ sub init_pattern { } +sub testcase_sort_order { + my ($a, $b, $sort_criteria)= @_; + my $a_sort_criteria= $sort_criteria->{$a->fullname()}; + my $b_sort_criteria= $sort_criteria->{$b->fullname()}; + my $res= $a_sort_criteria cmp $b_sort_criteria; + return $res if $res; + # Run slow tests first, trying to avoid getting stuck at the end + # with a slow test in one worker and the other workers idle. + return -1 if $a->{'long_test'} && !$b->{'long_test'}; + return 1 if !$a->{'long_test'} && $b->{'long_test'}; + + return $a->fullname() cmp $b->fullname(); +} + ############################################################################## # # Collect information about test cases to be run @@ -177,9 +191,7 @@ sub collect_test_cases ($$$) { $sort_criteria{$tinfo->fullname()} = join(" ", @criteria); } - @$cases = sort { - $sort_criteria{$a->fullname()} . $a->fullname() cmp - $sort_criteria{$b->fullname()} . $b->fullname() } @$cases; + @$cases = sort { testcase_sort_order($a, $b, \%sort_criteria) } @$cases; # For debugging the sort-order # foreach my $tinfo (@$cases) @@ -1054,6 +1066,7 @@ my @tags= ["include/not_valgrind.inc", "not_valgrind", 1], ["include/have_example_plugin.inc", "example_plugin_test", 1], ["include/have_ssl.inc", "need_ssl", 1], + ["include/long_test.inc", "long_test", 1], ); diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 1f420d2acde..4a652580d97 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -729,9 +729,11 @@ sub run_test_server ($$$) { last; } - # Second best choice is the first that does not fulfill - # any of the above conditions - if (!defined $second_best){ + # From secondary choices, we prefer to pick a 'long-running' test if + # possible; this helps avoid getting stuck with a few of those at the + # end of high --parallel runs, with most workers being idle. + if (!defined $second_best || + ($t->{'long_test'} && !($tests->[$second_best]{'long_test'}))){ #mtr_report("Setting second_best to $i"); $second_best= $i; } diff --git a/mysql-test/suite/federated/federated_debug.test b/mysql-test/suite/federated/federated_debug.test index 4152d2975b3..d63c1007088 100644 --- a/mysql-test/suite/federated/federated_debug.test +++ b/mysql-test/suite/federated/federated_debug.test @@ -1,4 +1,5 @@ --source include/have_debug.inc +--source include/long_test.inc --source federated.inc --echo # diff --git a/mysql-test/suite/maria/t/maria-recovery-rtree-ft.test b/mysql-test/suite/maria/t/maria-recovery-rtree-ft.test index 3ede5002b72..ac71be376f1 100644 --- a/mysql-test/suite/maria/t/maria-recovery-rtree-ft.test +++ b/mysql-test/suite/maria/t/maria-recovery-rtree-ft.test @@ -6,6 +6,7 @@ # Binary must be compiled with debug for crash to occur --source include/have_debug.inc --source include/have_maria.inc +--source include/long_test.inc set global maria_log_file_size=4294967295; let $MARIA_LOG=.; diff --git a/mysql-test/suite/parts/t/partition_alter2_1_myisam.test b/mysql-test/suite/parts/t/partition_alter2_1_myisam.test index 1c89a82b960..11ec9b51f7c 100644 --- a/mysql-test/suite/parts/t/partition_alter2_1_myisam.test +++ b/mysql-test/suite/parts/t/partition_alter2_1_myisam.test @@ -22,6 +22,8 @@ # any of the variables. # +--source include/long_test.inc + #------------------------------------------------------------------------------# # General not engine specific settings and requirements diff --git a/mysql-test/suite/parts/t/partition_alter2_2_myisam.test b/mysql-test/suite/parts/t/partition_alter2_2_myisam.test index c9b22ed8595..8fbb943a48d 100644 --- a/mysql-test/suite/parts/t/partition_alter2_2_myisam.test +++ b/mysql-test/suite/parts/t/partition_alter2_2_myisam.test @@ -22,6 +22,8 @@ # any of the variables. # +--source include/long_test.inc + #------------------------------------------------------------------------------# # General not engine specific settings and requirements diff --git a/mysql-test/suite/parts/t/partition_basic_innodb.test b/mysql-test/suite/parts/t/partition_basic_innodb.test index 2fa94cbde21..8240257f087 100644 --- a/mysql-test/suite/parts/t/partition_basic_innodb.test +++ b/mysql-test/suite/parts/t/partition_basic_innodb.test @@ -22,6 +22,8 @@ # any of the variables. # +--source include/long_test.inc + #------------------------------------------------------------------------------# # General not engine specific settings and requirements diff --git a/mysql-test/suite/parts/t/partition_decimal_myisam.test b/mysql-test/suite/parts/t/partition_decimal_myisam.test index 49fc64cbd37..9808dc878f8 100644 --- a/mysql-test/suite/parts/t/partition_decimal_myisam.test +++ b/mysql-test/suite/parts/t/partition_decimal_myisam.test @@ -22,6 +22,8 @@ # any of the variables. # +--source include/long_test.inc + #------------------------------------------------------------------------------# # General not engine specific settings and requirements diff --git a/mysql-test/suite/parts/t/partition_float_myisam.test b/mysql-test/suite/parts/t/partition_float_myisam.test index 51e0f1f5a21..f15e6ad3636 100644 --- a/mysql-test/suite/parts/t/partition_float_myisam.test +++ b/mysql-test/suite/parts/t/partition_float_myisam.test @@ -22,6 +22,8 @@ # any of the variables. # +--source include/long_test.inc + #------------------------------------------------------------------------------# # General not engine specific settings and requirements diff --git a/mysql-test/suite/parts/t/partition_int_myisam.test b/mysql-test/suite/parts/t/partition_int_myisam.test index b0ede4995e8..5f29b575244 100644 --- a/mysql-test/suite/parts/t/partition_int_myisam.test +++ b/mysql-test/suite/parts/t/partition_int_myisam.test @@ -22,6 +22,8 @@ # any of the variables. # +--source include/long_test.inc + #------------------------------------------------------------------------------# # General not engine specific settings and requirements diff --git a/mysql-test/suite/rpl/r/rpl_stop_slave.result b/mysql-test/suite/rpl/r/rpl_stop_slave.result index 49146417ab7..4e16e8264f6 100644 --- a/mysql-test/suite/rpl/r/rpl_stop_slave.result +++ b/mysql-test/suite/rpl/r/rpl_stop_slave.result @@ -38,6 +38,7 @@ STOP SLAVE SQL_THREAD; [ On Slave1 ] # To resume slave SQL thread SET DEBUG_SYNC= 'now SIGNAL signal.continue'; +SET DEBUG_SYNC= 'now WAIT_FOR signal.continued'; SET DEBUG_SYNC= 'RESET'; [ On Slave ] @@ -63,6 +64,7 @@ STOP SLAVE SQL_THREAD; [ On Slave1 ] # To resume slave SQL thread SET DEBUG_SYNC= 'now SIGNAL signal.continue'; +SET DEBUG_SYNC= 'now WAIT_FOR signal.continued'; SET DEBUG_SYNC= 'RESET'; [ On Slave ] @@ -89,6 +91,7 @@ STOP SLAVE SQL_THREAD; [ On Slave1 ] # To resume slave SQL thread SET DEBUG_SYNC= 'now SIGNAL signal.continue'; +SET DEBUG_SYNC= 'now WAIT_FOR signal.continued'; SET DEBUG_SYNC= 'RESET'; [ On Slave ] @@ -115,6 +118,7 @@ STOP SLAVE SQL_THREAD; [ On Slave1 ] # To resume slave SQL thread SET DEBUG_SYNC= 'now SIGNAL signal.continue'; +SET DEBUG_SYNC= 'now WAIT_FOR signal.continued'; SET DEBUG_SYNC= 'RESET'; [ On Slave ] diff --git a/mysql-test/suite/rpl/t/rpl_deadlock_innodb.test b/mysql-test/suite/rpl/t/rpl_deadlock_innodb.test index ee907f81b22..169ccbf7f18 100644 --- a/mysql-test/suite/rpl/t/rpl_deadlock_innodb.test +++ b/mysql-test/suite/rpl/t/rpl_deadlock_innodb.test @@ -7,5 +7,6 @@ ######################################################## -- source include/not_ndb_default.inc -- source include/have_innodb.inc +-- source include/long_test.inc let $engine_type=innodb; -- source extra/rpl_tests/rpl_deadlock.test diff --git a/mysql-test/suite/rpl/t/rpl_row_sp003.test b/mysql-test/suite/rpl/t/rpl_row_sp003.test index ab49174ddfa..8ed47232ba9 100644 --- a/mysql-test/suite/rpl/t/rpl_row_sp003.test +++ b/mysql-test/suite/rpl/t/rpl_row_sp003.test @@ -10,6 +10,7 @@ -- source include/have_binlog_format_row.inc # Slow test, don't run during staging part -- source include/not_staging.inc +--source include/long_test.inc -- source include/master-slave.inc let $engine_type=INNODB; diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test index a957c715bda..c8fa2a35538 100644 --- a/mysql-test/t/join_outer.test +++ b/mysql-test/t/join_outer.test @@ -1,3 +1,5 @@ +--source include/long_test.inc + # # test of left outer join # diff --git a/mysql-test/t/multi_update2.test b/mysql-test/t/multi_update2.test index 9c5078efb6f..a0f17fabec4 100644 --- a/mysql-test/t/multi_update2.test +++ b/mysql-test/t/multi_update2.test @@ -1,3 +1,5 @@ +--source include/long_test.inc + # # Test of update statement that uses many tables. # diff --git a/mysql-test/t/pool_of_threads.test b/mysql-test/t/pool_of_threads.test index e71b16e1f89..530038cee91 100644 --- a/mysql-test/t/pool_of_threads.test +++ b/mysql-test/t/pool_of_threads.test @@ -4,6 +4,7 @@ -- source include/have_pool_of_threads.inc # Slow test, don't run during staging part -- source include/not_staging.inc +-- source include/long_test.inc -- source include/common-tests.inc diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index de8467b509d..24487db826a 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -1,4 +1,5 @@ -- source include/have_query_cache.inc +-- source include/long_test.inc # # Tests with query cache diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 57ee5686bed..49879cb7edb 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3286,12 +3286,17 @@ end_with_restore_list: DBUG_EXECUTE_IF("after_mysql_insert", { - const char act[]= + const char act1[]= "now " "wait_for signal.continue"; + const char act2[]= + "now " + "signal signal.continued"; DBUG_ASSERT(opt_debug_sync_timeout > 0); - DBUG_ASSERT(!debug_sync_set_action(current_thd, - STRING_WITH_LEN(act))); + DBUG_ASSERT(!debug_sync_set_action(thd, + STRING_WITH_LEN(act1))); + DBUG_ASSERT(!debug_sync_set_action(thd, + STRING_WITH_LEN(act2))); };); break; } From 427c6c78ded2ee3f22f709a50a08eccfb0394503 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Tue, 4 Jan 2011 15:47:21 +0200 Subject: [PATCH 17/27] Updated README for MTR test suite --- mysql-test/README | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/mysql-test/README b/mysql-test/README index 3c8303ca070..d3be11278fc 100644 --- a/mysql-test/README +++ b/mysql-test/README @@ -4,13 +4,14 @@ this directory. It will fire up the newly built mysqld and test it. Note that you do not have to have to do "make install", and you could actually have a co-existing MySQL installation. The tests will not -conflict with it. +conflict with it. To run the test suite in a source directory, you +must do make first. All tests must pass. If one or more of them fail on your system, please read the following manual section for instructions on how to report the problem: -http://dev.mysql.com/doc/mysql/en/mysql-test-suite.html +http://kb.askmonty.org/v/reporting-bugs If you want to use an already running MySQL server for specific tests, use the --extern option to mysql-test-run. Please note that in this mode, @@ -27,7 +28,6 @@ With no test cases named on the command line, mysql-test-run falls back to the normal "non-extern" behavior. The reason for this is that some tests cannot run with an external server. - You can create your own test cases. To create a test case, create a new file in the t subdirectory using a text editor. The file should have a .test extension. For example: @@ -67,7 +67,12 @@ extension. For example: edit the test result to the correct results so that we can verify that the bug is corrected in future releases. -To submit your test case, put your .test file and .result file(s) into -a tar.gz archive, add a README that explains the problem, ftp the -archive to ftp://support.mysql.com/pub/mysql/secret/ and send a mail -to bugs@lists.mysql.com +If you want to submit your test case you can send it +to maria-developers@lists.launchpad.com or attach it to a bug report on +https://bugs.launchpad.net/maria/. + +If the test case is really big or if it contains 'not public' data, +then put your .test file and .result file(s) into a tar.gz archive, +add a README that explains the problem, ftp the archive to +ftp://ftp.askmonty.org/private and send a mail to +https://bugs.launchpad.net/maria/ about it. From 1e0b42d91ff9c9d806b95c4b04363fd61b42181e Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Wed, 5 Jan 2011 00:09:05 +0200 Subject: [PATCH 18/27] Fixed recovery problem in Aria where bitmap had wrong information after recovery. LP#619731: Aria recovery corruption "Page 1: Row: 1 has an extent with wrong information in bitmap storage/maria/ma_bitmap.c: Don't send broadcast if no one is waiting for it storage/maria/ma_blockrec.c: Don't update bitmap if the page is not in the dirty_page list (or LSN is after checkpoint start) Fixes the case where we have in the log redo_free_block followed by another redo entry for the same page which is ignored. Also fixed that _ma_apply_redo_insert_row_blobs() doesn't update the bitmap in similar circumstances. storage/maria/ma_blockrec.h: Updated prototype storage/maria/ma_check.c: Added printing of bitmap information if used with maria_chk -vvv (for debugging) storage/maria/ma_recovery.c: Updated call parameters to _ma_apply_redo_free_blocks(). --- storage/maria/ma_bitmap.c | 6 ++-- storage/maria/ma_blockrec.c | 54 ++++++++++++++++++++----------- storage/maria/ma_blockrec.h | 2 +- storage/maria/ma_check.c | 63 ++++++++++++++++++++++++++++++++++--- storage/maria/ma_recovery.c | 9 +++--- 5 files changed, 104 insertions(+), 30 deletions(-) diff --git a/storage/maria/ma_bitmap.c b/storage/maria/ma_bitmap.c index 7e68437de2b..bc83f6ea0e9 100644 --- a/storage/maria/ma_bitmap.c +++ b/storage/maria/ma_bitmap.c @@ -399,7 +399,8 @@ my_bool _ma_bitmap_flush_all(MARIA_SHARE *share) become false, wake them up. */ DBUG_PRINT("info", ("bitmap flusher waking up others")); - pthread_cond_broadcast(&bitmap->bitmap_cond); + if (bitmap->flush_all_requested) + pthread_cond_broadcast(&bitmap->bitmap_cond); } pthread_mutex_unlock(&bitmap->bitmap_lock); DBUG_RETURN(res); @@ -465,7 +466,8 @@ void _ma_bitmap_unlock(MARIA_SHARE *share) bitmap->flush_all_requested--; bitmap->non_flushable= 0; pthread_mutex_unlock(&bitmap->bitmap_lock); - pthread_cond_broadcast(&bitmap->bitmap_cond); + if (bitmap->flush_all_requested > 0) + pthread_cond_broadcast(&bitmap->bitmap_cond); DBUG_VOID_RETURN; } diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index 2c3ff43c6ec..abad594ad18 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -6485,7 +6485,13 @@ err: @param info Maria handler @param header Header (without FILEID) - @note It marks the pages free in the bitmap + Mark the pages free in the bitmap. + + We have to check against _ma_redo_not_needed_for_page() + to guard against the case where we first clear a block and after + that insert new data into the blocks. If we would unconditionally + clear the bitmap here, future changes would be ignored for the page + if it's not in the dirty list (ie, it would be flushed). @return Operation status @retval 0 OK @@ -6494,19 +6500,25 @@ err: uint _ma_apply_redo_free_blocks(MARIA_HA *info, LSN lsn __attribute__((unused)), + LSN redo_lsn, const uchar *header) { MARIA_SHARE *share= info->s; uint ranges; + uint16 sid; DBUG_ENTER("_ma_apply_redo_free_blocks"); share->state.changed|= (STATE_CHANGED | STATE_NOT_ZEROFILLED | STATE_NOT_MOVABLE); + sid= fileid_korr(header); + header+= FILEID_STORE_SIZE; ranges= pagerange_korr(header); header+= PAGERANGE_STORE_SIZE; DBUG_ASSERT(ranges > 0); + /** @todo leave bitmap lock to the bitmap code... */ + pthread_mutex_lock(&share->bitmap.bitmap_lock); while (ranges--) { my_bool res; @@ -6523,18 +6535,22 @@ uint _ma_apply_redo_free_blocks(MARIA_HA *info, DBUG_PRINT("info", ("page: %lu pages: %u", (long) page, page_range)); - /** @todo leave bitmap lock to the bitmap code... */ - pthread_mutex_lock(&share->bitmap.bitmap_lock); - res= _ma_bitmap_reset_full_page_bits(info, &share->bitmap, start_page, - page_range); - pthread_mutex_unlock(&share->bitmap.bitmap_lock); - if (res) + for ( ; page_range-- ; start_page++) { - _ma_mark_file_crashed(share); - DBUG_ASSERT(0); - DBUG_RETURN(res); + if (_ma_redo_not_needed_for_page(sid, redo_lsn, start_page, FALSE)) + continue; + res= _ma_bitmap_reset_full_page_bits(info, &share->bitmap, start_page, + 1); + if (res) + { + pthread_mutex_unlock(&share->bitmap.bitmap_lock); + _ma_mark_file_crashed(share); + DBUG_ASSERT(0); + DBUG_RETURN(res); + } } } + pthread_mutex_unlock(&share->bitmap.bitmap_lock); DBUG_RETURN(0); } @@ -6764,7 +6780,7 @@ uint _ma_apply_redo_insert_row_blobs(MARIA_HA *info, PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, LSN_IMPOSSIBLE, LSN_IMPOSSIBLE, 0, FALSE); - continue; + goto fix_bitmap; } DBUG_ASSERT((found_page_type == (uchar) BLOB_PAGE) || (found_page_type == (uchar) UNALLOCATED_PAGE)); @@ -6799,14 +6815,16 @@ uint _ma_apply_redo_insert_row_blobs(MARIA_HA *info, unlock_method, unpin_method, PAGECACHE_WRITE_DELAY, 0, LSN_IMPOSSIBLE)) goto err; - } + + fix_bitmap: /** @todo leave bitmap lock to the bitmap code... */ - pthread_mutex_lock(&share->bitmap.bitmap_lock); - res= _ma_bitmap_set_full_page_bits(info, &share->bitmap, start_page, - page_range); - pthread_mutex_unlock(&share->bitmap.bitmap_lock); - if (res) - goto err; + pthread_mutex_lock(&share->bitmap.bitmap_lock); + res= _ma_bitmap_set_full_page_bits(info, &share->bitmap, page, + 1); + pthread_mutex_unlock(&share->bitmap.bitmap_lock); + if (res) + goto err; + } } } *first_page= first_page2; diff --git a/storage/maria/ma_blockrec.h b/storage/maria/ma_blockrec.h index a5858880dd0..e63af8eed5b 100644 --- a/storage/maria/ma_blockrec.h +++ b/storage/maria/ma_blockrec.h @@ -235,7 +235,7 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, uint _ma_apply_redo_purge_row_head_or_tail(MARIA_HA *info, LSN lsn, uint page_type, const uchar *header); -uint _ma_apply_redo_free_blocks(MARIA_HA *info, LSN lsn, +uint _ma_apply_redo_free_blocks(MARIA_HA *info, LSN lsn, LSN rec_lsn, const uchar *header); uint _ma_apply_redo_free_head_or_tail(MARIA_HA *info, LSN lsn, const uchar *header); diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 1cb14567804..631fa879504 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -100,6 +100,9 @@ static my_bool _ma_flush_table_files_before_swap(HA_CHECK *param, static TrID max_trid_in_system(void); static void _ma_check_print_not_visible_error(HA_CHECK *param, TrID used_trid); void retry_if_quick(MARIA_SORT_PARAM *param, int error); +static void print_bitmap_description(MARIA_SHARE *share, + pgcache_page_no_t page, + uchar *buff); /* Initialize check param with default values */ @@ -1842,6 +1845,8 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, } param->used+= block_size; param->link_used+= block_size; + if (param->verbose > 2) + print_bitmap_description(share, page, bitmap_buff); continue; } /* Skip pages marked as empty in bitmap */ @@ -2177,12 +2182,17 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info, my_bool extend) llstr(param->del_length, llbuff2)); printf("Empty space: %12s Linkdata: %10s\n", llstr(param->empty, llbuff),llstr(param->link_used, llbuff2)); - if (param->lost) - printf("Lost space: %12s", llstr(param->lost, llbuff)); - if (param->max_found_trid) + if (share->data_file_type == BLOCK_RECORD) { - printf("Max trans. id: %11s\n", - llstr(param->max_found_trid, llbuff)); + printf("Full pages: %12s Tail count: %12s\n", + llstr(param->full_page_count, llbuff), + llstr(param->tail_count, llbuff2)); + printf("Lost space: %12s\n", llstr(param->lost, llbuff)); + if (param->max_found_trid) + { + printf("Max trans. id: %11s\n", + llstr(param->max_found_trid, llbuff)); + } } } my_free(record,MYF(0)); @@ -6799,3 +6809,46 @@ void retry_if_quick(MARIA_SORT_PARAM *sort_param, int error) param->testflag|=T_RETRY_WITHOUT_QUICK; } } + +/* Print information about bitmap page */ + +static void print_bitmap_description(MARIA_SHARE *share, + pgcache_page_no_t page, + uchar *bitmap_data) +{ + uchar *pos, *end; + MARIA_FILE_BITMAP *bitmap= &share->bitmap; + uint count=0, dot_printed= 0; + char buff[80], last[80]; + + printf("Bitmap page %lu\n", (ulong) page); + page++; + last[0]=0; + for (pos= bitmap_data, end= pos+ bitmap->used_size ; pos < end ; pos+= 6) + { + ulonglong bits= uint6korr(pos); /* 6 bytes = 6*8/3= 16 patterns */ + uint i; + + for (i= 0; i < 16 ; i++, bits>>= 3) + { + if (count > 60) + { + buff[count]= 0; + if (strcmp(buff, last)) + { + memcpy(last, buff, count+1); + printf("%8lu: %s\n", (ulong) page - count, buff); + dot_printed= 0; + } + else if (!(dot_printed++)) + printf("...\n"); + count= 0; + } + buff[count++]= '0' + (uint) (bits & 7); + page++; + } + } + buff[count]= 0; + printf("%8lu: %s\n", (ulong) page - count, buff); + fputs("\n", stdout); +} diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c index c88aedfca78..58cecabfe20 100644 --- a/storage/maria/ma_recovery.c +++ b/storage/maria/ma_recovery.c @@ -1643,8 +1643,8 @@ prototype_redo_exec_hook(REDO_FREE_BLOCKS) } buff= log_record_buffer.str; - if (_ma_apply_redo_free_blocks(info, current_group_end_lsn, - buff + FILEID_STORE_SIZE)) + if (_ma_apply_redo_free_blocks(info, current_group_end_lsn, rec->lsn, + buff)) goto end; error= 0; end: @@ -3015,10 +3015,11 @@ static MARIA_HA *get_MARIA_HA_from_REDO_record(const page= page_korr(rec->header + FILEID_STORE_SIZE); llstr(page, llbuf); break; + case LOGREC_REDO_FREE_BLOCKS: /* - For REDO_FREE_BLOCKS, no need to look at dirty pages list: it does not - read data pages, only reads/modifies bitmap page(s) which is cheap. + We are checking against the dirty pages in _ma_apply_redo_free_blocks() */ + break; default: break; } From 711b36732b6913c189e1075441c7c9bd8ef529da Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Wed, 5 Jan 2011 14:50:08 +0200 Subject: [PATCH 19/27] Make copy from heap to MyISAM / Aria killable. Fixes LP#695006 converting HEAP to Aria" status do not respond to KILL QUERY sql/sql_select.cc: Make copy from heap to MyISAM / Aria killable. --- sql/sql_select.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 60bfa0dfcd6..98ebef5bb9c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -11210,6 +11210,11 @@ create_internal_tmp_table_from_heap2(THD *thd, TABLE *table, DBUG_EXECUTE_IF("raise_error", write_err= HA_ERR_FOUND_DUPP_KEY ;); if (write_err) goto err; + if (thd->killed) + { + thd->send_kill_message(); + goto err_killed; + } } /* copy row that filled HEAP table */ if ((write_err=new_table.file->ha_write_row(table->record[0]))) @@ -11240,6 +11245,7 @@ create_internal_tmp_table_from_heap2(THD *thd, TABLE *table, err: DBUG_PRINT("error",("Got error: %d",write_err)); table->file->print_error(write_err, MYF(0)); +err_killed: (void) table->file->ha_rnd_end(); (void) new_table.file->close(); err1: From ab32ce9aa7fb09b2fb578e5bb44f004092bf1d89 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Wed, 5 Jan 2011 15:09:06 +0200 Subject: [PATCH 20/27] ALTER TABLE IGNORE didn't ignore duplicates for unique add index for InnoDB --- mysql-test/suite/innodb/r/innodb_mysql.result | 7 +++++++ mysql-test/suite/innodb/t/innodb_mysql.test | 9 +++++++++ sql/sql_table.cc | 10 ++++++++++ 3 files changed, 26 insertions(+) diff --git a/mysql-test/suite/innodb/r/innodb_mysql.result b/mysql-test/suite/innodb/r/innodb_mysql.result index 86a51b337ff..08fb0bdfe2e 100644 --- a/mysql-test/suite/innodb/r/innodb_mysql.result +++ b/mysql-test/suite/innodb/r/innodb_mysql.result @@ -2617,6 +2617,13 @@ rows 3 Extra Using index DROP TABLE t1; # +# ALTER TABLE IGNORE didn't ignore duplicates for unique add index +# +create table t1 (a int primary key, b int) engine = innodb; +insert into t1 values (1,1),(2,1); +alter ignore table t1 add unique `main` (b); +drop table t1; +# End of 5.1 tests # # Test for bug #39932 "create table fails if column for FK is in different diff --git a/mysql-test/suite/innodb/t/innodb_mysql.test b/mysql-test/suite/innodb/t/innodb_mysql.test index 991440e54dd..177dabdc3e1 100644 --- a/mysql-test/suite/innodb/t/innodb_mysql.test +++ b/mysql-test/suite/innodb/t/innodb_mysql.test @@ -840,6 +840,15 @@ CREATE INDEX b ON t1(a,b,c,d); DROP TABLE t1; +--echo # +--echo # ALTER TABLE IGNORE didn't ignore duplicates for unique add index +--echo # + +create table t1 (a int primary key, b int) engine = innodb; +insert into t1 values (1,1),(2,1); +alter ignore table t1 add unique `main` (b); +drop table t1; + --echo # diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 8446ca46e3c..a7a0a96ce10 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7136,6 +7136,16 @@ view_err: /* Non-primary unique key. */ needed_online_flags|= HA_ONLINE_ADD_UNIQUE_INDEX; needed_fast_flags|= HA_ONLINE_ADD_UNIQUE_INDEX_NO_WRITES; + if (ignore) + { + /* + If ignore is used, we have to remove all duplicate rows, + which require a full table copy. + */ + need_copy_table= ALTER_TABLE_DATA_CHANGED; + pk_changed= 2; // Don't change need_copy_table + break; + } } } else From 6b03fbf9fcacc74cb2999ba7715d22d754f356c7 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Wed, 5 Jan 2011 15:46:44 +0200 Subject: [PATCH 21/27] Fixed overwrite of directory information on the row page. This could only happen with very small rows on very full pages with old deleted information in middle of page. --- storage/maria/ma_blockrec.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index abad594ad18..dab88287f86 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -2816,7 +2816,6 @@ static my_bool write_block_record(MARIA_HA *info, DBUG_PRINT("info", ("Used head length on page: %u header_length: %u", head_length, (uint) (flag & ROW_FLAG_TRANSID ? TRANSID_SIZE : 0))); - DBUG_ASSERT(data <= end_of_data); if (head_length < share->base.min_block_length) { /* Extend row to be of size min_block_length */ @@ -2825,6 +2824,7 @@ static my_bool write_block_record(MARIA_HA *info, data+= diff_length; head_length= share->base.min_block_length; } + DBUG_ASSERT(data <= end_of_data); /* If this is a redo entry (ie, undo_lsn != LSN_ERROR) then we should have written exactly head_length bytes (same as original record). @@ -3492,7 +3492,9 @@ static my_bool allocate_and_write_block_record(MARIA_HA *info, /* page will be pinned & locked by get_head_or_tail_page */ if (get_head_or_tail_page(info, blocks->block, info->buff, - row->space_on_head_page, HEAD_PAGE, + max(row->space_on_head_page, + info->s->base.min_block_length), + HEAD_PAGE, PAGECACHE_LOCK_WRITE, &row_pos)) goto err; row->lastpos= ma_recordpos(blocks->block->page, row_pos.rownr); From d653a80d2a62669243477b82757068a1b7874dbb Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 6 Jan 2011 15:55:29 +0100 Subject: [PATCH 22/27] MBug#698132: Fix wrong buffer calculation in send_change_user_packet() --- sql-common/client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql-common/client.c b/sql-common/client.c index 3788ca9829b..c449cd17100 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1978,7 +1978,7 @@ static int send_change_user_packet(MCPVIO_EXT *mpvio, char *buff, *end; int res= 1; - buff= my_alloca(USERNAME_LENGTH + data_len + 1 + NAME_LEN + 2 + NAME_LEN); + buff= my_alloca(USERNAME_LENGTH+1 + data_len+1 + NAME_LEN+1 + 2 + NAME_LEN+1); end= strmake(buff, mysql->user, USERNAME_LENGTH) + 1; From 5b0afd8a0d57df6528e59b243e95881808bfb958 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Thu, 6 Jan 2011 22:49:17 +0200 Subject: [PATCH 23/27] Bug fixing in Aria: - Fixed some bugs in recovery of blobs - Don't ASSERT() on checksum errors when running check table - Added to maria_read_log option --tables-to-redo=list-of-tables to only recover some tables (good for debugging) storage/maria/ma_blockrec.c: Don't ASSERT() on checksum errors when running check table Fixed bug in recovery of blog page that was not in dirty pages list storage/maria/ma_check.c: Don't ASSERT() on checksum errors when running check table storage/maria/ma_recovery.c: Handling of --tables-to-redo storage/maria/ma_recovery.h: Handling of --tables-to-redo storage/maria/ma_recovery_util.c: Give better warning if table was not in dirty pages list storage/maria/maria_def.h: Added in_check_table storage/maria/maria_read_log.c: Added --tables-to-redo=list-of-tables to only recover some tables (good for debugging) Cleaned up message when wrong arguments --- storage/maria/ma_blockrec.c | 15 +++++----- storage/maria/ma_check.c | 4 +++ storage/maria/ma_recovery.c | 31 +++++++++++++++++++- storage/maria/ma_recovery.h | 2 ++ storage/maria/ma_recovery_util.c | 8 +++-- storage/maria/maria_def.h | 1 + storage/maria/maria_read_log.c | 50 ++++++++++++++++++++++++++++++-- 7 files changed, 97 insertions(+), 14 deletions(-) diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index dab88287f86..7fe88bb1848 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -4934,7 +4934,7 @@ int _ma_read_block_record2(MARIA_HA *info, uchar *record, goto err; } #ifdef EXTRA_DEBUG - if (share->calc_checksum) + if (share->calc_checksum && !info->in_check_table) { /* Esnure that row checksum is correct */ DBUG_ASSERT(((share->calc_checksum)(info, record) & 255) == @@ -6705,21 +6705,23 @@ uint _ma_apply_redo_insert_row_blobs(MARIA_HA *info, uint page_range; pgcache_page_no_t page, start_page; uchar *buff; + uint data_on_page= data_size; start_page= page= page_korr(header); header+= PAGE_STORE_SIZE; page_range= pagerange_korr(header); header+= PAGERANGE_STORE_SIZE; - for (i= page_range; i-- > 0 ; page++) + for (i= page_range; i-- > 0 ; page++, data+= data_on_page) { MARIA_PINNED_PAGE page_link; enum pagecache_page_lock unlock_method; enum pagecache_page_pin unpin_method; - uint length; set_if_smaller(first_page2, page); set_if_bigger(last_page2, page); + if (i == 0 && sub_ranges == 0) + data_on_page= data_size - empty_space; /* data on last page */ if (_ma_redo_not_needed_for_page(sid, redo_lsn, page, FALSE)) continue; @@ -6798,19 +6800,16 @@ uint _ma_apply_redo_insert_row_blobs(MARIA_HA *info, lsn_store(buff, lsn); buff[PAGE_TYPE_OFFSET]= BLOB_PAGE; - length= data_size; - if (i == 0 && sub_ranges == 0) + if (data_on_page != data_size) { /* Last page may be only partly filled. We zero the rest, like write_full_pages() does. */ - length-= empty_space; bzero(buff + share->block_size - PAGE_SUFFIX_SIZE - empty_space, empty_space); } - memcpy(buff+ PAGE_TYPE_OFFSET + 1, data, length); - data+= length; + memcpy(buff+ PAGE_TYPE_OFFSET + 1, data, data_on_page); if (pagecache_write(share->pagecache, &info->dfile, page, 0, buff, PAGECACHE_PLAIN_PAGE, diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 631fa879504..4619dac0d91 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -2039,6 +2039,8 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info, my_bool extend) bzero((char*) param->tmp_key_crc, share->base.keys * sizeof(param->tmp_key_crc[0])); + info->in_check_table= 1; /* Don't assert on checksum errors */ + switch (share->data_file_type) { case BLOCK_RECORD: error= check_block_record(param, info, extend, record); @@ -2054,6 +2056,8 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info, my_bool extend) break; } /* switch */ + info->in_check_table= 0; + if (error) goto err; diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c index 58cecabfe20..50e93cc1eb0 100644 --- a/storage/maria/ma_recovery.c +++ b/storage/maria/ma_recovery.c @@ -28,6 +28,7 @@ #include "trnman.h" #include "ma_key_recover.h" #include "ma_recovery_util.h" +#include "hash.h" struct st_trn_for_recovery /* used only in the REDO phase */ { @@ -58,6 +59,7 @@ static ulonglong now; /**< for tracking execution time of phases */ static int (*save_error_handler_hook)(uint, const char *,myf); static uint recovery_warnings; /**< count of warnings */ static uint recovery_found_crashed_tables; +HASH tables_to_redo; /* For maria_read_log */ #define prototype_redo_exec_hook(R) \ static int exec_REDO_LOGREC_ ## R(const TRANSLOG_HEADER_BUFFER *rec) @@ -184,6 +186,21 @@ static void print_preamble() } +static my_bool table_is_part_of_recovery_set(LEX_STRING *file_name) +{ + uint offset =0; + if (!tables_to_redo.records) + return 1; /* Default, recover table */ + + /* Skip base directory */ + if (file_name->str[0] == '.' && + (file_name->str[1] == '/' || file_name->str[1] == '\\')) + offset= 2; + /* Only recover if table is in hash */ + return my_hash_search(&tables_to_redo, (uchar*) file_name->str + offset, + file_name->length - offset) != 0; +} + /** @brief Recovers from the last checkpoint. @@ -3037,6 +3054,12 @@ static MARIA_HA *get_MARIA_HA_from_REDO_record(const share= info->s; tprint(tracef, ", '%s'", share->open_file_name.str); DBUG_ASSERT(in_redo_phase); + if (!table_is_part_of_recovery_set(&share->open_file_name)) + { + tprint(tracef, ", skipped by user\n"); + return NULL; + } + if (cmp_translog_addr(rec->lsn, share->lsn_of_file_id) <= 0) { /* @@ -3070,7 +3093,6 @@ static MARIA_HA *get_MARIA_HA_from_REDO_record(const REDO_INSERT_ROW_BLOBS will consult list by itself, as it covers several pages. */ - tprint(tracef, " page %s", llbuf); if (_ma_redo_not_needed_for_page(sid, rec->lsn, page, index_page_redo_entry)) return NULL; @@ -3107,6 +3129,13 @@ static MARIA_HA *get_MARIA_HA_from_UNDO_record(const } share= info->s; tprint(tracef, ", '%s'", share->open_file_name.str); + + if (!table_is_part_of_recovery_set(&share->open_file_name)) + { + tprint(tracef, ", skipped by user\n"); + return NULL; + } + if (cmp_translog_addr(rec->lsn, share->lsn_of_file_id) <= 0) { tprint(tracef, ", table's LOGREC_FILE_ID has LSN (%lu,0x%lx) more recent" diff --git a/storage/maria/ma_recovery.h b/storage/maria/ma_recovery.h index 0bfcdd17d39..5b22c4fd9b2 100644 --- a/storage/maria/ma_recovery.h +++ b/storage/maria/ma_recovery.h @@ -30,4 +30,6 @@ int maria_apply_log(LSN lsn, LSN lsn_end, enum maria_apply_log_way apply, FILE *trace_file, my_bool execute_undo_phase, my_bool skip_DDLs, my_bool take_checkpoints, uint *warnings_count); +/* Table of tables to recover */ +extern HASH tables_to_redo; C_MODE_END diff --git a/storage/maria/ma_recovery_util.c b/storage/maria/ma_recovery_util.c index 19e61daf4ef..ed9d8efc81b 100644 --- a/storage/maria/ma_recovery_util.c +++ b/storage/maria/ma_recovery_util.c @@ -129,16 +129,20 @@ my_bool _ma_redo_not_needed_for_page(uint16 shortid, LSN lsn, Next 2 bytes: table's short id Next 5 bytes: page number */ + char llbuf[22]; uint64 file_and_page_id= (((uint64)((index << 16) | shortid)) << 40) | page; struct st_dirty_page *dirty_page= (struct st_dirty_page *) hash_search(&all_dirty_pages, (uchar *)&file_and_page_id, sizeof(file_and_page_id)); - DBUG_PRINT("info", ("in dirty pages list: %d", dirty_page != NULL)); + DBUG_PRINT("info", ("page %lld in dirty pages list: %d", + (ulonglong) page, + dirty_page != NULL)); if ((dirty_page == NULL) || cmp_translog_addr(lsn, dirty_page->rec_lsn) < 0) { - tprint(tracef, ", ignoring because of dirty_pages list\n"); + tprint(tracef, ", ignoring page %s because of dirty_pages list\n", + llstr((ulonglong) page, llbuf)); return TRUE; } } diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index 85696d04858..2fbc84bae5f 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -570,6 +570,7 @@ struct st_maria_handler my_bool was_locked; /* Was locked in panic */ my_bool append_insert_at_end; /* Set if concurrent insert */ my_bool quick_mode; + my_bool in_check_table; /* We are running check tables */ /* Marker if key_del_changed */ /* If info->keyread_buff can't be used for rnext */ my_bool page_changed; diff --git a/storage/maria/maria_read_log.c b/storage/maria/maria_read_log.c index 98bc638c77f..f00a3924554 100644 --- a/storage/maria/maria_read_log.c +++ b/storage/maria/maria_read_log.c @@ -213,6 +213,9 @@ static struct my_option my_long_options[] = {"silent", 's', "Print less information during apply/undo phase", &opt_silent, &opt_silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"tables-to-redo", 'T', + "List of tables sepearated with , that we should apply REDO on. Use this if you only want to recover some tables", + 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"verbose", 'v', "Print more information during apply/undo phase", &maria_recovery_verbose, &maria_recovery_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -245,7 +248,7 @@ static void print_version(void) static void usage(void) { print_version(); - puts("Copyright (C) 2007 MySQL AB"); + puts("Copyright (C) 2007 MySQL AB, 2009-2011 Monty Program Ab"); puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,"); puts("and you are welcome to modify and redistribute it under the GPL license\n"); @@ -266,10 +269,18 @@ static void usage(void) #include +static uchar* my_hash_get_string(const uchar *record, size_t *length, + my_bool first __attribute__ ((unused))) +{ + *length= (size_t) (strcend((const char*) record,',')- (const char*) record); + return (uchar*) record; +} + + static my_bool get_one_option(int optid __attribute__((unused)), const struct my_option *opt __attribute__((unused)), - char *argument __attribute__((unused))) + char *argument) { switch (optid) { case '?': @@ -278,6 +289,23 @@ get_one_option(int optid __attribute__((unused)), case 'V': print_version(); exit(0); + case 'T': + { + char *pos; + if (!my_hash_inited(&tables_to_redo)) + { + my_hash_init2(&tables_to_redo, 16, &my_charset_bin, + 16, 0, 0, my_hash_get_string, 0, HASH_UNIQUE); + } + do + { + pos= strcend(argument, ','); + if (pos != argument) /* Skip empty strings */ + my_hash_insert(&tables_to_redo, (uchar*) argument); + argument= pos+1; + } while (*(pos++)); + break; + } #ifndef DBUG_OFF case '#': DBUG_SET_INITIAL(argument ? argument : default_dbug_option); @@ -290,6 +318,7 @@ get_one_option(int optid __attribute__((unused)), static void get_options(int *argc,char ***argv) { int ho_error; + my_bool need_help= 0; if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option))) exit(ho_error); @@ -297,8 +326,23 @@ static void get_options(int *argc,char ***argv) if (!opt_apply) opt_apply_undo= FALSE; - if (((opt_display_only + opt_apply) != 1) || (*argc > 0)) + if (*argc > 0) { + need_help= 1; + fprintf(stderr, "Too many arguments given\n"); + } + if ((opt_display_only + opt_apply) != 1) + { + need_help= 1; + fprintf(stderr, + "You must use one and only one of the options 'display-only' or " + "'apply'\n"); + } + + if (need_help) + { + fflush(stderr); + need_help =1; usage(); exit(1); } From 26f988594cc3d0224f4b391406b5390704df0248 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Fri, 7 Jan 2011 12:17:34 +0200 Subject: [PATCH 24/27] Aria fixes: - Don't delete pages without flushing that has had a tail or head information in pagecache_delete() This fixes a case where REPAIR could find old deleted rows. storage/maria/ha_maria.cc: Remove calls to depricated function ha_statistic_increment storage/maria/ma_blockrec.c: Don't delete pages without flushing that has had a tail or head information in pagecache_delete() storage/maria/ma_pagecache.c: Added possibility to mark pages to not be deleted by pagecache_delete() without beeing flushed. storage/maria/ma_pagecache.h: Added new prototype --- storage/maria/ha_maria.cc | 14 -------------- storage/maria/ma_blockrec.c | 7 +++++++ storage/maria/ma_pagecache.c | 29 ++++++++++++++++++++++++++++- storage/maria/ma_pagecache.h | 1 + 4 files changed, 36 insertions(+), 15 deletions(-) diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 2b6e7c1b3a6..dba930c1759 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -1059,8 +1059,6 @@ int ha_maria::close(void) int ha_maria::write_row(uchar * buf) { - ha_statistic_increment(&SSV::ha_write_count); - /* If we have a timestamp column, update it to the current time */ if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); @@ -2131,7 +2129,6 @@ bool ha_maria::is_crashed() const int ha_maria::update_row(const uchar * old_data, uchar * new_data) { CHECK_UNTIL_WE_FULLY_IMPLEMENTED_VERSIONING("UPDATE in WRITE CONCURRENT"); - ha_statistic_increment(&SSV::ha_update_count); if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) table->timestamp_field->set_time(); return maria_update(file, old_data, new_data); @@ -2141,7 +2138,6 @@ int ha_maria::update_row(const uchar * old_data, uchar * new_data) int ha_maria::delete_row(const uchar * buf) { CHECK_UNTIL_WE_FULLY_IMPLEMENTED_VERSIONING("DELETE in WRITE CONCURRENT"); - ha_statistic_increment(&SSV::ha_delete_count); return maria_delete(file, buf); } @@ -2151,7 +2147,6 @@ int ha_maria::index_read_map(uchar * buf, const uchar * key, enum ha_rkey_function find_flag) { DBUG_ASSERT(inited == INDEX); - ha_statistic_increment(&SSV::ha_read_key_count); int error= maria_rkey(file, buf, active_index, key, keypart_map, find_flag); table->status= error ? STATUS_NOT_FOUND : 0; return error; @@ -2162,7 +2157,6 @@ int ha_maria::index_read_idx_map(uchar * buf, uint index, const uchar * key, key_part_map keypart_map, enum ha_rkey_function find_flag) { - ha_statistic_increment(&SSV::ha_read_key_count); int error= maria_rkey(file, buf, index, key, keypart_map, find_flag); table->status= error ? STATUS_NOT_FOUND : 0; return error; @@ -2174,7 +2168,6 @@ int ha_maria::index_read_last_map(uchar * buf, const uchar * key, { DBUG_ENTER("ha_maria::index_read_last_map"); DBUG_ASSERT(inited == INDEX); - ha_statistic_increment(&SSV::ha_read_key_count); int error= maria_rkey(file, buf, active_index, key, keypart_map, HA_READ_PREFIX_LAST); table->status= error ? STATUS_NOT_FOUND : 0; @@ -2185,7 +2178,6 @@ int ha_maria::index_read_last_map(uchar * buf, const uchar * key, int ha_maria::index_next(uchar * buf) { DBUG_ASSERT(inited == INDEX); - ha_statistic_increment(&SSV::ha_read_next_count); int error= maria_rnext(file, buf, active_index); table->status= error ? STATUS_NOT_FOUND : 0; return error; @@ -2195,7 +2187,6 @@ int ha_maria::index_next(uchar * buf) int ha_maria::index_prev(uchar * buf) { DBUG_ASSERT(inited == INDEX); - ha_statistic_increment(&SSV::ha_read_prev_count); int error= maria_rprev(file, buf, active_index); table->status= error ? STATUS_NOT_FOUND : 0; return error; @@ -2205,7 +2196,6 @@ int ha_maria::index_prev(uchar * buf) int ha_maria::index_first(uchar * buf) { DBUG_ASSERT(inited == INDEX); - ha_statistic_increment(&SSV::ha_read_first_count); int error= maria_rfirst(file, buf, active_index); table->status= error ? STATUS_NOT_FOUND : 0; return error; @@ -2215,7 +2205,6 @@ int ha_maria::index_first(uchar * buf) int ha_maria::index_last(uchar * buf) { DBUG_ASSERT(inited == INDEX); - ha_statistic_increment(&SSV::ha_read_last_count); int error= maria_rlast(file, buf, active_index); table->status= error ? STATUS_NOT_FOUND : 0; return error; @@ -2228,7 +2217,6 @@ int ha_maria::index_next_same(uchar * buf, { int error; DBUG_ASSERT(inited == INDEX); - ha_statistic_increment(&SSV::ha_read_next_count); /* TODO: Delete this loop in Maria 1.5 as versioning will ensure this never happens @@ -2260,7 +2248,6 @@ int ha_maria::rnd_end() int ha_maria::rnd_next(uchar *buf) { - ha_statistic_increment(&SSV::ha_read_rnd_next_count); int error= maria_scan(file, buf); table->status= error ? STATUS_NOT_FOUND : 0; return error; @@ -2282,7 +2269,6 @@ int ha_maria::restart_rnd_next(uchar *buf) int ha_maria::rnd_pos(uchar *buf, uchar *pos) { - ha_statistic_increment(&SSV::ha_read_rnd_count); int error= maria_rrnd(file, buf, my_get_ptr(pos, ref_length)); table->status= error ? STATUS_NOT_FOUND : 0; return error; diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index 7fe88bb1848..a2faeb6e7fa 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -4181,6 +4181,13 @@ static my_bool delete_head_or_tail(MARIA_HA *info, log_data, NULL)) DBUG_RETURN(1); } + /* + Mark that this page must be written to disk by page cache, even + if we could call pagecache_delete() on it. + This is needed to ensure that repair finds the empty page on disk + and not old data. + */ + pagecache_set_write_on_delete_by_link(page_link.link); DBUG_ASSERT(empty_space >= share->bitmap.sizes[0]); } diff --git a/storage/maria/ma_pagecache.c b/storage/maria/ma_pagecache.c index 8105c6f752d..9a253fbf90c 100644 --- a/storage/maria/ma_pagecache.c +++ b/storage/maria/ma_pagecache.c @@ -158,6 +158,7 @@ struct st_pagecache_hash_link #define PCBLOCK_IN_FLUSH 16 /* block is in flush operation */ #define PCBLOCK_CHANGED 32 /* block buffer contains a dirty page */ #define PCBLOCK_DIRECT_W 64 /* possible direct write to the block */ +#define PCBLOCK_DEL_WRITE 128 /* should be written on delete */ /* page status, returned by find_block */ #define PAGE_READ 0 @@ -1215,7 +1216,7 @@ static void link_to_file_list(PAGECACHE *pagecache, link_changed(block, &pagecache->file_blocks[FILE_HASH(*file)]); if (block->status & PCBLOCK_CHANGED) { - block->status&= ~PCBLOCK_CHANGED; + block->status&= ~(PCBLOCK_CHANGED | PCBLOCK_DEL_WRITE); block->rec_lsn= LSN_MAX; pagecache->blocks_changed--; pagecache->global_blocks_changed--; @@ -3472,6 +3473,31 @@ no_key_cache: /* Key cache is not used */ } +/* + @brief Set/reset flag that page always should be flushed on delete + + @param pagecache pointer to a page cache data structure + @param link direct link to page (returned by read or write) + @param write write on delete flag value + +*/ + +void pagecache_set_write_on_delete_by_link(PAGECACHE_BLOCK_LINK *block) +{ + DBUG_ENTER("pagecache_set_write_on_delete_by_link"); + DBUG_PRINT("enter", ("fd: %d block 0x%lx %d -> TRUE", + block->hash_link->file.file, + (ulong) block, + (int) block->status & PCBLOCK_DEL_WRITE)); + DBUG_ASSERT(block->pins); /* should be pinned */ + DBUG_ASSERT(block->wlocks); /* should be write locked */ + + block->status|= PCBLOCK_DEL_WRITE; + + DBUG_VOID_RETURN; +} + + /* @brief Delete page from the buffer (common part for link and file/page) @@ -3501,6 +3527,7 @@ static my_bool pagecache_delete_internal(PAGECACHE *pagecache, } if (block->status & PCBLOCK_CHANGED) { + flush= (flush || (block->status & PCBLOCK_DEL_WRITE)); if (flush) { /* The block contains a dirty page - push it out of the cache */ diff --git a/storage/maria/ma_pagecache.h b/storage/maria/ma_pagecache.h index 821728ef374..475729bd46d 100644 --- a/storage/maria/ma_pagecache.h +++ b/storage/maria/ma_pagecache.h @@ -251,6 +251,7 @@ extern void pagecache_unpin(PAGECACHE *pagecache, extern void pagecache_unpin_by_link(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *link, LSN lsn); +extern void pagecache_set_write_on_delete_by_link(PAGECACHE_BLOCK_LINK *block); /* Results of flush operation (bit field in fact) */ From b2abd1cb0c7af997cca8819bd7df56b307fcb2b6 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Fri, 7 Jan 2011 13:45:59 +0200 Subject: [PATCH 25/27] Fixed typos Patch provided by Dolf Schimmel --- sql/sql_select.cc | 2 +- storage/ibmdb2i/db2i_ioBuffers.h | 2 +- storage/innodb_plugin/trx/trx0sys.c | 2 +- storage/myisammrg/ha_myisammrg.cc | 4 ++-- storage/ndb/include/ndbapi/NdbError.hpp | 2 +- storage/ndb/include/util/File.hpp | 2 +- storage/xtradb/trx/trx0sys.c | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 91d5f90a5f4..6f5a8dceb10 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5078,7 +5078,7 @@ optimize_straight_join(JOIN *join, table_map join_tables) All other cases are in-between these two extremes. Thus the parameter 'search_depth' controlls the exhaustiveness of the search. The higher the - value, the longer the optimizaton time and possibly the better the + value, the longer the optimization time and possibly the better the resulting plan. The lower the value, the fewer alternative plans are estimated, but the more likely to get a bad QEP. diff --git a/storage/ibmdb2i/db2i_ioBuffers.h b/storage/ibmdb2i/db2i_ioBuffers.h index 350d854f055..8fb815ba3be 100644 --- a/storage/ibmdb2i/db2i_ioBuffers.h +++ b/storage/ibmdb2i/db2i_ioBuffers.h @@ -290,7 +290,7 @@ class IOAsyncReadBuffer : public IOReadBuffer Return a pointer to the next row in the table, where "next" is defined by the orientation. - @param orientaton + @param orientation @param[out] rrn The relative record number of the row returned. Not reliable if NULL is returned by this function. diff --git a/storage/innodb_plugin/trx/trx0sys.c b/storage/innodb_plugin/trx/trx0sys.c index 6eb356947cc..48963bc7e45 100644 --- a/storage/innodb_plugin/trx/trx0sys.c +++ b/storage/innodb_plugin/trx/trx0sys.c @@ -1343,7 +1343,7 @@ trx_sys_print_mysql_binlog_offset_from_page( /* THESE ARE COPIED FROM NON-HOTBACKUP PART OF THE INNODB SOURCE TREE - (This code duplicaton should be fixed at some point!) + (This code duplication should be fixed at some point!) */ #define TRX_SYS_SPACE 0 /* the SYSTEM tablespace */ diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc index c61d65572cb..ff2d01e09c0 100644 --- a/storage/myisammrg/ha_myisammrg.cc +++ b/storage/myisammrg/ha_myisammrg.cc @@ -1057,9 +1057,9 @@ THR_LOCK_DATA **ha_myisammrg::store_lock(THD *thd, /* When MERGE table is open, but not yet attached, other threads - could flush it, which means call mysql_lock_abort_for_thread() + could flush it, which means calling mysql_lock_abort_for_thread() on this threads TABLE. 'children_attached' is FALSE in this - situaton. Since the table is not locked, return no lock data. + situation. Since the table is not locked, return no lock data. */ if (!this->file->children_attached) goto end; /* purecov: tested */ diff --git a/storage/ndb/include/ndbapi/NdbError.hpp b/storage/ndb/include/ndbapi/NdbError.hpp index aa27caf78f9..b752e578bc1 100644 --- a/storage/ndb/include/ndbapi/NdbError.hpp +++ b/storage/ndb/include/ndbapi/NdbError.hpp @@ -66,7 +66,7 @@ struct NdbError { /** * The error code indicates a permanent error.
- * (Includes classificatons: NdbError::PermanentError, + * (Includes classifications: NdbError::PermanentError, * NdbError::ApplicationError, NdbError::NoDataFound, * NdbError::ConstraintViolation, NdbError::SchemaError, * NdbError::UserDefinedError, NdbError::InternalError, and, diff --git a/storage/ndb/include/util/File.hpp b/storage/ndb/include/util/File.hpp index b9d348683ec..bbddc24583a 100644 --- a/storage/ndb/include/util/File.hpp +++ b/storage/ndb/include/util/File.hpp @@ -31,7 +31,7 @@ public: * Returns time for last contents modification of a file. * * @param aFileName a filename to check. - * @return the time for last contents modificaton of the file. + * @return the time for last contents modification of the file. */ static time_t mtime(const char* aFileName); diff --git a/storage/xtradb/trx/trx0sys.c b/storage/xtradb/trx/trx0sys.c index 566f7c95793..a9fb5bb38d8 100644 --- a/storage/xtradb/trx/trx0sys.c +++ b/storage/xtradb/trx/trx0sys.c @@ -1667,7 +1667,7 @@ trx_sys_print_mysql_binlog_offset_from_page( /* THESE ARE COPIED FROM NON-HOTBACKUP PART OF THE INNODB SOURCE TREE - (This code duplicaton should be fixed at some point!) + (This code duplication should be fixed at some point!) */ #define TRX_SYS_SPACE 0 /* the SYSTEM tablespace */ From c0fc6d42ace74938c0d39907ddf8acfbeb4d247e Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Fri, 7 Jan 2011 17:58:12 +0200 Subject: [PATCH 26/27] Don't do DBUG_ASSERT for checksum errors when using REPAIR mysql_convert_table_format ignored --engine option. Fix that zerofill() doesn't write out wrong data to client if run with auto repair. Ensure that pagecache is properly flushed, even in case of errors. Handle checksum errors in BLOCK_RECORD format. scripts/mysql_convert_table_format.sh: Fixed that --engine option works storage/maria/ha_maria.cc: Fix that zerofill() doesn't write out wrong data to client if run with auto repair. storage/maria/ma_check.c: Set in_check_table when scanning table to not get DBUG_ASSERT for checksum error. Ensure that pagecache is properly flushed, even in case of errors. Handle checksum errors in BLOCK_RECORD format. storage/maria/ma_sort.c: Set in_check_table when scanning table to not get DBUG_ASSERT for checksum error. --- scripts/mysql_convert_table_format.sh | 2 +- storage/maria/ha_maria.cc | 2 +- storage/maria/ma_check.c | 19 ++++++++++++++----- storage/maria/ma_sort.c | 14 ++++++++++---- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/scripts/mysql_convert_table_format.sh b/scripts/mysql_convert_table_format.sh index 6f586d0e8e0..7983982913c 100644 --- a/scripts/mysql_convert_table_format.sh +++ b/scripts/mysql_convert_table_format.sh @@ -28,7 +28,7 @@ $opt_port=0; $exit_status=0; GetOptions( - "e|engine|type=s" => \$opt_type, + "e|engine|type=s" => \$opt_engine, "f|force" => \$opt_force, "help|?" => \$opt_help, "h|host=s" => \$opt_host, diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 6852e84fc65..467b065513d 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -2022,6 +2022,7 @@ bool ha_maria::check_and_repair(THD *thd) DBUG_ENTER("ha_maria::check_and_repair"); check_opt.init(); + check_opt.flags= T_MEDIUM | T_AUTO_REPAIR; error= 1; if ((file->s->state.changed & @@ -2042,7 +2043,6 @@ bool ha_maria::check_and_repair(THD *thd) DBUG_RETURN(error); error= 0; - check_opt.flags= T_MEDIUM | T_AUTO_REPAIR; // Don't use quick if deleted rows if (!file->state->del && (maria_recover_options & HA_RECOVER_QUICK)) check_opt.flags |= T_QUICK; diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 4619dac0d91..939f7c0ac7e 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -2630,6 +2630,7 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info, maria_lock_memory(param); /* Everything is alloced */ + sort_param.sort_info->info->in_check_table= 1; /* Re-create all keys, which are set in key_map. */ while (!(error=sort_get_next_record(&sort_param))) { @@ -2797,6 +2798,7 @@ err: VOID(end_io_cache(&sort_info.new_info->rec_cache)); info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); sort_info.new_info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); + sort_param.sort_info->info->in_check_table= 0; /* this below could fail, shouldn't we detect error? */ if (got_error) { @@ -3247,6 +3249,7 @@ static my_bool maria_zerofill_index(HA_CHECK *param, MARIA_HA *info, uint block_size= share->block_size; my_bool zero_lsn= (share->base.born_transactional && !(param->testflag & T_ZEROFILL_KEEP_LSN)); + int error= 1; DBUG_ENTER("maria_zerofill_index"); if (!(param->testflag & T_SILENT)) @@ -3271,7 +3274,7 @@ static my_bool maria_zerofill_index(HA_CHECK *param, MARIA_HA *info, _ma_check_print_error(param, "Page %9s: Got error %d when reading index file", llstr(pos, llbuff), my_errno); - DBUG_RETURN(1); + goto end; } if (zero_lsn) bzero(buff, LSN_SIZE); @@ -3279,7 +3282,7 @@ static my_bool maria_zerofill_index(HA_CHECK *param, MARIA_HA *info, if (share->base.born_transactional) { uint keynr= _ma_get_keynr(share, buff); - if (keynr != MARIA_DELETE_KEY_NR) + if (keynr < share->base.keys) { MARIA_PAGE page; DBUG_ASSERT(keynr < share->base.keys); @@ -3291,7 +3294,7 @@ static my_bool maria_zerofill_index(HA_CHECK *param, MARIA_HA *info, "Page %9s: Got error %d when reading index " "file", llstr(pos, llbuff), my_errno); - DBUG_RETURN(1); + goto end; } } } @@ -3305,10 +3308,13 @@ static my_bool maria_zerofill_index(HA_CHECK *param, MARIA_HA *info, PAGECACHE_UNPIN, LSN_IMPOSSIBLE, LSN_IMPOSSIBLE, 1, FALSE); } + error= 0; /* ok */ + +end: if (flush_pagecache_blocks(share->pagecache, &share->kfile, FLUSH_FORCE_WRITE)) DBUG_RETURN(1); - DBUG_RETURN(0); + DBUG_RETURN(error); } @@ -4768,7 +4774,7 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) DBUG_RETURN(-1); } /* Retry only if wrong record, not if disk error */ - if (flag != HA_ERR_WRONG_IN_RECORD) + if (flag != HA_ERR_WRONG_IN_RECORD && flag != HA_ERR_WRONG_CRC) { retry_if_quick(sort_param, flag); DBUG_RETURN(flag); @@ -6458,6 +6464,9 @@ static void change_data_file_descriptor(MARIA_HA *info, File new_file) static void unuse_data_file_descriptor(MARIA_HA *info) { + (void) flush_pagecache_blocks(info->s->pagecache, + &info->s->bitmap.file, + FLUSH_IGNORE_CHANGED); info->dfile.file= info->s->bitmap.file.file= -1; _ma_bitmap_reset_cache(info->s); } diff --git a/storage/maria/ma_sort.c b/storage/maria/ma_sort.c index 387563ebaac..a58d10ca907 100644 --- a/storage/maria/ma_sort.c +++ b/storage/maria/ma_sort.c @@ -275,12 +275,13 @@ static ha_rows find_all_keys(MARIA_SORT_PARAM *info, uint keys, idx=error=0; sort_keys[0]= (uchar*) (sort_keys+keys); + info->sort_info->info->in_check_table= 1; while (!(error=(*info->key_read)(info,sort_keys[idx]))) { if (info->real_key_length > info->key_length) { if (write_key(info,sort_keys[idx],tempfile_for_exceptions)) - DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */ + goto err; /* purecov: inspected */ continue; } @@ -289,7 +290,7 @@ static ha_rows find_all_keys(MARIA_SORT_PARAM *info, uint keys, if (info->write_keys(info,sort_keys,idx-1, (BUFFPEK *)alloc_dynamic(buffpek), tempfile)) - DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */ + goto err; /* purecov: inspected */ sort_keys[0]=(uchar*) (sort_keys+keys); memcpy(sort_keys[0],sort_keys[idx-1],(size_t) info->key_length); @@ -298,18 +299,23 @@ static ha_rows find_all_keys(MARIA_SORT_PARAM *info, uint keys, sort_keys[idx]=sort_keys[idx-1]+info->key_length; } if (error > 0) - DBUG_RETURN(HA_POS_ERROR); /* Aborted by get_key */ /* purecov: inspected */ + goto err; /* purecov: inspected */ if (buffpek->elements) { if (info->write_keys(info,sort_keys,idx,(BUFFPEK *)alloc_dynamic(buffpek), tempfile)) - DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */ + goto err; /* purecov: inspected */ *maxbuffer=buffpek->elements-1; } else *maxbuffer=0; + info->sort_info->info->in_check_table= 0; DBUG_RETURN((*maxbuffer)*(keys-1)+idx); + +err: + info->sort_info->info->in_check_table= 0; /* purecov: inspected */ + DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */ } /* find_all_keys */ From 505c663a1e19af4c8ee726b305691414ab5fc999 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Mon, 10 Jan 2011 23:22:40 +0200 Subject: [PATCH 27/27] - Fixed that Aria works with HANDLER commands - Added test case for Aria - Tested HANDLER with HEAP (changes to HEAP code will be pushed in 5.3) - Moved all HANDLER test to suite/handler. mysql-test/Makefile.am: Added suite/handler mysql-test/mysql-test-run.pl: Added suite/handler mysql-test/r/lock_multi.result: Remove test that is already in handler test suite mysql-test/suite/handler/aria.result: Test for HANDLER with Aria storage engine mysql-test/suite/handler/aria.test: Test for HANDLER with Aria storage engine mysql-test/suite/handler/handler.inc: Extended the general handler test Moved interface testing to 'interface.test' mysql-test/suite/handler/init.inc: Common init for handler tests. mysql-test/suite/handler/innodb.result: New results mysql-test/suite/handler/innodb.test: Update to use new include files mysql-test/suite/handler/interface.result: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/interface.test: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/myisam.result: New results mysql-test/suite/handler/myisam.test: Update to use new include files mysql-test/t/lock_multi.test: Remove test that is already in handler test suite mysys/tree.c: Added missing handling of read previous (showed up in HEAP testing) sql/handler.cc: Don't marka 'HA_ERR_RECORD_CHANGED' as fatal (can be used with HANDLER READ, especially with MEMORY ENGINE) sql/handler.h: Added prototype for can_continue_handler_scan() sql/sql_handler.cc: Re-initialize search if we switch from key to table search. Check if handler can continue searching between calls (via can_continue_handler_scan()) Don't write common not fatal errors to log storage/maria/ma_extra.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_ft_boolean_search.c: Ensure that info->last_key.keyinfo is set storage/maria/ma_open.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_rkey.c: Trivial optimization storage/maria/ma_rnext.c: Added missing code from mi_rnext.c to ensure that handler next/prev works. storage/maria/ma_rsame.c: Simple optimizations storage/maria/ma_search.c: Initialize info->last_key once and for all when we change keys. storage/maria/ma_unique.c: Ensure that info->last_key.keyinfo is up to date. --- mysql-test/Makefile.am | 2 +- mysql-test/mysql-test-run.pl | 2 +- mysql-test/r/lock_multi.result | 7 - mysql-test/suite/handler/aria.result | 671 ++++++++++++++++++ mysql-test/suite/handler/aria.test | 82 +++ .../{include => suite/handler}/handler.inc | 382 ++-------- mysql-test/suite/handler/init.inc | 33 + .../handler/innodb.result} | 373 +++------- .../handler/innodb.test} | 13 +- mysql-test/suite/handler/interface.result | 259 +++++++ mysql-test/suite/handler/interface.test | 307 ++++++++ .../handler/myisam.result} | 398 +++-------- .../handler/myisam.test} | 24 +- mysql-test/t/lock_multi.test | 16 - mysys/tree.c | 4 + sql/handler.cc | 5 +- sql/handler.h | 1 + sql/sql_handler.cc | 17 +- storage/maria/ma_extra.c | 4 +- storage/maria/ma_ft_boolean_search.c | 4 +- storage/maria/ma_open.c | 2 + storage/maria/ma_rkey.c | 2 +- storage/maria/ma_rnext.c | 17 +- storage/maria/ma_rsame.c | 5 +- storage/maria/ma_search.c | 9 +- storage/maria/ma_unique.c | 1 + 26 files changed, 1670 insertions(+), 970 deletions(-) create mode 100644 mysql-test/suite/handler/aria.result create mode 100644 mysql-test/suite/handler/aria.test rename mysql-test/{include => suite/handler}/handler.inc (55%) create mode 100644 mysql-test/suite/handler/init.inc rename mysql-test/{r/handler_innodb.result => suite/handler/innodb.result} (54%) rename mysql-test/{t/handler_innodb.test => suite/handler/innodb.test} (55%) create mode 100644 mysql-test/suite/handler/interface.result create mode 100644 mysql-test/suite/handler/interface.test rename mysql-test/{r/handler_myisam.result => suite/handler/myisam.result} (58%) rename mysql-test/{t/handler_myisam.test => suite/handler/myisam.test} (74%) diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index f8b3721f600..f90c73d1e92 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -106,7 +106,7 @@ TEST_DIRS = t r include std_data std_data/parts collections \ suite/innodb suite/innodb/t suite/innodb/r suite/innodb/include \ suite/innodb_plugin suite/innodb_plugin/t suite/innodb_plugin/r \ suite/innodb_plugin/include \ - suite/percona \ + suite/percona suite/handler \ suite/engines suite/engines/funcs suite/engines/iuds suite/engines/rr_trx \ suite/engines/funcs/r suite/engines/funcs/t suite/engines/iuds/r \ suite/engines/iuds/t suite/engines/rr_trx/include suite/engines/rr_trx/r \ diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 4a652580d97..8a709df54c3 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -142,7 +142,7 @@ my $path_config_file; # The generated config file, var/my.cnf # executables will be used by the test suite. our $opt_vs_config = $ENV{'MTR_VS_CONFIG'}; -my $DEFAULT_SUITES= "main,binlog,federated,rpl,maria,parts,innodb,innodb_plugin,percona,ndb"; +my $DEFAULT_SUITES= "main,binlog,federated,rpl,maria,handler,parts,innodb,innodb_plugin,percona,ndb"; my $opt_suites; our $opt_verbose= 0; # Verbose output, enable with --verbose diff --git a/mysql-test/r/lock_multi.result b/mysql-test/r/lock_multi.result index d8768e802ea..3fc4de3da06 100644 --- a/mysql-test/r/lock_multi.result +++ b/mysql-test/r/lock_multi.result @@ -162,13 +162,6 @@ ERROR 70100: Query execution was interrupted unlock tables; drop table t1; drop table if exists t1; -create table t1 (a int) ENGINE=MEMORY; ---> client 2 -handler t1 open; -ERROR HY000: Table storage engine for 't1' doesn't have this option ---> client 1 -drop table t1; -drop table if exists t1; create table t1 (i int); connection: default lock tables t1 write; diff --git a/mysql-test/suite/handler/aria.result b/mysql-test/suite/handler/aria.result new file mode 100644 index 00000000000..a912a2559e3 --- /dev/null +++ b/mysql-test/suite/handler/aria.result @@ -0,0 +1,671 @@ +SET SESSION STORAGE_ENGINE = Aria; +drop table if exists t1,t3,t4,t5; +create table t1 (a int, b char(10), key a (a), key b (a,b)); +insert into t1 values +(17,"ddd"),(18,"eee"),(19,"fff"),(19,"yyy"), +(14,"aaa"),(16,"ccc"),(16,"xxx"), +(20,"ggg"),(21,"hhh"),(22,"iii"); +handler t1 open as t2; +handler t2 read a first; +a b +14 aaa +handler t2 read a next; +a b +16 ccc +handler t2 read a next; +a b +16 xxx +handler t2 read a prev; +a b +16 ccc +handler t2 read a last; +a b +22 iii +handler t2 read a prev; +a b +21 hhh +handler t2 read a prev; +a b +20 ggg +handler t2 read a first; +a b +14 aaa +handler t2 read a prev; +a b +handler t2 read a last; +a b +22 iii +handler t2 read a prev; +a b +21 hhh +handler t2 read a next; +a b +22 iii +handler t2 read a next; +a b +handler t2 read a=(15); +a b +handler t2 read a=(16); +a b +16 ccc +handler t2 read a=(19,"fff"); +ERROR 42000: Too many key parts specified; max 1 parts allowed +handler t2 read b=(19,"fff"); +a b +19 fff +handler t2 read b=(19,"yyy"); +a b +19 yyy +handler t2 read b=(19); +a b +19 fff +handler t1 read a last; +ERROR 42S02: Unknown table 't1' in HANDLER +handler t2 read a=(11); +a b +handler t2 read a>=(11); +a b +14 aaa +handler t2 read a=(18); +a b +18 eee +handler t2 read a>=(18); +a b +18 eee +handler t2 read a>(18); +a b +19 fff +handler t2 read a<=(18); +a b +18 eee +handler t2 read a<(18); +a b +17 ddd +handler t2 read a=(15); +a b +handler t2 read a>=(15); +a b +16 ccc +handler t2 read a>(15); +a b +16 ccc +handler t2 read a<=(15); +a b +14 aaa +handler t2 read a<(15); +a b +14 aaa +handler t2 read a=(54); +a b +handler t2 read a>=(54); +a b +handler t2 read a>(54); +a b +handler t2 read a<=(54); +a b +22 iii +handler t2 read a<(54); +a b +22 iii +handler t2 read a=(1); +a b +handler t2 read a>=(1); +a b +14 aaa +handler t2 read a>(1); +a b +14 aaa +handler t2 read a<=(1); +a b +handler t2 read a<(1); +a b +handler t2 read a first limit 5; +a b +14 aaa +16 ccc +16 xxx +17 ddd +18 eee +handler t2 read a next limit 3; +a b +19 fff +19 yyy +20 ggg +handler t2 read a prev limit 10; +a b +19 yyy +19 fff +18 eee +17 ddd +16 xxx +16 ccc +14 aaa +handler t2 read a>=(16) limit 4; +a b +16 ccc +16 xxx +17 ddd +18 eee +handler t2 read a>=(16) limit 2,2; +a b +17 ddd +18 eee +handler t2 read a last limit 3; +a b +22 iii +21 hhh +20 ggg +handler t2 read a=(19); +a b +19 fff +handler t2 read a=(19) where b="yyy"; +a b +19 yyy +handler t2 read first; +a b +17 ddd +handler t2 read next; +a b +18 eee +handler t2 read next; +a b +19 fff +handler t2 close; +handler t1 open; +handler t1 read a next; +a b +14 aaa +handler t1 read a next; +a b +16 ccc +handler t1 close; +handler t1 open; +handler t1 read a prev; +a b +22 iii +handler t1 read a prev; +a b +21 hhh +handler t1 close; +handler t1 open as t2; +handler t2 read first; +a b +17 ddd +alter table t1 engine = Aria; +handler t2 read first; +ERROR 42S02: Unknown table 't2' in HANDLER +handler t1 open as t2; +drop table t1; +create table t1 (a int not null); +insert into t1 values (17); +handler t2 read first; +ERROR 42S02: Unknown table 't2' in HANDLER +handler t1 open as t2; +alter table t1 engine=CSV; +handler t2 read first; +ERROR 42S02: Unknown table 't2' in HANDLER +drop table t1; +create table t1 (a int); +insert into t1 values (1),(2),(3),(4),(5),(6); +delete from t1 limit 2; +handler t1 open; +handler t1 read first; +a +3 +handler t1 read first limit 1,1; +a +4 +handler t1 read first limit 2,2; +a +5 +6 +delete from t1 limit 3; +handler t1 read first; +a +6 +drop table t1; +create table t1(a int, index (a)); +insert into t1 values (1), (2), (3); +handler t1 open; +handler t1 read a=(W); +ERROR 42S22: Unknown column 'W' in 'field list' +handler t1 read a=(a); +ERROR HY000: Incorrect arguments to HANDLER ... READ +drop table t1; +create table t1 (a char(5)); +insert into t1 values ("Ok"); +handler t1 open as t; +handler t read first; +a +Ok +use mysql; +handler t read first; +a +Ok +handler t close; +handler test.t1 open as t; +handler t read first; +a +Ok +handler t close; +use test; +drop table t1; +create table t1 ( a int, b int, INDEX a (a) ); +insert into t1 values (1,2), (2,1); +handler t1 open; +handler t1 read a=(1) where b=2; +a b +1 2 +handler t1 read a=(1) where b=3; +a b +handler t1 read a=(1) where b=1; +a b +handler t1 close; +drop table t1; +create table t1 (c1 char(20)); +insert into t1 values ("t1"); +handler t1 open as h1; +handler h1 read first limit 9; +c1 +t1 +create table t2 (c1 char(20)); +insert into t2 values ("t2"); +handler t2 open as h2; +handler h2 read first limit 9; +c1 +t2 +create table t3 (c1 char(20)); +insert into t3 values ("t3"); +handler t3 open as h3; +handler h3 read first limit 9; +c1 +t3 +create table t4 (c1 char(20)); +insert into t4 values ("t4"); +handler t4 open as h4; +handler h4 read first limit 9; +c1 +t4 +create table t5 (c1 char(20)); +insert into t5 values ("t5"); +handler t5 open as h5; +handler h5 read first limit 9; +c1 +t5 +alter table t1 engine=MyISAM; +handler h1 read first limit 9; +ERROR 42S02: Unknown table 'h1' in HANDLER +handler h2 read first limit 9; +c1 +t2 +handler h3 read first limit 9; +c1 +t3 +handler h4 read first limit 9; +c1 +t4 +handler h5 read first limit 9; +c1 +t5 +alter table t5 engine=MyISAM; +handler h1 read first limit 9; +ERROR 42S02: Unknown table 'h1' in HANDLER +handler h2 read first limit 9; +c1 +t2 +handler h3 read first limit 9; +c1 +t3 +handler h4 read first limit 9; +c1 +t4 +handler h5 read first limit 9; +ERROR 42S02: Unknown table 'h5' in HANDLER +alter table t3 engine=MyISAM; +handler h1 read first limit 9; +ERROR 42S02: Unknown table 'h1' in HANDLER +handler h2 read first limit 9; +c1 +t2 +handler h3 read first limit 9; +ERROR 42S02: Unknown table 'h3' in HANDLER +handler h4 read first limit 9; +c1 +t4 +handler h5 read first limit 9; +ERROR 42S02: Unknown table 'h5' in HANDLER +handler h2 close; +handler h4 close; +handler t1 open as h1_1; +handler t1 open as h1_2; +handler t1 open as h1_3; +handler h1_1 read first limit 9; +c1 +t1 +handler h1_2 read first limit 9; +c1 +t1 +handler h1_3 read first limit 9; +c1 +t1 +alter table t1 engine=Aria; +handler h1_1 read first limit 9; +ERROR 42S02: Unknown table 'h1_1' in HANDLER +handler h1_2 read first limit 9; +ERROR 42S02: Unknown table 'h1_2' in HANDLER +handler h1_3 read first limit 9; +ERROR 42S02: Unknown table 'h1_3' in HANDLER +drop table t1; +drop table t2; +drop table t3; +drop table t4; +drop table t5; +create table t1 (c1 int); +insert into t1 values (1); +handler t1 open; +handler t1 read first; +c1 +1 +send the below to another connection, do not wait for the result +optimize table t1; +proceed with the normal connection +handler t1 read next; +c1 +1 +handler t1 close; +read the result from the other connection +Table Op Msg_type Msg_text +test.t1 optimize status OK +proceed with the normal connection +drop table t1; +CREATE TABLE t1 ( no1 smallint(5) NOT NULL default '0', no2 int(10) NOT NULL default '0', PRIMARY KEY (no1,no2)); +INSERT INTO t1 VALUES (1,274),(1,275),(2,6),(2,8),(4,1),(4,2); +HANDLER t1 OPEN; +HANDLER t1 READ `primary` = (1, 1000); +no1 no2 +HANDLER t1 READ `primary` PREV; +no1 no2 +1 275 +HANDLER t1 READ `primary` = (1, 1000); +no1 no2 +HANDLER t1 READ `primary` NEXT; +no1 no2 +2 6 +DROP TABLE t1; +create table t1 (c1 int); +insert into t1 values (14397); +flush tables with read lock; +drop table t1; +ERROR HY000: Can't execute the query because you have a conflicting read lock +send the below to another connection, do not wait for the result +drop table t1; +proceed with the normal connection +select * from t1; +c1 +14397 +unlock tables; +read the result from the other connection +proceed with the normal connection +select * from t1; +ERROR 42S02: Table 'test.t1' doesn't exist +drop table if exists t1; +Warnings: +Note 1051 Unknown table 't1' +create table t1 (a int not null) ENGINE=CSV; +--> client 2 +handler t1 open; +ERROR HY000: Table storage engine for 't1' doesn't have this option +--> client 1 +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +handler t1_alias read a next; +ERROR 42000: Key 'a' doesn't exist in table 't1_alias' +handler t1_alias READ a next where inexistent > 0; +ERROR 42S22: Unknown column 'inexistent' in 'field list' +handler t1_alias read a next; +ERROR 42000: Key 'a' doesn't exist in table 't1_alias' +handler t1_alias READ a next where inexistent > 0; +ERROR 42S22: Unknown column 'inexistent' in 'field list' +handler t1_alias close; +drop table t1; +create temporary table t1 (a int, b char(1), key a (a), key b(a,b)); +insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"), +(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"),(9,'k'); +select a,b from t1; +a b +0 a +1 b +2 c +3 d +4 e +5 f +6 g +7 h +8 i +9 j +9 k +handler t1 open as a1; +handler a1 read a=(1); +a b +1 b +handler a1 read a next; +a b +2 c +handler a1 read a next; +a b +3 d +select a,b from t1; +ERROR HY000: Can't reopen table: 'a1' +handler a1 read a prev; +a b +2 c +handler a1 read a prev; +a b +1 b +handler a1 read a=(6) where b="g"; +a b +6 g +handler a1 close; +select a,b from t1; +a b +0 a +1 b +2 c +3 d +4 e +5 f +6 g +7 h +8 i +9 j +9 k +handler t1 open as a2; +handler a2 read a=(9); +a b +9 j +handler a2 read a next; +a b +9 k +handler a2 read a prev limit 2; +a b +9 j +8 i +handler a2 read a last; +a b +9 k +handler a2 read a prev; +a b +9 j +handler a2 close; +drop table t1; +create table t1 (a int); +create temporary table t2 (a int, key (a)); +handler t1 open as a1; +handler t2 open as a2; +handler a2 read a first; +a +drop table t1, t2; +handler a2 read a next; +ERROR 42S02: Unknown table 'a2' in HANDLER +handler a1 close; +ERROR 42S02: Unknown table 'a1' in HANDLER +create table t1 (a int, key (a)); +create table t2 like t1; +handler t1 open as a1; +handler t2 open as a2; +handler a1 read a first; +a +handler a2 read a first; +a +alter table t1 add b int; +handler a1 close; +ERROR 42S02: Unknown table 'a1' in HANDLER +handler a2 close; +drop table t1, t2; +create table t1 (a int, key (a)); +handler t1 open as a1; +handler a1 read a first; +a +rename table t1 to t2; +handler a1 read a first; +ERROR 42S02: Unknown table 'a1' in HANDLER +drop table t2; +create table t1 (a int, key (a)); +create table t2 like t1; +handler t1 open as a1; +handler t2 open as a2; +handler a1 read a first; +a +handler a2 read a first; +a +optimize table t1; +Table Op Msg_type Msg_text +test.t1 optimize status Table is already up to date +handler a1 close; +ERROR 42S02: Unknown table 'a1' in HANDLER +handler a2 close; +drop table t1, t2; +# +# BUG#51877 - HANDLER interface causes invalid memory read +# +CREATE TABLE t1(a INT, KEY (a)); +HANDLER t1 OPEN; +HANDLER t1 READ a FIRST; +a +INSERT INTO t1 VALUES(1); +HANDLER t1 READ a NEXT; +a +1 +HANDLER t1 CLOSE; +DROP TABLE t1; +# +# BUG #46456: HANDLER OPEN + TRUNCATE + DROP (temporary) TABLE, crash +# +CREATE TABLE t1 AS SELECT 1 AS f1; +HANDLER t1 OPEN; +TRUNCATE t1; +HANDLER t1 READ FIRST; +ERROR 42S02: Unknown table 't1' in HANDLER +DROP TABLE t1; +CREATE TEMPORARY TABLE t1 AS SELECT 1 AS f1; +HANDLER t1 OPEN; +TRUNCATE t1; +HANDLER t1 READ FIRST; +ERROR 42S02: Unknown table 't1' in HANDLER +DROP TABLE t1; +# +# Bug #54007: assert in ha_myisam::index_next , HANDLER +# +CREATE TABLE t1(a INT, b INT, PRIMARY KEY(a), KEY b(b), KEY ab(a, b)); +HANDLER t1 OPEN; +HANDLER t1 READ FIRST; +a b +HANDLER t1 READ `PRIMARY` NEXT; +a b +HANDLER t1 READ ab NEXT; +a b +HANDLER t1 READ b NEXT; +a b +HANDLER t1 READ NEXT; +a b +HANDLER t1 CLOSE; +INSERT INTO t1 VALUES (2, 20), (1, 10), (4, 40), (3, 30); +HANDLER t1 OPEN; +HANDLER t1 READ FIRST; +a b +2 20 +HANDLER t1 READ NEXT; +a b +1 10 +HANDLER t1 READ `PRIMARY` NEXT; +a b +1 10 +HANDLER t1 READ `PRIMARY` NEXT; +a b +2 20 +HANDLER t1 READ ab NEXT; +a b +1 10 +HANDLER t1 READ ab NEXT; +a b +2 20 +HANDLER t1 READ b NEXT; +a b +1 10 +HANDLER t1 READ b NEXT; +a b +2 20 +HANDLER t1 READ b NEXT; +a b +3 30 +HANDLER t1 READ b NEXT; +a b +4 40 +HANDLER t1 READ b NEXT; +a b +HANDLER t1 READ NEXT; +a b +2 20 +HANDLER t1 READ NEXT; +a b +1 10 +HANDLER t1 READ NEXT; +a b +4 40 +HANDLER t1 CLOSE; +HANDLER t1 OPEN; +HANDLER t1 READ FIRST; +a b +2 20 +HANDLER t1 READ `PRIMARY` PREV; +a b +4 40 +HANDLER t1 READ `PRIMARY` PREV; +a b +3 30 +HANDLER t1 READ b PREV; +a b +4 40 +HANDLER t1 READ b PREV; +a b +3 30 +HANDLER t1 CLOSE; +HANDLER t1 OPEN; +HANDLER t1 READ FIRST; +a b +2 20 +HANDLER t1 READ `PRIMARY` PREV LIMIT 3; +a b +4 40 +3 30 +2 20 +HANDLER t1 READ b NEXT LIMIT 5; +a b +1 10 +2 20 +3 30 +4 40 +HANDLER t1 CLOSE; +DROP TABLE t1; +End of 5.1 tests diff --git a/mysql-test/suite/handler/aria.test b/mysql-test/suite/handler/aria.test new file mode 100644 index 00000000000..1913d2b791c --- /dev/null +++ b/mysql-test/suite/handler/aria.test @@ -0,0 +1,82 @@ +# t/handler_innodb.test +# +# test of HANDLER ... +# +# Last update: +# 2006-07-31 ML test refactored (MySQL 5.1) +# code of t/handler.test and t/innodb_handler.test united +# main testing code put into handler.inc +# rename t/innodb_handler.test to t/handler_innodb.test +# + +--source include/have_maria.inc +let $engine_type= Aria; + +--source init.inc +--source handler.inc + +--echo # +--echo # BUG #46456: HANDLER OPEN + TRUNCATE + DROP (temporary) TABLE, crash +--echo # +CREATE TABLE t1 AS SELECT 1 AS f1; +HANDLER t1 OPEN; +TRUNCATE t1; +--error ER_UNKNOWN_TABLE +HANDLER t1 READ FIRST; +DROP TABLE t1; + +CREATE TEMPORARY TABLE t1 AS SELECT 1 AS f1; +HANDLER t1 OPEN; +TRUNCATE t1; +--error ER_UNKNOWN_TABLE +HANDLER t1 READ FIRST; +DROP TABLE t1; + +--echo # +--echo # Bug #54007: assert in ha_myisam::index_next , HANDLER +--echo # +CREATE TABLE t1(a INT, b INT, PRIMARY KEY(a), KEY b(b), KEY ab(a, b)); + +HANDLER t1 OPEN; +HANDLER t1 READ FIRST; +HANDLER t1 READ `PRIMARY` NEXT; +HANDLER t1 READ ab NEXT; +HANDLER t1 READ b NEXT; +HANDLER t1 READ NEXT; +HANDLER t1 CLOSE; + +INSERT INTO t1 VALUES (2, 20), (1, 10), (4, 40), (3, 30); +HANDLER t1 OPEN; +HANDLER t1 READ FIRST; +HANDLER t1 READ NEXT; +HANDLER t1 READ `PRIMARY` NEXT; +HANDLER t1 READ `PRIMARY` NEXT; +HANDLER t1 READ ab NEXT; +HANDLER t1 READ ab NEXT; +HANDLER t1 READ b NEXT; +HANDLER t1 READ b NEXT; +HANDLER t1 READ b NEXT; +HANDLER t1 READ b NEXT; +HANDLER t1 READ b NEXT; +HANDLER t1 READ NEXT; +HANDLER t1 READ NEXT; +HANDLER t1 READ NEXT; +HANDLER t1 CLOSE; + +HANDLER t1 OPEN; +HANDLER t1 READ FIRST; +HANDLER t1 READ `PRIMARY` PREV; +HANDLER t1 READ `PRIMARY` PREV; +HANDLER t1 READ b PREV; +HANDLER t1 READ b PREV; +HANDLER t1 CLOSE; + +HANDLER t1 OPEN; +HANDLER t1 READ FIRST; +HANDLER t1 READ `PRIMARY` PREV LIMIT 3; +HANDLER t1 READ b NEXT LIMIT 5; +HANDLER t1 CLOSE; + +DROP TABLE t1; + +--echo End of 5.1 tests diff --git a/mysql-test/include/handler.inc b/mysql-test/suite/handler/handler.inc similarity index 55% rename from mysql-test/include/handler.inc rename to mysql-test/suite/handler/handler.inc index 6e7f53ba9b2..48ed2ce0b8a 100644 --- a/mysql-test/include/handler.inc +++ b/mysql-test/suite/handler/handler.inc @@ -1,5 +1,7 @@ -# include/handler.inc +# handler.inc # +# See init.inc for setup of variables for this script +# # The variables # $engine_type -- storage engine to be tested # $other_engine_type -- storage engine <> $engine_type @@ -8,31 +10,19 @@ # 2. $other_handler_engine_type must point to an all # time available storage engine # 2006-08 MySQL 5.1 MyISAM and MEMORY only -# have to be set before sourcing this script. --- source include/not_embedded.inc # # test of HANDLER ... # # Last update: # 2006-07-31 ML test refactored (MySQL 5.1) # code of t/handler.test and t/innodb_handler.test united -# main testing code put into include/handler.inc +# main testing code put into handler.inc # -eval SET SESSION STORAGE_ENGINE = $engine_type; - ---disable_warnings -drop table if exists t1,t3,t4,t5; ---enable_warnings - -create table t1 (a int, b char(10), key a(a), key b(a,b)); -insert into t1 values -(17,"ddd"),(18,"eee"),(19,"fff"),(19,"yyy"), -(14,"aaa"),(15,"bbb"),(16,"ccc"),(16,"xxx"), -(20,"ggg"),(21,"hhh"),(22,"iii"); +# +# Start testing the table created in init.inc +# handler t1 open as t2; --- error 1064 -handler t2 read a=(SELECT 1); handler t2 read a first; handler t2 read a next; handler t2 read a next; @@ -65,12 +55,34 @@ handler t1 read a last; handler t2 read a=(11); handler t2 read a>=(11); +# Search on something we ca nfind handler t2 read a=(18); handler t2 read a>=(18); handler t2 read a>(18); handler t2 read a<=(18); handler t2 read a<(18); +# Search on something we can't find +handler t2 read a=(15); +handler t2 read a>=(15); +handler t2 read a>(15); +handler t2 read a<=(15); +handler t2 read a<(15); + +# Search from upper end +handler t2 read a=(54); +handler t2 read a>=(54); +handler t2 read a>(54); +handler t2 read a<=(54); +handler t2 read a<(54); + +# Search from lower end +handler t2 read a=(1); +handler t2 read a>=(1); +handler t2 read a>(1); +handler t2 read a<=(1); +handler t2 read a<(1); + handler t2 read a first limit 5; handler t2 read a next limit 3; handler t2 read a prev limit 10; @@ -85,8 +97,6 @@ handler t2 read a=(19) where b="yyy"; handler t2 read first; handler t2 read next; handler t2 read next; ---error 1064 -handler t2 read last; handler t2 close; handler t1 open; @@ -110,7 +120,7 @@ handler t2 read first; # handler t1 open as t2; drop table t1; -create table t1 (a int); +create table t1 (a int not null); insert into t1 values (17); --error 1109 handler t2 read first; @@ -137,7 +147,7 @@ drop table t1; # # Test for #751 # -create table t1(a int, index(a)); +eval create table t1(a int, index $key_type (a)); insert into t1 values (1), (2), (3); handler t1 open; --error 1054 @@ -164,7 +174,7 @@ drop table t1; # # BUG#3649 # -create table t1 ( a int, b int, INDEX a (a) ); +eval create table t1 ( a int, b int, INDEX a $key_type (a) ); insert into t1 values (1,2), (2,1); handler t1 open; handler t1 read a=(1) where b=2; @@ -173,143 +183,6 @@ handler t1 read a=(1) where b=1; handler t1 close; drop table t1; -# -# Check if two database names beginning the same are seen as different. -# -# This database begins like the usual 'test' database. -# ---disable_warnings -drop database if exists test_test; ---enable_warnings -create database test_test; -use test_test; -create table t1(table_id char(20) primary key); -insert into t1 values ('test_test.t1'); -insert into t1 values (''); -handler t1 open; -handler t1 read first limit 9; -create table t2(table_id char(20) primary key); -insert into t2 values ('test_test.t2'); -insert into t2 values (''); -handler t2 open; -handler t2 read first limit 9; -# -# This is the usual 'test' database. -# -use test; ---disable_warnings -drop table if exists t1; ---enable_warnings -create table t1(table_id char(20) primary key); -insert into t1 values ('test.t1'); -insert into t1 values (''); ---error 1066 -handler t1 open; -# -# Check accesibility of all the tables. -# -use test; ---error 1064 -handler test.t1 read first limit 9; ---error 1064 -handler test_test.t1 read first limit 9; -handler t1 read first limit 9; ---error 1064 -handler test_test.t2 read first limit 9; -handler t2 read first limit 9; - -# -# Cleanup. -# - ---error 1064 -handler test_test.t1 close; -handler t1 close; -drop table test_test.t1; ---error 1064 -handler test_test.t2 close; -handler t2 close; -drop table test_test.t2; -drop database test_test; - -# -use test; ---error 1064 -handler test.t1 close; ---error 1109 -handler t1 close; -drop table test.t1; - -# -# BUG#4335 -# ---disable_warnings -drop database if exists test_test; -drop table if exists t1; -drop table if exists t2; -drop table if exists t3; ---enable_warnings -create database test_test; -use test_test; -create table t1 (c1 char(20)); -insert into t1 values ('test_test.t1'); -create table t3 (c1 char(20)); -insert into t3 values ('test_test.t3'); -handler t1 open; -handler t1 read first limit 9; -handler t1 open h1; -handler h1 read first limit 9; -use test; -create table t1 (c1 char(20)); -create table t2 (c1 char(20)); -create table t3 (c1 char(20)); -insert into t1 values ('t1'); -insert into t2 values ('t2'); -insert into t3 values ('t3'); ---error 1066 -handler t1 open; ---error 1066 -handler t2 open t1; ---error 1066 -handler t3 open t1; -handler t1 read first limit 9; ---error 1064 -handler test.t1 close; ---error 1066 -handler test.t1 open h1; ---error 1066 -handler test_test.t1 open h1; -handler test_test.t3 open h3; -handler test.t1 open h2; -handler t1 read first limit 9; -handler h1 read first limit 9; -handler h2 read first limit 9; -handler h3 read first limit 9; -handler h2 read first limit 9; ---error 1064 -handler test.h1 close; -handler t1 close; -handler h1 close; -handler h2 close; ---error 1109 -handler t1 read first limit 9; ---error 1109 -handler h1 read first limit 9; ---error 1109 -handler h2 read first limit 9; -handler h3 read first limit 9; -handler h3 read first limit 9; -use test_test; -handler h3 read first limit 9; ---error 1064 -handler test.h3 read first limit 9; -handler h3 close; -use test; -drop table t3; -drop table t2; -drop table t1; -drop database test_test; - # # Test if fix for BUG#4286 correctly closes handler tables. # @@ -410,11 +283,13 @@ reap; connection default; drop table t1; -CREATE TABLE t1 ( no1 smallint(5) NOT NULL default '0', no2 int(10) NOT NULL default '0', PRIMARY KEY (no1,no2)); +eval CREATE TABLE t1 ( no1 smallint(5) NOT NULL default '0', no2 int(10) NOT NULL default '0', PRIMARY KEY $key_type (no1,no2)); INSERT INTO t1 VALUES (1,274),(1,275),(2,6),(2,8),(4,1),(4,2); HANDLER t1 OPEN; HANDLER t1 READ `primary` = (1, 1000); HANDLER t1 READ `primary` PREV; +HANDLER t1 READ `primary` = (1, 1000); +HANDLER t1 READ `primary` NEXT; DROP TABLE t1; # End of 4.1 tests @@ -468,10 +343,7 @@ drop table if exists t1; # # Bug#25856 - HANDLER table OPEN in one connection lock DROP TABLE in another one # ---disable_warnings -drop table if exists t1; ---enable_warnings -eval create table t1 (a int) ENGINE=$other_engine_type; +eval create table t1 (a int not null) ENGINE=$other_engine_type; --echo --> client 2 connection con2; --error 1031 @@ -484,9 +356,6 @@ disconnect con2; # # Bug#30632 HANDLER read failure causes hang # ---disable_warnings -drop table if exists t1; ---enable_warnings create table t1 (a int); handler t1 open as t1_alias; --error 1176 @@ -500,74 +369,6 @@ handler t1_alias READ a next where inexistent > 0; handler t1_alias close; drop table t1; -# -# Bug#21587 FLUSH TABLES causes server crash when used with HANDLER statements -# - ---disable_warnings -drop table if exists t1,t2; ---enable_warnings -create table t1 (c1 int); -create table t2 (c1 int); -insert into t1 values (1); -insert into t2 values (2); ---echo connection: default -handler t1 open; -handler t1 read first; -connect (flush,localhost,root,,); -connection flush; ---echo connection: flush ---send flush tables; -connection default; ---echo connection: default -let $wait_condition= - select count(*) = 1 from information_schema.processlist - where state = "Flushing tables"; ---source include/wait_condition.inc -handler t2 open; -handler t2 read first; -handler t1 read next; -handler t1 close; -handler t2 close; -connection flush; -reap; -connection default; -drop table t1,t2; -disconnect flush; - -# -# Bug#31409 RENAME TABLE causes server crash or deadlock when used with HANDLER statements -# - ---disable_warnings -drop table if exists t1,t2; ---enable_warnings -create table t1 (c1 int); ---echo connection: default -handler t1 open; -handler t1 read first; -connect (flush,localhost,root,,); -connection flush; ---echo connection: flush ---send rename table t1 to t2; -connection default; ---echo connection: default -let $wait_condition= - select count(*) = 1 from information_schema.processlist - where state = "Waiting for table" and info = "rename table t1 to t2"; ---source include/wait_condition.inc -handler t2 open; -handler t2 read first; ---error ER_NO_SUCH_TABLE -handler t1 read next; -handler t1 close; -handler t2 close; -connection flush; -reap; -connection default; -drop table t2; -disconnect flush; - # # Bug#30882 Dropping a temporary table inside a stored function may cause a server crash # @@ -575,15 +376,12 @@ disconnect flush; # is open by a HANDLER, no other statement can access it. # ---disable_warnings -drop table if exists t1; ---enable_warnings -create temporary table t1 (a int, b char(1), key a(a), key b(a,b)); +eval create temporary table t1 (a int, b char(1), key a $key_type (a), key b(a,b)); insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"), - (5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"); + (5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"),(9,'k'); select a,b from t1; handler t1 open as a1; -handler a1 read a first; +handler a1 read a=(1); handler a1 read a next; handler a1 read a next; --error ER_CANT_REOPEN_TABLE @@ -594,41 +392,19 @@ handler a1 read a=(6) where b="g"; handler a1 close; select a,b from t1; handler t1 open as a2; -handler a2 read a first; +handler a2 read a=(9); +handler a2 read a next; +handler a2 read a prev limit 2; +--error 0,1031 handler a2 read a last; handler a2 read a prev; handler a2 close; drop table t1; -# -# Bug#31397 Inconsistent drop table behavior of handler tables. -# - ---disable_warnings -drop table if exists t1,t2; ---enable_warnings -create table t1 (a int); -handler t1 open as t1_alias; -drop table t1; -create table t1 (a int); -handler t1 open as t1_alias; -flush tables; -drop table t1; -create table t1 (a int); -handler t1 open as t1_alias; -handler t1_alias close; -drop table t1; -create table t1 (a int); -handler t1 open as t1_alias; -handler t1_alias read first; -drop table t1; ---error ER_UNKNOWN_TABLE -handler t1_alias read next; - # Test that temporary tables associated with handlers are properly dropped. create table t1 (a int); -create temporary table t2 (a int, key(a)); +eval create temporary table t2 (a int, key $key_type (a)); handler t1 open as a1; handler t2 open as a2; handler a2 read a first; @@ -640,7 +416,7 @@ handler a1 close; # Alter table drop handlers -create table t1 (a int, key(a)); +eval create table t1 (a int, key $key_type (a)); create table t2 like t1; handler t1 open as a1; handler t2 open as a2; @@ -654,7 +430,7 @@ drop table t1, t2; # Rename table drop handlers -create table t1 (a int, key(a)); +eval create table t1 (a int, key $key_type (a)); handler t1 open as a1; handler a1 read a first; rename table t1 to t2; @@ -664,7 +440,7 @@ drop table t2; # Optimize table drop handlers -create table t1 (a int, key(a)); +eval create table t1 (a int, key $key_type (a)); create table t2 like t1; handler t1 open as a1; handler t2 open as a2; @@ -676,56 +452,14 @@ handler a1 close; handler a2 close; drop table t1, t2; -# Flush tables causes handlers reopen - -create table t1 (a int, b char(1), key a(a), key b(a,b)); -insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"), - (5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"); -handler t1 open; -handler t1 read a first; -handler t1 read a next; -flush tables; -handler t1 read a next; -handler t1 read a next; -flush tables with read lock; -handler t1 read a next; -unlock tables; -drop table t1; ---error ER_UNKNOWN_TABLE -handler t1 read a next; - -# -# Bug#41110: crash with handler command when used concurrently with alter table -# Bug#41112: crash in mysql_ha_close_table/get_lock_data with alter table -# - ---disable_warnings -drop table if exists t1; ---enable_warnings -create table t1 (a int); -insert into t1 values (1); -handler t1 open; -connect(con1,localhost,root,,); -send alter table t1 engine=memory; -connection default; -let $wait_condition= - select count(*) = 1 from information_schema.processlist - where state = "rename result table" and info = "alter table t1 engine=memory"; ---source include/wait_condition.inc ---error ER_ILLEGAL_HA -handler t1 read a next; -handler t1 close; -connection con1; ---reap -drop table t1; -disconnect con1; ---source include/wait_until_disconnected.inc -connection default; - -# -# Bug#44151 using handler commands on information_schema tables crashes server -# -USE information_schema; ---error ER_WRONG_USAGE -HANDLER COLUMNS OPEN; -USE test; +--echo # +--echo # BUG#51877 - HANDLER interface causes invalid memory read +--echo # +eval CREATE TABLE t1(a INT, KEY $key_type (a)); +HANDLER t1 OPEN; +HANDLER t1 READ a FIRST; +INSERT INTO t1 VALUES(1); +--error 0,ER_CHECKREAD +HANDLER t1 READ a NEXT; +HANDLER t1 CLOSE; +DROP TABLE t1; diff --git a/mysql-test/suite/handler/init.inc b/mysql-test/suite/handler/init.inc new file mode 100644 index 00000000000..32c6010f95b --- /dev/null +++ b/mysql-test/suite/handler/init.inc @@ -0,0 +1,33 @@ +# Setup things for handler.inc +# +# Input variables +# $engine_type -- storage engine to be tested +# $key_type -- set if you want a non standard key type +# +# This scripts sets up default values for: +# $other_engine_type -- storage engine <> $engine_type +# $other_handler_engine_type -- storage engine <> $engine_type, if possible +# 1. $other_handler_engine_type must support handler +# 2. $other_handler_engine_type must point to an all +# time available storage engine +# have to be set before sourcing this script. +# +# Handler tests don't work with embedded server +# +-- source include/not_embedded.inc + +eval SET SESSION STORAGE_ENGINE = $engine_type; +let $other_engine_type= CSV; +let $other_handler_engine_type= MyISAM; + +--disable_warnings +drop table if exists t1,t3,t4,t5; +--enable_warnings + +# Create default test table + +eval create table t1 (a int, b char(10), key a $key_type (a), key b $key_type (a,b)); +insert into t1 values +(17,"ddd"),(18,"eee"),(19,"fff"),(19,"yyy"), +(14,"aaa"),(16,"ccc"),(16,"xxx"), +(20,"ggg"),(21,"hhh"),(22,"iii"); diff --git a/mysql-test/r/handler_innodb.result b/mysql-test/suite/handler/innodb.result similarity index 54% rename from mysql-test/r/handler_innodb.result rename to mysql-test/suite/handler/innodb.result index 957fc30acef..83ce270612d 100644 --- a/mysql-test/r/handler_innodb.result +++ b/mysql-test/suite/handler/innodb.result @@ -1,25 +1,23 @@ SET SESSION STORAGE_ENGINE = InnoDB; drop table if exists t1,t3,t4,t5; -create table t1 (a int, b char(10), key a(a), key b(a,b)); +create table t1 (a int, b char(10), key a (a), key b (a,b)); insert into t1 values (17,"ddd"),(18,"eee"),(19,"fff"),(19,"yyy"), -(14,"aaa"),(15,"bbb"),(16,"ccc"),(16,"xxx"), +(14,"aaa"),(16,"ccc"),(16,"xxx"), (20,"ggg"),(21,"hhh"),(22,"iii"); handler t1 open as t2; -handler t2 read a=(SELECT 1); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT 1)' at line 1 handler t2 read a first; a b 14 aaa handler t2 read a next; a b -15 bbb +16 ccc handler t2 read a next; a b -16 ccc +16 xxx handler t2 read a prev; a b -15 bbb +16 ccc handler t2 read a last; a b 22 iii @@ -47,7 +45,6 @@ handler t2 read a next; a b handler t2 read a=(15); a b -15 bbb handler t2 read a=(16); a b 16 ccc @@ -84,26 +81,64 @@ a b handler t2 read a<(18); a b 17 ddd +handler t2 read a=(15); +a b +handler t2 read a>=(15); +a b +16 ccc +handler t2 read a>(15); +a b +16 ccc +handler t2 read a<=(15); +a b +14 aaa +handler t2 read a<(15); +a b +14 aaa +handler t2 read a=(54); +a b +handler t2 read a>=(54); +a b +handler t2 read a>(54); +a b +handler t2 read a<=(54); +a b +22 iii +handler t2 read a<(54); +a b +22 iii +handler t2 read a=(1); +a b +handler t2 read a>=(1); +a b +14 aaa +handler t2 read a>(1); +a b +14 aaa +handler t2 read a<=(1); +a b +handler t2 read a<(1); +a b handler t2 read a first limit 5; a b 14 aaa -15 bbb 16 ccc 16 xxx 17 ddd +18 eee handler t2 read a next limit 3; a b -18 eee 19 fff 19 yyy +20 ggg handler t2 read a prev limit 10; a b +19 yyy 19 fff 18 eee 17 ddd 16 xxx 16 ccc -15 bbb 14 aaa handler t2 read a>=(16) limit 4; a b @@ -135,8 +170,6 @@ a b handler t2 read next; a b 19 fff -handler t2 read last; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 handler t2 close; handler t1 open; handler t1 read a next; @@ -144,7 +177,7 @@ a b 14 aaa handler t1 read a next; a b -15 bbb +16 ccc handler t1 close; handler t1 open; handler t1 read a prev; @@ -163,12 +196,12 @@ handler t2 read first; ERROR 42S02: Unknown table 't2' in HANDLER handler t1 open as t2; drop table t1; -create table t1 (a int); +create table t1 (a int not null); insert into t1 values (17); handler t2 read first; ERROR 42S02: Unknown table 't2' in HANDLER handler t1 open as t2; -alter table t1 engine=MEMORY; +alter table t1 engine=CSV; handler t2 read first; ERROR 42S02: Unknown table 't2' in HANDLER drop table t1; @@ -191,7 +224,7 @@ handler t1 read first; a 6 drop table t1; -create table t1(a int, index(a)); +create table t1(a int, index (a)); insert into t1 values (1), (2), (3); handler t1 open; handler t1 read a=(W); @@ -217,7 +250,7 @@ Ok handler t close; use test; drop table t1; -create table t1 ( a int, b int, INDEX a (a) ); +create table t1 ( a int, b int, INDEX a (a) ); insert into t1 values (1,2), (2,1); handler t1 open; handler t1 read a=(1) where b=2; @@ -229,148 +262,6 @@ handler t1 read a=(1) where b=1; a b handler t1 close; drop table t1; -drop database if exists test_test; -create database test_test; -use test_test; -create table t1(table_id char(20) primary key); -insert into t1 values ('test_test.t1'); -insert into t1 values (''); -handler t1 open; -handler t1 read first limit 9; -table_id - -test_test.t1 -create table t2(table_id char(20) primary key); -insert into t2 values ('test_test.t2'); -insert into t2 values (''); -handler t2 open; -handler t2 read first limit 9; -table_id - -test_test.t2 -use test; -drop table if exists t1; -create table t1(table_id char(20) primary key); -insert into t1 values ('test.t1'); -insert into t1 values (''); -handler t1 open; -ERROR 42000: Not unique table/alias: 't1' -use test; -handler test.t1 read first limit 9; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'read first limit 9' at line 1 -handler test_test.t1 read first limit 9; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'read first limit 9' at line 1 -handler t1 read first limit 9; -table_id - -test_test.t1 -handler test_test.t2 read first limit 9; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'read first limit 9' at line 1 -handler t2 read first limit 9; -table_id - -test_test.t2 -handler test_test.t1 close; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'close' at line 1 -handler t1 close; -drop table test_test.t1; -handler test_test.t2 close; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'close' at line 1 -handler t2 close; -drop table test_test.t2; -drop database test_test; -use test; -handler test.t1 close; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'close' at line 1 -handler t1 close; -ERROR 42S02: Unknown table 't1' in HANDLER -drop table test.t1; -drop database if exists test_test; -drop table if exists t1; -drop table if exists t2; -drop table if exists t3; -create database test_test; -use test_test; -create table t1 (c1 char(20)); -insert into t1 values ('test_test.t1'); -create table t3 (c1 char(20)); -insert into t3 values ('test_test.t3'); -handler t1 open; -handler t1 read first limit 9; -c1 -test_test.t1 -handler t1 open h1; -handler h1 read first limit 9; -c1 -test_test.t1 -use test; -create table t1 (c1 char(20)); -create table t2 (c1 char(20)); -create table t3 (c1 char(20)); -insert into t1 values ('t1'); -insert into t2 values ('t2'); -insert into t3 values ('t3'); -handler t1 open; -ERROR 42000: Not unique table/alias: 't1' -handler t2 open t1; -ERROR 42000: Not unique table/alias: 't1' -handler t3 open t1; -ERROR 42000: Not unique table/alias: 't1' -handler t1 read first limit 9; -c1 -test_test.t1 -handler test.t1 close; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'close' at line 1 -handler test.t1 open h1; -ERROR 42000: Not unique table/alias: 'h1' -handler test_test.t1 open h1; -ERROR 42000: Not unique table/alias: 'h1' -handler test_test.t3 open h3; -handler test.t1 open h2; -handler t1 read first limit 9; -c1 -test_test.t1 -handler h1 read first limit 9; -c1 -test_test.t1 -handler h2 read first limit 9; -c1 -t1 -handler h3 read first limit 9; -c1 -test_test.t3 -handler h2 read first limit 9; -c1 -t1 -handler test.h1 close; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'close' at line 1 -handler t1 close; -handler h1 close; -handler h2 close; -handler t1 read first limit 9; -ERROR 42S02: Unknown table 't1' in HANDLER -handler h1 read first limit 9; -ERROR 42S02: Unknown table 'h1' in HANDLER -handler h2 read first limit 9; -ERROR 42S02: Unknown table 'h2' in HANDLER -handler h3 read first limit 9; -c1 -test_test.t3 -handler h3 read first limit 9; -c1 -test_test.t3 -use test_test; -handler h3 read first limit 9; -c1 -test_test.t3 -handler test.h3 read first limit 9; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'read first limit 9' at line 1 -handler h3 close; -use test; -drop table t3; -drop table t2; -drop table t1; -drop database test_test; create table t1 (c1 char(20)); insert into t1 values ("t1"); handler t1 open as h1; @@ -496,6 +387,11 @@ no1 no2 HANDLER t1 READ `primary` PREV; no1 no2 1 275 +HANDLER t1 READ `primary` = (1, 1000); +no1 no2 +HANDLER t1 READ `primary` NEXT; +no1 no2 +2 8 DROP TABLE t1; create table t1 (c1 int); insert into t1 values (14397); @@ -516,14 +412,12 @@ ERROR 42S02: Table 'test.t1' doesn't exist drop table if exists t1; Warnings: Note 1051 Unknown table 't1' -drop table if exists t1; -create table t1 (a int) ENGINE=MEMORY; +create table t1 (a int not null) ENGINE=CSV; --> client 2 handler t1 open; ERROR HY000: Table storage engine for 't1' doesn't have this option --> client 1 drop table t1; -drop table if exists t1; create table t1 (a int); handler t1 open as t1_alias; handler t1_alias read a next; @@ -536,50 +430,9 @@ handler t1_alias READ a next where inexistent > 0; ERROR 42S22: Unknown column 'inexistent' in 'field list' handler t1_alias close; drop table t1; -drop table if exists t1,t2; -create table t1 (c1 int); -create table t2 (c1 int); -insert into t1 values (1); -insert into t2 values (2); -connection: default -handler t1 open; -handler t1 read first; -c1 -1 -connection: flush -flush tables;; -connection: default -handler t2 open; -handler t2 read first; -c1 -2 -handler t1 read next; -c1 -1 -handler t1 close; -handler t2 close; -drop table t1,t2; -drop table if exists t1,t2; -create table t1 (c1 int); -connection: default -handler t1 open; -handler t1 read first; -c1 -connection: flush -rename table t1 to t2;; -connection: default -handler t2 open; -handler t2 read first; -c1 -handler t1 read next; -ERROR 42S02: Table 'test.t1' doesn't exist -handler t1 close; -handler t2 close; -drop table t2; -drop table if exists t1; -create temporary table t1 (a int, b char(1), key a(a), key b(a,b)); +create temporary table t1 (a int, b char(1), key a (a), key b(a,b)); insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"), -(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"); +(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"),(9,'k'); select a,b from t1; a b 0 a @@ -592,24 +445,25 @@ a b 7 h 8 i 9 j +9 k handler t1 open as a1; -handler a1 read a first; -a b -0 a -handler a1 read a next; +handler a1 read a=(1); a b 1 b handler a1 read a next; a b 2 c +handler a1 read a next; +a b +3 d select a,b from t1; ERROR HY000: Can't reopen table: 'a1' handler a1 read a prev; a b -1 b +2 c handler a1 read a prev; a b -0 a +1 b handler a1 read a=(6) where b="g"; a b 6 g @@ -626,39 +480,28 @@ a b 7 h 8 i 9 j +9 k handler t1 open as a2; -handler a2 read a first; -a b -0 a -handler a2 read a last; +handler a2 read a=(9); a b 9 j +handler a2 read a next; +a b +9 k +handler a2 read a prev limit 2; +a b +9 j +8 i +handler a2 read a last; +a b +9 k handler a2 read a prev; a b -8 i +9 j handler a2 close; drop table t1; -drop table if exists t1,t2; create table t1 (a int); -handler t1 open as t1_alias; -drop table t1; -create table t1 (a int); -handler t1 open as t1_alias; -flush tables; -drop table t1; -create table t1 (a int); -handler t1 open as t1_alias; -handler t1_alias close; -drop table t1; -create table t1 (a int); -handler t1 open as t1_alias; -handler t1_alias read first; -a -drop table t1; -handler t1_alias read next; -ERROR 42S02: Unknown table 't1_alias' in HANDLER -create table t1 (a int); -create temporary table t2 (a int, key(a)); +create temporary table t2 (a int, key (a)); handler t1 open as a1; handler t2 open as a2; handler a2 read a first; @@ -668,7 +511,7 @@ handler a2 read a next; ERROR 42S02: Unknown table 'a2' in HANDLER handler a1 close; ERROR 42S02: Unknown table 'a1' in HANDLER -create table t1 (a int, key(a)); +create table t1 (a int, key (a)); create table t2 like t1; handler t1 open as a1; handler t2 open as a2; @@ -681,7 +524,7 @@ handler a1 close; ERROR 42S02: Unknown table 'a1' in HANDLER handler a2 close; drop table t1, t2; -create table t1 (a int, key(a)); +create table t1 (a int, key (a)); handler t1 open as a1; handler a1 read a first; a @@ -689,7 +532,7 @@ rename table t1 to t2; handler a1 read a first; ERROR 42S02: Unknown table 'a1' in HANDLER drop table t2; -create table t1 (a int, key(a)); +create table t1 (a int, key (a)); create table t2 like t1; handler t1 open as a1; handler t2 open as a2; @@ -705,41 +548,15 @@ handler a1 close; ERROR 42S02: Unknown table 'a1' in HANDLER handler a2 close; drop table t1, t2; -create table t1 (a int, b char(1), key a(a), key b(a,b)); -insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"), -(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"); -handler t1 open; -handler t1 read a first; -a b -0 a -handler t1 read a next; -a b -1 b -flush tables; -handler t1 read a next; -a b -0 a -handler t1 read a next; -a b -1 b -flush tables with read lock; -handler t1 read a next; -a b -0 a -unlock tables; -drop table t1; -handler t1 read a next; -ERROR 42S02: Unknown table 't1' in HANDLER -drop table if exists t1; -create table t1 (a int); -insert into t1 values (1); -handler t1 open; -alter table t1 engine=memory; -handler t1 read a next; -ERROR HY000: Table storage engine for 't1' doesn't have this option -handler t1 close; -drop table t1; -USE information_schema; -HANDLER COLUMNS OPEN; -ERROR HY000: Incorrect usage of HANDLER OPEN and information_schema -USE test; +# +# BUG#51877 - HANDLER interface causes invalid memory read +# +CREATE TABLE t1(a INT, KEY (a)); +HANDLER t1 OPEN; +HANDLER t1 READ a FIRST; +a +INSERT INTO t1 VALUES(1); +HANDLER t1 READ a NEXT; +a +HANDLER t1 CLOSE; +DROP TABLE t1; diff --git a/mysql-test/t/handler_innodb.test b/mysql-test/suite/handler/innodb.test similarity index 55% rename from mysql-test/t/handler_innodb.test rename to mysql-test/suite/handler/innodb.test index 02982716f78..f4e4bf7cc3f 100644 --- a/mysql-test/t/handler_innodb.test +++ b/mysql-test/suite/handler/innodb.test @@ -5,16 +5,13 @@ # Last update: # 2006-07-31 ML test refactored (MySQL 5.1) # code of t/handler.test and t/innodb_handler.test united -# main testing code put into include/handler.inc +# main testing code put into handler.inc # rename t/innodb_handler.test to t/handler_innodb.test # -# should work in embedded server after mysqltest is fixed ---source include/not_embedded.inc - --source include/have_innodb.inc -let $engine_type= InnoDB; -let $other_engine_type= MEMORY; -let $other_handler_engine_type= MyISAM; ---source include/handler.inc +let $engine_type= InnoDB; + +--source init.inc +--source handler.inc diff --git a/mysql-test/suite/handler/interface.result b/mysql-test/suite/handler/interface.result new file mode 100644 index 00000000000..0b5a4447739 --- /dev/null +++ b/mysql-test/suite/handler/interface.result @@ -0,0 +1,259 @@ +drop table if exists t1,t3,t4,t5; +drop database if exists test_test; +SET SESSION STORAGE_ENGINE = MyISAM; +drop table if exists t1,t3,t4,t5; +create table t1 (a int, b char(10), key a (a), key b (a,b)); +insert into t1 values +(17,"ddd"),(18,"eee"),(19,"fff"),(19,"yyy"), +(14,"aaa"),(16,"ccc"),(16,"xxx"), +(20,"ggg"),(21,"hhh"),(22,"iii"); +handler t1 open; +handler t1 read a=(SELECT 1); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT 1)' at line 1 +handler t1 read a=(1) FIRST; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FIRST' at line 1 +handler t1 read a=(1) NEXT; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'NEXT' at line 1 +handler t1 read last; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 +handler t1 close; +drop table t1; +CREATE TABLE t1(a INT, PRIMARY KEY(a)); +insert into t1 values(1),(2); +handler t1 open; +handler t1 read primary=(1); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'primary=(1)' at line 1 +handler t1 read `primary`=(1); +a +1 +handler t1 close; +drop table t1; +create database test_test; +use test_test; +create table t1(table_id char(20), primary key (table_id)); +insert into t1 values ('test_test.t1'); +insert into t1 values (''); +handler t1 open; +handler t1 read first limit 9; +table_id +test_test.t1 + +create table t2(table_id char(20), primary key (table_id)); +insert into t2 values ('test_test.t2'); +insert into t2 values (''); +handler t2 open; +handler t2 read first limit 9; +table_id +test_test.t2 + +use test; +create table t1(table_id char(20), primary key (table_id)); +insert into t1 values ('test.t1'); +insert into t1 values (''); +handler t1 open; +ERROR 42000: Not unique table/alias: 't1' +use test; +handler test.t1 read first limit 9; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'read first limit 9' at line 1 +handler test_test.t1 read first limit 9; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'read first limit 9' at line 1 +handler t1 read first limit 9; +table_id +test_test.t1 + +handler test_test.t2 read first limit 9; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'read first limit 9' at line 1 +handler t2 read first limit 9; +table_id +test_test.t2 + +handler test_test.t1 close; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'close' at line 1 +handler t1 close; +drop table test_test.t1; +handler test_test.t2 close; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'close' at line 1 +handler t2 close; +drop table test_test.t2; +drop database test_test; +use test; +handler test.t1 close; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'close' at line 1 +handler t1 close; +ERROR 42S02: Unknown table 't1' in HANDLER +drop table test.t1; +create database test_test; +use test_test; +create table t1 (c1 char(20)); +insert into t1 values ('test_test.t1'); +create table t3 (c1 char(20)); +insert into t3 values ('test_test.t3'); +handler t1 open; +handler t1 read first limit 9; +c1 +test_test.t1 +handler t1 open h1; +handler h1 read first limit 9; +c1 +test_test.t1 +use test; +create table t1 (c1 char(20)); +create table t2 (c1 char(20)); +create table t3 (c1 char(20)); +insert into t1 values ('t1'); +insert into t2 values ('t2'); +insert into t3 values ('t3'); +handler t1 open; +ERROR 42000: Not unique table/alias: 't1' +handler t2 open t1; +ERROR 42000: Not unique table/alias: 't1' +handler t3 open t1; +ERROR 42000: Not unique table/alias: 't1' +handler t1 read first limit 9; +c1 +test_test.t1 +handler test.t1 close; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'close' at line 1 +handler test.t1 open h1; +ERROR 42000: Not unique table/alias: 'h1' +handler test_test.t1 open h1; +ERROR 42000: Not unique table/alias: 'h1' +handler test_test.t3 open h3; +handler test.t1 open h2; +handler t1 read first limit 9; +c1 +test_test.t1 +handler h1 read first limit 9; +c1 +test_test.t1 +handler h2 read first limit 9; +c1 +t1 +handler h3 read first limit 9; +c1 +test_test.t3 +handler h2 read first limit 9; +c1 +t1 +handler test.h1 close; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'close' at line 1 +handler t1 close; +handler h1 close; +handler h2 close; +handler t1 read first limit 9; +ERROR 42S02: Unknown table 't1' in HANDLER +handler h1 read first limit 9; +ERROR 42S02: Unknown table 'h1' in HANDLER +handler h2 read first limit 9; +ERROR 42S02: Unknown table 'h2' in HANDLER +handler h3 read first limit 9; +c1 +test_test.t3 +handler h3 read first limit 9; +c1 +test_test.t3 +use test_test; +handler h3 read first limit 9; +c1 +test_test.t3 +handler test.h3 read first limit 9; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'read first limit 9' at line 1 +handler h3 close; +use test; +drop table t3; +drop table t2; +drop table t1; +drop database test_test; +create table t1 (c1 int); +create table t2 (c1 int); +insert into t1 values (1); +insert into t2 values (2); +connection: default +handler t1 open; +handler t1 read first; +c1 +1 +connection: flush +flush tables;; +connection: default +handler t2 open; +handler t2 read first; +c1 +2 +handler t1 read next; +c1 +1 +handler t1 close; +handler t2 close; +drop table t1,t2; +create table t1 (a int); +handler t1 open as t1_alias; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +flush tables; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +handler t1_alias close; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +handler t1_alias read first; +a +drop table t1; +handler t1_alias read next; +ERROR 42S02: Unknown table 't1_alias' in HANDLER +create table t1 (c1 int); +connection: default +handler t1 open; +handler t1 read first; +c1 +connection: flush +rename table t1 to t2;; +connection: default +handler t2 open; +handler t2 read first; +c1 +handler t1 read next; +ERROR 42S02: Table 'test.t1' doesn't exist +handler t1 close; +handler t2 close; +drop table t2; +create table t1 (a int, b char(1), key a (a), key b (a,b)); +insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"), +(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"); +handler t1 open; +handler t1 read a first; +a b +0 a +handler t1 read a next; +a b +1 b +flush tables; +handler t1 read a next; +a b +0 a +handler t1 read a next; +a b +1 b +flush tables with read lock; +handler t1 read a next; +a b +0 a +unlock tables; +drop table t1; +handler t1 read a next; +ERROR 42S02: Unknown table 't1' in HANDLER +drop table if exists t1; +create table t1 (a int not null); +insert into t1 values (1); +handler t1 open; +alter table t1 engine=csv; +handler t1 read a next; +ERROR HY000: Table storage engine for 't1' doesn't have this option +handler t1 close; +drop table t1; +USE information_schema; +HANDLER COLUMNS OPEN; +ERROR HY000: Incorrect usage of HANDLER OPEN and information_schema diff --git a/mysql-test/suite/handler/interface.test b/mysql-test/suite/handler/interface.test new file mode 100644 index 00000000000..809f0228f98 --- /dev/null +++ b/mysql-test/suite/handler/interface.test @@ -0,0 +1,307 @@ +# +# Tests of handler interface that are system independent +# +# Handler tests don't work yet with embedded server +# +-- source include/not_embedded.inc + +--disable_warnings +drop table if exists t1,t3,t4,t5; +drop database if exists test_test; +--enable_warnings + +# Run tests with myisam (any engine should be ok) + +let $engine_type= MyISAM; + +--source init.inc + +# +# Do some syntax checking +# + +handler t1 open; +--error ER_PARSE_ERROR +handler t1 read a=(SELECT 1); +--error ER_PARSE_ERROR +handler t1 read a=(1) FIRST; +--error ER_PARSE_ERROR +handler t1 read a=(1) NEXT; +--error ER_PARSE_ERROR +handler t1 read last; +handler t1 close; +drop table t1; + +CREATE TABLE t1(a INT, PRIMARY KEY(a)); +insert into t1 values(1),(2); +handler t1 open; +--error ER_PARSE_ERROR +handler t1 read primary=(1); +handler t1 read `primary`=(1); +handler t1 close; +drop table t1; + +# +# Check if two database names beginning the same are seen as different. +# +# This database begins like the usual 'test' database. +# +create database test_test; +use test_test; +eval create table t1(table_id char(20), primary key $key_type (table_id)); +insert into t1 values ('test_test.t1'); +insert into t1 values (''); +handler t1 open; +handler t1 read first limit 9; +eval create table t2(table_id char(20), primary key $key_type (table_id)); +insert into t2 values ('test_test.t2'); +insert into t2 values (''); +handler t2 open; +handler t2 read first limit 9; +# +# This is the usual 'test' database. +# +use test; +eval create table t1(table_id char(20), primary key $key_type (table_id)); +insert into t1 values ('test.t1'); +insert into t1 values (''); +--error 1066 +handler t1 open; +# +# Check accessibility of all the tables. +# +use test; +--error 1064 +handler test.t1 read first limit 9; +--error 1064 +handler test_test.t1 read first limit 9; +handler t1 read first limit 9; +--error 1064 +handler test_test.t2 read first limit 9; +handler t2 read first limit 9; + +# +# Cleanup. +# + +--error 1064 +handler test_test.t1 close; +handler t1 close; +drop table test_test.t1; +--error 1064 +handler test_test.t2 close; +handler t2 close; +drop table test_test.t2; +drop database test_test; + +# +use test; +--error 1064 +handler test.t1 close; +--error 1109 +handler t1 close; +drop table test.t1; + +# +# BUG#4335 one name can be handler open'ed many times +# + +create database test_test; +use test_test; +create table t1 (c1 char(20)); +insert into t1 values ('test_test.t1'); +create table t3 (c1 char(20)); +insert into t3 values ('test_test.t3'); +handler t1 open; +handler t1 read first limit 9; +handler t1 open h1; +handler h1 read first limit 9; +use test; +create table t1 (c1 char(20)); +create table t2 (c1 char(20)); +create table t3 (c1 char(20)); +insert into t1 values ('t1'); +insert into t2 values ('t2'); +insert into t3 values ('t3'); +--error 1066 +handler t1 open; +--error 1066 +handler t2 open t1; +--error 1066 +handler t3 open t1; +handler t1 read first limit 9; +--error 1064 +handler test.t1 close; +--error 1066 +handler test.t1 open h1; +--error 1066 +handler test_test.t1 open h1; +handler test_test.t3 open h3; +handler test.t1 open h2; +handler t1 read first limit 9; +handler h1 read first limit 9; +handler h2 read first limit 9; +handler h3 read first limit 9; +handler h2 read first limit 9; +--error 1064 +handler test.h1 close; +handler t1 close; +handler h1 close; +handler h2 close; +--error 1109 +handler t1 read first limit 9; +--error 1109 +handler h1 read first limit 9; +--error 1109 +handler h2 read first limit 9; +handler h3 read first limit 9; +handler h3 read first limit 9; +use test_test; +handler h3 read first limit 9; +--error 1064 +handler test.h3 read first limit 9; +handler h3 close; +use test; +drop table t3; +drop table t2; +drop table t1; +drop database test_test; + +# +# Bug#21587 FLUSH TABLES causes server crash when used with HANDLER statements +# + +create table t1 (c1 int); +create table t2 (c1 int); +insert into t1 values (1); +insert into t2 values (2); +--echo connection: default +handler t1 open; +handler t1 read first; +connect (flush,localhost,root,,); +connection flush; +--echo connection: flush +--send flush tables; +connection default; +--echo connection: default +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Flushing tables"; +--source include/wait_condition.inc +handler t2 open; +handler t2 read first; +handler t1 read next; +handler t1 close; +handler t2 close; +connection flush; +reap; +connection default; +drop table t1,t2; +disconnect flush; + +# +# Bug#31397 Inconsistent drop table behavior of handler tables. +# + +create table t1 (a int); +handler t1 open as t1_alias; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +flush tables; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +handler t1_alias close; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +handler t1_alias read first; +drop table t1; +--error ER_UNKNOWN_TABLE +handler t1_alias read next; + +# +# Bug#31409 RENAME TABLE causes server crash or deadlock when used with +# HANDLER statements +# + +create table t1 (c1 int); +--echo connection: default +handler t1 open; +handler t1 read first; +connect (flush,localhost,root,,); +connection flush; +--echo connection: flush +--send rename table t1 to t2; +connection default; +--echo connection: default +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Waiting for table" and info = "rename table t1 to t2"; +--source include/wait_condition.inc +handler t2 open; +handler t2 read first; +--error ER_NO_SUCH_TABLE +handler t1 read next; +handler t1 close; +handler t2 close; +connection flush; +reap; +connection default; +drop table t2; +disconnect flush; + +# Flush tables causes handlers reopen + +eval create table t1 (a int, b char(1), key a $key_type (a), key b $key_type (a,b)); +insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"), + (5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"); +handler t1 open; +handler t1 read a first; +handler t1 read a next; +flush tables; +handler t1 read a next; +handler t1 read a next; +flush tables with read lock; +handler t1 read a next; +unlock tables; +drop table t1; +--error ER_UNKNOWN_TABLE +handler t1 read a next; + +# +# Bug#41110: crash with handler command when used concurrently with alter table +# Bug#41112: crash in mysql_ha_close_table/get_lock_data with alter table +# + +--disable_warnings +drop table if exists t1; +--enable_warnings +create table t1 (a int not null); +insert into t1 values (1); +handler t1 open; +connect(con1,localhost,root,,); +send alter table t1 engine=csv; +connection default; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "rename result table" and info = "alter table t1 engine=csv"; +--source include/wait_condition.inc +--error ER_ILLEGAL_HA +handler t1 read a next; +handler t1 close; +connection con1; +--reap +drop table t1; +disconnect con1; +--source include/wait_until_disconnected.inc +connection default; + +# +# Bug#44151 using handler commands on information_schema tables crashes server +# + +USE information_schema; +--error ER_WRONG_USAGE +HANDLER COLUMNS OPEN; diff --git a/mysql-test/r/handler_myisam.result b/mysql-test/suite/handler/myisam.result similarity index 58% rename from mysql-test/r/handler_myisam.result rename to mysql-test/suite/handler/myisam.result index b20b8dbb138..bd356d6e81d 100644 --- a/mysql-test/r/handler_myisam.result +++ b/mysql-test/suite/handler/myisam.result @@ -1,25 +1,23 @@ SET SESSION STORAGE_ENGINE = MyISAM; drop table if exists t1,t3,t4,t5; -create table t1 (a int, b char(10), key a(a), key b(a,b)); +create table t1 (a int, b char(10), key a (a), key b (a,b)); insert into t1 values (17,"ddd"),(18,"eee"),(19,"fff"),(19,"yyy"), -(14,"aaa"),(15,"bbb"),(16,"ccc"),(16,"xxx"), +(14,"aaa"),(16,"ccc"),(16,"xxx"), (20,"ggg"),(21,"hhh"),(22,"iii"); handler t1 open as t2; -handler t2 read a=(SELECT 1); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT 1)' at line 1 handler t2 read a first; a b 14 aaa handler t2 read a next; a b -15 bbb +16 ccc handler t2 read a next; a b -16 ccc +16 xxx handler t2 read a prev; a b -15 bbb +16 ccc handler t2 read a last; a b 22 iii @@ -47,7 +45,6 @@ handler t2 read a next; a b handler t2 read a=(15); a b -15 bbb handler t2 read a=(16); a b 16 ccc @@ -84,26 +81,64 @@ a b handler t2 read a<(18); a b 17 ddd +handler t2 read a=(15); +a b +handler t2 read a>=(15); +a b +16 ccc +handler t2 read a>(15); +a b +16 ccc +handler t2 read a<=(15); +a b +14 aaa +handler t2 read a<(15); +a b +14 aaa +handler t2 read a=(54); +a b +handler t2 read a>=(54); +a b +handler t2 read a>(54); +a b +handler t2 read a<=(54); +a b +22 iii +handler t2 read a<(54); +a b +22 iii +handler t2 read a=(1); +a b +handler t2 read a>=(1); +a b +14 aaa +handler t2 read a>(1); +a b +14 aaa +handler t2 read a<=(1); +a b +handler t2 read a<(1); +a b handler t2 read a first limit 5; a b 14 aaa -15 bbb 16 ccc 16 xxx 17 ddd +18 eee handler t2 read a next limit 3; a b -18 eee 19 fff 19 yyy +20 ggg handler t2 read a prev limit 10; a b +19 yyy 19 fff 18 eee 17 ddd 16 xxx 16 ccc -15 bbb 14 aaa handler t2 read a>=(16) limit 4; a b @@ -135,8 +170,6 @@ a b handler t2 read next; a b 19 fff -handler t2 read last; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 handler t2 close; handler t1 open; handler t1 read a next; @@ -144,7 +177,7 @@ a b 14 aaa handler t1 read a next; a b -15 bbb +16 ccc handler t1 close; handler t1 open; handler t1 read a prev; @@ -163,12 +196,12 @@ handler t2 read first; ERROR 42S02: Unknown table 't2' in HANDLER handler t1 open as t2; drop table t1; -create table t1 (a int); +create table t1 (a int not null); insert into t1 values (17); handler t2 read first; ERROR 42S02: Unknown table 't2' in HANDLER handler t1 open as t2; -alter table t1 engine=MEMORY; +alter table t1 engine=CSV; handler t2 read first; ERROR 42S02: Unknown table 't2' in HANDLER drop table t1; @@ -191,7 +224,7 @@ handler t1 read first; a 6 drop table t1; -create table t1(a int, index(a)); +create table t1(a int, index (a)); insert into t1 values (1), (2), (3); handler t1 open; handler t1 read a=(W); @@ -217,7 +250,7 @@ Ok handler t close; use test; drop table t1; -create table t1 ( a int, b int, INDEX a (a) ); +create table t1 ( a int, b int, INDEX a (a) ); insert into t1 values (1,2), (2,1); handler t1 open; handler t1 read a=(1) where b=2; @@ -229,148 +262,6 @@ handler t1 read a=(1) where b=1; a b handler t1 close; drop table t1; -drop database if exists test_test; -create database test_test; -use test_test; -create table t1(table_id char(20) primary key); -insert into t1 values ('test_test.t1'); -insert into t1 values (''); -handler t1 open; -handler t1 read first limit 9; -table_id -test_test.t1 - -create table t2(table_id char(20) primary key); -insert into t2 values ('test_test.t2'); -insert into t2 values (''); -handler t2 open; -handler t2 read first limit 9; -table_id -test_test.t2 - -use test; -drop table if exists t1; -create table t1(table_id char(20) primary key); -insert into t1 values ('test.t1'); -insert into t1 values (''); -handler t1 open; -ERROR 42000: Not unique table/alias: 't1' -use test; -handler test.t1 read first limit 9; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'read first limit 9' at line 1 -handler test_test.t1 read first limit 9; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'read first limit 9' at line 1 -handler t1 read first limit 9; -table_id -test_test.t1 - -handler test_test.t2 read first limit 9; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'read first limit 9' at line 1 -handler t2 read first limit 9; -table_id -test_test.t2 - -handler test_test.t1 close; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'close' at line 1 -handler t1 close; -drop table test_test.t1; -handler test_test.t2 close; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'close' at line 1 -handler t2 close; -drop table test_test.t2; -drop database test_test; -use test; -handler test.t1 close; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'close' at line 1 -handler t1 close; -ERROR 42S02: Unknown table 't1' in HANDLER -drop table test.t1; -drop database if exists test_test; -drop table if exists t1; -drop table if exists t2; -drop table if exists t3; -create database test_test; -use test_test; -create table t1 (c1 char(20)); -insert into t1 values ('test_test.t1'); -create table t3 (c1 char(20)); -insert into t3 values ('test_test.t3'); -handler t1 open; -handler t1 read first limit 9; -c1 -test_test.t1 -handler t1 open h1; -handler h1 read first limit 9; -c1 -test_test.t1 -use test; -create table t1 (c1 char(20)); -create table t2 (c1 char(20)); -create table t3 (c1 char(20)); -insert into t1 values ('t1'); -insert into t2 values ('t2'); -insert into t3 values ('t3'); -handler t1 open; -ERROR 42000: Not unique table/alias: 't1' -handler t2 open t1; -ERROR 42000: Not unique table/alias: 't1' -handler t3 open t1; -ERROR 42000: Not unique table/alias: 't1' -handler t1 read first limit 9; -c1 -test_test.t1 -handler test.t1 close; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'close' at line 1 -handler test.t1 open h1; -ERROR 42000: Not unique table/alias: 'h1' -handler test_test.t1 open h1; -ERROR 42000: Not unique table/alias: 'h1' -handler test_test.t3 open h3; -handler test.t1 open h2; -handler t1 read first limit 9; -c1 -test_test.t1 -handler h1 read first limit 9; -c1 -test_test.t1 -handler h2 read first limit 9; -c1 -t1 -handler h3 read first limit 9; -c1 -test_test.t3 -handler h2 read first limit 9; -c1 -t1 -handler test.h1 close; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'close' at line 1 -handler t1 close; -handler h1 close; -handler h2 close; -handler t1 read first limit 9; -ERROR 42S02: Unknown table 't1' in HANDLER -handler h1 read first limit 9; -ERROR 42S02: Unknown table 'h1' in HANDLER -handler h2 read first limit 9; -ERROR 42S02: Unknown table 'h2' in HANDLER -handler h3 read first limit 9; -c1 -test_test.t3 -handler h3 read first limit 9; -c1 -test_test.t3 -use test_test; -handler h3 read first limit 9; -c1 -test_test.t3 -handler test.h3 read first limit 9; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'read first limit 9' at line 1 -handler h3 close; -use test; -drop table t3; -drop table t2; -drop table t1; -drop database test_test; create table t1 (c1 char(20)); insert into t1 values ("t1"); handler t1 open as h1; @@ -495,6 +386,11 @@ no1 no2 HANDLER t1 READ `primary` PREV; no1 no2 1 275 +HANDLER t1 READ `primary` = (1, 1000); +no1 no2 +HANDLER t1 READ `primary` NEXT; +no1 no2 +2 6 DROP TABLE t1; create table t1 (c1 int); insert into t1 values (14397); @@ -515,14 +411,12 @@ ERROR 42S02: Table 'test.t1' doesn't exist drop table if exists t1; Warnings: Note 1051 Unknown table 't1' -drop table if exists t1; -create table t1 (a int) ENGINE=MEMORY; +create table t1 (a int not null) ENGINE=CSV; --> client 2 handler t1 open; ERROR HY000: Table storage engine for 't1' doesn't have this option --> client 1 drop table t1; -drop table if exists t1; create table t1 (a int); handler t1 open as t1_alias; handler t1_alias read a next; @@ -535,50 +429,9 @@ handler t1_alias READ a next where inexistent > 0; ERROR 42S22: Unknown column 'inexistent' in 'field list' handler t1_alias close; drop table t1; -drop table if exists t1,t2; -create table t1 (c1 int); -create table t2 (c1 int); -insert into t1 values (1); -insert into t2 values (2); -connection: default -handler t1 open; -handler t1 read first; -c1 -1 -connection: flush -flush tables;; -connection: default -handler t2 open; -handler t2 read first; -c1 -2 -handler t1 read next; -c1 -1 -handler t1 close; -handler t2 close; -drop table t1,t2; -drop table if exists t1,t2; -create table t1 (c1 int); -connection: default -handler t1 open; -handler t1 read first; -c1 -connection: flush -rename table t1 to t2;; -connection: default -handler t2 open; -handler t2 read first; -c1 -handler t1 read next; -ERROR 42S02: Table 'test.t1' doesn't exist -handler t1 close; -handler t2 close; -drop table t2; -drop table if exists t1; -create temporary table t1 (a int, b char(1), key a(a), key b(a,b)); +create temporary table t1 (a int, b char(1), key a (a), key b(a,b)); insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"), -(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"); +(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"),(9,'k'); select a,b from t1; a b 0 a @@ -591,24 +444,25 @@ a b 7 h 8 i 9 j +9 k handler t1 open as a1; -handler a1 read a first; -a b -0 a -handler a1 read a next; +handler a1 read a=(1); a b 1 b handler a1 read a next; a b 2 c +handler a1 read a next; +a b +3 d select a,b from t1; ERROR HY000: Can't reopen table: 'a1' handler a1 read a prev; a b -1 b +2 c handler a1 read a prev; a b -0 a +1 b handler a1 read a=(6) where b="g"; a b 6 g @@ -625,39 +479,28 @@ a b 7 h 8 i 9 j +9 k handler t1 open as a2; -handler a2 read a first; -a b -0 a -handler a2 read a last; +handler a2 read a=(9); a b 9 j +handler a2 read a next; +a b +9 k +handler a2 read a prev limit 2; +a b +9 j +8 i +handler a2 read a last; +a b +9 k handler a2 read a prev; a b -8 i +9 j handler a2 close; drop table t1; -drop table if exists t1,t2; create table t1 (a int); -handler t1 open as t1_alias; -drop table t1; -create table t1 (a int); -handler t1 open as t1_alias; -flush tables; -drop table t1; -create table t1 (a int); -handler t1 open as t1_alias; -handler t1_alias close; -drop table t1; -create table t1 (a int); -handler t1 open as t1_alias; -handler t1_alias read first; -a -drop table t1; -handler t1_alias read next; -ERROR 42S02: Unknown table 't1_alias' in HANDLER -create table t1 (a int); -create temporary table t2 (a int, key(a)); +create temporary table t2 (a int, key (a)); handler t1 open as a1; handler t2 open as a2; handler a2 read a first; @@ -667,7 +510,7 @@ handler a2 read a next; ERROR 42S02: Unknown table 'a2' in HANDLER handler a1 close; ERROR 42S02: Unknown table 'a1' in HANDLER -create table t1 (a int, key(a)); +create table t1 (a int, key (a)); create table t2 like t1; handler t1 open as a1; handler t2 open as a2; @@ -680,7 +523,7 @@ handler a1 close; ERROR 42S02: Unknown table 'a1' in HANDLER handler a2 close; drop table t1, t2; -create table t1 (a int, key(a)); +create table t1 (a int, key (a)); handler t1 open as a1; handler a1 read a first; a @@ -688,7 +531,7 @@ rename table t1 to t2; handler a1 read a first; ERROR 42S02: Unknown table 'a1' in HANDLER drop table t2; -create table t1 (a int, key(a)); +create table t1 (a int, key (a)); create table t2 like t1; handler t1 open as a1; handler t2 open as a2; @@ -703,44 +546,19 @@ handler a1 close; ERROR 42S02: Unknown table 'a1' in HANDLER handler a2 close; drop table t1, t2; -create table t1 (a int, b char(1), key a(a), key b(a,b)); -insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"), -(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"); -handler t1 open; -handler t1 read a first; -a b -0 a -handler t1 read a next; -a b -1 b -flush tables; -handler t1 read a next; -a b -0 a -handler t1 read a next; -a b -1 b -flush tables with read lock; -handler t1 read a next; -a b -0 a -unlock tables; -drop table t1; -handler t1 read a next; -ERROR 42S02: Unknown table 't1' in HANDLER -drop table if exists t1; -create table t1 (a int); -insert into t1 values (1); -handler t1 open; -alter table t1 engine=memory; -handler t1 read a next; -ERROR HY000: Table storage engine for 't1' doesn't have this option -handler t1 close; -drop table t1; -USE information_schema; -HANDLER COLUMNS OPEN; -ERROR HY000: Incorrect usage of HANDLER OPEN and information_schema -USE test; +# +# BUG#51877 - HANDLER interface causes invalid memory read +# +CREATE TABLE t1(a INT, KEY (a)); +HANDLER t1 OPEN; +HANDLER t1 READ a FIRST; +a +INSERT INTO t1 VALUES(1); +HANDLER t1 READ a NEXT; +a +1 +HANDLER t1 CLOSE; +DROP TABLE t1; # # BUG #46456: HANDLER OPEN + TRUNCATE + DROP (temporary) TABLE, crash # @@ -757,19 +575,6 @@ HANDLER t1 READ FIRST; ERROR 42S02: Unknown table 't1' in HANDLER DROP TABLE t1; # -# BUG#51877 - HANDLER interface causes invalid memory read -# -CREATE TABLE t1(a INT, KEY(a)); -HANDLER t1 OPEN; -HANDLER t1 READ a FIRST; -a -INSERT INTO t1 VALUES(1); -HANDLER t1 READ a NEXT; -a -1 -HANDLER t1 CLOSE; -DROP TABLE t1; -# # Bug #54007: assert in ha_myisam::index_next , HANDLER # CREATE TABLE t1(a INT, b INT, PRIMARY KEY(a), KEY b(b), KEY ab(a, b)); @@ -821,12 +626,13 @@ HANDLER t1 READ b NEXT; a b HANDLER t1 READ NEXT; a b +2 20 +HANDLER t1 READ NEXT; +a b +1 10 +HANDLER t1 READ NEXT; +a b 4 40 -HANDLER t1 READ NEXT; -a b -3 30 -HANDLER t1 READ NEXT; -a b HANDLER t1 CLOSE; HANDLER t1 OPEN; HANDLER t1 READ FIRST; diff --git a/mysql-test/t/handler_myisam.test b/mysql-test/suite/handler/myisam.test similarity index 74% rename from mysql-test/t/handler_myisam.test rename to mysql-test/suite/handler/myisam.test index e78072ef8a0..c6acf1e822c 100644 --- a/mysql-test/t/handler_myisam.test +++ b/mysql-test/suite/handler/myisam.test @@ -5,20 +5,14 @@ # Last update: # 2006-07-31 ML test refactored (MySQL 5.1) # code of t/handler.test and t/innodb_handler.test united -# main testing code put into include/handler.inc +# main testing code put into handler.inc # rename t/handler.test to t/handler_myisam.test # -# should work in embedded server after mysqltest is fixed ---source include/not_embedded.inc - let $engine_type= MyISAM; -let $other_engine_type= MEMORY; -# There is unfortunately no other all time available storage engine -# which supports the handler interface -let $other_handler_engine_type= MyISAM; ---source include/handler.inc +--source init.inc +--source handler.inc --echo # --echo # BUG #46456: HANDLER OPEN + TRUNCATE + DROP (temporary) TABLE, crash @@ -37,18 +31,6 @@ TRUNCATE t1; HANDLER t1 READ FIRST; DROP TABLE t1; ---echo # ---echo # BUG#51877 - HANDLER interface causes invalid memory read ---echo # -CREATE TABLE t1(a INT, KEY(a)); -HANDLER t1 OPEN; -HANDLER t1 READ a FIRST; -INSERT INTO t1 VALUES(1); -HANDLER t1 READ a NEXT; -HANDLER t1 CLOSE; -DROP TABLE t1; - - --echo # --echo # Bug #54007: assert in ha_myisam::index_next , HANDLER --echo # diff --git a/mysql-test/t/lock_multi.test b/mysql-test/t/lock_multi.test index 4df1a0f3478..742a83f7bad 100644 --- a/mysql-test/t/lock_multi.test +++ b/mysql-test/t/lock_multi.test @@ -484,22 +484,6 @@ unlock tables; connection default; drop table t1; -# -# Bug#25856 HANDLER table OPEN in one connection lock DROP TABLE in another one -# ---disable_warnings -drop table if exists t1; ---enable_warnings -create table t1 (a int) ENGINE=MEMORY; ---echo --> client 2 -connection locker; ---error ER_ILLEGAL_HA -handler t1 open; ---echo --> client 1 -connection default; -drop table t1; - - # Disconnect sessions used in many subtests above disconnect locker; disconnect reader; diff --git a/mysys/tree.c b/mysys/tree.c index e4854581204..68eaecbb27b 100644 --- a/mysys/tree.c +++ b/mysys/tree.c @@ -375,6 +375,7 @@ void *tree_search_key(TREE *tree, const void *key, case HA_READ_KEY_EXACT: case HA_READ_KEY_OR_NEXT: case HA_READ_BEFORE_KEY: + case HA_READ_KEY_OR_PREV: last_equal_element= parents; cmp= 1; break; @@ -418,6 +419,9 @@ void *tree_search_key(TREE *tree, const void *key, case HA_READ_BEFORE_KEY: *last_pos= last_right_step_parent; break; + case HA_READ_KEY_OR_PREV: + *last_pos= last_equal_element ? last_equal_element : last_right_step_parent; + break; default: return NULL; } diff --git a/sql/handler.cc b/sql/handler.cc index 5bba6034a4d..2190ab1776c 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2724,7 +2724,10 @@ void handler::print_error(int error, myf errflag) textno=ER_DUP_UNIQUE; break; case HA_ERR_RECORD_CHANGED: - SET_FATAL_ERROR; + /* + This is not fatal error when using HANDLER interface + SET_FATAL_ERROR; + */ textno=ER_CHECKREAD; break; case HA_ERR_CRASHED: diff --git a/sql/handler.h b/sql/handler.h index 862da3d2ca7..52828d4f149 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1593,6 +1593,7 @@ public: { return(NULL);} /* gets tablespace name from handler */ /** used in ALTER TABLE; 1 if changing storage engine is allowed */ virtual bool can_switch_engines() { return 1; } + virtual int can_continue_handler_scan() { return 0; } /** used in REPLACE; is > 0 if table is referred by a FOREIGN KEY */ virtual int get_foreign_key_list(THD *thd, List *f_key_list) { return 0; } diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index bbc3d0b27a4..ccc6d2b57f0 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -548,6 +548,12 @@ retry: mode= RLAST; } } + else if (table->file->inited != handler::RND) + { + /* Convert RNEXT to RFIRST if we haven't started row scan */ + if (mode == RNEXT) + mode= RFIRST; + } if (insert_fields(thd, &thd->lex->select_lex.context, tables->db, tables->alias, &it, 0)) @@ -569,6 +575,8 @@ retry: case RNEXT: if (table->file->inited != handler::NONE) { + if ((error= table->file->can_continue_handler_scan())) + break; if (keyname) { /* Check if we read from the same index. */ @@ -603,6 +611,8 @@ retry: DBUG_ASSERT((uint) keyno == table->file->get_index()); if (table->file->inited != handler::NONE) { + if ((error= table->file->can_continue_handler_scan())) + break; error=table->file->index_prev(table->record[0]); break; } @@ -673,8 +683,11 @@ retry: continue; if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE) { - sql_print_error("mysql_ha_read: Got error %d when reading table '%s'", - error, tables->table_name); + /* Don't give error in the log file for some expected problems */ + if (error != HA_ERR_RECORD_CHANGED && error != HA_ERR_WRONG_COMMAND) + sql_print_error("mysql_ha_read: Got error %d when reading " + "table '%s'", + error, tables->table_name); table->file->print_error(error,MYF(0)); goto err; } diff --git a/storage/maria/ma_extra.c b/storage/maria/ma_extra.c index 81f3789523f..e436a51248a 100644 --- a/storage/maria/ma_extra.c +++ b/storage/maria/ma_extra.c @@ -50,7 +50,7 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, switch (function) { case HA_EXTRA_RESET_STATE: /* Reset state (don't free buffers) */ - info->lastinx= 0; /* Use first index as def */ + info->lastinx= ~0; /* Detect index changes */ info->last_search_keypage= info->cur_row.lastpos= HA_OFFSET_ERROR; info->page_changed= 1; /* Next/prev gives first/last */ @@ -545,7 +545,7 @@ int maria_reset(MARIA_HA *info) #endif info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS); info->quick_mode= 0; - info->lastinx= 0; /* Use first index as def */ + info->lastinx= ~0; /* detect index changes */ info->last_search_keypage= info->cur_row.lastpos= HA_OFFSET_ERROR; info->page_changed= 1; info->update= ((info->update & HA_STATE_CHANGED) | HA_STATE_NEXT_FOUND | diff --git a/storage/maria/ma_ft_boolean_search.c b/storage/maria/ma_ft_boolean_search.c index 6cd23558784..db471d2879c 100644 --- a/storage/maria/ma_ft_boolean_search.c +++ b/storage/maria/ma_ft_boolean_search.c @@ -356,7 +356,7 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search) { ftbw->key_root=info->s->state.key_root[ftb->keynr]; ftbw->keyinfo=info->s->keyinfo+ftb->keynr; - key.keyinfo= ftbw->keyinfo; + info->last_key.keyinfo= key.keyinfo= ftbw->keyinfo; key.data= ftbw->word; key.data_length= ftbw->len; key.ref_length= 0; @@ -380,7 +380,7 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search) max_docid); } - key.keyinfo= ftbw->keyinfo; + info->last_key.keyinfo= key.keyinfo= ftbw->keyinfo; key.data= lastkey_buf; key.data_length= USE_WHOLE_KEY; key.ref_length= 0; diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 63e1801a39a..0890ff7e000 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -130,6 +130,8 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, const char *name, info.s=share; info.cur_row.lastpos= HA_OFFSET_ERROR; + /* Impossible first index to force initialization in _ma_check_index() */ + info.lastinx= ~0; info.update= (short) (HA_STATE_NEXT_FOUND+HA_STATE_PREV_FOUND); info.opt_flag=READ_CHECK_USED; info.this_unique= (ulong) info.dfile.file; /* Uniq number in process */ diff --git a/storage/maria/ma_rkey.c b/storage/maria/ma_rkey.c index daf1fd5a60c..85b3b463f49 100644 --- a/storage/maria/ma_rkey.c +++ b/storage/maria/ma_rkey.c @@ -43,7 +43,7 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key_data, info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); info->last_key_func= search_flag; - keyinfo= share->keyinfo + inx; + keyinfo= info->last_key.keyinfo; key_buff= info->lastkey_buff+info->s->base.max_key_length; diff --git a/storage/maria/ma_rnext.c b/storage/maria/ma_rnext.c index be960eccfe0..c49bbb19e83 100644 --- a/storage/maria/ma_rnext.c +++ b/storage/maria/ma_rnext.c @@ -30,6 +30,7 @@ int maria_rnext(MARIA_HA *info, uchar *buf, int inx) uint flag; MARIA_SHARE *share= info->s; MARIA_KEYDEF *keyinfo; + uint update_mask= HA_STATE_NEXT_FOUND; DBUG_ENTER("maria_rnext"); if ((inx = _ma_check_index(info,inx)) < 0) @@ -61,6 +62,20 @@ int maria_rnext(MARIA_HA *info, uchar *buf, int inx) error= _ma_search_first(info, keyinfo, share->state.key_root[inx]); break; } + /* + "search first" failed. This means we have no pivot for + "search next", or in other words MI_INFO::lastkey is + likely uninitialized. + + Normally SQL layer would never request "search next" if + "search first" failed. But HANDLER may do anything. + + As mi_rnext() without preceeding mi_rkey()/mi_rfirst() + equals to mi_rfirst(), we must restore original state + as if failing mi_rfirst() was not called. + */ + if (error) + update_mask|= HA_STATE_PREV_FOUND; } else { @@ -104,7 +119,7 @@ int maria_rnext(MARIA_HA *info, uchar *buf, int inx) /* Don't clear if database-changed */ info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - info->update|= HA_STATE_NEXT_FOUND; + info->update|= update_mask; if (error) { diff --git a/storage/maria/ma_rsame.c b/storage/maria/ma_rsame.c index 4bdbfd526ba..4bd218a01df 100644 --- a/storage/maria/ma_rsame.c +++ b/storage/maria/ma_rsame.c @@ -36,7 +36,7 @@ int maria_rsame(MARIA_HA *info, uchar *record, int inx) { DBUG_ENTER("maria_rsame"); - if (inx != -1 && ! maria_is_key_active(info->s->state.key_map, inx)) + if (inx >= 0 && !_ma_check_index(info, inx)) { DBUG_PRINT("error", ("wrong index usage")); DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX); @@ -55,8 +55,7 @@ int maria_rsame(MARIA_HA *info, uchar *record, int inx) if (inx >= 0) { - MARIA_KEYDEF *keyinfo= info->s->keyinfo + inx; - info->lastinx= inx; + MARIA_KEYDEF *keyinfo= info->last_key.keyinfo; (*keyinfo->make_key)(info, &info->last_key, (uint) inx, info->lastkey_buff, record, info->cur_row.lastpos, diff --git a/storage/maria/ma_search.c b/storage/maria/ma_search.c index e1683dad34a..76e31fc9553 100644 --- a/storage/maria/ma_search.c +++ b/storage/maria/ma_search.c @@ -38,6 +38,8 @@ int _ma_check_index(MARIA_HA *info, int inx) if (info->lastinx != inx) /* Index changed */ { info->lastinx = inx; + info->last_key.keyinfo= info->s->keyinfo + inx; + info->last_key.flag= 0; info->page_changed=1; info->update= ((info->update & (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED)) | HA_STATE_NEXT_FOUND | HA_STATE_PREV_FOUND); @@ -180,7 +182,6 @@ static int _ma_search_no_save(register MARIA_HA *info, MARIA_KEY *key, } } - info->last_key.keyinfo= keyinfo; if ((nextflag & (SEARCH_SMALLER | SEARCH_LAST)) && flag != 0) { uint not_used[2]; @@ -1696,7 +1697,7 @@ int _ma_search_next(register MARIA_HA *info, MARIA_KEY *key, } tmp_key.data= lastkey; - info->last_key.keyinfo= tmp_key.keyinfo= keyinfo; + tmp_key.keyinfo= keyinfo; if (nextflag & SEARCH_BIGGER) /* Next key */ { @@ -1778,8 +1779,6 @@ int _ma_search_first(MARIA_HA *info, MARIA_KEYDEF *keyinfo, first_pos= page.buff + share->keypage_header + page.node; } while ((pos= _ma_kpos(page.node, first_pos)) != HA_OFFSET_ERROR); - info->last_key.keyinfo= keyinfo; - if (!(*keyinfo->get_key)(&info->last_key, page.flag, page.node, &first_pos)) DBUG_RETURN(-1); /* Crashed */ @@ -1830,8 +1829,6 @@ int _ma_search_last(MARIA_HA *info, MARIA_KEYDEF *keyinfo, end_of_page= page.buff + page.size; } while ((pos= _ma_kpos(page.node, end_of_page)) != HA_OFFSET_ERROR); - info->last_key.keyinfo= keyinfo; - if (!_ma_get_last_key(&info->last_key, &page, end_of_page)) DBUG_RETURN(-1); info->cur_row.lastpos= _ma_row_pos_from_key(&info->last_key); diff --git a/storage/maria/ma_unique.c b/storage/maria/ma_unique.c index a90578c2162..6090c624f36 100644 --- a/storage/maria/ma_unique.c +++ b/storage/maria/ma_unique.c @@ -43,6 +43,7 @@ my_bool _ma_check_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, uchar *record, /* The above changed info->lastkey_buff2. Inform maria_rnext_same(). */ info->update&= ~HA_STATE_RNEXT_SAME; + info->last_key.keyinfo= keyinfo; DBUG_ASSERT(key.data_length == MARIA_UNIQUE_HASH_LENGTH); if (_ma_search(info, &key, SEARCH_FIND, info->s->state.key_root[def->key]))