diff --git a/mysql-test/r/limit.result b/mysql-test/r/limit.result index 2acf74162a4..caed588acdb 100644 --- a/mysql-test/r/limit.result +++ b/mysql-test/r/limit.result @@ -111,3 +111,6 @@ set @a=-14632475938453979136; execute s using @a, @a; ERROR HY000: Incorrect arguments to EXECUTE End of 5.0 tests +select 1 as a limit 4294967296,10; +a +End of 5.1 tests diff --git a/mysql-test/r/lock_multi.result b/mysql-test/r/lock_multi.result index 079f92ca420..0430d560a7a 100644 --- a/mysql-test/r/lock_multi.result +++ b/mysql-test/r/lock_multi.result @@ -99,3 +99,37 @@ kill query ERROR 70100: Query execution was interrupted unlock tables; drop table t1; +CREATE TABLE t1 ( +a int(11) unsigned default NULL, +b varchar(255) default NULL, +UNIQUE KEY a (a), +KEY b (b) +); +INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3); +CREATE TABLE t2 SELECT * FROM t1; +CREATE TABLE t3 SELECT * FROM t1; +# test altering of columns that multiupdate doesn't use +# normal mode +# PS mode +# test altering of columns that multiupdate uses +# normal mode +# PS mode +DROP TABLE t1, t2, t3; +CREATE TABLE t1( a INT, b INT ); +INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4); +# 1. test regular tables +# 1.1. test altering of columns that multiupdate doesn't use +# 1.1.1. normal mode +# 1.1.2. PS mode +# 1.2. test altering of columns that multiupdate uses +# 1.2.1. normal mode +# 1.2.2. PS mode +ALTER TABLE t1 ADD COLUMN a INT; +# 2. test UNIONs +# 2.1. test altering of columns that multiupdate doesn't use +# 2.1.1. normal mode +# 2.1.2. PS mode +# 2.2. test altering of columns that multiupdate uses +# 2.2.1. normal mode +# 2.2.2. PS mode +DROP TABLE t1; diff --git a/mysql-test/r/metadata.result b/mysql-test/r/metadata.result index a4b6fd2ce8f..5aad5874ffc 100644 --- a/mysql-test/r/metadata.result +++ b/mysql-test/r/metadata.result @@ -181,4 +181,21 @@ c1 c2 3 3 DROP VIEW v1,v2; DROP TABLE t1,t2; +CREATE TABLE t1 (i INT, d DATE); +INSERT INTO t1 VALUES (1, '2008-01-01'), (2, '2008-01-02'), (3, '2008-01-03'); +SELECT COALESCE(d, d), IFNULL(d, d), IF(i, d, d), +CASE i WHEN i THEN d ELSE d END, GREATEST(d, d), LEAST(d, d) +FROM t1 ORDER BY RAND(); +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +2008-01-01 2008-01-01 2008-01-01 2008-01-01 2008-01-01 2008-01-01 +2008-01-02 2008-01-02 2008-01-02 2008-01-02 2008-01-02 2008-01-02 +2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 +COALESCE(d, d) IFNULL(d, d) IF(i, d, d) CASE i WHEN i THEN d ELSE d END GREATEST(d, d) LEAST(d, d) +def CASE i WHEN i THEN d ELSE d END CASE i WHEN i THEN d ELSE d END 10 10 10 Y 128 0 63 +def COALESCE(d, d) COALESCE(d, d) 10 10 10 Y 128 0 63 +def GREATEST(d, d) GREATEST(d, d) 10 10 10 Y 128 0 63 +def IF(i, d, d) IF(i, d, d) 10 10 10 Y 128 0 63 +def IFNULL(d, d) IFNULL(d, d) 10 10 10 Y 128 0 63 +def LEAST(d, d) LEAST(d, d) 10 10 10 Y 128 0 63 +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index 9f6a1b3932c..f64bbc79cbd 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -1076,3 +1076,19 @@ set session max_sort_length= 2180; select * from t1 order by b; ERROR HY001: Out of sort memory; increase server sort buffer size drop table t1; +# +# Bug #39844: Query Crash Mysql Server 5.0.67 +# +CREATE TABLE t1 (a INT PRIMARY KEY); +CREATE TABLE t2 (a INT PRIMARY KEY, b INT); +CREATE TABLE t3 (c INT); +INSERT INTO t1 (a) VALUES (1), (2); +INSERT INTO t2 (a,b) VALUES (1,2), (2,3); +INSERT INTO t3 (c) VALUES (1), (2); +SELECT +(SELECT t1.a FROM t1, t2 WHERE t1.a = t2.b AND t2.a = t3.c ORDER BY t1.a) +FROM t3; +(SELECT t1.a FROM t1, t2 WHERE t1.a = t2.b AND t2.a = t3.c ORDER BY t1.a) +2 +NULL +DROP TABLE t1, t2, t3; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index e788d30a14b..dea51bb4c2c 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -6672,6 +6672,19 @@ select substr(`str`, `pos`+ 1 ) into `str`; end $ call `p2`('s s s s s s'); drop procedure `p2`; +drop table if exists t1; +drop procedure if exists p1; +create procedure p1() begin select * from t1; end$ +call p1$ +ERROR 42S02: Table 'test.t1' doesn't exist +create table t1 (a integer)$ +call p1$ +a +alter table t1 add b integer; +call p1$ +a +drop table t1; +drop procedure p1; # ------------------------------------------------------------------ # -- End of 5.0 tests # ------------------------------------------------------------------ diff --git a/mysql-test/r/subselect3.result b/mysql-test/r/subselect3.result index 5221fa09744..97479418bec 100644 --- a/mysql-test/r/subselect3.result +++ b/mysql-test/r/subselect3.result @@ -779,4 +779,20 @@ SELECT 1 FROM t1 WHERE t1.a NOT IN (SELECT 1 FROM t1, t2 WHERE 0); 1 1 DROP TABLE t1, t2; +CREATE TABLE t1 ( +pk INT PRIMARY KEY, +int_key INT, +varchar_key VARCHAR(5) UNIQUE, +varchar_nokey VARCHAR(5) +); +INSERT INTO t1 VALUES (9, 7,NULL,NULL), (10,8,'p' ,'p'); +SELECT varchar_nokey +FROM t1 +WHERE NULL NOT IN ( +SELECT INNR.pk FROM t1 AS INNR2 +LEFT JOIN t1 AS INNR ON ( INNR2.int_key = INNR.int_key ) +WHERE INNR.varchar_key > 'n{' +); +varchar_nokey +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/r/windows.result b/mysql-test/r/windows.result index b5f9a48d805..5a54db8bb84 100644 --- a/mysql-test/r/windows.result +++ b/mysql-test/r/windows.result @@ -18,4 +18,5 @@ EXPLAIN SELECT * FROM t1 WHERE b = (SELECT max(2)); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables 2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used +DROP TABLE t1; End of 5.0 tests. diff --git a/mysql-test/t/limit.test b/mysql-test/t/limit.test index 9cccca1adc3..5847b90367a 100644 --- a/mysql-test/t/limit.test +++ b/mysql-test/t/limit.test @@ -95,3 +95,11 @@ set @a=-14632475938453979136; execute s using @a, @a; --echo End of 5.0 tests + +# +# Bug#37075: offset of limit clause might be truncated to 0 on 32-bits server w/o big tables +# + +select 1 as a limit 4294967296,10; + +--echo End of 5.1 tests diff --git a/mysql-test/t/lock_multi.test b/mysql-test/t/lock_multi.test index 649c1a4efbd..089a60edb3d 100644 --- a/mysql-test/t/lock_multi.test +++ b/mysql-test/t/lock_multi.test @@ -281,4 +281,325 @@ unlock tables; connection default; drop table t1; +# +# Bug #38691: segfault/abort in ``UPDATE ...JOIN'' while +# ``FLUSH TABLES WITH READ LOCK'' +# + +--connection default +CREATE TABLE t1 ( + a int(11) unsigned default NULL, + b varchar(255) default NULL, + UNIQUE KEY a (a), + KEY b (b) +); + +INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3); +CREATE TABLE t2 SELECT * FROM t1; +CREATE TABLE t3 SELECT * FROM t1; + +--echo # test altering of columns that multiupdate doesn't use + +--echo # normal mode + +--disable_query_log +let $i = 100; +while ($i) { +--dec $i + +--connection writer + send UPDATE t2 INNER JOIN (t1 JOIN t3 USING(a)) USING(a) + SET a = NULL WHERE t1.b <> t2.b; + +--connection locker + ALTER TABLE t2 ADD COLUMN (c INT); + ALTER TABLE t2 DROP COLUMN c; + +--connection writer +--reap +} + +--echo # PS mode + +--connection writer +PREPARE stmt FROM 'UPDATE t2 INNER JOIN (t1 JOIN t3 USING(a)) USING(a) + SET a = NULL WHERE t1.b <> t2.b'; + +let $i = 100; +while ($i) { +--dec $i + +--connection writer +--send EXECUTE stmt + +--connection locker + ALTER TABLE t2 ADD COLUMN (c INT); + ALTER TABLE t2 DROP COLUMN c; + +--connection writer +--reap +} +--enable_query_log + + +--echo # test altering of columns that multiupdate uses + +--echo # normal mode + +--connection default + +--disable_query_log +let $i = 100; +while ($i) { + dec $i; + +--connection locker +--error 0,1060 + ALTER TABLE t2 ADD COLUMN a int(11) unsigned default NULL; + UPDATE t2 SET a=b; + +--connection writer +--send UPDATE t2 INNER JOIN (t1 JOIN t3 USING(a)) USING(a) SET a = NULL WHERE t1.b <> t2.b + +--connection locker +--error 0,1091 + ALTER TABLE t2 DROP COLUMN a; + +--connection writer +--error 0,1054 +--reap +} +--enable_query_log + +--echo # PS mode + +--disable_query_log +let $i = 100; +while ($i) { + dec $i; + +--connection locker +--error 0,1060 + ALTER TABLE t2 ADD COLUMN a int(11) unsigned default NULL; + UPDATE t2 SET a=b; + +--connection writer + PREPARE stmt FROM 'UPDATE t2 INNER JOIN (t1 JOIN t3 USING(a)) USING(a) SET a = NULL WHERE t1.b <> t2.b'; +--send EXECUTE stmt + +--connection locker +--error 0,1091 + ALTER TABLE t2 DROP COLUMN a; + +--connection writer +--error 0,1054 +--reap + +} +--enable_query_log +--connection default +DROP TABLE t1, t2, t3; + +# +# Bug#38499: flush tables and multitable table update with derived table cause +# crash +# + +CREATE TABLE t1( a INT, b INT ); +INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4); + +--echo # 1. test regular tables +--echo # 1.1. test altering of columns that multiupdate doesn't use +--echo # 1.1.1. normal mode + +--disable_query_log +let $i = 100; +while ($i) { +--dec $i + +--connection writer + send UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0; + +--connection locker + ALTER TABLE t1 ADD COLUMN (c INT); + ALTER TABLE t1 DROP COLUMN c; + +--connection writer +--reap +} + +--echo # 1.1.2. PS mode + +--connection writer +PREPARE stmt FROM 'UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0'; + +let $i = 100; +while ($i) { +--dec $i + +--connection writer +--send EXECUTE stmt + +--connection locker + ALTER TABLE t1 ADD COLUMN (c INT); + ALTER TABLE t1 DROP COLUMN c; + +--connection writer +--reap +} +--enable_query_log + +--echo # 1.2. test altering of columns that multiupdate uses +--echo # 1.2.1. normal mode + +--connection default + +--disable_query_log +let $i = 100; +while ($i) { + dec $i; + +--connection locker +--error 0,1060 + ALTER TABLE t1 ADD COLUMN a int(11) unsigned default NULL; + UPDATE t1 SET a=b; + +--connection writer +--send UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0; + +--connection locker +--error 0,1091 + ALTER TABLE t1 DROP COLUMN a; + +--connection writer +--error 0,1054 # unknown column error +--reap +} +--enable_query_log + +--echo # 1.2.2. PS mode + +--disable_query_log +let $i = 100; +while ($i) { + dec $i; + +--connection locker +--error 0,1060 + ALTER TABLE t1 ADD COLUMN a INT; + UPDATE t1 SET a=b; + +--connection writer + PREPARE stmt FROM 'UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0'; +--send EXECUTE stmt + +--connection locker +--error 0,1091 + ALTER TABLE t1 DROP COLUMN a; + +--connection writer +--error 0,1054 # Unknown column 'a' in 'field list' +--reap +} +--enable_query_log +--connection default +ALTER TABLE t1 ADD COLUMN a INT; + +--echo # 2. test UNIONs +--echo # 2.1. test altering of columns that multiupdate doesn't use +--echo # 2.1.1. normal mode + +--disable_query_log +let $i = 100; +while ($i) { +--dec $i + +--connection writer + send UPDATE t1, ((SELECT 1 FROM t1 t1i) UNION (SELECT 2 FROM t1 t1ii)) e SET a = 0 WHERE 1=0; + +--connection locker + ALTER TABLE t1 ADD COLUMN (c INT); + ALTER TABLE t1 DROP COLUMN c; + +--connection writer +--reap +} + +--echo # 2.1.2. PS mode + +--connection writer +PREPARE stmt FROM 'UPDATE t1, ((SELECT 1 FROM t1 t1i) UNION (SELECT 2 FROM t1 t1ii)) e SET a = 0 WHERE 1=0'; + +let $i = 100; +while ($i) { +--dec $i + +--connection writer +--send EXECUTE stmt + +--connection locker + ALTER TABLE t1 ADD COLUMN (c INT); + ALTER TABLE t1 DROP COLUMN c; + +--connection writer +--reap +} +--enable_query_log + +--echo # 2.2. test altering of columns that multiupdate uses +--echo # 2.2.1. normal mode + +--connection default + +--disable_query_log +let $i = 100; +while ($i) { + dec $i; + +--connection locker +--error 0,1060 + ALTER TABLE t1 ADD COLUMN a int(11) unsigned default NULL; + UPDATE t1 SET a=b; + +--connection writer +--send UPDATE t1, ((SELECT 1 FROM t1 t1i) UNION (SELECT 2 FROM t1 t1ii)) e SET a = 0 WHERE 1=0; + +--connection locker +--error 0,1091 + ALTER TABLE t1 DROP COLUMN a; + +--connection writer +--error 0,1054 # Unknown column 'a' in 'field list' +--reap +} +--enable_query_log + +--echo # 2.2.2. PS mode + +--disable_query_log +let $i = 100; +while ($i) { + dec $i; + +--connection locker +--error 0,1060 + ALTER TABLE t1 ADD COLUMN a INT; + UPDATE t1 SET a=b; + +--connection writer + PREPARE stmt FROM 'UPDATE t1, ((SELECT 1 FROM t1 t1i) UNION (SELECT 2 FROM t1 t1ii)) e SET a = 0 WHERE 1=0'; +--send EXECUTE stmt + +--connection locker +--error 0,1091 + ALTER TABLE t1 DROP COLUMN a; + +--connection writer +--error 0,1054 # Unknown column 'a' in 'field list' +--reap +} +--enable_query_log +--connection default +DROP TABLE t1; + # End of 5.0 tests diff --git a/mysql-test/t/metadata.test b/mysql-test/t/metadata.test index 65c062399b7..a10767579fb 100644 --- a/mysql-test/t/metadata.test +++ b/mysql-test/t/metadata.test @@ -112,4 +112,21 @@ SELECT v1.c1, v2.c2 FROM v1 JOIN v2 ON c1=c2 GROUP BY v1.c1 ORDER BY v2.c2; DROP VIEW v1,v2; DROP TABLE t1,t2; +# +# Bug #39283: Date returned as VARBINARY to client for queries +# with COALESCE and JOIN +# + +CREATE TABLE t1 (i INT, d DATE); +INSERT INTO t1 VALUES (1, '2008-01-01'), (2, '2008-01-02'), (3, '2008-01-03'); + +--enable_metadata +--sorted_result +SELECT COALESCE(d, d), IFNULL(d, d), IF(i, d, d), + CASE i WHEN i THEN d ELSE d END, GREATEST(d, d), LEAST(d, d) + FROM t1 ORDER BY RAND(); # force filesort +--disable_metadata + +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index 9a55c27df99..6d7ee1c1ca7 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -738,3 +738,21 @@ set session max_sort_length= 2180; select * from t1 order by b; drop table t1; + +--echo # +--echo # Bug #39844: Query Crash Mysql Server 5.0.67 +--echo # + +CREATE TABLE t1 (a INT PRIMARY KEY); +CREATE TABLE t2 (a INT PRIMARY KEY, b INT); +CREATE TABLE t3 (c INT); + +INSERT INTO t1 (a) VALUES (1), (2); +INSERT INTO t2 (a,b) VALUES (1,2), (2,3); +INSERT INTO t3 (c) VALUES (1), (2); + +SELECT + (SELECT t1.a FROM t1, t2 WHERE t1.a = t2.b AND t2.a = t3.c ORDER BY t1.a) + FROM t3; + +DROP TABLE t1, t2, t3; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 21ca2528e4f..6d7a4b96167 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -7836,6 +7836,28 @@ delimiter ;$ call `p2`('s s s s s s'); drop procedure `p2`; +# +# Bug#38823: Invalid memory access when a SP statement does wildcard expansion +# + +--disable_warnings +drop table if exists t1; +drop procedure if exists p1; +--enable_warnings + +delimiter $; +create procedure p1() begin select * from t1; end$ +--error ER_NO_SUCH_TABLE +call p1$ +create table t1 (a integer)$ +call p1$ +alter table t1 add b integer; +call p1$ +delimiter ;$ + +drop table t1; +drop procedure p1; + --echo # ------------------------------------------------------------------ --echo # -- End of 5.0 tests --echo # ------------------------------------------------------------------ diff --git a/mysql-test/t/subselect3.test b/mysql-test/t/subselect3.test index d7bb1f7186a..7e9aa1554c0 100644 --- a/mysql-test/t/subselect3.test +++ b/mysql-test/t/subselect3.test @@ -618,4 +618,26 @@ SELECT 1 FROM t1 WHERE t1.a NOT IN (SELECT 1 FROM t1, t2 WHERE 0); DROP TABLE t1, t2; +# +# Bug #37894: Assertion in init_read_record_seq in handler.h line 1444 +# + +CREATE TABLE t1 ( + pk INT PRIMARY KEY, + int_key INT, + varchar_key VARCHAR(5) UNIQUE, + varchar_nokey VARCHAR(5) +); +INSERT INTO t1 VALUES (9, 7,NULL,NULL), (10,8,'p' ,'p'); + +SELECT varchar_nokey +FROM t1 +WHERE NULL NOT IN ( + SELECT INNR.pk FROM t1 AS INNR2 + LEFT JOIN t1 AS INNR ON ( INNR2.int_key = INNR.int_key ) + WHERE INNR.varchar_key > 'n{' +); + +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/mysql-test/t/windows.test b/mysql-test/t/windows.test old mode 100644 new mode 100755 index 6976ee98750..6e6a7ec93a3 --- a/mysql-test/t/windows.test +++ b/mysql-test/t/windows.test @@ -33,5 +33,6 @@ drop table t1; # CREATE TABLE t1 (a int, b int); INSERT INTO t1 VALUES (1,1); EXPLAIN SELECT * FROM t1 WHERE b = (SELECT max(2)); +DROP TABLE t1; --echo End of 5.0 tests. diff --git a/sql/item.cc b/sql/item.cc index f247f49293d..182f4abdfe6 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1758,14 +1758,17 @@ Item_field::Item_field(THD *thd, Name_resolution_context *context_arg, We need to copy db_name, table_name and field_name because they must be allocated in the statement memory, not in table memory (the table structure can go away and pop up again between subsequent executions - of a prepared statement). + of a prepared statement or after the close_tables_for_reopen() call + in mysql_multi_update_prepare() or due to wildcard expansion in stored + procedures). */ - if (thd->stmt_arena->is_stmt_prepare_or_first_sp_execute()) { if (db_name) orig_db_name= thd->strdup(db_name); - orig_table_name= thd->strdup(table_name); - orig_field_name= thd->strdup(field_name); + if (table_name) + orig_table_name= thd->strdup(table_name); + if (field_name) + orig_field_name= thd->strdup(field_name); /* We don't restore 'name' in cleanup because it's not changed during execution. Still we need it to point to persistent diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 2ae86b876d2..204ebdb6f33 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1015,7 +1015,7 @@ int QUICK_RANGE_SELECT::init() if (file->inited != handler::NONE) file->ha_index_or_rnd_end(); - DBUG_RETURN(error= file->ha_index_init(index)); + DBUG_RETURN(FALSE); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 533b0070fee..d969c837891 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3617,8 +3617,21 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name, { /* This is a base table. */ DBUG_ASSERT(nj_col->view_field == NULL); - DBUG_ASSERT(nj_col->table_ref->table == nj_col->table_field->table); - found_field= nj_col->table_field; + /* + This fix_fields is not necessary (initially this item is fixed by + the Item_field constructor; after reopen_tables the Item_func_eq + calls fix_fields on that item), it's just a check during table + reopening for columns that was dropped by the concurrent connection. + */ + if (!nj_col->table_field->fixed && + nj_col->table_field->fix_fields(thd, (Item **)&nj_col->table_field)) + { + DBUG_PRINT("info", ("column '%s' was dropped by the concurrent connection", + nj_col->table_field->name)); + DBUG_RETURN(NULL); + } + DBUG_ASSERT(nj_col->table_ref->table == nj_col->table_field->field->table); + found_field= nj_col->table_field->field; update_field_dependencies(thd, found_field, nj_col->table_ref->table); } @@ -4450,7 +4463,7 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, const char *field_name_1; /* true if field_name_1 is a member of using_fields */ bool is_using_column_1; - if (!(nj_col_1= it_1.get_or_create_column_ref(leaf_1))) + if (!(nj_col_1= it_1.get_or_create_column_ref(thd, leaf_1))) goto err; field_name_1= nj_col_1->name(); is_using_column_1= using_fields && @@ -4471,7 +4484,7 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, { Natural_join_column *cur_nj_col_2; const char *cur_field_name_2; - if (!(cur_nj_col_2= it_2.get_or_create_column_ref(leaf_2))) + if (!(cur_nj_col_2= it_2.get_or_create_column_ref(thd, leaf_2))) goto err; cur_field_name_2= cur_nj_col_2->name(); DBUG_PRINT ("info", ("cur_field_name_2=%s.%s", @@ -4957,15 +4970,24 @@ static bool setup_natural_join_row_types(THD *thd, TABLE_LIST *left_neighbor; /* Table reference to the right of the current. */ TABLE_LIST *right_neighbor= NULL; + bool save_first_natural_join_processing= + context->select_lex->first_natural_join_processing; + + context->select_lex->first_natural_join_processing= FALSE; /* Note that tables in the list are in reversed order */ for (left_neighbor= table_ref_it++; left_neighbor ; ) { table_ref= left_neighbor; left_neighbor= table_ref_it++; - /* For stored procedures do not redo work if already done. */ - if (context->select_lex->first_execution) + /* + Do not redo work if already done: + 1) for stored procedures, + 2) for multitable update after lock failure and table reopening. + */ + if (save_first_natural_join_processing) { + context->select_lex->first_natural_join_processing= FALSE; if (store_top_level_join_columns(thd, table_ref, left_neighbor, right_neighbor)) return TRUE; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 0cf7c11b447..71aa80b8170 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1205,6 +1205,7 @@ void st_select_lex::init_query() subquery_in_having= explicit_limit= 0; is_item_list_lookup= 0; first_execution= 1; + first_natural_join_processing= 1; first_cond_optimization= 1; parsing_place= NO_MATTER; exclude_from_table_unique_test= no_wrap_view_item= FALSE; @@ -2040,12 +2041,26 @@ st_lex::copy_db_to(char **p_db, uint *p_db_length) const void st_select_lex_unit::set_limit(SELECT_LEX *sl) { ha_rows select_limit_val; + ulonglong val; DBUG_ASSERT(! thd->stmt_arena->is_stmt_prepare()); - select_limit_val= (ha_rows)(sl->select_limit ? sl->select_limit->val_uint() : - HA_POS_ERROR); - offset_limit_cnt= (ha_rows)(sl->offset_limit ? sl->offset_limit->val_uint() : - ULL(0)); + val= sl->select_limit ? sl->select_limit->val_uint() : HA_POS_ERROR; + select_limit_val= (ha_rows)val; +#ifndef BIG_TABLES + /* + Check for overflow : ha_rows can be smaller then ulonglong if + BIG_TABLES is off. + */ + if (val != (ulonglong)select_limit_val) + select_limit_val= HA_POS_ERROR; +#endif + val= sl->offset_limit ? sl->offset_limit->val_uint() : ULL(0); + offset_limit_cnt= (ha_rows)val; +#ifndef BIG_TABLES + /* Check for truncation. */ + if (val != (ulonglong)offset_limit_cnt) + offset_limit_cnt= HA_POS_ERROR; +#endif select_limit_cnt= select_limit_val + offset_limit_cnt; if (select_limit_cnt < select_limit_val) select_limit_cnt= HA_POS_ERROR; // no limit diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 563172594d2..9f020f4adc5 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -586,6 +586,7 @@ public: case of an error during prepare the PS is not created. */ bool first_execution; + bool first_natural_join_processing; bool first_cond_optimization; /* do not wrap view fields with Item_ref */ bool no_wrap_view_item; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 6928effc1a5..9723dd8c4e4 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6574,6 +6574,7 @@ only_eq_ref_tables(JOIN *join,ORDER *order,table_map tables) { if (specialflag & SPECIAL_SAFE_MODE) return 0; // skip this optimize /* purecov: inspected */ + tables&= ~PSEUDO_TABLE_BITS; for (JOIN_TAB **tab=join->map2table ; tables ; tab++, tables>>=1) { if (tables & 1 && !eq_ref_table(join, order, *tab)) @@ -8964,6 +8965,7 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, */ if ((type= item->field_type()) == MYSQL_TYPE_DATETIME || type == MYSQL_TYPE_TIME || type == MYSQL_TYPE_DATE || + type == MYSQL_TYPE_NEWDATE || type == MYSQL_TYPE_TIMESTAMP || type == MYSQL_TYPE_GEOMETRY) new_field= item->tmp_table_field_from_field_type(table); /* diff --git a/sql/sql_union.cc b/sql/sql_union.cc index da5e118b069..2875aefbd97 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -399,7 +399,6 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, } else { - DBUG_ASSERT(!thd->stmt_arena->is_conventional()); /* We're in execution of a prepared statement or stored procedure: reset field items to point at fields from the created temporary table. diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 7d47659fbcc..eb4e9b7ed73 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -852,11 +852,14 @@ reopen_tables: } /* now lock and fill tables */ - if (lock_tables(thd, table_list, table_count, &need_reopen)) + if (!thd->stmt_arena->is_stmt_prepare() && + lock_tables(thd, table_list, table_count, &need_reopen)) { if (!need_reopen) DBUG_RETURN(TRUE); + DBUG_PRINT("info", ("lock_tables failed, reopening")); + /* We have to reopen tables since some of them were altered or dropped during lock_tables() or something was done with their triggers. @@ -872,6 +875,34 @@ reopen_tables: for (TABLE_LIST *tbl= table_list; tbl; tbl= tbl->next_global) tbl->cleanup_items(); + /* + To not to hog memory (as a result of the + unit->reinit_exec_mechanism() call below): + */ + lex->unit.cleanup(); + + for (SELECT_LEX *sl= lex->all_selects_list; + sl; + sl= sl->next_select_in_list()) + { + SELECT_LEX_UNIT *unit= sl->master_unit(); + unit->reinit_exec_mechanism(); // reset unit->prepared flags + /* + Reset 'clean' flag back to force normal execution of + unit->cleanup() in Prepared_statement::cleanup_stmt() + (call to lex->unit.cleanup() above sets this flag to TRUE). + */ + unit->unclean(); + } + + /* + Also we need to cleanup Natural_join_column::table_field items. + To not to traverse a join tree we will cleanup whole + thd->free_list (in PS execution mode that list may not contain + items from 'fields' list, so the cleanup above is necessary to. + */ + cleanup_items(thd->free_list); + close_tables_for_reopen(thd, &table_list); goto reopen_tables; } diff --git a/sql/table.cc b/sql/table.cc index 7fe9aa774f3..3abd2c24c94 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2191,7 +2191,7 @@ TABLE_LIST *TABLE_LIST::find_underlying_table(TABLE *table_to_find) } /* - cleunup items belonged to view fields translation table + cleanup items belonged to view fields translation table SYNOPSIS TABLE_LIST::cleanup_items() @@ -2637,10 +2637,10 @@ Natural_join_column::Natural_join_column(Field_translator *field_param, } -Natural_join_column::Natural_join_column(Field *field_param, +Natural_join_column::Natural_join_column(Item_field *field_param, TABLE_LIST *tab) { - DBUG_ASSERT(tab->table == field_param->table); + DBUG_ASSERT(tab->table == field_param->field->table); table_field= field_param; view_field= NULL; table_ref= tab; @@ -2668,7 +2668,7 @@ Item *Natural_join_column::create_item(THD *thd) return create_view_field(thd, table_ref, &view_field->item, view_field->name); } - return new Item_field(thd, &thd->lex->current_select->context, table_field); + return table_field; } @@ -2679,7 +2679,7 @@ Field *Natural_join_column::field() DBUG_ASSERT(table_field == NULL); return NULL; } - return table_field; + return table_field->field; } @@ -2811,7 +2811,7 @@ void Field_iterator_natural_join::next() cur_column_ref= column_ref_it++; DBUG_ASSERT(!cur_column_ref || ! cur_column_ref->table_field || cur_column_ref->table_ref->table == - cur_column_ref->table_field->table); + cur_column_ref->table_field->field->table); } @@ -2975,7 +2975,7 @@ GRANT_INFO *Field_iterator_table_ref::grant() */ Natural_join_column * -Field_iterator_table_ref::get_or_create_column_ref(TABLE_LIST *parent_table_ref) +Field_iterator_table_ref::get_or_create_column_ref(THD *thd, TABLE_LIST *parent_table_ref) { Natural_join_column *nj_col; bool is_created= TRUE; @@ -2988,7 +2988,11 @@ Field_iterator_table_ref::get_or_create_column_ref(TABLE_LIST *parent_table_ref) { /* The field belongs to a stored table. */ Field *tmp_field= table_field_it.field(); - nj_col= new Natural_join_column(tmp_field, table_ref); + Item_field *tmp_item= + new Item_field(thd, &thd->lex->current_select->context, tmp_field); + if (!tmp_item) + return NULL; + nj_col= new Natural_join_column(tmp_item, table_ref); field_count= table_ref->table->s->fields; } else if (field_it == &view_field_it) @@ -3012,7 +3016,7 @@ Field_iterator_table_ref::get_or_create_column_ref(TABLE_LIST *parent_table_ref) DBUG_ASSERT(nj_col); } DBUG_ASSERT(!nj_col->table_field || - nj_col->table_ref->table == nj_col->table_field->table); + nj_col->table_ref->table == nj_col->table_field->field->table); /* If the natural join column was just created add it to the list of @@ -3077,7 +3081,7 @@ Field_iterator_table_ref::get_natural_column_ref() nj_col= natural_join_it.column_ref(); DBUG_ASSERT(nj_col && (!nj_col->table_field || - nj_col->table_ref->table == nj_col->table_field->table)); + nj_col->table_ref->table == nj_col->table_field->field->table)); return nj_col; } diff --git a/sql/table.h b/sql/table.h index cff4be630e4..08326e2fbe0 100644 --- a/sql/table.h +++ b/sql/table.h @@ -18,6 +18,7 @@ class Item; /* Needed by ORDER */ class Item_subselect; +class Item_field; class GRANT_TABLE; class st_select_lex_unit; class st_select_lex; @@ -469,7 +470,7 @@ class Natural_join_column: public Sql_alloc { public: Field_translator *view_field; /* Column reference of merge view. */ - Field *table_field; /* Column reference of table or temp view. */ + Item_field *table_field; /* Column reference of table or temp view. */ TABLE_LIST *table_ref; /* Original base table/view reference. */ /* True if a common join column of two NATURAL/USING join operands. Notice @@ -481,7 +482,7 @@ public: bool is_common; public: Natural_join_column(Field_translator *field_param, TABLE_LIST *tab); - Natural_join_column(Field *field_param, TABLE_LIST *tab); + Natural_join_column(Item_field *field_param, TABLE_LIST *tab); const char *name(); Item *create_item(THD *thd); Field *field(); @@ -899,7 +900,7 @@ public: GRANT_INFO *grant(); Item *create_item(THD *thd) { return field_it->create_item(thd); } Field *field() { return field_it->field(); } - Natural_join_column *get_or_create_column_ref(TABLE_LIST *parent_table_ref); + Natural_join_column *get_or_create_column_ref(THD *thd, TABLE_LIST *parent_table_ref); Natural_join_column *get_natural_column_ref(); };