summaryrefslogtreecommitdiff
path: root/sql/sql_prepare.cc
diff options
context:
space:
mode:
authorSergey Petrunya <psergey@askmonty.org>2010-10-10 17:18:11 +0300
committerSergey Petrunya <psergey@askmonty.org>2010-10-10 17:18:11 +0300
commit72dd7575cd8b9372ddb79cc4c94050e4ee1e5ee1 (patch)
tree220c965bb467b020a4db171d7803586f9ed22cea /sql/sql_prepare.cc
parentcfbd9270243e4b429cdc26e8554bcc99690f2422 (diff)
parent00a2f36bbf22a4d8b2367724e7919c0603cf6f71 (diff)
downloadmariadb-git-72dd7575cd8b9372ddb79cc4c94050e4ee1e5ee1.tar.gz
Merge 5.2->5.3
- Re-commit Monty's merge, partially fixed by Igor and SergeyP, but still broken
Diffstat (limited to 'sql/sql_prepare.cc')
-rw-r--r--sql/sql_prepare.cc73
1 files changed, 56 insertions, 17 deletions
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 863e7a36aab..7185b8ffdda 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -263,8 +263,11 @@ static bool send_prep_stmt(Prepared_statement *stmt, uint columns)
&stmt->lex->param_list,
Protocol::SEND_EOF);
}
- /* Flag that a response has already been sent */
- thd->main_da.disable_status();
+
+ if (!error)
+ /* Flag that a response has already been sent */
+ thd->main_da.disable_status();
+
DBUG_RETURN(error);
}
#else
@@ -702,6 +705,19 @@ static void setup_one_conversion_function(THD *thd, Item_param *param,
}
#ifndef EMBEDDED_LIBRARY
+
+/**
+ Check whether this parameter data type is compatible with long data.
+ Used to detect whether a long data stream has been supplied to a
+ incompatible data type.
+*/
+inline bool is_param_long_data_type(Item_param *param)
+{
+ return ((param->param_type >= MYSQL_TYPE_TINY_BLOB) &&
+ (param->param_type <= MYSQL_TYPE_STRING));
+}
+
+
/**
Routines to assign parameters from data supplied by the client.
@@ -771,6 +787,14 @@ static bool insert_params_with_log(Prepared_statement *stmt, uchar *null_array,
DBUG_RETURN(1);
}
}
+ /*
+ A long data stream was supplied for this parameter marker.
+ This was done after prepare, prior to providing a placeholder
+ type (the types are supplied at execute). Check that the
+ supplied type of placeholder can accept a data stream.
+ */
+ else if (! is_param_long_data_type(param))
+ DBUG_RETURN(1);
res= param->query_val_str(&str);
if (param->convert_str_value(thd))
DBUG_RETURN(1); /* out of memory */
@@ -809,6 +833,14 @@ static bool insert_params(Prepared_statement *stmt, uchar *null_array,
DBUG_RETURN(1);
}
}
+ /*
+ A long data stream was supplied for this parameter marker.
+ This was done after prepare, prior to providing a placeholder
+ type (the types are supplied at execute). Check that the
+ supplied type of placeholder can accept a data stream.
+ */
+ else if (! is_param_long_data_type(param))
+ DBUG_RETURN(1);
if (param->convert_str_value(stmt->thd))
DBUG_RETURN(1); /* out of memory */
}
@@ -1242,7 +1274,7 @@ static int mysql_test_update(Prepared_statement *stmt,
if (mysql_prepare_update(thd, table_list, &select->where,
select->order_list.elements,
- (ORDER *) select->order_list.first))
+ select->order_list.first))
goto error;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -1751,11 +1783,10 @@ error:
static int mysql_insert_select_prepare_tester(THD *thd)
{
SELECT_LEX *first_select= &thd->lex->select_lex;
- TABLE_LIST *second_table= ((TABLE_LIST*)first_select->table_list.first)->
- next_local;
+ TABLE_LIST *second_table= first_select->table_list.first->next_local;
/* Skip first table, which is the table we are inserting in */
- first_select->table_list.first= (uchar *) second_table;
+ first_select->table_list.first= second_table;
thd->lex->select_lex.context.table_list=
thd->lex->select_lex.context.first_name_resolution_table= second_table;
@@ -1792,7 +1823,7 @@ static bool mysql_test_insert_select(Prepared_statement *stmt,
return 1;
/* store it, because mysql_insert_select_prepare_tester change it */
- first_local_table= (TABLE_LIST *)lex->select_lex.table_list.first;
+ first_local_table= lex->select_lex.table_list.first;
DBUG_ASSERT(first_local_table != 0);
res=
@@ -1800,7 +1831,7 @@ static bool mysql_test_insert_select(Prepared_statement *stmt,
&mysql_insert_select_prepare_tester,
OPTION_SETUP_TABLES_DONE);
/* revert changes made by mysql_insert_select_prepare_tester */
- lex->select_lex.table_list.first= (uchar*) first_local_table;
+ lex->select_lex.table_list.first= first_local_table;
return res;
}
@@ -2158,7 +2189,7 @@ static const char *get_dynamic_sql_string(LEX *lex, uint *query_len)
lex->prepared_stmt_code.length))
&& entry->value)
{
- my_bool is_var_null;
+ bool is_var_null;
var_value= entry->val_str(&is_var_null, &str, NOT_FIXED_DEC);
/*
NULL value of variable checked early as entry->value so here
@@ -2344,10 +2375,10 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
DBUG_ASSERT(sl->join == 0);
ORDER *order;
/* Fix GROUP list */
- for (order= (ORDER *)sl->group_list.first; order; order= order->next)
+ for (order= sl->group_list.first; order; order= order->next)
order->item= &order->item_ptr;
/* Fix ORDER list */
- for (order= (ORDER *)sl->order_list.first; order; order= order->next)
+ for (order= sl->order_list.first; order; order= order->next)
order->item= &order->item_ptr;
/* clear the no_error flag for INSERT/UPDATE IGNORE */
@@ -2384,7 +2415,7 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
(multi-delete). We do a full clean up, although at the moment all we
need to clean in the tables of MULTI-DELETE list is 'table' member.
*/
- for (TABLE_LIST *tables= (TABLE_LIST*) lex->auxiliary_table_list.first;
+ for (TABLE_LIST *tables= lex->auxiliary_table_list.first;
tables;
tables= tables->next_global)
{
@@ -3039,13 +3070,21 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
old_stmt_arena= thd->stmt_arena;
thd->stmt_arena= this;
- Parser_state parser_state(thd, thd->query(), thd->query_length());
+ Parser_state parser_state;
+ if (parser_state.init(thd, thd->query(), thd->query_length()))
+ {
+ thd->restore_backup_statement(this, &stmt_backup);
+ thd->restore_active_arena(this, &stmt_backup);
+ thd->stmt_arena= old_stmt_arena;
+ DBUG_RETURN(TRUE);
+ }
+
parser_state.m_lip.stmt_prepare_mode= TRUE;
lex_start(thd);
error= parse_sql(thd, & parser_state, NULL) ||
- thd->is_error() ||
- init_param_array(this);
+ thd->is_error() ||
+ init_param_array(this);
lex->set_trg_event_type_for_tables();
@@ -3301,7 +3340,7 @@ reexecute:
bool
Prepared_statement::reprepare()
{
- char saved_cur_db_name_buf[NAME_LEN+1];
+ char saved_cur_db_name_buf[SAFE_NAME_LEN+1];
LEX_STRING saved_cur_db_name=
{ saved_cur_db_name_buf, sizeof(saved_cur_db_name_buf) };
LEX_STRING stmt_db_name= { db, db_length };
@@ -3462,7 +3501,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
Query_arena *old_stmt_arena;
bool error= TRUE;
- char saved_cur_db_name_buf[NAME_LEN+1];
+ char saved_cur_db_name_buf[SAFE_NAME_LEN+1];
LEX_STRING saved_cur_db_name=
{ saved_cur_db_name_buf, sizeof(saved_cur_db_name_buf) };
bool cur_db_changed;