summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <sergefp@mysql.com>2004-05-24 21:08:22 +0400
committerunknown <sergefp@mysql.com>2004-05-24 21:08:22 +0400
commitc0729cbbca7632177a341cdd40e7e062af1a57a7 (patch)
tree56dc4248df889c1f513b4a0bc15f8cea4257ab1a
parentfc68be78eb830df4bf8afe0096f0e5bf08fcd47f (diff)
downloadmariadb-git-c0729cbbca7632177a341cdd40e7e062af1a57a7.tar.gz
Added support for PREPARE stmt1 FROM @var,
Fixed the problem of previous patch with replication, More post-review fixes sql/sql_parse.cc: Added support for PREPARE stmt1 FROM @var sql/sql_prepare.cc: Added support for PREPARE stmt1 FROM @var, Fixed the problem of previous patch with replication Post-review fixes.
-rw-r--r--sql/sql_parse.cc27
-rw-r--r--sql/sql_prepare.cc108
2 files changed, 83 insertions, 52 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 013cac12e9b..1d5012a97a0 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1978,17 +1978,21 @@ mysql_execute_command(THD *thd)
uint query_len;
if (lex->prepared_stmt_code_is_varref)
{
- /* This is PREPARE stmt FROM @var*/
+ /* 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);
+ LINT_INIT(from_cs); /* protected by need_conversion */
user_var_entry *entry;
uint32 unused;
+ /*
+ Convert @var contents to string in connection character set. Although
+ it is known that int/real/NULL value cannot be a valid query we still
+ convert it for error messages to uniform.
+ */
if ((entry=
(user_var_entry*)hash_search(&thd->user_vars,
(byte*)lex->prepared_stmt_code.str,
@@ -2033,32 +2037,29 @@ mysql_execute_command(THD *thd)
to_cs, &unused);
}
- query_len = need_conversion? (buf_len* to_cs->mbmaxlen) : buf_len;
+ 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;
+ query_str[query_len]= 0;
}
else
{
+ query_str= lex->prepared_stmt_code.str;
+ query_len= lex->prepared_stmt_code.length;
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;
+ query_len, query_str));
}
thd->command= COM_PREPARE;
- if (!mysql_stmt_prepare(thd, query_str, query_len + 1,
- &lex->prepared_stmt_name))
+ if (!mysql_stmt_prepare(thd, query_str, query_len + 1,
+ &lex->prepared_stmt_name))
send_ok(thd, 0L, 0L, "Statement prepared");
break;
}
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 39add455b45..32e70f24c9f 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -94,19 +94,21 @@ public:
bool log_full_query;
#ifndef EMBEDDED_LIBRARY
bool (*set_params)(Prepared_statement *st, uchar *data, uchar *data_end,
- uchar *read_pos);
+ uchar *read_pos, String *expanded_query);
#else
- bool (*set_params_data)(Prepared_statement *st);
+ bool (*set_params_data)(Prepared_statement *st, String *expanded_query);
#endif
bool (*set_params_from_vars)(Prepared_statement *stmt,
- List<LEX_STRING>& varnames);
+ List<LEX_STRING>& varnames,
+ String *expanded_query);
public:
Prepared_statement(THD *thd_arg);
virtual ~Prepared_statement();
virtual Statement::Type type() const;
};
-static void execute_stmt(THD *thd, Prepared_statement *stmt);
+static void execute_stmt(THD *thd, Prepared_statement *stmt,
+ String *expanded_query);
/******************************************************************************
Implementation
@@ -517,19 +519,20 @@ static void setup_one_conversion_function(Item_param *param, uchar param_type)
*/
static bool insert_params_withlog(Prepared_statement *stmt, uchar *null_array,
- uchar *read_pos, uchar *data_end)
+ uchar *read_pos, uchar *data_end,
+ String *query)
{
THD *thd= stmt->thd;
Item_param **begin= stmt->param_array;
Item_param **end= begin + stmt->param_count;
uint32 length= 0;
- String str, query;
+ String str;
const String *res;
DBUG_ENTER("insert_params_withlog");
- if (query.copy(stmt->query, stmt->query_length, default_charset_info))
+ if (query->copy(stmt->query, stmt->query_length, default_charset_info))
DBUG_RETURN(1);
for (Item_param **it= begin; it < end; ++it)
@@ -552,20 +555,18 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *null_array,
res= param->query_val_str(&str);
}
}
- if (query.replace(param->pos_in_query+length, 1, *res))
+ if (query->replace(param->pos_in_query+length, 1, *res))
DBUG_RETURN(1);
length+= res->length()-1;
}
- if (alloc_query(thd, (char *)query.ptr(), query.length()+1))
- DBUG_RETURN(1);
-
DBUG_RETURN(0);
}
static bool insert_params(Prepared_statement *stmt, uchar *null_array,
- uchar *read_pos, uchar *data_end)
+ uchar *read_pos, uchar *data_end,
+ String *expanded_query)
{
Item_param **begin= stmt->param_array;
Item_param **end= begin + stmt->param_count;
@@ -627,7 +628,7 @@ static bool setup_conversion_functions(Prepared_statement *stmt,
#else
-static bool emb_insert_params(Prepared_statement *stmt)
+static bool emb_insert_params(Prepared_statement *stmt, String *expanded_query)
{
Item_param **it= stmt->param_array;
Item_param **end= it + stmt->param_count;
@@ -658,20 +659,20 @@ static bool emb_insert_params(Prepared_statement *stmt)
}
-static bool emb_insert_params_withlog(Prepared_statement *stmt)
+static bool emb_insert_params_withlog(Prepared_statement *stmt, String *query)
{
THD *thd= stmt->thd;
Item_param **it= stmt->param_array;
Item_param **end= it + stmt->param_count;
MYSQL_BIND *client_param= thd->client_params;
- String str, query;
+ String str;
const String *res;
uint32 length= 0;
DBUG_ENTER("emb_insert_params_withlog");
- if (query.copy(stmt->query, stmt->query_length, default_charset_info))
+ if (query->copy(stmt->query, stmt->query_length, default_charset_info))
DBUG_RETURN(1);
for (; it < end; ++it, ++client_param)
@@ -697,14 +698,10 @@ static bool emb_insert_params_withlog(Prepared_statement *stmt)
res= param->query_val_str(&str);
}
}
- if (query.replace(param->pos_in_query+length, 1, *res))
+ if (query->replace(param->pos_in_query+length, 1, *res))
DBUG_RETURN(1);
length+= res->length()-1;
}
-
- if (alloc_query(thd, (char *) query.ptr(), query.length()+1))
- DBUG_RETURN(1);
-
DBUG_RETURN(0);
}
@@ -718,11 +715,12 @@ static bool emb_insert_params_withlog(Prepared_statement *stmt)
stmt Statement
varnames List of variables. Caller must ensure that number of variables
in the list is equal to number of statement parameters
-
+ query Ignored
*/
static bool insert_params_from_vars(Prepared_statement *stmt,
- List<LEX_STRING>& varnames)
+ List<LEX_STRING>& varnames,
+ String *query __attribute__((unused)))
{
Item_param **begin= stmt->param_array;
Item_param **end= begin + stmt->param_count;
@@ -763,8 +761,21 @@ static bool insert_params_from_vars(Prepared_statement *stmt,
DBUG_RETURN(0);
}
+
+/*
+ Do the same as insert_params_from_vars but also construct query text for
+ binary log.
+ SYNOPSIS
+ insert_params_from_vars()
+ stmt Statement
+ varnames List of variables. Caller must ensure that number of variables
+ in the list is equal to number of statement parameters
+ query The query with parameter markers replaced with their values
+*/
+
static bool insert_params_from_vars_with_log(Prepared_statement *stmt,
- List<LEX_STRING>& varnames)
+ List<LEX_STRING>& varnames,
+ String *query)
{
Item_param **begin= stmt->param_array;
Item_param **end= begin + stmt->param_count;
@@ -773,10 +784,10 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt,
DBUG_ENTER("insert_params_from_vars");
List_iterator<LEX_STRING> var_it(varnames);
- String str, query;
+ String str;
const String *res;
uint32 length= 0;
- if (query.copy(stmt->query, stmt->query_length, default_charset_info))
+ if (query->copy(stmt->query, stmt->query_length, default_charset_info))
DBUG_RETURN(1);
for (Item_param **it= begin; it < end; ++it)
@@ -812,12 +823,10 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt,
res= &my_null_string;
}
- if (query.replace(param->pos_in_query+length, 1, *res))
+ if (query->replace(param->pos_in_query+length, 1, *res))
DBUG_RETURN(1);
length+= res->length()-1;
}
- if (alloc_query(stmt->thd, (char *) query.ptr(), query.length()+1))
- DBUG_RETURN(1);
DBUG_RETURN(0);
}
@@ -1708,13 +1717,14 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
DBUG_VOID_RETURN;
}
-
+ String expanded_query;
#ifndef EMBEDDED_LIBRARY
if (stmt->param_count)
{
uchar *null_array= (uchar *) packet;
if (setup_conversion_functions(stmt, (uchar **) &packet, packet_end) ||
- stmt->set_params(stmt, null_array, (uchar *) packet, packet_end))
+ stmt->set_params(stmt, null_array, (uchar *) packet, packet_end,
+ &expanded_query))
goto set_params_data_err;
}
#else
@@ -1727,7 +1737,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
goto set_params_data_err;
#endif
thd->protocol= &thd->protocol_prep; // Switch to binary protocol
- execute_stmt(thd, stmt);
+ execute_stmt(thd, stmt, &expanded_query);
thd->protocol= &thd->protocol_simple; // Use normal protocol
DBUG_VOID_RETURN;
@@ -1747,6 +1757,7 @@ set_params_data_err:
void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name)
{
Prepared_statement *stmt;
+ String expanded_query;
DBUG_ENTER("mysql_sql_stmt_execute");
if (!(stmt= (Prepared_statement*)thd->stmt_map.find_by_name(stmt_name)))
@@ -1766,27 +1777,47 @@ void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name)
/* Item_param allows setting parameters in COM_EXECUTE only */
thd->command= COM_EXECUTE;
- if (stmt->set_params_from_vars(stmt, thd->lex->prepared_stmt_params))
+ if (stmt->set_params_from_vars(stmt, thd->lex->prepared_stmt_params,
+ &expanded_query))
{
my_error(ER_WRONG_ARGUMENTS, MYF(0), "mysql_execute");
send_error(thd);
}
- execute_stmt(thd, stmt);
+ execute_stmt(thd, stmt, &expanded_query);
DBUG_VOID_RETURN;
}
+
/*
Execute prepared statement.
+ SYNOPSIS
+ execute_stmt()
+ thd Current thread
+ stmt Statement to execute
+ expanded_query If binary log is enabled, query string with parameter
+ placeholders replaced with actual values. Otherwise empty
+ string.
+ NOTES
Caller must set parameter values and thd::protocol.
thd->free_list is assumed to be garbage.
*/
-static void execute_stmt(THD *thd, Prepared_statement *stmt)
+
+static void execute_stmt(THD *thd, Prepared_statement *stmt,
+ String *expanded_query)
{
DBUG_ENTER("execute_stmt");
thd->free_list= NULL;
thd->stmt_backup.set_statement(thd);
thd->set_statement(stmt);
reset_stmt_for_execute(stmt);
+
+ if (expanded_query->length() &&
+ alloc_query(thd, (char *)expanded_query->ptr(),
+ expanded_query->length()+1))
+ {
+ my_error(ER_OUTOFMEMORY, 0, expanded_query->length());
+ DBUG_VOID_RETURN;
+ }
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(),QUERY_PRIOR);
@@ -1808,13 +1839,12 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt)
}
-
/*
- Reset a prepared statement in case there was a recoverable error.
+ Reset a prepared statement in case there was a recoverable error.
SYNOPSIS
mysql_stmt_reset()
- thd Thread handle
- packet Packet with stmt id
+ thd Thread handle
+ packet Packet with stmt id
DESCRIPTION
This function resets statement to the state it was right after prepare.