From 5f462f96266c193ea13bd2aa0a13c181c1d0919c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Jul 2007 14:42:06 +0400 Subject: [PATCH 01/23] Add a test case for Bug#27248 Triggers: error if insert affects temporary table. The bug itself is yet another manifestation of Bug 26141. mysql-test/r/trigger.result: Update results. mysql-test/t/trigger.test: Add a test case for Bug#27248 Triggers: error if insert affects temporary table --- mysql-test/r/trigger.result | 28 ++++++++++++++++++++++++++++ mysql-test/t/trigger.test | 23 +++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index 4b18e525e62..a07318435f6 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -1933,4 +1933,32 @@ Before UPDATE, new=multi-UPDATE, SET for t2, but the trigger is fired, old=multi After UPDATE, new=multi-UPDATE, SET for t2, but the trigger is fired, old=multi-UPDATE drop view v1; drop table t1, t2, t1_op_log; + +Bug#27248 Triggers: error if insert affects temporary table + +The bug was fixed by the fix for Bug#26141 + +drop table if exists t1; +drop temporary table if exists t2; +create table t1 (s1 int); +create temporary table t2 (s1 int); +create trigger t1_bi before insert on t1 for each row insert into t2 values (0); +create trigger t1_bd before delete on t1 for each row delete from t2; +insert into t1 values (0); +insert into t1 values (0); +select * from t1; +s1 +0 +0 +select * from t2; +s1 +0 +0 +delete from t1; +select * from t1; +s1 +select * from t2; +s1 +drop table t1; +drop temporary table t2; End of 5.0 tests diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index a6390036322..2f62ad38621 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -2194,4 +2194,27 @@ drop table t1, t2, t1_op_log; # # TODO: test LOAD DATA INFILE +# +--echo +--echo Bug#27248 Triggers: error if insert affects temporary table +--echo +--echo The bug was fixed by the fix for Bug#26141 +--echo +--disable_warnings +drop table if exists t1; +drop temporary table if exists t2; +--enable_warnings +create table t1 (s1 int); +create temporary table t2 (s1 int); +create trigger t1_bi before insert on t1 for each row insert into t2 values (0); +create trigger t1_bd before delete on t1 for each row delete from t2; +insert into t1 values (0); +insert into t1 values (0); +select * from t1; +select * from t2; +delete from t1; +select * from t1; +select * from t2; +drop table t1; +drop temporary table t2; --echo End of 5.0 tests From c0277a1192d0526ea76968196584e7d2b5a51203 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Jul 2007 16:22:05 +0400 Subject: [PATCH 02/23] A fix and a test case for Bug#26104 Bug on foreign key class constructor. Fix the typo in the constructor. Cover a semantic check that previously never worked with a test. mysql-test/r/create.result: Update results (Bug#26104) mysql-test/r/innodb.result: Update results. mysql-test/t/create.test: Add a test case for Bug#26104 Bug on foreign key class constructor mysql-test/t/innodb.test: Return a new error number (MySQL error instead of internal InnoDB error). sql/sql_class.h: A fix for Bug#26104 Bug on foreign key class constructor -- fix the typo in the constructor --- mysql-test/r/create.result | 16 ++++++++++++++++ mysql-test/r/innodb.result | 2 +- mysql-test/t/create.test | 19 +++++++++++++++++++ mysql-test/t/innodb.test | 2 +- sql/sql_class.h | 2 +- 5 files changed, 38 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index e692dbf3938..a1843573794 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -1503,4 +1503,20 @@ t1 CREATE TABLE `t1` ( `c17` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; + +Bug #26104 Bug on foreign key class constructor + +Check that ref_columns is initalized correctly in the constructor +and semantic checks in mysql_prepare_table work. + +We do not need a storage engine that supports foreign keys +for this test, as the checks are purely syntax-based, and the +syntax is supported for all engines. + +drop table if exists t1,t2; +create table t1(a int not null, b int not null, primary key (a, b)); +create table t2(a int not null, b int not null, c int not null, primary key (a), +foreign key fk_bug26104 (b,c) references t1(a)); +ERROR 42000: Incorrect foreign key definition for 'fk_bug26104': Key reference and table reference don't match +drop table t1; End of 5.0 tests diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 80b46e5098a..6082a30bce3 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1648,7 +1648,7 @@ t2 CREATE TABLE `t2` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1 drop table t2; create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id2,id) references t1 (id)) engine = innodb; -ERROR HY000: Can't create table './test/t2' (errno: 150) +ERROR 42000: Incorrect foreign key definition for 't1_id_fk': Key reference and table reference don't match create table t2 (a int auto_increment primary key, b int, index(b), foreign key (b) references t1(id), unique(b)) engine=innodb; show create table t2; Table Create Table diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 99f3fea416a..a6679cd674a 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -1118,5 +1118,24 @@ show create table t1; drop table t1; +--echo +--echo Bug #26104 Bug on foreign key class constructor +--echo +--echo Check that ref_columns is initalized correctly in the constructor +--echo and semantic checks in mysql_prepare_table work. +--echo +--echo We do not need a storage engine that supports foreign keys +--echo for this test, as the checks are purely syntax-based, and the +--echo syntax is supported for all engines. +--echo +--disable_warnings +drop table if exists t1,t2; +--enable_warnings + +create table t1(a int not null, b int not null, primary key (a, b)); +--error ER_WRONG_FK_DEF +create table t2(a int not null, b int not null, c int not null, primary key (a), +foreign key fk_bug26104 (b,c) references t1(a)); +drop table t1; --echo End of 5.0 tests diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index a9679c01071..04dfa1d0836 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -1180,7 +1180,7 @@ drop table t2; # Clean up filename -- embedded server reports whole path without .frm, # regular server reports relative path with .frm (argh!) --replace_result \\ / $MYSQL_TEST_DIR . /var/master-data/ / t2.frm t2 ---error 1005 +--error ER_WRONG_FK_DEF create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id2,id) references t1 (id)) engine = innodb; # bug#3749 diff --git a/sql/sql_class.h b/sql/sql_class.h index a5cbc21684f..1c52afb5bc5 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -450,7 +450,7 @@ public: Table_ident *table, List &ref_cols, uint delete_opt_arg, uint update_opt_arg, uint match_opt_arg) :Key(FOREIGN_KEY, name_arg, HA_KEY_ALG_UNDEF, 0, cols), - ref_table(table), ref_columns(cols), + ref_table(table), ref_columns(ref_cols), delete_opt(delete_opt_arg), update_opt(update_opt_arg), match_opt(match_opt_arg) {} From 6981af6ff53d63254284a4b6a5370c17075793bc Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Jul 2007 17:09:03 +0400 Subject: [PATCH 03/23] Add a test case for Bug#22427 create table if not exists + stored function results in inconsistent behavior. The bug itself was fixed by the patch for bug 20662. mysql-test/r/sp-prelocking.result: Update results (Bug#22427) mysql-test/t/sp-prelocking.test: Add a test case for Bug#22427 create table if not exists + stored function results in inconsistent behavior --- mysql-test/r/sp-prelocking.result | 22 ++++++++++++++++++++++ mysql-test/t/sp-prelocking.test | 23 +++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/mysql-test/r/sp-prelocking.result b/mysql-test/r/sp-prelocking.result index 5eac54803f0..c19bd1abd26 100644 --- a/mysql-test/r/sp-prelocking.result +++ b/mysql-test/r/sp-prelocking.result @@ -267,4 +267,26 @@ drop table bug_27907_logs; insert into bug_27907_t1(a) values (1); ERROR 42S02: Table 'test.bug_27907_logs' doesn't exist drop table bug_27907_t1; + +Bug#22427 create table if not exists + stored function results in +inconsistent behavior + +Add a test case, the bug itself was fixed by the patch for +Bug#20662 + +drop table if exists t1; +drop function if exists f_bug22427; +create table t1 (i int); +insert into t1 values (1); +create function f_bug22427() returns int return (select max(i) from t1); +select f_bug22427(); +f_bug22427() +1 +create table if not exists t1 select f_bug22427() as i; +Warnings: +Note 1050 Table 't1' already exists +create table t1 select f_bug22427() as i; +ERROR 42S01: Table 't1' already exists +drop table t1; +drop function f_bug22427; End of 5.0 tests diff --git a/mysql-test/t/sp-prelocking.test b/mysql-test/t/sp-prelocking.test index ec5b7fbad7c..60e97260839 100644 --- a/mysql-test/t/sp-prelocking.test +++ b/mysql-test/t/sp-prelocking.test @@ -333,4 +333,27 @@ insert into bug_27907_t1(a) values (1); drop table bug_27907_t1; +--echo +--echo Bug#22427 create table if not exists + stored function results in +--echo inconsistent behavior +--echo +--echo Add a test case, the bug itself was fixed by the patch for +--echo Bug#20662 +--echo +--disable_warnings +drop table if exists t1; +drop function if exists f_bug22427; +--enable_warnings +create table t1 (i int); +insert into t1 values (1); +create function f_bug22427() returns int return (select max(i) from t1); +select f_bug22427(); +# Until this bug was fixed, the following emitted error +# ERROR 1213: Deadlock found when trying to get lock +create table if not exists t1 select f_bug22427() as i; +--error ER_TABLE_EXISTS_ERROR +create table t1 select f_bug22427() as i; +drop table t1; +drop function f_bug22427; + --echo End of 5.0 tests From 36f1e4848ca0ddebe60b98286291057bb3d5e314 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jul 2007 18:39:01 +0500 Subject: [PATCH 04/23] Fixed bug #29338. Optimization of queries with DETERMINISTIC functions in the WHERE clause was not effective: sequential scan was always used. Now a SF with the DETERMINISTIC flags is treated as constant when it's arguments are constants (or a SF doesn't has arguments). sql/item_func.h: Fixed bug #29338. The Item_func_sp::used_tables has been removed (virtual Item_func::used_tables function is enough). The virtual Item_func_sp::update_used_tables function has been added. sql/item_func.cc: Fixed bug #29338. The Item_func_sp::update_used_tables and the Item_func_sp::fix_field functions have been modified to take into account the DETERMINISTIC flag of SF definition. mysql-test/r/sp.result: Updated test case for bug #29338. mysql-test/t/sp.test: Updated test case for bug #29338. --- mysql-test/r/sp.result | 33 ++++++++++++++++++++++++++++++++- mysql-test/t/sp.test | 32 +++++++++++++++++++++++++++++++- sql/item_func.cc | 10 ++++++++++ sql/item_func.h | 2 +- 4 files changed, 74 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index b411c65faee..4321cd92826 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -1,5 +1,7 @@ use test; drop table if exists t1,t2,t3,t4; +drop function if exists f1; +drop function if exists f2; create table t1 ( id char(16) not null default '', data int not null @@ -6144,7 +6146,7 @@ drop table t1,t2; CREATE TABLE t1 (a int auto_increment primary key) engine=MyISAM; CREATE TABLE t2 (a int auto_increment primary key, b int) engine=innodb; set @a=0; -CREATE function bug27354() RETURNS int deterministic +CREATE function bug27354() RETURNS int not deterministic begin insert into t1 values (null); set @a=@a+1; @@ -6176,4 +6178,33 @@ v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VI DROP VIEW v1; DROP FUNCTION metered; DROP TABLE t1; +CREATE FUNCTION f1() RETURNS INT DETERMINISTIC RETURN 2; +CREATE FUNCTION f2(I INT) RETURNS INT DETERMINISTIC RETURN 3; +CREATE TABLE t1 (c1 INT, INDEX(c1)); +INSERT INTO t1 VALUES (1), (2), (3), (4), (5); +CREATE VIEW v1 AS SELECT c1 FROM t1; +EXPLAIN SELECT * FROM t1 WHERE c1=1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref c1 c1 5 const 1 Using where; Using index +EXPLAIN SELECT * FROM t1 WHERE c1=f1(); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref c1 c1 5 const 1 Using where; Using index +EXPLAIN SELECT * FROM v1 WHERE c1=1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref c1 c1 5 const 1 Using where; Using index +EXPLAIN SELECT * FROM v1 WHERE c1=f1(); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref c1 c1 5 const 1 Using where; Using index +EXPLAIN SELECT * FROM t1 WHERE c1=f2(10); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref c1 c1 5 const 1 Using where; Using index +EXPLAIN SELECT * FROM t1 WHERE c1=f2(c1); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL c1 5 NULL 5 Using where; Using index +EXPLAIN SELECT * FROM t1 WHERE c1=f2(rand()); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL c1 5 NULL 5 Using where; Using index +DROP VIEW v1; +DROP FUNCTION f1; +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 2f82482bdf7..aeb85ac6012 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -23,6 +23,8 @@ use test; # --disable_warnings drop table if exists t1,t2,t3,t4; +drop function if exists f1; +drop function if exists f2; --enable_warnings create table t1 ( id char(16) not null default '', @@ -7098,7 +7100,7 @@ CREATE TABLE t2 (a int auto_increment primary key, b int) engine=innodb; set @a=0; delimiter |; -CREATE function bug27354() RETURNS int deterministic +CREATE function bug27354() RETURNS int not deterministic begin insert into t1 values (null); set @a=@a+1; @@ -7134,5 +7136,33 @@ DROP VIEW v1; DROP FUNCTION metered; DROP TABLE t1; +# +# Bug #29338: no optimization for stored functions with a trivial body +# always returning constant. +# + +CREATE FUNCTION f1() RETURNS INT DETERMINISTIC RETURN 2; +CREATE FUNCTION f2(I INT) RETURNS INT DETERMINISTIC RETURN 3; + +CREATE TABLE t1 (c1 INT, INDEX(c1)); + +INSERT INTO t1 VALUES (1), (2), (3), (4), (5); + +CREATE VIEW v1 AS SELECT c1 FROM t1; + +EXPLAIN SELECT * FROM t1 WHERE c1=1; +EXPLAIN SELECT * FROM t1 WHERE c1=f1(); + +EXPLAIN SELECT * FROM v1 WHERE c1=1; +EXPLAIN SELECT * FROM v1 WHERE c1=f1(); + +EXPLAIN SELECT * FROM t1 WHERE c1=f2(10); +EXPLAIN SELECT * FROM t1 WHERE c1=f2(c1); +EXPLAIN SELECT * FROM t1 WHERE c1=f2(rand()); + + +DROP VIEW v1; +DROP FUNCTION f1; +DROP TABLE t1; --echo End of 5.0 tests diff --git a/sql/item_func.cc b/sql/item_func.cc index b256ce4624a..e05f0a45083 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -5591,5 +5591,15 @@ Item_func_sp::fix_fields(THD *thd, Item **ref) #endif /* ! NO_EMBEDDED_ACCESS_CHECKS */ } + if (!m_sp->m_chistics->detistic) + used_tables_cache |= RAND_TABLE_BIT; DBUG_RETURN(res); } + + +void Item_func_sp::update_used_tables() +{ + Item_func::update_used_tables(); + if (!m_sp->m_chistics->detistic) + used_tables_cache |= RAND_TABLE_BIT; +} diff --git a/sql/item_func.h b/sql/item_func.h index 9a0201cb28b..56b5e75652c 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1467,7 +1467,7 @@ public: virtual ~Item_func_sp() {} - table_map used_tables() const { return RAND_TABLE_BIT; } + void update_used_tables(); void cleanup(); From e81e55e78306643031e237c884c48f1d3d7b76c6 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jul 2007 19:28:00 +0400 Subject: [PATCH 05/23] A fix for Bug#29431 killing an insert delayed thread causes crash No test case, since the bug requires a stress case with 30 INSERT DELAYED threads and 1 killer thread to repeat. The patch is verified manually. Review fixes. The server that is running DELAYED inserts would deadlock itself or crash under high load if some of the delayed threads were KILLed in the meanwhile. The fix is to change internal lock acquisition order of delayed inserts subsystem and to ensure that Delayed_insert::table_list::db does not point to volatile memory in some cases. For details, please see a comment for sql_insert.cc. sql/sql_insert.cc: A fix for Bug#29431 killing an insert delayed thread causes crash 1) The deadlock was caused by different lock acquisition order between delayed_get_table and handle_delayed_insert. delayed_get_table would: - acquire LOCK_delayed_create - create a new Delayed_insert instance - acquire instance mutex (di->mutex) - "lock the instance in memory" by increasing di->locked_in_memory variable - start the delayed thread - release di->mutex - let the delayed thread open the delayed table - discover that the delayed thread was killed - try to unlock() the delayed insert instance in memory - in Delayed_insert::unlock() do * lock LOCK_delayed_insert * decrease locks_in_memory and discover it's 0 * attempt to lock di->mutex to broadcast di->cond condition <-- deadlock here Meanwhile, the delayed thread would * lock di->mutex * open the table * get killed * not notice that and attempt to lock LOCK_delayed_insert to register itself in the delayed insert list <-- deadlock here. Simply put, delayed_get_table used to lock LOCK_delayed_insert and then di->mutex, and handle_delayed_insert would lock di->mutex and then LOCK_delayed_insert. Fixed by moving registration in the list of delayed insert threads from handle_delayed_insert to delayed_get_table - so that now handle_delayed_insert doesn't need to acquire LOCK_delayed_insert mutex. 2) di->table_list.db was copied by-pointer from table_list.db of the first producer -- the one who initiated creation of the delayed insert thread. This producer might be long gone when the member is needed (handle_delayed_insert:open_ltable), e.g. by having been killed with KILL CONNECTION statement. Fixed by using a pointer to the consumer's deep copy of THD::db. 3) In find_handler, we shouldn't assume that Delayed_insert object already (or still) has a table opened all the time it is present in the delayed insert list. E.g. it's not the case when Delayed_insert decided to terminate, closed the table, but haven't yet unregistered from the list (see the end of handle_delayed_insert). --- sql/sql_insert.cc | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 73f8c5e4418..1a8cacd4f8e 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1705,8 +1705,8 @@ Delayed_insert *find_handler(THD *thd, TABLE_LIST *table_list) Delayed_insert *tmp; while ((tmp=it++)) { - if (!strcmp(tmp->thd.db,table_list->db) && - !strcmp(table_list->table_name,tmp->table->s->table_name)) + if (!strcmp(table_list->db, tmp->table_list.db) && + !strcmp(table_list->table_name, tmp->table_list.table_name)) { tmp->lock(); break; @@ -1739,7 +1739,27 @@ Delayed_insert *find_handler(THD *thd, TABLE_LIST *table_list) Two latter cases indicate a request for lock upgrade. XXX: why do we regard INSERT DELAYED into a view as an error and - do not simply a lock upgrade? + do not simply perform a lock upgrade? + + TODO: The approach with using two mutexes to work with the + delayed thread list -- LOCK_delayed_insert and + LOCK_delayed_create -- is redundant, and we only need one of + them to protect the list. The reason we have two locks is that + we do not want to block look-ups in the list while we're waiting + for the newly created thread to open the delayed table. However, + this wait itself is redundant -- we always call get_local_table + later on, and there wait again until the created thread acquires + a table lock. + + As is redundant the concept of locks_in_memory, since we already + have another counter with similar semantics - tables_in_use, + both of them are devoted to counting the number of producers for + a given consumer (delayed insert thread), only at different + stages of producer-consumer relationship. + + 'dead' and 'status' variables in Delayed_insert are redundant + too, since there is already 'di->thd.killed' and + di->stacked_inserts. */ static @@ -1788,7 +1808,9 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) goto end_create; } tmp->table_list= *table_list; // Needed to open table + /* Replace volatile strings with local copies */ tmp->table_list.alias= tmp->table_list.table_name= tmp->thd.query; + tmp->table_list.db= tmp->thd.db; tmp->lock(); pthread_mutex_lock(&tmp->mutex); if ((error=pthread_create(&tmp->thd.real_id,&connection_attrib, @@ -1834,6 +1856,9 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) tmp->unlock(); goto end_create; } + pthread_mutex_lock(&LOCK_delayed_insert); + delayed_threads.append(tmp); + pthread_mutex_unlock(&LOCK_delayed_insert); } pthread_mutex_unlock(&LOCK_delayed_create); } @@ -2176,11 +2201,6 @@ pthread_handler_t handle_delayed_insert(void *arg) } di->table->copy_blobs=1; - /* One can now use this */ - pthread_mutex_lock(&LOCK_delayed_insert); - delayed_threads.append(di); - pthread_mutex_unlock(&LOCK_delayed_insert); - /* Tell client that the thread is initialized */ pthread_cond_signal(&di->cond_client); From 62eb5f17945972c1c1f6a78c95440c71afc7d7bc Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jul 2007 19:36:52 +0400 Subject: [PATCH 06/23] Rename all references to 'Delayed_insert' instances from 'tmp' to 'di' for consistency. --- sql/sql_insert.cc | 100 +++++++++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 1a8cacd4f8e..19c9360b0ed 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1702,18 +1702,18 @@ Delayed_insert *find_handler(THD *thd, TABLE_LIST *table_list) thd->proc_info="waiting for delay_list"; pthread_mutex_lock(&LOCK_delayed_insert); // Protect master list I_List_iterator it(delayed_threads); - Delayed_insert *tmp; - while ((tmp=it++)) + Delayed_insert *di; + while ((di= it++)) { - if (!strcmp(table_list->db, tmp->table_list.db) && - !strcmp(table_list->table_name, tmp->table_list.table_name)) + if (!strcmp(table_list->db, di->table_list.db) && + !strcmp(table_list->table_name, di->table_list.table_name)) { - tmp->lock(); + di->lock(); break; } } pthread_mutex_unlock(&LOCK_delayed_insert); // For unlink from list - return tmp; + return di; } @@ -1766,14 +1766,14 @@ static bool delayed_get_table(THD *thd, TABLE_LIST *table_list) { int error; - Delayed_insert *tmp; + Delayed_insert *di; DBUG_ENTER("delayed_get_table"); /* Must be set in the parser */ DBUG_ASSERT(table_list->db); /* Find the thread which handles this table. */ - if (!(tmp=find_handler(thd,table_list))) + if (!(di= find_handler(thd, table_list))) { /* No match. Create a new thread to handle the table, but @@ -1787,9 +1787,9 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) The first search above was done without LOCK_delayed_create. Another thread might have created the handler in between. Search again. */ - if (! (tmp= find_handler(thd, table_list))) + if (! (di= find_handler(thd, table_list))) { - if (!(tmp=new Delayed_insert())) + if (!(di= new Delayed_insert())) { my_error(ER_OUTOFMEMORY,MYF(0),sizeof(Delayed_insert)); thd->fatal_error(); @@ -1798,30 +1798,30 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) pthread_mutex_lock(&LOCK_thread_count); thread_count++; pthread_mutex_unlock(&LOCK_thread_count); - tmp->thd.set_db(table_list->db, strlen(table_list->db)); - tmp->thd.query= my_strdup(table_list->table_name,MYF(MY_WME)); - if (tmp->thd.db == NULL || tmp->thd.query == NULL) + di->thd.set_db(table_list->db, strlen(table_list->db)); + di->thd.query= my_strdup(table_list->table_name, MYF(MY_WME)); + if (di->thd.db == NULL || di->thd.query == NULL) { /* The error is reported */ - delete tmp; + delete di; thd->fatal_error(); goto end_create; } - tmp->table_list= *table_list; // Needed to open table + di->table_list= *table_list; // Needed to open table /* Replace volatile strings with local copies */ - tmp->table_list.alias= tmp->table_list.table_name= tmp->thd.query; - tmp->table_list.db= tmp->thd.db; - tmp->lock(); - pthread_mutex_lock(&tmp->mutex); - if ((error=pthread_create(&tmp->thd.real_id,&connection_attrib, - handle_delayed_insert,(void*) tmp))) + di->table_list.alias= di->table_list.table_name= di->thd.query; + di->table_list.db= di->thd.db; + di->lock(); + pthread_mutex_lock(&di->mutex); + if ((error= pthread_create(&di->thd.real_id, &connection_attrib, + handle_delayed_insert, (void*) di))) { DBUG_PRINT("error", ("Can't create thread to handle delayed insert (error %d)", error)); - pthread_mutex_unlock(&tmp->mutex); - tmp->unlock(); - delete tmp; + pthread_mutex_unlock(&di->mutex); + di->unlock(); + delete di; my_error(ER_CANT_CREATE_THREAD, MYF(0), error); thd->fatal_error(); goto end_create; @@ -1829,15 +1829,15 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) /* Wait until table is open */ thd->proc_info="waiting for handler open"; - while (!tmp->thd.killed && !tmp->table && !thd->killed) + while (!di->thd.killed && !di->table && !thd->killed) { - pthread_cond_wait(&tmp->cond_client,&tmp->mutex); + pthread_cond_wait(&di->cond_client, &di->mutex); } - pthread_mutex_unlock(&tmp->mutex); + pthread_mutex_unlock(&di->mutex); thd->proc_info="got old table"; - if (tmp->thd.killed) + if (di->thd.killed) { - if (tmp->thd.net.report_error) + if (di->thd.net.report_error) { /* Copy the error message. Note that we don't treat fatal @@ -1845,34 +1845,34 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) main thread. Use of my_message will enable stored procedures continue handlers. */ - my_message(tmp->thd.net.last_errno, tmp->thd.net.last_error, + my_message(di->thd.net.last_errno, di->thd.net.last_error, MYF(0)); } - tmp->unlock(); + di->unlock(); goto end_create; } if (thd->killed) { - tmp->unlock(); + di->unlock(); goto end_create; } pthread_mutex_lock(&LOCK_delayed_insert); - delayed_threads.append(tmp); + delayed_threads.append(di); pthread_mutex_unlock(&LOCK_delayed_insert); } pthread_mutex_unlock(&LOCK_delayed_create); } - pthread_mutex_lock(&tmp->mutex); - table_list->table= tmp->get_local_table(thd); - pthread_mutex_unlock(&tmp->mutex); + pthread_mutex_lock(&di->mutex); + table_list->table= di->get_local_table(thd); + pthread_mutex_unlock(&di->mutex); if (table_list->table) { DBUG_ASSERT(thd->net.report_error == 0); - thd->di=tmp; + thd->di= di; } /* Unlock the delayed insert object after its last access. */ - tmp->unlock(); + di->unlock(); DBUG_RETURN(table_list->table == NULL); end_create: @@ -2102,26 +2102,26 @@ void kill_delayed_threads(void) VOID(pthread_mutex_lock(&LOCK_delayed_insert)); // For unlink from list I_List_iterator it(delayed_threads); - Delayed_insert *tmp; - while ((tmp=it++)) + Delayed_insert *di; + while ((di= it++)) { - tmp->thd.killed= THD::KILL_CONNECTION; - if (tmp->thd.mysys_var) + di->thd.killed= THD::KILL_CONNECTION; + if (di->thd.mysys_var) { - pthread_mutex_lock(&tmp->thd.mysys_var->mutex); - if (tmp->thd.mysys_var->current_cond) + pthread_mutex_lock(&di->thd.mysys_var->mutex); + if (di->thd.mysys_var->current_cond) { /* We need the following test because the main mutex may be locked in handle_delayed_insert() */ - if (&tmp->mutex != tmp->thd.mysys_var->current_mutex) - pthread_mutex_lock(tmp->thd.mysys_var->current_mutex); - pthread_cond_broadcast(tmp->thd.mysys_var->current_cond); - if (&tmp->mutex != tmp->thd.mysys_var->current_mutex) - pthread_mutex_unlock(tmp->thd.mysys_var->current_mutex); + if (&di->mutex != di->thd.mysys_var->current_mutex) + pthread_mutex_lock(di->thd.mysys_var->current_mutex); + pthread_cond_broadcast(di->thd.mysys_var->current_cond); + if (&di->mutex != di->thd.mysys_var->current_mutex) + pthread_mutex_unlock(di->thd.mysys_var->current_mutex); } - pthread_mutex_unlock(&tmp->thd.mysys_var->mutex); + pthread_mutex_unlock(&di->thd.mysys_var->mutex); } } VOID(pthread_mutex_unlock(&LOCK_delayed_insert)); // For unlink from list From 93de616578d601d49dfee8927bdd539da94dc69f Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jul 2007 19:56:07 +0400 Subject: [PATCH 07/23] A post-merge fix --- mysql-test/r/create.result | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index cdbb767dd9f..de25fb754e4 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -1516,6 +1516,22 @@ t1 CREATE TABLE `t1` ( `c17` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; + +Bug #26104 Bug on foreign key class constructor + +Check that ref_columns is initalized correctly in the constructor +and semantic checks in mysql_prepare_table work. + +We do not need a storage engine that supports foreign keys +for this test, as the checks are purely syntax-based, and the +syntax is supported for all engines. + +drop table if exists t1,t2; +create table t1(a int not null, b int not null, primary key (a, b)); +create table t2(a int not null, b int not null, c int not null, primary key (a), +foreign key fk_bug26104 (b,c) references t1(a)); +ERROR 42000: Incorrect foreign key definition for 'fk_bug26104': Key reference and table reference don't match +drop table t1; End of 5.0 tests CREATE TABLE t1 (a int, b int); insert into t1 values (1,1),(1,2); From 6c24dd7f0cdc3d996610c4cfc8181d25c5f580fe Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jul 2007 21:10:19 +0400 Subject: [PATCH 08/23] A follow-up fix for Bug#29431 "killing an insert delayed thread causes crash" in 5.1 sql/sql_insert.cc: Additional safety fix: do not assume we already have a share in get_local_table. --- sql/sql_insert.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 903300c0402..b362835412a 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1961,7 +1961,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) my_ptrdiff_t adjust_ptrs; Field **field,**org_field, *found_next_number_field; TABLE *copy; - TABLE_SHARE *share= table->s; + TABLE_SHARE *share; uchar *bitmap; DBUG_ENTER("Delayed_insert::get_local_table"); @@ -1985,6 +1985,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) goto error; } } + share= table->s; /* Allocate memory for the TABLE object, the field pointers array, and From 1a2d2117ffcd9641ed472039f29c8996023e7b60 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jul 2007 16:05:55 +0500 Subject: [PATCH 09/23] Bug #29494 Field packet with NULL fields crashes libmysqlclient. unpack_fields() didn't expect NULL_LENGHT in the field's descriptions. In this case we get NULL in the resulting string so cannot use strdup_root to make a copy of it. strdup_root changed with strmake_root as it's NULL-safe sql-common/client.c: Bug #29494 Field packet with NULL fields crashes libmysqlclient strdup_root changed with strmake_root in unpack_fields() --- sql-common/client.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sql-common/client.c b/sql-common/client.c index 431c1bdf418..bf9c7252283 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1176,12 +1176,12 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, /* fields count may be wrong */ DBUG_ASSERT ((field - result) < fields); cli_fetch_lengths(&lengths[0], row->data, default_value ? 8 : 7); - field->catalog = strdup_root(alloc,(char*) row->data[0]); - field->db = strdup_root(alloc,(char*) row->data[1]); - field->table = strdup_root(alloc,(char*) row->data[2]); - field->org_table= strdup_root(alloc,(char*) row->data[3]); - field->name = strdup_root(alloc,(char*) row->data[4]); - field->org_name = strdup_root(alloc,(char*) row->data[5]); + field->catalog= strmake_root(alloc,(char*) row->data[0], lengths[0]); + field->db= strmake_root(alloc,(char*) row->data[1], lengths[1]); + field->table= strmake_root(alloc,(char*) row->data[2], lengths[2]); + field->org_table= strmake_root(alloc,(char*) row->data[3], lengths[3]); + field->name= strmake_root(alloc,(char*) row->data[4], lengths[4]); + field->org_name= strmake_root(alloc,(char*) row->data[5], lengths[5]); field->catalog_length= lengths[0]; field->db_length= lengths[1]; @@ -1202,7 +1202,7 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, field->flags|= NUM_FLAG; if (default_value && row->data[7]) { - field->def=strdup_root(alloc,(char*) row->data[7]); + field->def=strmake_root(alloc,(char*) row->data[7], lengths[7]); field->def_length= lengths[7]; } else From eea5c2a3c5968c458d872484d9afe9ca228e6700 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jul 2007 14:17:15 +0300 Subject: [PATCH 10/23] Bug #29644: alter table hangs if records locked in share mode by long running transaction On Windows opened files can't be deleted. There was a special upgraded lock mode (TL_WRITE instead of TL_WRITE_ALLOW_READ) in ALTER TABLE to make sure nobody has the table opened when deleting the old table in ALTER TABLE. This special mode was causing ALTER TABLE to hang waiting on a lock inside InnoDB. This special lock is no longer necessary as the server is closing the tables it needs to delete in ALTER TABLE. Fixed by removing the special lock. Note that this also reverses the fix for bug 17264 that deals with another consequence of this special lock mode being used. mysql-test/r/innodb_mysql.result: Bug #29644: test case mysql-test/t/innodb_mysql.test: Bug #29644: test case sql/ha_innodb.cc: Bug #29644: reverse the (now excessive) fix for bug 17264 (but leave the test case). sql/sql_base.cc: Bug #29644: don't need a special lock mode for Win32 anymore: the table is closed before the drop. --- mysql-test/r/innodb_mysql.result | 23 ++++++++++++++ mysql-test/t/innodb_mysql.test | 51 ++++++++++++++++++++++++++++++++ sql/ha_innodb.cc | 11 ------- sql/sql_base.cc | 7 ----- 4 files changed, 74 insertions(+), 18 deletions(-) diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 4535710c905..1cb9563216b 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -735,4 +735,27 @@ COUNT(*) 3072 set @@sort_buffer_size=default; DROP TABLE t1,t2; +CREATE TABLE t1 (a INT, PRIMARY KEY (a)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8); +INSERT INTO t1 SELECT a + 8 FROM t1; +INSERT INTO t1 SELECT a + 16 FROM t1; +CREATE PROCEDURE p1 () +BEGIN +DECLARE i INT DEFAULT 50; +DECLARE cnt INT; +START TRANSACTION; +ALTER TABLE t1 ENGINE=InnoDB; +COMMIT; +START TRANSACTION; +WHILE (i > 0) DO +SET i = i - 1; +SELECT COUNT(*) INTO cnt FROM t1 LOCK IN SHARE MODE; +END WHILE; +COMMIT; +END;| +CALL p1(); +CALL p1(); +CALL p1(); +DROP PROCEDURE p1; +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index d4ce997ddb1..a8724d2e7d5 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -741,4 +741,55 @@ set @@sort_buffer_size=default; DROP TABLE t1,t2; +# +# Bug #29644: alter table hangs if records locked in share mode by long +# running transaction +# + +CREATE TABLE t1 (a INT, PRIMARY KEY (a)) ENGINE=InnoDB; + +INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8); +INSERT INTO t1 SELECT a + 8 FROM t1; +INSERT INTO t1 SELECT a + 16 FROM t1; + +DELIMITER |; +CREATE PROCEDURE p1 () +BEGIN + DECLARE i INT DEFAULT 50; + DECLARE cnt INT; + START TRANSACTION; + ALTER TABLE t1 ENGINE=InnoDB; + COMMIT; + START TRANSACTION; + WHILE (i > 0) DO + SET i = i - 1; + SELECT COUNT(*) INTO cnt FROM t1 LOCK IN SHARE MODE; + END WHILE; + COMMIT; +END;| + +DELIMITER ;| + +CONNECT (con1,localhost,root,,); +CONNECT (con2,localhost,root,,); + +CONNECTION con1; +SEND CALL p1(); +CONNECTION con2; +SEND CALL p1(); +CONNECTION default; +CALL p1(); + +CONNECTION con1; +REAP; +CONNECTION con2; +REAP; +CONNECTION default; +DISCONNECT con1; +DISCONNECT con2; + +DROP PROCEDURE p1; +DROP TABLE t1; + + --echo End of 5.0 tests diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index a3676bd7e1b..0177829614d 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -6702,17 +6702,6 @@ ha_innobase::store_lock( && !thd->tablespace_op && thd->lex->sql_command != SQLCOM_TRUNCATE && thd->lex->sql_command != SQLCOM_OPTIMIZE - -#ifdef __WIN__ - /* For alter table on win32 for succesful operation - completion it is used TL_WRITE(=10) lock instead of - TL_WRITE_ALLOW_READ(=6), however here in innodb handler - TL_WRITE is lifted to TL_WRITE_ALLOW_WRITE, which causes - race condition when several clients do alter table - simultaneously (bug #17264). This fix avoids the problem. */ - && thd->lex->sql_command != SQLCOM_ALTER_TABLE -#endif - && thd->lex->sql_command != SQLCOM_CREATE_TABLE) { lock_type = TL_WRITE_ALLOW_WRITE; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index ed006714143..e633b548a08 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2938,13 +2938,6 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type) if (table) { -#if defined( __WIN__) || defined(OS2) - /* Win32 can't drop a file that is open */ - if (lock_type == TL_WRITE_ALLOW_READ) - { - lock_type= TL_WRITE; - } -#endif /* __WIN__ || OS2 */ table_list->lock_type= lock_type; table_list->table= table; table->grant= table_list->grant; From 7a99db0b7308f1636bbc7fafe36b478968497e50 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jul 2007 19:46:13 +0400 Subject: [PATCH 11/23] Remove obvious comments. --- sql/sql_base.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index bf1c6d7cb0d..3860dfa1ded 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -62,11 +62,11 @@ Prelock_error_handler::handle_error(uint sql_errno, if (sql_errno == ER_NO_SUCH_TABLE) { m_handled_errors++; - return TRUE; // 'TRUE', as per coding style + return TRUE; } m_unhandled_errors++; - return FALSE; // 'FALSE', as per coding style + return FALSE; } @@ -2674,7 +2674,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) */ for (tables= *start; tables ;tables= tables->next_global) { - safe_to_ignore_table= FALSE; // 'FALSE', as per coding style + safe_to_ignore_table= FALSE; if (tables->lock_type == TL_WRITE_DEFAULT) { From 16711062954bd202973339ac73382b435d209d9d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jul 2007 19:52:25 +0400 Subject: [PATCH 12/23] Fix the coding style. sql/sql_lex.cc: Fix the style. sql/sql_lex.h: Fix the style. --- sql/sql_lex.cc | 18 +++++++++--------- sql/sql_lex.h | 44 ++++++++++++++++++++++---------------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 9f69e7dee05..e493dc05047 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -124,7 +124,7 @@ Lex_input_stream::Lex_input_stream(THD *thd, m_tok_start_prev(NULL), m_buf(buffer), m_buf_length(length), - m_echo(true), + m_echo(TRUE), m_cpp_tok_start(NULL), m_cpp_tok_start_prev(NULL), m_cpp_tok_end(NULL), @@ -1200,7 +1200,7 @@ int MYSQLlex(void *arg, void *yythd) { lip->in_comment= DISCARD_COMMENT; /* Accept '/' '*' '!', but do not keep this marker. */ - lip->set_echo(false); + lip->set_echo(FALSE); lip->yySkip(); lip->yySkip(); lip->yySkip(); @@ -1233,7 +1233,7 @@ int MYSQLlex(void *arg, void *yythd) if (version <= MYSQL_VERSION_ID) { /* Expand the content of the special comment as real code */ - lip->set_echo(true); + lip->set_echo(TRUE); state=MY_LEX_START; break; } @@ -1241,7 +1241,7 @@ int MYSQLlex(void *arg, void *yythd) else { state=MY_LEX_START; - lip->set_echo(true); + lip->set_echo(TRUE); break; } } @@ -1261,7 +1261,7 @@ int MYSQLlex(void *arg, void *yythd) if (! lip->eof()) lip->yySkip(); // remove last '/' state = MY_LEX_START; // Try again - lip->set_echo(true); + lip->set_echo(TRUE); break; case MY_LEX_END_LONG_COMMENT: if ((lip->in_comment != NO_COMMENT) && lip->yyPeek() == '/') @@ -1272,7 +1272,7 @@ int MYSQLlex(void *arg, void *yythd) lip->set_echo(lip->in_comment == PRESERVE_COMMENT); lip->yySkipn(2); /* And start recording the tokens again */ - lip->set_echo(true); + lip->set_echo(TRUE); lip->in_comment=NO_COMMENT; state=MY_LEX_START; } @@ -1297,7 +1297,7 @@ int MYSQLlex(void *arg, void *yythd) lip->found_semicolon= lip->get_ptr(); thd->server_status|= SERVER_MORE_RESULTS_EXISTS; lip->next_state= MY_LEX_END; - lip->set_echo(true); + lip->set_echo(TRUE); return (END_OF_INPUT); } state= MY_LEX_CHAR; // Return ';' @@ -1309,9 +1309,9 @@ int MYSQLlex(void *arg, void *yythd) if (lip->eof()) { lip->yyUnget(); // Reject the last '\0' - lip->set_echo(false); + lip->set_echo(FALSE); lip->yySkip(); - lip->set_echo(true); + lip->set_echo(TRUE); lip->next_state=MY_LEX_END; // Mark for next loop return(END_OF_INPUT); } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 4ac59fbacde..9ac7f2835f0 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1239,19 +1239,19 @@ public: } /** Get the raw query buffer. */ - const char* get_buf() + const char *get_buf() { return m_buf; } /** Get the pre-processed query buffer. */ - const char* get_cpp_buf() + const char *get_cpp_buf() { return m_cpp_buf; } /** Get the end of the raw query buffer. */ - const char* get_end_of_query() + const char *get_end_of_query() { return m_end_of_query; } @@ -1279,43 +1279,43 @@ public: } /** Get the token start position, in the raw buffer. */ - const char* get_tok_start() + const char *get_tok_start() { return m_tok_start; } /** Get the token start position, in the pre-processed buffer. */ - const char* get_cpp_tok_start() + const char *get_cpp_tok_start() { return m_cpp_tok_start; } /** Get the token end position, in the raw buffer. */ - const char* get_tok_end() + const char *get_tok_end() { return m_tok_end; } /** Get the token end position, in the pre-processed buffer. */ - const char* get_cpp_tok_end() + const char *get_cpp_tok_end() { return m_cpp_tok_end; } /** Get the previous token start position, in the raw buffer. */ - const char* get_tok_start_prev() + const char *get_tok_start_prev() { return m_tok_start_prev; } /** Get the current stream pointer, in the raw buffer. */ - const char* get_ptr() + const char *get_ptr() { return m_ptr; } /** Get the current stream pointer, in the pre-processed buffer. */ - const char* get_cpp_ptr() + const char *get_cpp_ptr() { return m_cpp_ptr; } @@ -1365,22 +1365,22 @@ public: private: /** Pointer to the current position in the raw input stream. */ - const char* m_ptr; + const char *m_ptr; /** Starting position of the last token parsed, in the raw buffer. */ - const char* m_tok_start; + const char *m_tok_start; /** Ending position of the previous token parsed, in the raw buffer. */ - const char* m_tok_end; + const char *m_tok_end; /** End of the query text in the input stream, in the raw buffer. */ - const char* m_end_of_query; + const char *m_end_of_query; /** Starting position of the previous token parsed, in the raw buffer. */ - const char* m_tok_start_prev; + const char *m_tok_start_prev; /** Begining of the query text in the input stream, in the raw buffer. */ - const char* m_buf; + const char *m_buf; /** Length of the raw buffer. */ uint m_buf_length; @@ -1389,28 +1389,28 @@ private: bool m_echo; /** Pre-processed buffer. */ - char* m_cpp_buf; + char *m_cpp_buf; /** Pointer to the current position in the pre-processed input stream. */ - char* m_cpp_ptr; + char *m_cpp_ptr; /** Starting position of the last token parsed, in the pre-processed buffer. */ - const char* m_cpp_tok_start; + const char *m_cpp_tok_start; /** Starting position of the previous token parsed, in the pre-procedded buffer. */ - const char* m_cpp_tok_start_prev; + const char *m_cpp_tok_start_prev; /** Ending position of the previous token parsed, in the pre-processed buffer. */ - const char* m_cpp_tok_end; + const char *m_cpp_tok_end; /** UTF8-body buffer created during parsing. */ char *m_body_utf8; @@ -1433,7 +1433,7 @@ public: Position of ';' in the stream, to delimit multiple queries. This delimiter is in the raw buffer. */ - const char* found_semicolon; + const char *found_semicolon; /** SQL_MODE = IGNORE_SPACE. */ bool ignore_space; From 95a8c6c327a477c3bcaf67ba6acf7f48bbab4158 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jul 2007 21:05:29 +0300 Subject: [PATCH 13/23] Bug #28591: MySQL need not sort the records in case of ORDER BY primary_key on InnoDB table Queries that use an InnoDB secondary index to retrieve data don't need to sort in case of ORDER BY primary key if the secondary index is compared to constant(s). They can also skip sorting if ORDER BY contains both the the secondary key parts and the primary key parts (in that order). This is because InnoDB returns the rows in order of the primary key for rows with the same values of the secondary key columns. Fixed by preventing temp table sort for the qualifying queries. mysql-test/r/innodb_mysql.result: Bug #28591: test case mysql-test/t/innodb_mysql.test: Bug #28591: test case sql/sql_select.cc: Bug #28591: Use the primary key as suffix when testing if the key can be used for ORDER BY on supporting engines. sql/table.cc: Bug #28591: can use the primary key as a suffix for the secondary keys --- mysql-test/r/innodb_mysql.result | 245 +++++++++++++++++++++++++++++++ mysql-test/t/innodb_mysql.test | 33 +++++ sql/sql_select.cc | 29 +++- sql/table.cc | 4 + 4 files changed, 309 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 4535710c905..28f53a628ee 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -735,4 +735,249 @@ COUNT(*) 3072 set @@sort_buffer_size=default; DROP TABLE t1,t2; +CREATE TABLE t1 (a int, b int, PRIMARY KEY (a), KEY bkey (b)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,2),(3,2),(2,2),(4,2),(5,2),(6,2),(7,2),(8,2); +INSERT INTO t1 SELECT a + 8, 2 FROM t1; +INSERT INTO t1 SELECT a + 16, 1 FROM t1; +EXPLAIN SELECT * FROM t1 WHERE b=2 ORDER BY a; +id 1 +select_type SIMPLE +table t1 +type ref +possible_keys bkey +key bkey +key_len 5 +ref const +rows 16 +Extra Using where; Using index +SELECT * FROM t1 WHERE b=2 ORDER BY a; +a b +1 2 +2 2 +3 2 +4 2 +5 2 +6 2 +7 2 +8 2 +9 2 +10 2 +11 2 +12 2 +13 2 +14 2 +15 2 +16 2 +EXPLAIN SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY a; +id 1 +select_type SIMPLE +table t1 +type range +possible_keys bkey +key bkey +key_len 5 +ref NULL +rows 16 +Extra Using where; Using index; Using filesort +SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY a; +a b +1 2 +2 2 +3 2 +4 2 +5 2 +6 2 +7 2 +8 2 +9 2 +10 2 +11 2 +12 2 +13 2 +14 2 +15 2 +16 2 +17 1 +18 1 +19 1 +20 1 +21 1 +22 1 +23 1 +24 1 +25 1 +26 1 +27 1 +28 1 +29 1 +30 1 +31 1 +32 1 +EXPLAIN SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY b,a; +id 1 +select_type SIMPLE +table t1 +type range +possible_keys bkey +key bkey +key_len 5 +ref NULL +rows 16 +Extra Using where; Using index +SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY b,a; +a b +17 1 +18 1 +19 1 +20 1 +21 1 +22 1 +23 1 +24 1 +25 1 +26 1 +27 1 +28 1 +29 1 +30 1 +31 1 +32 1 +1 2 +2 2 +3 2 +4 2 +5 2 +6 2 +7 2 +8 2 +9 2 +10 2 +11 2 +12 2 +13 2 +14 2 +15 2 +16 2 +CREATE TABLE t2 (a int, b int, c int, PRIMARY KEY (a), KEY bkey (b,c)) +ENGINE=InnoDB; +INSERT INTO t2 VALUES (1,1,1),(3,1,1),(2,1,1),(4,1,1); +INSERT INTO t2 SELECT a + 4, 1, 1 FROM t2; +INSERT INTO t2 SELECT a + 8, 1, 1 FROM t2; +EXPLAIN SELECT * FROM t2 WHERE b=1 ORDER BY a; +id 1 +select_type SIMPLE +table t2 +type ref +possible_keys bkey +key bkey +key_len 5 +ref const +rows 8 +Extra Using where; Using index; Using filesort +SELECT * FROM t2 WHERE b=1 ORDER BY a; +a b c +1 1 1 +2 1 1 +3 1 1 +4 1 1 +5 1 1 +6 1 1 +7 1 1 +8 1 1 +9 1 1 +10 1 1 +11 1 1 +12 1 1 +13 1 1 +14 1 1 +15 1 1 +16 1 1 +EXPLAIN SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY a; +id 1 +select_type SIMPLE +table t2 +type ref +possible_keys bkey +key bkey +key_len 10 +ref const,const +rows 8 +Extra Using where; Using index +SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY a; +a b c +1 1 1 +2 1 1 +3 1 1 +4 1 1 +5 1 1 +6 1 1 +7 1 1 +8 1 1 +9 1 1 +10 1 1 +11 1 1 +12 1 1 +13 1 1 +14 1 1 +15 1 1 +16 1 1 +EXPLAIN SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY b,c,a; +id 1 +select_type SIMPLE +table t2 +type ref +possible_keys bkey +key bkey +key_len 10 +ref const,const +rows 8 +Extra Using where; Using index +SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY b,c,a; +a b c +1 1 1 +2 1 1 +3 1 1 +4 1 1 +5 1 1 +6 1 1 +7 1 1 +8 1 1 +9 1 1 +10 1 1 +11 1 1 +12 1 1 +13 1 1 +14 1 1 +15 1 1 +16 1 1 +EXPLAIN SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY c,a; +id 1 +select_type SIMPLE +table t2 +type ref +possible_keys bkey +key bkey +key_len 10 +ref const,const +rows 8 +Extra Using where; Using index +SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY c,a; +a b c +1 1 1 +2 1 1 +3 1 1 +4 1 1 +5 1 1 +6 1 1 +7 1 1 +8 1 1 +9 1 1 +10 1 1 +11 1 1 +12 1 1 +13 1 1 +14 1 1 +15 1 1 +16 1 1 +DROP TABLE t1,t2; End of 5.0 tests diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index d4ce997ddb1..9a44c673548 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -741,4 +741,37 @@ set @@sort_buffer_size=default; DROP TABLE t1,t2; +# +# Bug #28591: MySQL need not sort the records in case of ORDER BY +# primary_key on InnoDB table +# + +CREATE TABLE t1 (a int, b int, PRIMARY KEY (a), KEY bkey (b)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,2),(3,2),(2,2),(4,2),(5,2),(6,2),(7,2),(8,2); +INSERT INTO t1 SELECT a + 8, 2 FROM t1; +INSERT INTO t1 SELECT a + 16, 1 FROM t1; +query_vertical EXPLAIN SELECT * FROM t1 WHERE b=2 ORDER BY a; +SELECT * FROM t1 WHERE b=2 ORDER BY a; +query_vertical EXPLAIN SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY a; +SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY a; +query_vertical EXPLAIN SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY b,a; +SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY b,a; + +CREATE TABLE t2 (a int, b int, c int, PRIMARY KEY (a), KEY bkey (b,c)) + ENGINE=InnoDB; +INSERT INTO t2 VALUES (1,1,1),(3,1,1),(2,1,1),(4,1,1); +INSERT INTO t2 SELECT a + 4, 1, 1 FROM t2; +INSERT INTO t2 SELECT a + 8, 1, 1 FROM t2; + +query_vertical EXPLAIN SELECT * FROM t2 WHERE b=1 ORDER BY a; +SELECT * FROM t2 WHERE b=1 ORDER BY a; +query_vertical EXPLAIN SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY a; +SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY a; +query_vertical EXPLAIN SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY b,c,a; +SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY b,c,a; +query_vertical EXPLAIN SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY c,a; +SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY c,a; + +DROP TABLE t1,t2; + --echo End of 5.0 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index c62a19b2752..c77fb341232 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -12009,6 +12009,7 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx, key_part_end=key_part+table->key_info[idx].key_parts; key_part_map const_key_parts=table->const_key_parts[idx]; int reverse=0; + my_bool on_primary_key= FALSE; DBUG_ENTER("test_if_order_by_key"); for (; order ; order=order->next, const_key_parts>>=1) @@ -12023,7 +12024,30 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx, for (; const_key_parts & 1 ; const_key_parts>>= 1) key_part++; - if (key_part == key_part_end || key_part->field != field) + if (key_part == key_part_end) + { + /* + We are at the end of the key. Check if the engine has the primary + key as a suffix to the secondary keys. If it has continue to check + the primary key as a suffix. + */ + if (!on_primary_key && + (table->file->table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) && + table->s->primary_key != MAX_KEY) + { + on_primary_key= TRUE; + key_part= table->key_info[table->s->primary_key].key_part; + key_part_end=key_part+table->key_info[table->s->primary_key].key_parts; + const_key_parts=table->const_key_parts[table->s->primary_key]; + + for (; const_key_parts & 1 ; const_key_parts>>= 1) + key_part++; + } + else + DBUG_RETURN(0); + } + + if (key_part->field != field) DBUG_RETURN(0); /* set flag to 1 if we can use read-next on key, else to -1 */ @@ -12034,7 +12058,8 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx, reverse=flag; // Remember if reverse key_part++; } - *used_key_parts= (uint) (key_part - table->key_info[idx].key_part); + *used_key_parts= on_primary_key ? table->key_info[idx].key_parts : + (uint) (key_part - table->key_info[idx].key_part); if (reverse == -1 && !(table->file->index_flags(idx, *used_key_parts-1, 1) & HA_READ_PREV)) reverse= 0; // Index can't be used diff --git a/sql/table.cc b/sql/table.cc index 4e0f2b5d287..8cfd206a74f 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -780,7 +780,11 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, the primary key, then we can use any key to find this column */ if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX) + { field->part_of_key= share->keys_in_use; + if (field->part_of_sortkey.is_set(key)) + field->part_of_sortkey= share->keys_in_use; + } } if (field->key_length() != key_part->length) { From cff531ffc104179679648ee8b83f1ea74b7b376c Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 21 Jul 2007 04:50:11 +0500 Subject: [PATCH 14/23] Fixed bug #29788. After dumping triggers mysqldump copied the value of the OLD_SQL_MODE variable to the SQL_MODE variable. If the --compact option of the mysqldump was not set the OLD_SQL_MODE variable had the value of the uninitialized SQL_MODE variable. So usually the NO_AUTO_VALUE_ON_ZERO option of the SQL_MODE variable was discarded. This fix is for non-"--compact" mode of the mysqldump, because mysqldump --compact never set SQL_MODE to the value of NO_AUTO_VALUE_ON_ZERO. The dump_triggers_for_table function has been modified to restore previous value of the SQL_MODE variable after dumping triggers using the SAVE_SQL_MODE temporary variable. client/mysqldump.c: Fixed bug #29788. The dump_triggers_for_table function has been modified to restore previous value of the SQL_MODE variable after dumping triggers using the SAVE_SQL_MODE temporary variable. mysql-test/r/mysqldump.result: Updated test case for bug #29788. mysql-test/t/mysqldump.test: Updated test case for bug #29788. --- client/mysqldump.c | 7 ++++--- mysql-test/r/mysqldump.result | 38 +++++++++++++++++++++++++++++++---- mysql-test/t/mysqldump.test | 22 ++++++++++++++++++++ 3 files changed, 60 insertions(+), 7 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index f72cb0171e1..9ccea308a1f 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -2122,8 +2122,7 @@ static void dump_triggers_for_table(char *table, } if (mysql_num_rows(result)) { - if (opt_compact) - fprintf(sql_file, "\n/*!50003 SET @OLD_SQL_MODE=@@SQL_MODE*/;\n"); + fprintf(sql_file, "\n/*!50003 SET @SAVE_SQL_MODE=@@SQL_MODE*/;\n"); fprintf(sql_file, "\nDELIMITER ;;\n"); } while ((row= mysql_fetch_row(result))) @@ -2167,9 +2166,11 @@ static void dump_triggers_for_table(char *table, row[3] /* Statement */); } if (mysql_num_rows(result)) + { fprintf(sql_file, "DELIMITER ;\n" - "/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE */;\n"); + "/*!50003 SET SESSION SQL_MODE=@SAVE_SQL_MODE*/;\n"); + } mysql_free_result(result); /* make sure to set back opt_compatible mode to diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index da05fe7bc5b..7178cbb5d49 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -2238,6 +2238,8 @@ INSERT INTO `t1` VALUES (1,NULL),(2,NULL),(4,NULL),(11,NULL); /*!40000 ALTER TABLE `t1` ENABLE KEYS */; UNLOCK TABLES; +/*!50003 SET @SAVE_SQL_MODE=@@SQL_MODE*/; + DELIMITER ;; /*!50003 SET SESSION SQL_MODE="" */;; /*!50003 CREATE */ /*!50017 DEFINER=`root`@`localhost` */ /*!50003 TRIGGER `trg1` BEFORE INSERT ON `t1` FOR EACH ROW begin @@ -2260,7 +2262,7 @@ end if; end */;; DELIMITER ; -/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE */; +/*!50003 SET SESSION SQL_MODE=@SAVE_SQL_MODE*/; DROP TABLE IF EXISTS `t2`; CREATE TABLE `t2` ( `a` int(11) default NULL @@ -2271,6 +2273,8 @@ LOCK TABLES `t2` WRITE; /*!40000 ALTER TABLE `t2` ENABLE KEYS */; UNLOCK TABLES; +/*!50003 SET @SAVE_SQL_MODE=@@SQL_MODE*/; + DELIMITER ;; /*!50003 SET SESSION SQL_MODE="STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER" */;; /*!50003 CREATE */ /*!50017 DEFINER=`root`@`localhost` */ /*!50003 TRIGGER `trg4` BEFORE INSERT ON `t2` FOR EACH ROW begin @@ -2280,7 +2284,7 @@ end if; end */;; DELIMITER ; -/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE */; +/*!50003 SET SESSION SQL_MODE=@SAVE_SQL_MODE*/; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; @@ -2628,13 +2632,15 @@ INSERT INTO "t1 test" VALUES (1),(2),(3); /*!40000 ALTER TABLE "t1 test" ENABLE KEYS */; UNLOCK TABLES; +/*!50003 SET @SAVE_SQL_MODE=@@SQL_MODE*/; + DELIMITER ;; /*!50003 SET SESSION SQL_MODE="" */;; /*!50003 CREATE */ /*!50017 DEFINER=`root`@`localhost` */ /*!50003 TRIGGER `test trig` BEFORE INSERT ON `t1 test` FOR EACH ROW BEGIN INSERT INTO `t2 test` SET a2 = NEW.a1; END */;; DELIMITER ; -/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE */; +/*!50003 SET SESSION SQL_MODE=@SAVE_SQL_MODE*/; DROP TABLE IF EXISTS "t2 test"; CREATE TABLE "t2 test" ( "a2" int(11) default NULL @@ -2788,6 +2794,8 @@ LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` ENABLE KEYS */; UNLOCK TABLES; +/*!50003 SET @SAVE_SQL_MODE=@@SQL_MODE*/; + DELIMITER ;; /*!50003 SET SESSION SQL_MODE="IGNORE_SPACE" */;; /*!50003 CREATE */ /*!50017 DEFINER=`root`@`localhost` */ /*!50003 TRIGGER `tr1` BEFORE INSERT ON `t1` FOR EACH ROW BEGIN @@ -2795,7 +2803,7 @@ SET new.a = 0; END */;; DELIMITER ; -/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE */; +/*!50003 SET SESSION SQL_MODE=@SAVE_SQL_MODE*/; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; @@ -3334,5 +3342,27 @@ SELECT * FROM v1; 1 DROP VIEW v1; # +# Bug #29788: mysqldump discards the NO_AUTO_VALUE_ON_ZERO value of +# the SQL_MODE variable after the dumping of triggers. +# +CREATE TABLE t1 (c1 INT); +CREATE TRIGGER t1bd BEFORE DELETE ON t1 FOR EACH ROW BEGIN END; +CREATE TABLE t2 (c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY); +SET @TMP_SQL_MODE = @@SQL_MODE; +SET SQL_MODE = 'NO_AUTO_VALUE_ON_ZERO'; +INSERT INTO t2 VALUES (0), (1), (2); +SET SQL_MODE = @TMP_SQL_MODE; +SELECT * FROM t2; +c1 +0 +1 +2 +SELECT * FROM t2; +c1 +0 +1 +2 +DROP TABLE t1,t2; +# # End of 5.0 tests # diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index d42162541de..3c62577e781 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -1554,6 +1554,28 @@ DROP VIEW v1; SELECT * FROM v1; DROP VIEW v1; +--echo # +--echo # Bug #29788: mysqldump discards the NO_AUTO_VALUE_ON_ZERO value of +--echo # the SQL_MODE variable after the dumping of triggers. +--echo # + +CREATE TABLE t1 (c1 INT); +CREATE TRIGGER t1bd BEFORE DELETE ON t1 FOR EACH ROW BEGIN END; + +CREATE TABLE t2 (c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY); + +SET @TMP_SQL_MODE = @@SQL_MODE; +SET SQL_MODE = 'NO_AUTO_VALUE_ON_ZERO'; +INSERT INTO t2 VALUES (0), (1), (2); +SET SQL_MODE = @TMP_SQL_MODE; +SELECT * FROM t2; + +--exec $MYSQL_DUMP --routines test >$MYSQLTEST_VARDIR/tmp/bug29788.sql +--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/bug29788.sql +SELECT * FROM t2; + +DROP TABLE t1,t2; + --echo # --echo # End of 5.0 tests --echo # From 72c6c789cf206977894fc531ada2c253bc0b1806 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jul 2007 22:56:19 -0700 Subject: [PATCH 15/23] Fixed bug #29911. This bug manifested itself for join queries with GROUP BY and HAVING clauses whose SELECT lists contained DISTINCT. It occurred when the optimizer could deduce that the result set would have not more than one row. The bug could lead to wrong result sets for queries of this type because HAVING conditions were erroneously ignored in some cases in the function remove_duplicates. mysql-test/r/having.result: Added a test case for bug #29911. mysql-test/t/having.test: Added a test case for bug #29911. --- mysql-test/r/having.result | 19 +++++++++++++++++++ mysql-test/t/having.test | 26 ++++++++++++++++++++++++++ sql/sql_select.cc | 2 +- 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result index ccd1f0e61e7..7b4340a133b 100644 --- a/mysql-test/r/having.result +++ b/mysql-test/r/having.result @@ -158,3 +158,22 @@ EXPLAIN SELECT 0 AS x, a FROM t1 GROUP BY x,a HAVING x=1 AND a > 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible HAVING DROP table t1; +CREATE TABLE t1 (a int PRIMARY KEY); +CREATE TABLE t2 (b int PRIMARY KEY, a int); +CREATE TABLE t3 (b int, flag int); +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1,1), (2,1), (3,1); +INSERT INTO t3(b,flag) VALUES (2, 1); +SELECT t1.a +FROM t1 INNER JOIN t2 ON t1.a=t2.a LEFT JOIN t3 ON t2.b=t3.b +GROUP BY t1.a, t2.b HAVING MAX(t3.flag)=0; +a +SELECT DISTINCT t1.a, MAX(t3.flag) +FROM t1 INNER JOIN t2 ON t1.a=t2.a LEFT JOIN t3 ON t2.b=t3.b +GROUP BY t1.a, t2.b HAVING MAX(t3.flag)=0; +a MAX(t3.flag) +SELECT DISTINCT t1.a +FROM t1 INNER JOIN t2 ON t1.a=t2.a LEFT JOIN t3 ON t2.b=t3.b +GROUP BY t1.a, t2.b HAVING MAX(t3.flag)=0; +a +DROP TABLE t1,t2,t3; diff --git a/mysql-test/t/having.test b/mysql-test/t/having.test index 8b39e3bd454..c0ce3cbace7 100644 --- a/mysql-test/t/having.test +++ b/mysql-test/t/having.test @@ -151,4 +151,30 @@ EXPLAIN SELECT 0 AS x, a FROM t1 GROUP BY x,a HAVING x=1 AND a > 1; DROP table t1; +# +# Bug #29911: HAVING clause depending on constant table and evaluated to false +# + +CREATE TABLE t1 (a int PRIMARY KEY); +CREATE TABLE t2 (b int PRIMARY KEY, a int); +CREATE TABLE t3 (b int, flag int); + +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1,1), (2,1), (3,1); +INSERT INTO t3(b,flag) VALUES (2, 1); + +SELECT t1.a + FROM t1 INNER JOIN t2 ON t1.a=t2.a LEFT JOIN t3 ON t2.b=t3.b + GROUP BY t1.a, t2.b HAVING MAX(t3.flag)=0; + +SELECT DISTINCT t1.a, MAX(t3.flag) + FROM t1 INNER JOIN t2 ON t1.a=t2.a LEFT JOIN t3 ON t2.b=t3.b + GROUP BY t1.a, t2.b HAVING MAX(t3.flag)=0; + +SELECT DISTINCT t1.a + FROM t1 INNER JOIN t2 ON t1.a=t2.a LEFT JOIN t3 ON t2.b=t3.b + GROUP BY t1.a, t2.b HAVING MAX(t3.flag)=0; + +DROP TABLE t1,t2,t3; + # End of 4.1 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 8b5664a7f96..afbffc499ad 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8118,7 +8118,7 @@ remove_duplicates(JOIN *join, TABLE *entry,List &fields, Item *having) field_count++; } - if (!field_count && !(join->select_options & OPTION_FOUND_ROWS)) + if (!field_count && !(join->select_options & OPTION_FOUND_ROWS) && !having) { // only const items with no OPTION_FOUND_ROWS join->unit->select_limit_cnt= 1; // Only send first row DBUG_RETURN(0); From 9cad4f08dbcdced743a402ded32139c848757d27 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 22 Jul 2007 01:49:41 +0500 Subject: [PATCH 16/23] sp.test, sp.result: Additional test case fix for bug #29338. mysql-test/t/sp.test: Additional test case fix for bug #29338. mysql-test/r/sp.result: Additional test case fix for bug #29338. --- mysql-test/r/sp.result | 1 + mysql-test/t/sp.test | 1 + 2 files changed, 2 insertions(+) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 4321cd92826..3103174cf2e 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -6206,5 +6206,6 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL c1 5 NULL 5 Using where; Using index DROP VIEW v1; DROP FUNCTION f1; +DROP FUNCTION f2; DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index aeb85ac6012..22615c1cb28 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -7163,6 +7163,7 @@ EXPLAIN SELECT * FROM t1 WHERE c1=f2(rand()); DROP VIEW v1; DROP FUNCTION f1; +DROP FUNCTION f2; DROP TABLE t1; --echo End of 5.0 tests From d50caace5fa82b2281f5118c49f6754609d51ba9 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 22 Jul 2007 18:26:16 -0700 Subject: [PATCH 17/23] Fixed bug #29611. If a primary key is defined over column c of enum type then the EXPLAIN command for a look-up query of the form SELECT * FROM t WHERE c=0 said that the query was with an impossible where condition though the query correctly returned non-empty result set when the table indeed contained rows with error empty strings for column c. This kind of misbehavior was due to a bug in the function Field_enum::store(longlong,bool) that erroneously returned 1 if the the value to be stored was equal to 0. Note that the method Field_enum::store(const char *from,uint length,CHARSET_INFO *cs) correctly returned 0 if a value of the error empty string was stored. mysql-test/r/type_enum.result: Added a test case for bug #29661. mysql-test/t/type_enum.test: Added a test case for bug #29661. sql/field.cc: Fixed bug #29611. If a primary key was defined over column c of enum type then the EXPLAIN command for a look-up query of the form SELECT * FROM t WHERE c=0 said that the query was with an impossible where condition though the query correctly returned non-empty result set when the table indeed contained rows with error empty strings for column c. This kind of misbehavior was due to a bug in the function Field_enum::store(longlong,bool) that erroneously returned 1 if the the value to be stored was equal to 0. Note that the method Field_enum::store(const char *from,uint length,CHARSET_INFO *cs) correctly returned 0 if a value of the error empty string was stored. --- mysql-test/r/type_enum.result | 24 ++++++++++++++++++++++++ mysql-test/t/type_enum.test | 24 ++++++++++++++++++++++++ sql/field.cc | 7 +++++-- 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/type_enum.result b/mysql-test/r/type_enum.result index ca516f027ba..994001d94e5 100644 --- a/mysql-test/r/type_enum.result +++ b/mysql-test/r/type_enum.result @@ -1829,3 +1829,27 @@ c1 + 0 0 2 DROP TABLE t1,t2; +CREATE TABLE t1(a enum('a','b','c','d')); +INSERT INTO t1 VALUES (4),(1),(0),(3); +Warnings: +Warning 1265 Data truncated for column 'a' at row 3 +SELECT a FROM t1; +a +d +a + +c +EXPLAIN SELECT a FROM t1 WHERE a=0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where +SELECT a FROM t1 WHERE a=0; +a + +ALTER TABLE t1 ADD PRIMARY KEY (a); +EXPLAIN SELECT a FROM t1 WHERE a=0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 const PRIMARY PRIMARY 1 const 1 Using index +SELECT a FROM t1 WHERE a=0; +a + +DROP TABLE t1; diff --git a/mysql-test/t/type_enum.test b/mysql-test/t/type_enum.test index fbba38f926d..3dedb0018b1 100644 --- a/mysql-test/t/type_enum.test +++ b/mysql-test/t/type_enum.test @@ -200,3 +200,27 @@ CREATE TABLE t2 SELECT * FROM t1; SELECT c1 + 0 FROM t2; DROP TABLE t1,t2; + +# +# Bug#29661: Lookup by 0 for a primary index over a enum type +# + +CREATE TABLE t1(a enum('a','b','c','d')); +INSERT INTO t1 VALUES (4),(1),(0),(3); + +SELECT a FROM t1; + +EXPLAIN SELECT a FROM t1 WHERE a=0; +SELECT a FROM t1 WHERE a=0; + +ALTER TABLE t1 ADD PRIMARY KEY (a); + +EXPLAIN SELECT a FROM t1 WHERE a=0; +SELECT a FROM t1 WHERE a=0; + +DROP TABLE t1; + + + + + diff --git a/sql/field.cc b/sql/field.cc index 993c1fb3c4f..4a1320af48c 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7640,8 +7640,11 @@ int Field_enum::store(longlong nr, bool unsigned_val) if ((ulonglong) nr > typelib->count || nr == 0) { set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); - nr=0; - error=1; + if (nr != 0 || table->in_use->count_cuted_fields) + { + nr= 0; + error= 1; + } } store_type((ulonglong) (uint) nr); return error; From c38fa3f3acb380c5c18c982b7cdc0370b2328c76 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Jul 2007 06:26:57 +0300 Subject: [PATCH 18/23] table.cc, sql_select.cc: Limit the fix for bug 28591 to InnoDB only sql/sql_select.cc: Limit the fix for bug 28591 to InnoDB only sql/table.cc: Limit the fix for bug 28591 to InnoDB only --- sql/sql_select.cc | 1 + sql/table.cc | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d82a0fdcf41..2d9d261bb31 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -12033,6 +12033,7 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx, */ if (!on_primary_key && (table->file->table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) && + table->s->db_type == DB_TYPE_INNODB && table->s->primary_key != MAX_KEY) { on_primary_key= TRUE; diff --git a/sql/table.cc b/sql/table.cc index b231033d4f2..7b826bcdf2d 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -782,7 +782,8 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX) { field->part_of_key= share->keys_in_use; - if (field->part_of_sortkey.is_set(key)) + if (share->db_type == DB_TYPE_INNODB && + field->part_of_sortkey.is_set(key)) field->part_of_sortkey= share->keys_in_use; } } From 54c9742922864ee711e024bb93307c553d66fb38 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Jul 2007 19:09:48 +0300 Subject: [PATCH 19/23] coding style fix : Index_hint --- sql/sql_lex.cc | 6 +++--- sql/sql_lex.h | 14 +++++++------- sql/sql_parse.cc | 2 +- sql/table.cc | 4 ++-- sql/table.h | 4 ++-- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 9f69e7dee05..ab5bdc1e6fa 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1770,7 +1770,7 @@ TABLE_LIST *st_select_lex_node::add_table_to_list (THD *thd, Table_ident *table, LEX_STRING *alias, ulong table_join_options, thr_lock_type flags, - List *hints, + List *hints, LEX_STRING *option) { return 0; @@ -2723,7 +2723,7 @@ void st_select_lex::set_index_hint_type(enum index_hint_type type, void st_select_lex::alloc_index_hints (THD *thd) { - index_hints= new (thd->mem_root) List(); + index_hints= new (thd->mem_root) List(); } @@ -2744,7 +2744,7 @@ void st_select_lex::alloc_index_hints (THD *thd) bool st_select_lex::add_index_hint (THD *thd, char *str, uint length) { return index_hints->push_front (new (thd->mem_root) - index_hint(current_index_hint_type, + Index_hint(current_index_hint_type, current_index_hint_clause, str, length)); } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 4ac59fbacde..6044f4f752e 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -236,7 +236,7 @@ typedef uchar index_clause_map; INDEX_HINT_MASK_ORDER) /* Single element of an USE/FORCE/IGNORE INDEX list specified as a SQL hint */ -class index_hint : public Sql_alloc +class Index_hint : public Sql_alloc { public: /* The type of the hint : USE/FORCE/IGNORE */ @@ -249,7 +249,7 @@ public: */ LEX_STRING key_name; - index_hint (enum index_hint_type type_arg, index_clause_map clause_arg, + Index_hint (enum index_hint_type type_arg, index_clause_map clause_arg, char *str, uint length) : type(type_arg), clause(clause_arg) { @@ -441,7 +441,7 @@ public: LEX_STRING *alias, ulong table_options, thr_lock_type flags= TL_UNLOCK, - List *hints= 0, + List *hints= 0, LEX_STRING *option= 0); virtual void set_lock_for_tables(thr_lock_type lock_type) {} @@ -719,7 +719,7 @@ public: LEX_STRING *alias, ulong table_options, thr_lock_type flags= TL_UNLOCK, - List *hints= 0, + List *hints= 0, LEX_STRING *option= 0); TABLE_LIST* get_table_list(); bool init_nested_join(THD *thd); @@ -779,9 +779,9 @@ public: /* make a list to hold index hints */ void alloc_index_hints (THD *thd); /* read and clear the index hints */ - List* pop_index_hints(void) + List* pop_index_hints(void) { - List *hints= index_hints; + List *hints= index_hints; index_hints= NULL; return hints; } @@ -793,7 +793,7 @@ private: enum index_hint_type current_index_hint_type; index_clause_map current_index_hint_clause; /* a list of USE/FORCE/IGNORE INDEX */ - List *index_hints; + List *index_hints; }; typedef class st_select_lex SELECT_LEX; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index f2a61b7f7c5..93887db88e1 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5636,7 +5636,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, LEX_STRING *alias, ulong table_options, thr_lock_type lock_type, - List *index_hints_arg, + List *index_hints_arg, LEX_STRING *option) { register TABLE_LIST *ptr; diff --git a/sql/table.cc b/sql/table.cc index 5ac43343934..2c4d18ca4ff 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -4642,11 +4642,11 @@ bool TABLE_LIST::process_index_hints(TABLE *table) key_map index_join[INDEX_HINT_FORCE + 1]; key_map index_order[INDEX_HINT_FORCE + 1]; key_map index_group[INDEX_HINT_FORCE + 1]; - index_hint *hint; + Index_hint *hint; int type; bool have_empty_use_join= FALSE, have_empty_use_order= FALSE, have_empty_use_group= FALSE; - List_iterator iter(*index_hints); + List_iterator iter(*index_hints); /* initialize temporary variables used to collect hints of each kind */ for (type= INDEX_HINT_IGNORE; type <= INDEX_HINT_FORCE; type++) diff --git a/sql/table.h b/sql/table.h index 494b74d564c..a276a9f32fd 100644 --- a/sql/table.h +++ b/sql/table.h @@ -754,7 +754,7 @@ public: (TABLE_LIST::join_using_fields != NULL) */ -class index_hint; +class Index_hint; struct TABLE_LIST { TABLE_LIST() {} /* Remove gcc warning */ @@ -826,7 +826,7 @@ struct TABLE_LIST */ TABLE_LIST *next_name_resolution_table; /* Index names in a "... JOIN ... USE/IGNORE INDEX ..." clause. */ - List *index_hints; + List *index_hints; TABLE *table; /* opened table */ uint table_id; /* table id (from binlog) for opened table */ /* From 20b9d9bb2ffec3eb2490047b4c9e4b6502342904 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Jul 2007 22:01:22 -0600 Subject: [PATCH 20/23] Bug#29993 (Default value of log_output should be 'FILE', not 'TABLE') Changed the default location of the log output to LOG_FILE, for backward compatibility with MySQL 5.0 mysql-test/r/log_state.result: Changed the default location of the log output to LOG_FILE, for backward compatibility with MySQL 5.0 sql/set_var.cc: Changed the default location of the log output to LOG_FILE, for backward compatibility with MySQL 5.0 --- mysql-test/r/log_state.result | 2 +- sql/set_var.cc | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/log_state.result b/mysql-test/r/log_state.result index 946797aeec7..38b3ebd6e98 100644 --- a/mysql-test/r/log_state.result +++ b/mysql-test/r/log_state.result @@ -131,7 +131,7 @@ set global general_log=ON; set global log_output=default; show variables like 'log_output'; Variable_name Value -log_output TABLE +log_output FILE set global general_log=OFF; set global log_output=FILE; truncate table mysql.general_log; diff --git a/sql/set_var.cc b/sql/set_var.cc index bd5234b42be..7f3e808090d 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2220,9 +2220,9 @@ void sys_var_log_output::set_default(THD *thd, enum_var_type type) { pthread_mutex_lock(&LOCK_global_system_variables); logger.lock(); - logger.init_slow_log(LOG_TABLE); - logger.init_general_log(LOG_TABLE); - *value= LOG_TABLE; + logger.init_slow_log(LOG_FILE); + logger.init_general_log(LOG_FILE); + *value= LOG_FILE; logger.unlock(); pthread_mutex_unlock(&LOCK_global_system_variables); } From c4d53e31b0d7c242ebcaaf354605fa4ebbad0acc Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Jul 2007 18:15:44 +0400 Subject: [PATCH 21/23] Bug#15130: CREATE .. SELECT was denied to use advantages of the SQL_BIG_RESULT. When the SQL_BIG_RESULT flag is specified SELECT should store items from the select list in the filesort data and use them when sending to a client. The get_addon_fields function is responsible for creating necessary structures for that. But this function was allowed to do so only for SELECT and INSERT .. SELECT queries. This makes the SQL_BIG_RESULT useless for the CREATE .. SELECT queries. Now the get_addon_fields allows storing select list items in the filesort data for the CREATE .. SELECT queries. mysql-test/t/create.test: Added a test case for the bug#15130: CREATE .. SELECT was denied to use advantages of the SQL_BIG_RESULT. mysql-test/r/create.result: Added a test case for the bug#15130: CREATE .. SELECT was denied to use advantages of the SQL_BIG_RESULT. sql/filesort.cc: Bug#15130: CREATE .. SELECT was denied to use advantages of the SQL_BIG_RESULT. Now the get_addon_fields allows storing select list items in the filesort data for the CREATE .. SELECT queries. --- mysql-test/r/create.result | 13 +++++++++++++ mysql-test/t/create.test | 10 ++++++++++ sql/filesort.cc | 3 ++- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index e692dbf3938..dedd01be340 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -1503,4 +1503,17 @@ t1 CREATE TABLE `t1` ( `c17` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +create table t1(f1 int,f2 int); +insert into t1 value(1,1),(1,2),(1,3),(2,1),(2,2),(2,3); +flush status; +create table t2 select sql_big_result f1,count(f2) from t1 group by f1; +show status like 'handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 0 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_next 7 +drop table t1,t2; End of 5.0 tests diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 99f3fea416a..822620aa552 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -1119,4 +1119,14 @@ show create table t1; drop table t1; +# +# Bug#15130:CREATE .. SELECT was denied to use advantages of the SQL_BIG_RESULT. +# +create table t1(f1 int,f2 int); +insert into t1 value(1,1),(1,2),(1,3),(2,1),(2,2),(2,3); +flush status; +create table t2 select sql_big_result f1,count(f2) from t1 group by f1; +show status like 'handler_read%'; +drop table t1,t2; + --echo End of 5.0 tests diff --git a/sql/filesort.cc b/sql/filesort.cc index f8868ed6927..db73ede99b0 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -1430,7 +1430,8 @@ get_addon_fields(THD *thd, Field **ptabfield, uint sortlength, uint *plength) doesn't work for alter table */ if (thd->lex->sql_command != SQLCOM_SELECT && - thd->lex->sql_command != SQLCOM_INSERT_SELECT) + thd->lex->sql_command != SQLCOM_INSERT_SELECT && + thd->lex->sql_command != SQLCOM_CREATE_TABLE) return 0; for (pfield= ptabfield; (field= *pfield) ; pfield++) { From c59488321d894dbaa5fb158972ccd93748927375 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 26 Jul 2007 04:08:58 +0500 Subject: [PATCH 22/23] sql_select.cc: Post-merge fix. sql/sql_select.cc: Post-merge fix. --- sql/sql_select.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b1954620800..0973971de1c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -12312,8 +12312,8 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx, the primary key as a suffix. */ if (!on_primary_key && - (table->file->table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) && - table->s->db_type == DB_TYPE_INNODB && + (table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) && + table->s->db_type()->db_type == DB_TYPE_INNODB && table->s->primary_key != MAX_KEY) { on_primary_key= TRUE; From ddd728990802dc2e043312d291a69bee71fd851b Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 26 Jul 2007 04:41:48 +0500 Subject: [PATCH 23/23] table.cc, sql_select.cc: Post-merge fix. sql/sql_select.cc: Post-merge fix. sql/table.cc: Post-merge fix. --- sql/sql_select.cc | 2 +- sql/table.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 0973971de1c..668b7e99549 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -12313,7 +12313,7 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx, */ if (!on_primary_key && (table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) && - table->s->db_type()->db_type == DB_TYPE_INNODB && + ha_legacy_type(table->s->db_type()) == DB_TYPE_INNODB && table->s->primary_key != MAX_KEY) { on_primary_key= TRUE; diff --git a/sql/table.cc b/sql/table.cc index a7ab27f0760..fb88b46972c 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1351,7 +1351,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX) { field->part_of_key= share->keys_in_use; - if (share->db_type == DB_TYPE_INNODB && + if (ha_legacy_type(share->db_type()) == DB_TYPE_INNODB && field->part_of_sortkey.is_set(key)) field->part_of_sortkey= share->keys_in_use; }