diff options
author | Alexander Barkov <bar@mariadb.org> | 2018-01-23 17:43:12 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.org> | 2018-01-23 17:43:12 +0400 |
commit | ec6b8c546a433b4a4f66e3c483807c1159c9c543 (patch) | |
tree | 2bed00fba5974a92ef1e4ef3504060cc43acaa07 /sql/sql_prepare.cc | |
parent | c425dcd8f23c4677bf71d03980753fe60b31f6a4 (diff) | |
parent | 7cc507f22e6eaec5ec83e24cd45275656bc7962f (diff) | |
download | mariadb-git-ec6b8c546a433b4a4f66e3c483807c1159c9c543.tar.gz |
Merge remote-tracking branch 'origin/10.2' into bb-10.2-ext
Diffstat (limited to 'sql/sql_prepare.cc')
-rw-r--r-- | sql/sql_prepare.cc | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index d5d786e8ec7..33a7ee7f78f 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2769,6 +2769,25 @@ void mysql_sql_stmt_prepare(THD *thd) DBUG_VOID_RETURN; } + /* + Make sure we call Prepared_statement::prepare() with an empty + THD::change_list. It can be non-empty as LEX::get_dynamic_sql_string() + calls fix_fields() for the Item containing the PS source, + e.g. on character set conversion: + + SET NAMES utf8; + DELIMITER $$ + CREATE PROCEDURE p1() + BEGIN + PREPARE stmt FROM CONCAT('SELECT ',CONVERT(RAND() USING latin1)); + EXECUTE stmt; + END; + $$ + DELIMITER ; + CALL p1(); + */ + Item_change_list_savepoint change_list_savepoint(thd); + if (stmt->prepare(query.str, (uint) query.length)) { /* Statement map deletes the statement on erase */ @@ -2779,6 +2798,7 @@ void mysql_sql_stmt_prepare(THD *thd) SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL); my_ok(thd, 0L, 0L, "Statement prepared"); } + change_list_savepoint.rollback(thd); DBUG_VOID_RETURN; } @@ -2810,7 +2830,28 @@ void mysql_sql_stmt_execute_immediate(THD *thd) // See comments on thd->free_list in mysql_sql_stmt_execute() Item *free_list_backup= thd->free_list; thd->free_list= NULL; + /* + Make sure we call Prepared_statement::execute_immediate() + with an empty THD::change_list. It can be non empty as the above + LEX::prepared_stmt_params_fix_fields() and LEX::get_dynamic_str_string() + call fix_fields() for the PS source and PS parameter Items and + can do Item tree changes, e.g. on character set conversion: + + - Example #1: Item tree changes in get_dynamic_str_string() + SET NAMES utf8; + CREATE PROCEDURE p1() + EXECUTE IMMEDIATE CONCAT('SELECT ',CONVERT(RAND() USING latin1)); + CALL p1(); + + - Example #2: Item tree changes in prepared_stmt_param_fix_fields(): + SET NAMES utf8; + CREATE PROCEDURE p1(a VARCHAR(10) CHARACTER SET utf8) + EXECUTE IMMEDIATE 'SELECT ?' USING CONCAT(a, CONVERT(RAND() USING latin1)); + CALL p1('x'); + */ + Item_change_list_savepoint change_list_savepoint(thd); (void) stmt->execute_immediate(query.str, (uint) query.length); + change_list_savepoint.rollback(thd); thd->free_items(); thd->free_list= free_list_backup; @@ -3208,7 +3249,27 @@ void mysql_sql_stmt_execute(THD *thd) */ Item *free_list_backup= thd->free_list; thd->free_list= NULL; // Hide the external (e.g. "SET STATEMENT") Items + /* + Make sure we call Prepared_statement::execute_loop() with an empty + THD::change_list. It can be non-empty because the above + LEX::prepared_stmt_params_fix_fields() calls fix_fields() for + the PS parameter Items and can do some Item tree changes, + e.g. on character set conversion: + + SET NAMES utf8; + DELIMITER $$ + CREATE PROCEDURE p1(a VARCHAR(10) CHARACTER SET utf8) + BEGIN + PREPARE stmt FROM 'SELECT ?'; + EXECUTE stmt USING CONCAT(a, CONVERT(RAND() USING latin1)); + END; + $$ + DELIMITER ; + CALL p1('x'); + */ + Item_change_list_savepoint change_list_savepoint(thd); (void) stmt->execute_loop(&expanded_query, FALSE, NULL, NULL); + change_list_savepoint.rollback(thd); thd->free_items(); // Free items created by execute_loop() /* Now restore the "external" (e.g. "SET STATEMENT") Item list. |