diff options
Diffstat (limited to 'sql/sql_parse.cc')
-rw-r--r-- | sql/sql_parse.cc | 135 |
1 files changed, 29 insertions, 106 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 937fd736282..7d430f2a44a 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1644,7 +1644,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } case COM_STMT_PREPARE: { - mysql_stmt_prepare(thd, packet, packet_length, 0); + mysql_stmt_prepare(thd, packet, packet_length); break; } case COM_STMT_CLOSE: @@ -1664,6 +1664,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd, char *packet_end= thd->query + thd->query_length; mysql_log.write(thd,command,"%s",thd->query); DBUG_PRINT("query",("%-.4096s",thd->query)); + + if (!(specialflag & SPECIAL_NO_PRIOR)) + my_pthread_setprio(pthread_self(),QUERY_PRIOR); + mysql_parse(thd,thd->query, thd->query_length); while (!thd->killed && thd->lex->found_semicolon && !thd->net.report_error) @@ -2220,7 +2224,7 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, TRUE error; In this case thd->fatal_error is set */ -bool alloc_query(THD *thd, char *packet, ulong packet_length) +bool alloc_query(THD *thd, const char *packet, uint packet_length) { packet_length--; // Remove end null /* Remove garbage at start and end of query */ @@ -2229,7 +2233,7 @@ bool alloc_query(THD *thd, char *packet, ulong packet_length) packet++; packet_length--; } - char *pos=packet+packet_length; // Point at end null + const char *pos= packet + packet_length; // Point at end null while (packet_length > 0 && (pos[-1] == ';' || my_isspace(thd->charset() ,pos[-1]))) { @@ -2250,8 +2254,6 @@ bool alloc_query(THD *thd, char *packet, ulong packet_length) thd->packet.shrink(thd->variables.net_buffer_length); thd->convert_buffer.shrink(thd->variables.net_buffer_length); - if (!(specialflag & SPECIAL_NO_PRIOR)) - my_pthread_setprio(pthread_self(),QUERY_PRIOR); return FALSE; } @@ -2466,112 +2468,17 @@ mysql_execute_command(THD *thd) } case SQLCOM_PREPARE: { - 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; - bool need_conversion; - user_var_entry *entry; - String *pstr= &str; - 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, - lex->prepared_stmt_code.length)) - && entry->value) - { - my_bool is_var_null; - pstr= entry->val_str(&is_var_null, &str, NOT_FIXED_DEC); - /* - NULL value of variable checked early as entry->value so here - we can't get NULL in normal conditions - */ - DBUG_ASSERT(!is_var_null); - if (!pstr) - goto error; - } - else - { - /* - variable absent or equal to NULL, so we need to set variable to - something reasonable to get readable error message during parsing - */ - str.set("NULL", 4, &my_charset_latin1); - } - - need_conversion= - String::needs_conversion(pstr->length(), pstr->charset(), - to_cs, &unused); - - query_len= need_conversion? (pstr->length() * to_cs->mbmaxlen) : - pstr->length(); - if (!(query_str= alloc_root(thd->mem_root, query_len+1))) - goto error; - - if (need_conversion) - { - uint dummy_errors; - query_len= copy_and_convert(query_str, query_len, to_cs, - pstr->ptr(), pstr->length(), - pstr->charset(), &dummy_errors); - } - else - memcpy(query_str, pstr->ptr(), pstr->length()); - 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, - query_len, query_str)); - } - thd->command= COM_STMT_PREPARE; - if (!(res= mysql_stmt_prepare(thd, query_str, query_len + 1, - &lex->prepared_stmt_name))) - send_ok(thd, 0L, 0L, "Statement prepared"); + mysql_sql_stmt_prepare(thd); break; } case SQLCOM_EXECUTE: { - DBUG_PRINT("info", ("EXECUTE: %.*s\n", - lex->prepared_stmt_name.length, - lex->prepared_stmt_name.str)); - mysql_sql_stmt_execute(thd, &lex->prepared_stmt_name); - lex->prepared_stmt_params.empty(); + mysql_sql_stmt_execute(thd); break; } case SQLCOM_DEALLOCATE_PREPARE: { - Statement* stmt; - DBUG_PRINT("info", ("DEALLOCATE PREPARE: %.*s\n", - lex->prepared_stmt_name.length, - lex->prepared_stmt_name.str)); - /* We account deallocate in the same manner as mysql_stmt_close */ - statistic_increment(thd->status_var.com_stmt_close, &LOCK_status); - if ((stmt= thd->stmt_map.find_by_name(&lex->prepared_stmt_name))) - { - thd->stmt_map.erase(stmt); - send_ok(thd); - } - else - { - my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), - lex->prepared_stmt_name.length, - lex->prepared_stmt_name.str, - "DEALLOCATE PREPARE"); - goto error; - } + mysql_sql_stmt_close(thd); break; } case SQLCOM_DO: @@ -4124,7 +4031,7 @@ end_with_restore_list: } #endif if (lex->sphead->m_type == TYPE_ENUM_FUNCTION && - !lex->sphead->m_has_return) + !(lex->sphead->m_flags & sp_head::HAS_RETURN)) { my_error(ER_SP_NORETURN, MYF(0), name); delete lex->sphead; @@ -4213,15 +4120,31 @@ end_with_restore_list: ha_rows select_limit; /* bits that should be cleared in thd->server_status */ uint bits_to_be_cleared= 0; + /* + Check that the stored procedure doesn't contain Dynamic SQL + and doesn't return result sets: such stored procedures can't + be called from a function or trigger. + */ + if (thd->in_sub_stmt) + { + const char *where= (thd->in_sub_stmt & SUB_STMT_TRIGGER ? + "trigger" : "function"); + if (sp->is_not_allowed_in_function(where)) + goto error; + } #ifndef EMBEDDED_LIBRARY my_bool nsok= thd->net.no_send_ok; thd->net.no_send_ok= TRUE; #endif - if (sp->m_multi_results) + if (sp->m_flags & sp_head::MULTI_RESULTS) { if (! (thd->client_capabilities & CLIENT_MULTI_RESULTS)) { + /* + The client does not support multiple result sets being sent + back + */ my_error(ER_SP_BADSELECT, MYF(0), sp->m_qname.str); #ifndef EMBEDDED_LIBRARY thd->net.no_send_ok= nsok; @@ -4265,7 +4188,7 @@ end_with_restore_list: thd->row_count_func= 0; /* - We never write CALL statements int binlog: + We never write CALL statements into binlog: - If the mode is non-prelocked, each statement will be logged separately. - If the mode is prelocked, the invoking statement will care |