diff options
author | unknown <sergefp@mysql.com> | 2004-05-24 21:08:22 +0400 |
---|---|---|
committer | unknown <sergefp@mysql.com> | 2004-05-24 21:08:22 +0400 |
commit | c0729cbbca7632177a341cdd40e7e062af1a57a7 (patch) | |
tree | 56dc4248df889c1f513b4a0bc15f8cea4257ab1a | |
parent | fc68be78eb830df4bf8afe0096f0e5bf08fcd47f (diff) | |
download | mariadb-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.cc | 27 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 108 |
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. |