Commit fb17025b authored by sergefp@mysql.com's avatar sergefp@mysql.com

WL#1622 "SQL Syntax for Prepared Statements": Post-review fixes (1 of 2)

parent 3711c98b
......@@ -21,7 +21,7 @@ a b
2 two
3 three
deallocate prepare no_such_statement;
ERROR HY000: Undefined prepared statement
ERROR HY000: Unknown prepared statement handler (no_such_statement) given to DEALLOCATE PREPARE
execute stmt1;
ERROR HY000: Wrong arguments to mysql_execute
prepare stmt2 from 'prepare nested_stmt from "select 1"';
......@@ -98,4 +98,18 @@ set @arg00=NULL ;
prepare stmt1 from 'select 1 FROM t2 where a=?' ;
execute stmt1 using @arg00 ;
1
prepare stmt1 from @nosuchvar;
ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'NULL' at line 1
set @ivar= 1234;
prepare stmt1 from @ivar;
ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '1234' at line 1
set @fvar= 123.4567;
prepare stmt1 from @fvar;
ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '123.4567' at line 1
set @str1 = 'select ?';
set @str2 = convert(@str1 using ucs2);
prepare stmt1 from @str2;
execute stmt1 using @ivar;
?
1234
drop table t1,t2;
......@@ -98,5 +98,22 @@ set @arg00=NULL ;
prepare stmt1 from 'select 1 FROM t2 where a=?' ;
execute stmt1 using @arg00 ;
# prepare using variables:
--error 1064
prepare stmt1 from @nosuchvar;
set @ivar= 1234;
--error 1064
prepare stmt1 from @ivar;
set @fvar= 123.4567;
--error 1064
prepare stmt1 from @fvar;
set @str1 = 'select ?';
set @str2 = convert(@str1 using ucs2);
prepare stmt1 from @str2;
execute stmt1 using @ivar;
drop table t1,t2;
......@@ -33,6 +33,12 @@ char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE];
nr Errno
MyFlags Flags
... variable list
NOTE
The following subset of printf format is supported:
"%[0-9.-]*l?[sdu]", where all length flags are parsed but ignored.
Additionally "%.*s" is supported and "%.*[ud]" is correctly parsed but
length value is ignored.
*/
int my_error(int nr,myf MyFlags, ...)
......@@ -43,7 +49,10 @@ int my_error(int nr,myf MyFlags, ...)
reg2 char *endpos;
char * par;
char ebuff[ERRMSGSIZE+20];
int prec_chars;
my_bool prec_supplied;
DBUG_ENTER("my_error");
LINT_INIT(prec_chars); /* protected by prec_supplied */
va_start(ap,MyFlags);
DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d", nr, MyFlags, errno));
......@@ -59,7 +68,6 @@ int my_error(int nr,myf MyFlags, ...)
if (tpos[0] != '%')
{
*endpos++= *tpos++; /* Copy ordinary char */
olen++;
continue;
}
if (*++tpos == '%') /* test if %% */
......@@ -68,21 +76,48 @@ int my_error(int nr,myf MyFlags, ...)
}
else
{
/* Skipp if max size is used (to be compatible with printf) */
while (my_isdigit(&my_charset_latin1, *tpos) || *tpos == '.' || *tpos == '-')
tpos++;
if (*tpos == 'l') /* Skipp 'l' argument */
tpos++;
/*
Skip size/precision flags to be compatible with printf.
The only size/precision flag supported is "%.*s".
"%.*u" and "%.*d" cause
*/
prec_supplied= 0;
if (*tpos== '.')
{
tpos++;
olen--;
if (*tpos == '*')
{
tpos++;
olen--;
prec_chars= va_arg(ap, int); /* get length parameter */
prec_supplied= 1;
}
}
if (!prec_supplied)
{
while (my_isdigit(&my_charset_latin1, *tpos) || *tpos == '.' ||
*tpos == '-')
tpos++;
if (*tpos == 'l') /* Skipp 'l' argument */
tpos++;
}
if (*tpos == 's') /* String parameter */
{
par = va_arg(ap, char *);
plen = (uint) strlen(par);
if (prec_supplied && prec_chars > 0)
plen= min((uint)prec_chars, plen);
if (olen + plen < ERRMSGSIZE+2) /* Replace if possible */
{
endpos=strmov(endpos,par);
tpos++;
olen+=plen-2;
continue;
memcpy(endpos,par, plen);
endpos += plen;
tpos++;
olen+=plen-2;
continue;
}
}
else if (*tpos == 'd' || *tpos == 'u') /* Integer parameter */
......
......@@ -253,7 +253,7 @@ bool Item::get_time(TIME *ltime)
return 0;
}
CHARSET_INFO * Item::default_charset() const
CHARSET_INFO * Item::default_charset()
{
return current_thd->variables.collation_connection;
}
......@@ -678,11 +678,6 @@ void Item_param::set_value(const char *str, uint length, CHARSET_INFO *ci)
DBUG_VOID_RETURN;
}
void Item_param::set_value(const char *str, uint length)
{
set_value(str, length, default_charset());
}
void Item_param::set_time(TIME *tm, timestamp_type type)
{
......
......@@ -220,7 +220,7 @@ public:
virtual Item *real_item() { return this; }
virtual Item *get_tmp_table_item(THD *thd) { return copy_or_same(thd); }
CHARSET_INFO *default_charset() const;
static CHARSET_INFO *default_charset();
virtual CHARSET_INFO *compare_collation() { return NULL; }
virtual bool walk(Item_processor processor, byte *arg)
......@@ -413,7 +413,6 @@ public:
void set_null();
void set_int(longlong i);
void set_double(double i);
void set_value(const char *str, uint length);
void set_value(const char *str, uint length, CHARSET_INFO *ci);
void set_long_str(const char *str, ulong length);
void set_long_binary(const char *str, ulong length);
......
......@@ -4842,9 +4842,12 @@ struct show_var_st status_vars[]= {
{"Com_unlock_tables", (char*) (com_stat+(uint) SQLCOM_UNLOCK_TABLES),SHOW_LONG},
{"Com_update", (char*) (com_stat+(uint) SQLCOM_UPDATE),SHOW_LONG},
{"Com_update_multi", (char*) (com_stat+(uint) SQLCOM_UPDATE_MULTI),SHOW_LONG},
{"Com_prepare_sql", (char*) (com_stat+(uint) SQLCOM_PREPARE), SHOW_LONG},
{"Com_execute_sql", (char*) (com_stat+(uint) SQLCOM_EXECUTE), SHOW_LONG},
{"Com_dealloc_sql", (char*) (com_stat+(uint) SQLCOM_DEALLOCATE_PREPARE), SHOW_LONG},
{"Com_prepare_sql", (char*) (com_stat+(uint) SQLCOM_PREPARE),
SHOW_LONG},
{"Com_execute_sql", (char*) (com_stat+(uint) SQLCOM_EXECUTE),
SHOW_LONG},
{"Com_dealloc_sql", (char*) (com_stat+(uint)
SQLCOM_DEALLOCATE_PREPARE), SHOW_LONG},
{"Connections", (char*) &thread_id, SHOW_LONG_CONST},
{"Created_tmp_disk_tables", (char*) &created_tmp_disk_tables,SHOW_LONG},
{"Created_tmp_files", (char*) &my_tmp_file_created, SHOW_LONG},
......
......@@ -255,7 +255,7 @@ character-set=latin2
"Key reference and table reference doesn't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
"Unknown prepared statement handler (%ld) given to %s",
"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
......
......@@ -257,7 +257,7 @@ character-set=latin1
"Key reference and table reference doesn't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
"Unknown prepared statement handler (%ld) given to %s",
"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
......
......@@ -246,7 +246,7 @@ character-set=latin1
"Key reference and table reference doesn't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
"Unknown prepared statement handler (%ld) given to %s",
"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
......
......@@ -251,7 +251,7 @@ character-set=latin7
"Key reference and table reference doesn't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
"Unknown prepared statement handler (%ld) given to %s",
"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
......
......@@ -246,7 +246,7 @@ character-set=latin1
"Key reference and table reference doesn't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
"Unknown prepared statement handler (%ld) given to %s",
"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
......
......@@ -258,7 +258,7 @@ character-set=latin1
"Schlüssel- und Tabellenverweis passen nicht zusammen",
"Operand solle %d Spalte(n) enthalten",
"Unterabfrage lieferte mehr als einen Datensatz zurück",
"Unbekannter Prepared-Statement-Handler (%ld) für %s angegeben",
"Unbekannter Prepared-Statement-Handler (%.*s) für %s angegeben",
"Die Hilfe-Datenbank ist beschädigt oder existiert nicht",
"Zyklischer Verweis in Unterabfragen",
"Spalte '%s' wird von %s nach %s umgewandelt",
......
......@@ -246,7 +246,7 @@ character-set=greek
"Key reference and table reference doesn't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
"Unknown prepared statement handler (%ld) given to %s",
"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
......
......@@ -248,7 +248,7 @@ character-set=latin2
"Key reference and table reference doesn't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
"Unknown prepared statement handler (%ld) given to %s",
"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
......
......@@ -246,7 +246,7 @@ character-set=latin1
"Key reference and table reference doesn't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
"Unknown prepared statement handler (%ld) given to %s",
"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
......
......@@ -248,7 +248,7 @@ character-set=ujis
"Key reference and table reference doesn't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
"Unknown prepared statement handler (%ld) given to %s",
"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
......
......@@ -246,7 +246,7 @@ character-set=euckr
"Key reference and table reference doesn't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
"Unknown prepared statement handler (%ld) given to %s",
"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
......
......@@ -248,7 +248,7 @@ character-set=latin1
"Key reference and table reference doesn't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
"Unknown prepared statement handler (%ld) given to %s",
"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
......
......@@ -248,7 +248,7 @@ character-set=latin1
"Key reference and table reference doesn't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
"Unknown prepared statement handler (%ld) given to %s",
"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
......
......@@ -250,7 +250,7 @@ character-set=latin2
"Key reference and table reference doesn't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
"Unknown prepared statement handler (%ld) given to %s",
"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
......
......@@ -247,7 +247,7 @@ character-set=latin1
"Referência da chave e referência da tabela não coincidem",
"Operand should contain %d column(s)",
"Subconsulta retorna mais que 1 registro",
"Desconhecido manipulador de declaração preparado (%ld) determinado para %s",
"Desconhecido manipulador de declaração preparado (%.*s) determinado para %s",
"Banco de dado de ajuda corrupto ou não existente",
"Referência cíclica em subconsultas",
"Convertendo coluna '%s' de %s para %s",
......
......@@ -250,7 +250,7 @@ character-set=latin2
"Key reference and table reference doesn't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
"Unknown prepared statement handler (%ld) given to %s",
"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
......
......@@ -248,7 +248,7 @@ character-set=koi8r
"Key reference and table reference doesn't match",
" %d ",
" ",
"Unknown prepared statement handler (%ld) given to %s",
"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
" ",
" '%s' %s %s",
......
......@@ -254,7 +254,7 @@ character-set=latin2
"Key reference and table reference doesn't match",
"Operand should contain %d column(s)",
"Subquery returns more than 1 row",
"Unknown prepared statement handler (%ld) given to %s",
"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"Cyclic reference on subqueries",
"Converting column '%s' from %s to %s",
......
......@@ -248,7 +248,7 @@ character-set=latin1
"Referencia de llave y referencia de tabla no coinciden",
"Operando debe tener %d columna(s)",
"Subconsulta retorna mas que 1 línea",
"Desconocido preparado comando handler (%ld) dado para %s",
"Desconocido preparado comando handler (%.*s) dado para %s",
"Base de datos Help está corrupto o no existe",
"Cíclica referencia en subconsultas",
"Convirtiendo columna '%s' de %s para %s",
......
......@@ -246,7 +246,7 @@ character-set=latin1
"Nyckelreferensen och tabellreferensen stämmer inte överens",
"Operand should contain %d column(s)",
"Subquery returnerade mer än 1 rad",
"Okänd PREPARED STATEMENT id (%ld) var given till %s",
"Okänd PREPARED STATEMENT id (%.*s) var given till %s",
"Hjälpdatabasen finns inte eller är skadad",
"Cyklisk referens i subqueries",
"Konvertar kolumn '%s' från %s till %s",
......
......@@ -251,7 +251,7 @@ character-set=koi8u
"Key reference and table reference doesn't match",
" %d æ",
" ¦ i 1 ",
"Unknown prepared statement handler (%ld) given to %s",
"Unknown prepared statement handler (%.*s) given to %s",
"Help database is corrupt or does not exist",
"̦ Ц",
" '%s' %s %s",
......
......@@ -556,8 +556,13 @@ public:
Statement *find(ulong id)
{
if (last_found_statement == 0 || id != last_found_statement->id)
last_found_statement= (Statement *) hash_search(&st_hash, (byte *) &id,
sizeof(id));
{
Statement *stmt;
stmt= (Statement *) hash_search(&st_hash, (byte *) &id, sizeof(id));
if (stmt->name.str)
return NULL;
last_found_statement= stmt;
}
return last_found_statement;
}
void erase(Statement *statement)
......
......@@ -608,7 +608,13 @@ typedef struct st_lex
bool safe_to_cache_query;
/* Prepared statements SQL syntax:*/
LEX_STRING prepared_stmt_name; /* Statement name (in all queries) */
LEX_STRING prepared_stmt_code; /* Statement query (in PREPARE )*/
/*
Prepared statement query text or name of variable that holds the
prepared statement (in PREPARE ... queries)
*/
LEX_STRING prepared_stmt_code;
/* If true, prepared_stmt_code is a name of variable that holds the query */
bool prepared_stmt_code_is_varref;
/* Names of user variables holding parameters (in EXECUTE) */
List<LEX_STRING> prepared_stmt_params;
st_lex() {}
......
......@@ -1972,14 +1972,90 @@ mysql_execute_command(THD *thd)
}
case SQLCOM_PREPARE:
{
DBUG_PRINT("info", ("PREPARE: %.*s FROM '%.*s' \n",
lex->prepared_stmt_name.length,
lex->prepared_stmt_name.str,
lex->prepared_stmt_code.length,
lex->prepared_stmt_code.str));
char *query_str;
uint query_len;
if (lex->prepared_stmt_code_is_varref)
{
/* This is PREPARE stmt FROM @var*/
String str;
CHARSET_INFO *to_cs= thd->variables.collation_connection;
CHARSET_INFO *from_cs;
const char *buf;
uint buf_len;
bool need_conversion;
//// psergey: find the variable and convert it.
LINT_INIT(from_cs);
user_var_entry *entry;
uint32 unused;
if ((entry=
(user_var_entry*)hash_search(&thd->user_vars,
(byte*)lex->prepared_stmt_code.str,
lex->prepared_stmt_code.length))
&& entry->value)
{
switch (entry->type)
{
case REAL_RESULT:
str.set(*(double*)entry->value, NOT_FIXED_DEC, to_cs);
buf_len= str.length();
buf= str.ptr();
need_conversion= false;
break;
case INT_RESULT:
str.set(*(longlong*)entry->value, to_cs);
buf_len= str.length();
buf= str.ptr();
need_conversion= false;
break;
case STRING_RESULT:
buf_len= entry->length;
buf= entry->value;
from_cs = entry->collation.collation;
need_conversion= String::needs_conversion(entry->length, from_cs,
to_cs, &unused);
break;
default:
buf= "";
need_conversion= false;
buf_len= 0;
DBUG_ASSERT(0);
}
}
else
{
from_cs= &my_charset_bin;
str.set("NULL", 4, from_cs);
buf= str.ptr();
buf_len= str.length();
need_conversion= String::needs_conversion(str.length(), from_cs,
to_cs, &unused);
}
query_len = need_conversion? (buf_len* to_cs->mbmaxlen) : buf_len;
if (!(query_str= alloc_root(&thd->mem_root, query_len+1)))
{
send_error(thd, ER_OUT_OF_RESOURCES);
}
if (need_conversion)
query_len= copy_and_convert(query_str, query_len, to_cs, buf, buf_len,
from_cs);
else
memcpy(query_str, buf, query_len);
query_str[query_len] = 0;
}
else
{
DBUG_PRINT("info", ("PREPARE: %.*s FROM '%.*s' \n",
lex->prepared_stmt_name.length,
lex->prepared_stmt_name.str,
lex->prepared_stmt_code.length,
lex->prepared_stmt_code.str));
query_str= lex->prepared_stmt_code.str;
query_len= lex->prepared_stmt_code.length + 1;
}
thd->command= COM_PREPARE;
if (!mysql_stmt_prepare(thd, lex->prepared_stmt_code.str,
lex->prepared_stmt_code.length + 1,
if (!mysql_stmt_prepare(thd, query_str, query_len + 1,
&lex->prepared_stmt_name))
send_ok(thd, 0L, 0L, "Statement prepared");
break;
......@@ -2005,7 +2081,12 @@ mysql_execute_command(THD *thd)
send_ok(thd);
}
else
send_error(thd,ER_UNKNOWN_STMT_HANDLER,"Undefined prepared statement");
{
res= -1;
my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0),
lex->prepared_stmt_name.length, lex->prepared_stmt_name.str,
"DEALLOCATE PREPARE");
}
break;
}
case SQLCOM_DO:
......@@ -3438,7 +3519,7 @@ error:
*/
int check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *tables)
{
if (check_access(thd, privilege, tables->db, &tables->grant.privilege,0,0))
return 1;
......
......@@ -135,7 +135,8 @@ find_prepared_statement(THD *thd, ulong id, const char *where,
if (stmt == 0 || stmt->type() != Statement::PREPARED_STATEMENT)
{
my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), id, where);
char llbuf[22];
my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), 22, llstr(id, llbuf), where);
if (se == SEND_ERROR)
send_error(thd);
return 0;
......@@ -392,7 +393,7 @@ void set_param_date(Item_param *param, uchar **pos, ulong len)
void set_param_str(Item_param *param, uchar **pos, ulong len)
{
ulong length= get_param_length(pos, len);
param->set_value((const char *)*pos, length);
param->set_value((const char *)*pos, length, Item::default_charset());
*pos+= length;
}
......@@ -1376,7 +1377,7 @@ static int send_prepare_results(Prepared_statement *stmt, bool text_protocol)
goto error;
}
if (res == 0)
DBUG_RETURN(text_protocol?0:send_prep_stmt(stmt, 0));
DBUG_RETURN(text_protocol? 0 : send_prep_stmt(stmt, 0));
error:
if (res < 0)
send_error(thd, thd->killed ? ER_SERVER_SHUTDOWN : 0);
......@@ -1417,25 +1418,31 @@ static bool init_param_array(Prepared_statement *stmt)
/*
Given a query string with parameter markers, create a Prepared Statement
from it and send PS info back to the client.
SYNOPSIS
mysql_stmt_prepare()
packet Prepared query
packet_length query length, with ignored trailing NULL or quote char.
packet query to be prepared
packet_length query string length, including ignored trailing NULL or
quote char.
name NULL or statement name. For unnamed statements binary PS
protocol is used, for named statmenents text protocol is
protocol is used, for named statements text protocol is
used.
Parse the query and send the total number of parameters
and resultset metadata information back to client (if any),
without executing the query i.e. without any log/disk
writes. This will allow the queries to be re-executed
without re-parsing during execute.
If parameter markers are found in the query, then store
the information using Item_param along with maintaining a
list in lex->param_array, so that a fast and direct
retrieval can be made without going through all field
items.
RETURN
0 OK, statement prepared successfully
other Error
NOTES
This function parses the query and sends the total number of parameters
and resultset metadata information back to client (if any), without
executing the query i.e. without any log/disk writes. This allows the
queries to be re-executed without re-parsing during execute.
If parameter markers are found in the query, then store the information
using Item_param along with maintaining a list in lex->param_array, so
that a fast and direct retrieval can be made without going through all
field items.
*/
......@@ -1672,13 +1679,14 @@ set_params_data_err:
void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name)
{
Prepared_statement *stmt;
DBUG_ENTER("mysql_stmt_execute");
DBUG_ENTER("mysql_sql_stmt_execute");
if (!(stmt= (Prepared_statement*)thd->stmt_map.find_by_name(stmt_name)))
{
send_error(thd, ER_UNKNOWN_STMT_HANDLER,
"Undefined prepared statement");
DBUG_VOID_RETURN;
my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), stmt_name->length,
stmt_name->str, "EXECUTE");
send_error(thd);
DBUG_VOID_RETURN;
}
if (stmt->param_count != thd->lex->prepared_stmt_params.elements)
......
......@@ -726,7 +726,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
precision subselect_start opt_and charset
subselect_end select_var_list select_var_list_init help opt_len
opt_extended_describe
prepare execute deallocate
prepare prepare_src execute deallocate
END_OF_INPUT
%type <NONE>
......@@ -816,7 +816,7 @@ deallocate:
};
prepare:
PREPARE_SYM ident FROM TEXT_STRING_sys
PREPARE_SYM ident FROM prepare_src
{
THD *thd=YYTHD;
LEX *lex= thd->lex;
......@@ -827,9 +827,24 @@ prepare:
}
lex->sql_command= SQLCOM_PREPARE;
lex->prepared_stmt_name= $2;
lex->prepared_stmt_code= $4;
};
prepare_src:
TEXT_STRING_sys
{
THD *thd=YYTHD;
LEX *lex= thd->lex;
lex->prepared_stmt_code= $1;
lex->prepared_stmt_code_is_varref= false;
}
| '@' ident_or_text
{
THD *thd=YYTHD;
LEX *lex= thd->lex;
lex->prepared_stmt_code= $2;
lex->prepared_stmt_code_is_varref= true;
};
execute:
EXECUTE_SYM ident
{
......
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