summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <sergefp@mysql.com>2004-05-21 04:27:50 +0400
committerunknown <sergefp@mysql.com>2004-05-21 04:27:50 +0400
commite7710af7f4c41e77355f5599aafb04999b358292 (patch)
treea744f3804c5f4a55fabbc3344ef1ec8b1c9e3b52
parent201412da7571f5078dae6cdb2067f64a3de5bef8 (diff)
downloadmariadb-git-e7710af7f4c41e77355f5599aafb04999b358292.tar.gz
WL#1622 "SQL Syntax for Prepared Statements": Post-review fixes (1 of 2)
mysql-test/r/ps.result: Added tests for PREPARE stmt1 FROM @var syntax mysql-test/t/ps.test: Added tests for PREPARE stmt1 FROM @var syntax mysys/my_error.c: Added support for "%.*s" format sql/item.cc: Removed one redundant Item_param::set_value function sql/item.h: Removed one redundant Item_param::set_value function sql/mysqld.cc: Reformmated the code sql/share/czech/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/dutch/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/english/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/estonian/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/french/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/german/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/greek/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/hungarian/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/italian/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/japanese/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/korean/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/norwegian-ny/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/norwegian/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/polish/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/portuguese/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/romanian/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/russian/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/slovak/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/spanish/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/swedish/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/share/ukrainian/errmsg.txt: Changed ER_UNKNOWN_STMT_HANDLER format string sql/sql_class.h: SQL Prepared statements now can't be used by binary protocol commands sql/sql_lex.h: Added support for PREPARE stmt1 FROM @var syntax. sql/sql_parse.cc: Added support for PREPARE stmt1 FROM @var syntax. sql/sql_prepare.cc: Code cleanup sql/sql_yacc.yy: Added support for PREPARE stmt1 FROM @var syntax.
-rw-r--r--mysql-test/r/ps.result16
-rw-r--r--mysql-test/t/ps.test17
-rw-r--r--mysys/my_error.c55
-rw-r--r--sql/item.cc7
-rw-r--r--sql/item.h3
-rw-r--r--sql/mysqld.cc9
-rw-r--r--sql/share/czech/errmsg.txt2
-rw-r--r--sql/share/dutch/errmsg.txt2
-rw-r--r--sql/share/english/errmsg.txt2
-rw-r--r--sql/share/estonian/errmsg.txt2
-rw-r--r--sql/share/french/errmsg.txt2
-rw-r--r--sql/share/german/errmsg.txt2
-rw-r--r--sql/share/greek/errmsg.txt2
-rw-r--r--sql/share/hungarian/errmsg.txt2
-rw-r--r--sql/share/italian/errmsg.txt2
-rw-r--r--sql/share/japanese/errmsg.txt2
-rw-r--r--sql/share/korean/errmsg.txt2
-rw-r--r--sql/share/norwegian-ny/errmsg.txt2
-rw-r--r--sql/share/norwegian/errmsg.txt2
-rw-r--r--sql/share/polish/errmsg.txt2
-rw-r--r--sql/share/portuguese/errmsg.txt2
-rw-r--r--sql/share/romanian/errmsg.txt2
-rw-r--r--sql/share/russian/errmsg.txt2
-rw-r--r--sql/share/slovak/errmsg.txt2
-rw-r--r--sql/share/spanish/errmsg.txt2
-rw-r--r--sql/share/swedish/errmsg.txt2
-rw-r--r--sql/share/ukrainian/errmsg.txt2
-rw-r--r--sql/sql_class.h9
-rw-r--r--sql/sql_lex.h8
-rw-r--r--sql/sql_parse.cc99
-rw-r--r--sql/sql_prepare.cc52
-rw-r--r--sql/sql_yacc.yy21
32 files changed, 258 insertions, 80 deletions
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index fc82645840c..6c228327b8d 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -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;
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
index 989dc6026fe..d9e0f0852c5 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -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;
diff --git a/mysys/my_error.c b/mysys/my_error.c
index 6fd346c89f7..7ca7dbae8de 100644
--- a/mysys/my_error.c
+++ b/mysys/my_error.c
@@ -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 */
diff --git a/sql/item.cc b/sql/item.cc
index b6b99a9f717..8557820474d 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -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)
{
diff --git a/sql/item.h b/sql/item.h
index 471d502a6e1..062e1da990d 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -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);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index e810393af60..aa266861dd7 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -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},
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index f3a0c5e0eec..f554a1171d3 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -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",
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index 9d9dfb14a89..0db72a4fb22 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -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",
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index 14a854fbafb..592c44dc3f4 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -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",
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index 5d0f34fd4b2..caa0d8f039e 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -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",
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index adc9f66e96b..fb4a2f0f5b1 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -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",
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index 0b732ba48f8..6d484c36116 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -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",
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index f96c10b0e65..4bea8b2dfc6 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -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",
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index a26790a4ef9..f7552d6fa15 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -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",
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 7c519e4e4bf..0a81a534fbc 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -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",
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index f973f84d2a4..ce58d87871b 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -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",
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index 8b5d318ab19..6f3de30c6a5 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -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",
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index c0a7d736e1f..1ce737955af 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -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",
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index fc9b5d2f6da..bb7afd5a8f4 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -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",
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index 36b7d67d134..b4ff175822a 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -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",
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index d4ffa2d5ef5..907ca6fc80c 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -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",
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index 4918a6e1a10..cefd2074bf2 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -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",
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index dbc93306a38..f8bf9ea10b2 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -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",
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index 80d21f8e31f..16f9b0a8f35 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -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",
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index 512f06c8c50..9ae998184e5 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -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",
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index 22e7cb786b5..aed3e9d3d34 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -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",
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index 3149d58b413..c0ccd76f157 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -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",
diff --git a/sql/sql_class.h b/sql/sql_class.h
index f208a3f4d73..b5774688e1e 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -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)
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index a525bc485c1..9bea0de7b39 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -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() {}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 65d538e3ac4..cd8891ad326 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -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;
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 1612432cd67..af489d20783 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -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)
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 6a683a26b01..bb226f76b2c 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -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
{