Commit ec527fac authored by Alexander Barkov's avatar Alexander Barkov

MDEV-10801 sql_mode: dynamic SQL placeholders

parent f564ceb4
SET sql_mode=ORACLE;
#
# MDEV-10801 sql_mode: dynamic SQL placeholders
#
CREATE TABLE t1 (a INT, b INT);
SET @a=10, @b=20;
PREPARE stmt FROM 'INSERT INTO t1 VALUES (?,?)';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'INSERT INTO t1 VALUES (:a,:b)';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'INSERT INTO t1 VALUES (:aaa,:bbb)';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'INSERT INTO t1 VALUES (:"a",:"b")';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'INSERT INTO t1 VALUES (:"aaa",:"bbb")';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'INSERT INTO t1 VALUES (:1,:2)';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'INSERT INTO t1 VALUES (:222,:111)';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'INSERT INTO t1 VALUES (:0,:65535)';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'INSERT INTO t1 VALUES (:65535,:0)';
EXECUTE stmt USING @a, @b;
SELECT * FROM t1;
a b
10 20
10 20
10 20
10 20
10 20
10 20
10 20
10 20
10 20
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b INT)
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10,20)
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10,20)
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10,20)
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10,20)
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10,20)
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10,20)
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10,20)
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10,20)
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10,20)
master-bin.000001 # Query # # COMMIT
DROP TABLE t1;
SET sql_mode=ORACLE;
#
# MDEV-10801 sql_mode: dynamic SQL placeholders
#
SET @a=10, @b=20;
PREPARE stmt FROM 'SELECT ?,?';
EXECUTE stmt USING @a, @b;
? ?
10 20
PREPARE stmt FROM 'SELECT :a,:b';
EXECUTE stmt USING @a, @b;
:a :b
10 20
PREPARE stmt FROM 'SELECT :aaa,:bbb';
EXECUTE stmt USING @a, @b;
:aaa :bbb
10 20
PREPARE stmt FROM 'SELECT :"a",:"b"';
EXECUTE stmt USING @a, @b;
:"a" :"b"
10 20
PREPARE stmt FROM 'SELECT :"aaa",:"bbb"';
EXECUTE stmt USING @a, @b;
:"aaa" :"bbb"
10 20
PREPARE stmt FROM 'SELECT :1,:2';
EXECUTE stmt USING @a, @b;
:1 :2
10 20
PREPARE stmt FROM 'SELECT :222,:111';
EXECUTE stmt USING @a, @b;
:222 :111
10 20
PREPARE stmt FROM 'SELECT :0,:65535';
EXECUTE stmt USING @a, @b;
:0 :65535
10 20
PREPARE stmt FROM 'SELECT :65535,:0';
EXECUTE stmt USING @a, @b;
:65535 :0
10 20
--source include/not_embedded.inc
--source include/have_binlog_format_statement.inc
--disable_query_log
reset master; # get rid of previous tests binlog
--enable_query_log
SET sql_mode=ORACLE;
--echo #
--echo # MDEV-10801 sql_mode: dynamic SQL placeholders
--echo #
CREATE TABLE t1 (a INT, b INT);
SET @a=10, @b=20;
PREPARE stmt FROM 'INSERT INTO t1 VALUES (?,?)';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'INSERT INTO t1 VALUES (:a,:b)';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'INSERT INTO t1 VALUES (:aaa,:bbb)';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'INSERT INTO t1 VALUES (:"a",:"b")';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'INSERT INTO t1 VALUES (:"aaa",:"bbb")';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'INSERT INTO t1 VALUES (:1,:2)';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'INSERT INTO t1 VALUES (:222,:111)';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'INSERT INTO t1 VALUES (:0,:65535)';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'INSERT INTO t1 VALUES (:65535,:0)';
EXECUTE stmt USING @a, @b;
SELECT * FROM t1;
--let $binlog_file = LAST
source include/show_binlog_events.inc;
DROP TABLE t1;
SET sql_mode=ORACLE;
--echo #
--echo # MDEV-10801 sql_mode: dynamic SQL placeholders
--echo #
SET @a=10, @b=20;
PREPARE stmt FROM 'SELECT ?,?';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'SELECT :a,:b';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'SELECT :aaa,:bbb';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'SELECT :"a",:"b"';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'SELECT :"aaa",:"bbb"';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'SELECT :1,:2';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'SELECT :222,:111';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'SELECT :0,:65535';
EXECUTE stmt USING @a, @b;
PREPARE stmt FROM 'SELECT :65535,:0';
EXECUTE stmt USING @a, @b;
......@@ -3341,9 +3341,10 @@ default_set_param_func(Item_param *param,
}
Item_param::Item_param(THD *thd, uint pos_in_query_arg):
Item_param::Item_param(THD *thd, char *name_arg,
uint pos_in_query_arg, uint len_in_query_arg):
Item_basic_value(thd),
Rewritable_query_parameter(pos_in_query_arg, 1),
Rewritable_query_parameter(pos_in_query_arg, len_in_query_arg),
Type_handler_hybrid_field_type(MYSQL_TYPE_VARCHAR),
state(NO_VALUE),
/* Don't pretend to be a literal unless value for this item is set. */
......@@ -3360,7 +3361,7 @@ Item_param::Item_param(THD *thd, uint pos_in_query_arg):
*/
m_is_settable_routine_parameter(true)
{
name= (char*) "?";
name= name_arg;
/*
Since we can't say whenever this item can be NULL or cannot be NULL
before mysql_stmt_execute(), so we assuming that it can be NULL until
......
......@@ -2813,7 +2813,8 @@ class Item_param :public Item_basic_value,
enum Item_result cmp_type () const
{ return Type_handler_hybrid_field_type::cmp_type(); }
Item_param(THD *thd, uint pos_in_query_arg);
Item_param(THD *thd, char *name_arg,
uint pos_in_query_arg, uint len_in_query_arg);
enum Type type() const
{
......
......@@ -5876,6 +5876,33 @@ Item *LEX::create_and_link_Item_trigger_field(THD *thd, const char *name,
}
Item_param *LEX::add_placeholder(THD *thd, char *name,
uint pos_in_query, uint len_in_query)
{
if (!parsing_options.allows_variable)
{
my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
return NULL;
}
Item_param *item= new (thd->mem_root) Item_param(thd, name,
pos_in_query, len_in_query);
if (!item || param_list.push_back(item, thd->mem_root))
{
my_error(ER_OUT_OF_RESOURCES, MYF(0));
return NULL;
}
return item;
}
Item_param *LEX::add_placeholder(THD *thd, char *name,
const char *pos, const char *end)
{
const char *query_start= sphead ? sphead->m_tmp_query : thd->query();
return add_placeholder(thd, name, pos - query_start, end - pos);
}
#ifdef MYSQL_SERVER
uint binlog_unsafe_map[256];
......
......@@ -3182,6 +3182,11 @@ struct LEX: public Query_tables_list
bool sp_while_loop_expression(THD *thd, Item *expr);
bool sp_while_loop_finalize(THD *thd);
Item_param *add_placeholder(THD *thd, char *name,
uint pos_in_query, uint len_in_query);
Item_param *add_placeholder(THD *thd, char *name,
const char *pos, const char *end);
sp_variable *sp_add_for_loop_variable(THD *thd, const LEX_STRING name,
Item *value);
sp_variable *sp_add_for_loop_upper_bound(THD *thd, Item *value)
......
......@@ -13464,17 +13464,10 @@ hex_or_bin_String:
param_marker:
PARAM_MARKER
{
LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP;
Item_param *item;
if (! lex->parsing_options.allows_variable)
my_yyabort_error((ER_VIEW_SELECT_VARIABLE, MYF(0)));
const char *query_start= lex->sphead ? lex->sphead->m_tmp_query
: thd->query();
item= new (thd->mem_root) Item_param(thd, lip->get_tok_start() -
query_start);
if (!($$= item) || lex->param_list.push_back(item, thd->mem_root))
my_yyabort_error((ER_OUT_OF_RESOURCES, MYF(0)));
if (!($$= Lex->add_placeholder(thd, (char *) "?",
YYLIP->get_tok_start(),
YYLIP->get_tok_start() + 1)))
MYSQL_YYABORT;
}
;
......
......@@ -1006,6 +1006,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
remember_name remember_end opt_db remember_tok_start
wild_and_where
field_length opt_field_length opt_field_length_default_1
colon_with_pos
%type <const_simple_string>
opt_place
......@@ -8074,6 +8075,13 @@ select_item:
}
;
colon_with_pos:
':'
{
$$= (char *) YYLIP->get_tok_start();
}
;
remember_tok_start:
{
$$= (char*) YYLIP->get_tok_start();
......@@ -13142,17 +13150,22 @@ hex_or_bin_String:
param_marker:
PARAM_MARKER
{
LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP;
Item_param *item;
if (! lex->parsing_options.allows_variable)
my_yyabort_error((ER_VIEW_SELECT_VARIABLE, MYF(0)));
const char *query_start= lex->sphead ? lex->sphead->m_tmp_query
: thd->query();
item= new (thd->mem_root) Item_param(thd, lip->get_tok_start() -
query_start);
if (!($$= item) || lex->param_list.push_back(item, thd->mem_root))
my_yyabort_error((ER_OUT_OF_RESOURCES, MYF(0)));
if (!($$= Lex->add_placeholder(thd, (char *) "?",
YYLIP->get_tok_start(),
YYLIP->get_tok_start() + 1)))
MYSQL_YYABORT;
}
| colon_with_pos ident
{
if (!($$= Lex->add_placeholder(thd, NULL,
$1, YYLIP->get_tok_end())))
MYSQL_YYABORT;
}
| colon_with_pos NUM
{
if (!($$= Lex->add_placeholder(thd, NULL,
$1, YYLIP->get_ptr())))
MYSQL_YYABORT;
}
;
......@@ -13538,7 +13551,7 @@ simple_ident_q:
MYSQL_YYABORT;
}
}
| ':' ident '.' ident
| colon_with_pos ident '.' ident
{
LEX *lex= Lex;
if (lex->is_trigger_new_or_old_reference($2))
......@@ -14691,7 +14704,7 @@ internal_variable_name_directly_assignable:
if (Lex->init_default_internal_variable(&$$, $3))
MYSQL_YYABORT;
}
| ':' ident_directly_assignable '.' ident
| colon_with_pos ident_directly_assignable '.' ident
{
if (!Lex->is_trigger_new_or_old_reference($2))
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment