summaryrefslogtreecommitdiff
path: root/sql/sql_prepare.cc
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2018-01-23 17:43:12 +0400
committerAlexander Barkov <bar@mariadb.org>2018-01-23 17:43:12 +0400
commitec6b8c546a433b4a4f66e3c483807c1159c9c543 (patch)
tree2bed00fba5974a92ef1e4ef3504060cc43acaa07 /sql/sql_prepare.cc
parentc425dcd8f23c4677bf71d03980753fe60b31f6a4 (diff)
parent7cc507f22e6eaec5ec83e24cd45275656bc7962f (diff)
downloadmariadb-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.cc61
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.