diff options
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | mysql-test/r/loaddata.result | 50 | ||||
-rw-r--r-- | mysql-test/r/sp.result | 33 | ||||
-rw-r--r-- | mysql-test/t/loaddata.test | 45 | ||||
-rw-r--r-- | mysql-test/t/sp.test | 41 | ||||
-rw-r--r-- | sql/sql_delete.cc | 6 | ||||
-rw-r--r-- | sql/sql_derived.cc | 31 | ||||
-rw-r--r-- | sql/sql_derived.h | 1 | ||||
-rw-r--r-- | sql/sql_insert.cc | 3 | ||||
-rw-r--r-- | sql/sql_lex.cc | 16 | ||||
-rw-r--r-- | sql/sql_lex.h | 32 | ||||
-rw-r--r-- | sql/sql_load.cc | 10 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 21 | ||||
-rw-r--r-- | sql/sql_union.cc | 5 | ||||
-rw-r--r-- | win/packaging/create_msi.cmake.in | 5 |
15 files changed, 240 insertions, 61 deletions
@@ -1,3 +1,3 @@ MYSQL_VERSION_MAJOR=10 MYSQL_VERSION_MINOR=0 -MYSQL_VERSION_PATCH=39 +MYSQL_VERSION_PATCH=38 diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result index f446a503317..977932ced74 100644 --- a/mysql-test/r/loaddata.result +++ b/mysql-test/r/loaddata.result @@ -550,3 +550,53 @@ SELECT HEX(a) FROM t1; HEX(a) C3A4 DROP TABLE t1; +# +# MDEV-15744: Assertion `derived->table' failed in mysql_derived_merge_for_insert +# +create table t1 (a int, b int); +CREATE OR REPLACE VIEW t2 AS SELECT * FROM t1; +CREATE VIEW v2 AS SELECT * FROM t2; +LOAD DATA INFILE '../../std_data/loaddata7.dat' INTO TABLE v2 +FIELDS TERMINATED BY ',' LINES TERMINATED BY '\r\n'; +select * from v2; +a b +2 2 +3 3 +4 4 +5 5 +6 6 +select * from t2; +a b +2 2 +3 3 +4 4 +5 5 +6 6 +DROP VIEW IF EXISTS v2,t2; +DROP TABLE IF EXISTS t1; +# +# MDEV-15950: LOAD DATA INTO compex_view crashed +# +create table t1 (a int, b int); +create table t0 (x int, y int); +CREATE OR REPLACE VIEW v1 AS SELECT * FROM t1,t0; +CREATE VIEW v2 AS SELECT * FROM v1; +LOAD DATA INFILE '../../std_data/loaddata7.dat' INTO TABLE v1 +FIELDS TERMINATED BY ',' LINES TERMINATED BY '\r\n'; +ERROR HY000: Incorrect usage of Multi-table VIEW and LOAD +LOAD DATA INFILE '../../std_data/loaddata7.dat' INTO TABLE v2 +FIELDS TERMINATED BY ',' LINES TERMINATED BY '\r\n'; +ERROR HY000: Incorrect usage of Multi-table VIEW and LOAD +DROP VIEW IF EXISTS v2,v1; +DROP TABLE IF EXISTS t1,t0; +CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a), UNIQUE(b)); +INSERT INTO t1 VALUES (1,1); +CREATE TABLE t2 (c INT); +CREATE VIEW v AS SELECT t1.* FROM t1 JOIN t2; +SELECT a, b FROM t1 INTO OUTFILE '15645.data'; +LOAD DATA INFILE '15645.data' IGNORE INTO TABLE v (a,b); +ERROR HY000: Incorrect usage of Multi-table VIEW and LOAD +LOAD DATA INFILE '15645.data' REPLACE INTO TABLE v (a,b); +ERROR HY000: Incorrect usage of Multi-table VIEW and LOAD +drop table t1,t2; +drop view v; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 058ef69c548..7cff6492fad 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -7915,6 +7915,39 @@ CALL sp; c a b a b DROP PROCEDURE sp; DROP TABLE t1; +# +# MDEV-17055: Server crashes in find_order_in_list upon +# 2nd (3rd) execution of SP with UPDATE +# +CREATE TABLE t1 (a INT); +CREATE VIEW v1 AS SELECT * FROM t1; +CREATE TABLE t2 (c INT); +CREATE PROCEDURE sp() UPDATE v1 SET a = 1 ORDER BY a, b LIMIT 1; +LOCK TABLE t2 READ; +CALL sp; +ERROR HY000: Table 'v1' was not locked with LOCK TABLES +UNLOCK TABLES; +CALL sp; +ERROR 42S22: Unknown column 'b' in 'order clause' +CALL sp; +ERROR 42S22: Unknown column 'b' in 'order clause' +CALL sp; +ERROR 42S22: Unknown column 'b' in 'order clause' +DROP PROCEDURE sp; +CREATE PROCEDURE sp() UPDATE v1 SET a = 1 WHERE a=1 and b=2; +LOCK TABLE t2 READ; +CALL sp; +ERROR HY000: Table 'v1' was not locked with LOCK TABLES +UNLOCK TABLES; +CALL sp; +ERROR 42S22: Unknown column 'b' in 'where clause' +CALL sp; +ERROR 42S22: Unknown column 'b' in 'where clause' +CALL sp; +ERROR 42S22: Unknown column 'b' in 'where clause' +DROP PROCEDURE sp; +DROP VIEW v1; +DROP TABLE t1, t2; # End of 5.5 test # # MDEV-7040: Crash in field_conv, memcpy_field_possible, part#2 diff --git a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test index 8f8ff3520a2..de9de4305a3 100644 --- a/mysql-test/t/loaddata.test +++ b/mysql-test/t/loaddata.test @@ -676,3 +676,48 @@ CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET utf8); LOAD DATA INFILE '../../std_data/loaddata/mdev-11631.txt' INTO TABLE t1 CHARACTER SET utf8; SELECT HEX(a) FROM t1; DROP TABLE t1; + +--echo # +--echo # MDEV-15744: Assertion `derived->table' failed in mysql_derived_merge_for_insert +--echo # + +create table t1 (a int, b int); +CREATE OR REPLACE VIEW t2 AS SELECT * FROM t1; +CREATE VIEW v2 AS SELECT * FROM t2; +LOAD DATA INFILE '../../std_data/loaddata7.dat' INTO TABLE v2 + FIELDS TERMINATED BY ',' LINES TERMINATED BY '\r\n'; +select * from v2; +select * from t2; +DROP VIEW IF EXISTS v2,t2; +DROP TABLE IF EXISTS t1; + +--echo # +--echo # MDEV-15950: LOAD DATA INTO compex_view crashed +--echo # +create table t1 (a int, b int); +create table t0 (x int, y int); +CREATE OR REPLACE VIEW v1 AS SELECT * FROM t1,t0; +CREATE VIEW v2 AS SELECT * FROM v1; + +--error ER_WRONG_USAGE +LOAD DATA INFILE '../../std_data/loaddata7.dat' INTO TABLE v1 +FIELDS TERMINATED BY ',' LINES TERMINATED BY '\r\n'; + +--error ER_WRONG_USAGE +LOAD DATA INFILE '../../std_data/loaddata7.dat' INTO TABLE v2 +FIELDS TERMINATED BY ',' LINES TERMINATED BY '\r\n'; + +DROP VIEW IF EXISTS v2,v1; +DROP TABLE IF EXISTS t1,t0; + +CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a), UNIQUE(b)); +INSERT INTO t1 VALUES (1,1); +CREATE TABLE t2 (c INT); +CREATE VIEW v AS SELECT t1.* FROM t1 JOIN t2; +SELECT a, b FROM t1 INTO OUTFILE '15645.data'; +--error ER_WRONG_USAGE +LOAD DATA INFILE '15645.data' IGNORE INTO TABLE v (a,b); +--error ER_WRONG_USAGE +LOAD DATA INFILE '15645.data' REPLACE INTO TABLE v (a,b); +drop table t1,t2; +drop view v; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 1b765f0eb2d..dc1a244e716 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -9373,6 +9373,47 @@ CALL sp; DROP PROCEDURE sp; DROP TABLE t1; +--echo # +--echo # MDEV-17055: Server crashes in find_order_in_list upon +--echo # 2nd (3rd) execution of SP with UPDATE +--echo # + +CREATE TABLE t1 (a INT); +CREATE VIEW v1 AS SELECT * FROM t1; +CREATE TABLE t2 (c INT); + +CREATE PROCEDURE sp() UPDATE v1 SET a = 1 ORDER BY a, b LIMIT 1; +LOCK TABLE t2 READ; +--error ER_TABLE_NOT_LOCKED +CALL sp; +UNLOCK TABLES; +--error ER_BAD_FIELD_ERROR +CALL sp; +--error ER_BAD_FIELD_ERROR +CALL sp; +--error ER_BAD_FIELD_ERROR +CALL sp; + +# Cleanup +DROP PROCEDURE sp; + +CREATE PROCEDURE sp() UPDATE v1 SET a = 1 WHERE a=1 and b=2; +LOCK TABLE t2 READ; +--error ER_TABLE_NOT_LOCKED +CALL sp; +UNLOCK TABLES; +--error ER_BAD_FIELD_ERROR +CALL sp; +--error ER_BAD_FIELD_ERROR +CALL sp; +--error ER_BAD_FIELD_ERROR +CALL sp; + +# Cleanup +DROP PROCEDURE sp; + +DROP VIEW v1; +DROP TABLE t1, t2; --echo # End of 5.5 test diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index bbea9815547..46415566bc2 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -40,7 +40,7 @@ #include "sql_statistics.h" #include "transaction.h" #include "records.h" // init_read_record, -#include "sql_derived.h" // mysql_handle_list_of_derived +#include "sql_derived.h" // mysql_handle_derived // end_read_record #include "sql_partition.h" // make_used_partitions_str @@ -234,9 +234,9 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, if (open_and_lock_tables(thd, table_list, TRUE, 0)) DBUG_RETURN(TRUE); - if (mysql_handle_list_of_derived(thd->lex, table_list, DT_MERGE_FOR_INSERT)) + if (thd->lex->handle_list_of_derived(table_list, DT_MERGE_FOR_INSERT)) DBUG_RETURN(TRUE); - if (mysql_handle_list_of_derived(thd->lex, table_list, DT_PREPARE)) + if (thd->lex->handle_list_of_derived(table_list, DT_PREPARE)) DBUG_RETURN(TRUE); if (!table_list->single_table_updatable()) diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 7ad0b4b4c69..b545adf5a2d 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -91,6 +91,7 @@ mysql_handle_derived(LEX *lex, uint phases) sl= sl->next_select_in_list()) { TABLE_LIST *cursor= sl->get_table_list(); + sl->changed_elements|= TOUCHED_SEL_DERIVED; /* DT_MERGE_FOR_INSERT is not needed for views/derived tables inside subqueries. Views and derived tables of subqueries should be @@ -201,36 +202,6 @@ mysql_handle_single_derived(LEX *lex, TABLE_LIST *derived, uint phases) /** - Run specified phases for derived tables/views in the given list - - @param lex LEX for this thread - @param table_list list of derived tables/view to handle - @param phase_map phases to process tables/views through - - @details - This function runs phases specified by the 'phases_map' on derived - tables/views found in the 'dt_list' with help of the - TABLE_LIST::handle_derived function. - 'lex' is passed as an argument to the TABLE_LIST::handle_derived. - - @return FALSE ok - @return TRUE error -*/ - -bool -mysql_handle_list_of_derived(LEX *lex, TABLE_LIST *table_list, uint phases) -{ - for (TABLE_LIST *tl= table_list; tl; tl= tl->next_local) - { - if (tl->is_view_or_derived() && - tl->handle_derived(lex, phases)) - return TRUE; - } - return FALSE; -} - - -/** Merge a derived table/view into the embedding select @param thd thread handle diff --git a/sql/sql_derived.h b/sql/sql_derived.h index 1dffef7235b..301ae31b016 100644 --- a/sql/sql_derived.h +++ b/sql/sql_derived.h @@ -22,7 +22,6 @@ struct LEX; bool mysql_handle_derived(LEX *lex, uint phases); bool mysql_handle_single_derived(LEX *lex, TABLE_LIST *derived, uint phases); -bool mysql_handle_list_of_derived(LEX *lex, TABLE_LIST *dt_list, uint phases); bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived); /** diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 5ecdd72541f..c10d3517b5e 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1383,7 +1383,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, DBUG_RETURN(TRUE); if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT)) DBUG_RETURN(TRUE); - if (mysql_handle_list_of_derived(thd->lex, table_list, DT_PREPARE)) + if (thd->lex->handle_list_of_derived(table_list, DT_PREPARE)) DBUG_RETURN(TRUE); /* For subqueries in VALUES() we should not see the table in which we are @@ -1490,7 +1490,6 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, DBUG_RETURN(TRUE); } select_lex->fix_prepare_information(thd, &fake_conds, &fake_conds); - select_lex->first_execution= 0; } /* Only call prepare_for_posistion() if we are not performing a DELAYED diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 2fb239ed498..9bc0cf39ac7 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1896,7 +1896,7 @@ void st_select_lex::init_query() n_child_sum_items= 0; subquery_in_having= explicit_limit= 0; is_item_list_lookup= 0; - first_execution= 1; + changed_elements= 0; first_natural_join_processing= 1; first_cond_optimization= 1; parsing_place= NO_MATTER; @@ -3368,9 +3368,10 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds, Item **having_conds) { DBUG_ENTER("st_select_lex::fix_prepare_information"); - if (!thd->stmt_arena->is_conventional() && first_execution) + if (!thd->stmt_arena->is_conventional() && + !(changed_elements & TOUCHED_SEL_COND)) { - first_execution= 0; + changed_elements|= TOUCHED_SEL_COND; if (group_list.first) { if (!group_list_ptrs) @@ -3608,14 +3609,7 @@ bool st_select_lex::optimize_unflattened_subqueries(bool const_only) bool st_select_lex::handle_derived(LEX *lex, uint phases) { - for (TABLE_LIST *cursor= (TABLE_LIST*) table_list.first; - cursor; - cursor= cursor->next_local) - { - if (cursor->is_view_or_derived() && cursor->handle_derived(lex, phases)) - return TRUE; - } - return FALSE; + return lex->handle_list_of_derived(table_list.first, phases); } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index d58be8b336a..6483aa0e44d 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -667,6 +667,10 @@ public: typedef class st_select_lex_unit SELECT_LEX_UNIT; + +#define TOUCHED_SEL_COND 1/* WHERE/HAVING/ON should be reinited before use */ +#define TOUCHED_SEL_DERIVED (1<<1)/* derived should be reinited before use */ + /* SELECT_LEX - store information of parsed SELECT statment */ @@ -822,7 +826,8 @@ public: subquery. Prepared statements work OK in that regard, as in case of an error during prepare the PS is not created. */ - bool first_execution; + uint8 changed_elements; // see TOUCHED_SEL_* + /* TODO: add foloowing first_* to bitmap above */ bool first_natural_join_processing; bool first_cond_optimization; /* do not wrap view fields with Item_ref */ @@ -2772,6 +2777,31 @@ struct LEX: public Query_tables_list int print_explain(select_result_sink *output, uint8 explain_flags, bool *printed_anything); + + /* + Run specified phases for derived tables/views in the given list + + @param table_list - list of derived tables/view to handle + @param phase - phases to process tables/views through + + @details + This method runs phases specified by the 'phases' on derived + tables/views found in the 'table_list' with help of the + TABLE_LIST::handle_derived function. + 'this' is passed as an argument to the TABLE_LIST::handle_derived. + + @return false - ok + @return true - error + */ + bool handle_list_of_derived(TABLE_LIST *table_list, uint phases) + { + for (TABLE_LIST *tl= table_list; tl; tl= tl->next_local) + { + if (tl->is_view_or_derived() && tl->handle_derived(this, phases)) + return true; + } + return false; + } }; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 530f4379530..bdc8880ec68 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -308,8 +308,9 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, if (open_and_lock_tables(thd, table_list, TRUE, 0)) DBUG_RETURN(TRUE); - if (mysql_handle_single_derived(thd->lex, table_list, DT_MERGE_FOR_INSERT) || - mysql_handle_single_derived(thd->lex, table_list, DT_PREPARE)) + if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT)) + DBUG_RETURN(TRUE); + if (thd->lex->handle_list_of_derived(table_list, DT_PREPARE)) DBUG_RETURN(TRUE); if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context, &thd->lex->select_lex.top_join_list, @@ -325,6 +326,11 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "LOAD"); DBUG_RETURN(TRUE); } + if (table_list->is_multitable()) + { + my_error(ER_WRONG_USAGE, MYF(0), "Multi-table VIEW", "LOAD"); + DBUG_RETURN(TRUE); + } if (table_list->prepare_where(thd, 0, TRUE) || table_list->prepare_check_option(thd)) { diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 18f95490a82..5599e419b28 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2535,7 +2535,7 @@ void reinit_stmt_before_use(THD *thd, LEX *lex) } for (; sl; sl= sl->next_select_in_list()) { - if (!sl->first_execution) + if (sl->changed_elements & TOUCHED_SEL_COND) { /* remove option which was put by mysql_explain_union() */ sl->options&= ~SELECT_DESCRIBE; @@ -2582,19 +2582,28 @@ void reinit_stmt_before_use(THD *thd, LEX *lex) order->next= sl->group_list_ptrs->at(ix+1); } } + } + { // no harm to do it (item_ptr set on parsing) + ORDER *order; for (order= sl->group_list.first; order; order= order->next) + { order->item= &order->item_ptr; + } /* Fix ORDER list */ for (order= sl->order_list.first; order; order= order->next) - order->item= &order->item_ptr; { + order->item= &order->item_ptr; + } + } + if (sl->changed_elements & TOUCHED_SEL_DERIVED) + { #ifndef DBUG_OFF - bool res= + bool res= #endif - sl->handle_derived(lex, DT_REINIT); - DBUG_ASSERT(res == 0); - } + sl->handle_derived(lex, DT_REINIT); + DBUG_ASSERT(res == 0); } + { SELECT_LEX_UNIT *unit= sl->master_unit(); unit->unclean(); diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 01de3098783..b8bcbd6909d 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -215,8 +215,9 @@ st_select_lex_unit::init_prepare_fake_select_lex(THD *thd_arg, called at the first execution of the statement, while first_execution shows whether this is called at the first execution of the union that may form just a subselect. - */ - if (!fake_select_lex->first_execution && first_execution) + */ + if ((fake_select_lex->changed_elements & TOUCHED_SEL_COND) && + first_execution) { for (ORDER *order= global_parameters->order_list.first; order; diff --git a/win/packaging/create_msi.cmake.in b/win/packaging/create_msi.cmake.in index 62ce5f1edd2..db6f57e023d 100644 --- a/win/packaging/create_msi.cmake.in +++ b/win/packaging/create_msi.cmake.in @@ -398,9 +398,10 @@ IF("$ENV{EXTRA_LIGHT_ARGS}") ENDIF() FILE(REMOVE mysql_server.wixobj extra.wixobj) +STRING(REPLACE " " ";" EXTRA_WIX_PREPROCESSOR_FLAGS_LIST ${EXTRA_WIX_PREPROCESSOR_FLAGS}) EXECUTE_PROCESS( COMMAND ${CANDLE_EXECUTABLE} - ${EXTRA_WIX_PREPROCESSOR_FLAGS} + ${EXTRA_WIX_PREPROCESSOR_FLAGS_LIST} ${CANDLE_ARCH} -ext WixUtilExtension -ext WixFirewallExtension @@ -410,7 +411,7 @@ EXECUTE_PROCESS( EXECUTE_PROCESS( COMMAND ${CANDLE_EXECUTABLE} ${CANDLE_ARCH} - ${EXTRA_WIX_PREPROCESSOR_FLAGS} + ${EXTRA_WIX_PREPROCESSOR_FLAGS_LIST} -ext WixUtilExtension -ext WixFirewallExtension ${CMAKE_CURRENT_BINARY_DIR}/extra.wxs |