From 36f1e4848ca0ddebe60b98286291057bb3d5e314 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jul 2007 18:39:01 +0500 Subject: [PATCH 01/13] 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 1a2d2117ffcd9641ed472039f29c8996023e7b60 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jul 2007 16:05:55 +0500 Subject: [PATCH 02/13] 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 03/13] 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 95a8c6c327a477c3bcaf67ba6acf7f48bbab4158 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jul 2007 21:05:29 +0300 Subject: [PATCH 04/13] 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 05/13] 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 06/13] 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 07/13] 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 08/13] 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 09/13] 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 10/13] 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 c4d53e31b0d7c242ebcaaf354605fa4ebbad0acc Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Jul 2007 18:15:44 +0400 Subject: [PATCH 11/13] 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 12/13] 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 13/13] 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; }