diff options
author | unknown <konstantin@mysql.com> | 2005-09-03 03:13:18 +0400 |
---|---|---|
committer | unknown <konstantin@mysql.com> | 2005-09-03 03:13:18 +0400 |
commit | c910050a769a20db0eee0d5a4f7069959d3e3470 (patch) | |
tree | 981df38c4f1f46f7080926e10ff505778048f4af /sql/sp_head.h | |
parent | dc92221300d4d5b9e72d85373187d14d7f398c19 (diff) | |
download | mariadb-git-c910050a769a20db0eee0d5a4f7069959d3e3470.tar.gz |
Implement WL#2661 "Prepared Statements: Dynamic SQL in Stored Procedures".
The idea of the patch is to separate statement processing logic,
such as parsing, validation of the parsed tree, execution and cleanup,
from global query processing logic, such as logging, resetting
priorities of a thread, resetting stored procedure cache, resetting
thread count of errors and warnings.
This makes PREPARE and EXECUTE behave similarly to the rest of SQL
statements and allows their use in stored procedures.
This patch contains a change in behaviour:
until recently for each SQL prepared statement command, 2 queries
were written to the general log, e.g.
[Query] prepare stmt from @stmt_text;
[Prepare] select * from t1 <-- contents of @stmt_text
The chagne was necessary to prevent [Prepare] commands from being written
to the general log when executing a stored procedure with Dynamic SQL.
We should consider whether the old behavior is preferrable and probably
restore it.
This patch refixes Bug#7115, Bug#10975 (partially), Bug#10605 (various bugs
in Dynamic SQL reported before it was disabled).
mysql-test/r/not_embedded_server.result:
Since we don't want to log Dynamic SQL in stored procedures,
now the general log gets only one log entry per SQL statement.
mysql-test/r/sp-error.result:
- remove obsolete tests
- a better error message for the case when a stored procedure that
returns a result set is called from a function
mysql-test/r/trigger.result:
- a better error message for the case when a stored procedure that
returns a result set is called from a trigger
mysql-test/t/sp-error.test:
- a better error message for the case when a stored procedure that
returns a result set is called from a function.
- move the comment to its place (end of file).
mysql-test/t/trigger.test:
- a better error message for the case when a stored procedure that
returns a result set is called from a trigger
sql/item_func.cc:
- we need to pass sql_command explicitly to get_var_with_binlog, because
when creating a query for SQL prepared statement thd->lex->sql_command
points at SQLCOM_EXECUTE, which is not listed in the list of update
queries.
sql/log_event.h:
- remove an extra copy of the previous sentence
sql/mysql_priv.h:
- fix declarations of sql_prepare.cc API
sql/share/errmsg.txt:
- a new error message, when one attempts to execute a prepared statement
which is currently being executed (this can happen only in Dynamic SQL
at the moment).
sql/sp_head.cc:
- extend sp_multi_results_command to return different flags for a
command (and rename it)
- add support for SQLCOM_PREPARE,SQLCOM_EXECUTE, SQLCOM_DEALLOCATE
to sp_get_flags_for_command
- replace multiple boolean sp_head members with uint m_flags
- a fix for a crash when user variables are used in a stored procedure
and binlog is on. A temporary fix for Bug#12637 "SP crashes the server
if it has update query with user var & binlog is enabled", which actually
stands for stored functions: now instead of a crash we break
replication if a user variable is used in a stored function which
is executed in prelocked mode.
sql/sp_head.h:
- replace multiple boolean flags of sp_head with uint m_flags;
- add flag CONTAINS_DYNAMIC_SQL
- use this flag to error if a stored procedure with Dynamic SQL is
called from a function or trigger.
sql/sql_class.cc:
- Statement_map::insert should not delete a statement if it exists,
now it's done externally to be able to handle the case when the
statement being deleted is in use.
- remove extra code (free_list is already reset in free_items)
sql/sql_lex.cc:
- add lex->stmt_prepare_mode; we can't rely on thd->command any more,
because we don't reset it any more (Dynamic SQL requirement is that
PS are as little intrusive as possible).
sql/sql_lex.h:
- declare bool LEX::stmt_prepare_mode
sql/sql_parse.cc:
- move prepared statement code to sql_prepare.cc
- change declarations (refactored code)
- better error message when one attempts to use Dynamic SQL or a
stored procedure that returns a result set in a function or trigger.
sql/sql_prepare.cc:
- major refactoring to ensure PREPARE/EXECUTE commands do not reset global THD
state and allow their use in stored procedures.
- add Prepared_statement::flags and use it to ensure no recursive execution
of a prepared statement is possible
- better comments
sql/sql_yacc.yy:
- enable PREPARE/EXECUTE/DEALLOCATE in stored procedures
- produce an error message on attempt to use PREPARE/EXECUTE/DEALLOCATE
in a stored function or trigger
mysql-test/r/sp-dynamic.result:
- sp-dynamic.test results
mysql-test/t/sp-dynamic.test:
- a new test for PREPARE/EXECUTE/DEALLOCATE in stored procedures.
Diffstat (limited to 'sql/sp_head.h')
-rw-r--r-- | sql/sp_head.h | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/sql/sp_head.h b/sql/sp_head.h index 1d4bfb514d3..1c54b1a567d 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -33,8 +33,8 @@ Item_result sp_map_result_type(enum enum_field_types type); -bool -sp_multi_results_command(enum enum_sql_command cmd); +uint +sp_get_flags_for_command(LEX *lex); struct sp_label; class sp_instr; @@ -107,18 +107,23 @@ class sp_head :private Query_arena MEM_ROOT main_mem_root; public: + /* Possible values of m_flags */ + const static int + HAS_RETURN= 1, // For FUNCTIONs only: is set if has RETURN + IN_SIMPLE_CASE= 2, // Is set if parsing a simple CASE + IN_HANDLER= 4, // Is set if the parser is in a handler body + MULTI_RESULTS= 8, // Is set if a procedure with SELECT(s) + CONTAINS_DYNAMIC_SQL= 16, // Is set if a procedure with PREPARE/EXECUTE + IS_INVOKED= 32; // Is set if this sp_head is being used. int m_type; // TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE + uint m_flags; // Boolean attributes of a stored routine enum enum_field_types m_returns; // For FUNCTIONs only Field::geometry_type m_geom_returns; CHARSET_INFO *m_returns_cs; // For FUNCTIONs only TYPELIB *m_returns_typelib; // For FUNCTIONs only uint m_returns_len; // For FUNCTIONs only uint m_returns_pack; // For FUNCTIONs only - my_bool m_has_return; // For FUNCTIONs only - my_bool m_simple_case; // TRUE if parsing simple case, FALSE otherwise - my_bool m_multi_results; // TRUE if a procedure with SELECT(s) - my_bool m_in_handler; // TRUE if parser in a handler body uchar *m_tmp_query; // Temporary pointer to sub query string uint m_old_cmq; // Old CLIENT_MULTI_QUERIES value st_sp_chistics *m_chistics; @@ -265,6 +270,19 @@ public: bool add_used_tables_to_table_list(THD *thd, TABLE_LIST ***query_tables_last_ptr); + /* + Check if this stored routine contains statements disallowed + in a stored function or trigger, and set an appropriate error message + if this is the case. + */ + bool is_not_allowed_in_function(const char *where) + { + if (m_flags & CONTAINS_DYNAMIC_SQL) + my_error(ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0), "Dynamic SQL"); + else if (m_flags & MULTI_RESULTS) + my_error(ER_SP_NO_RETSET, MYF(0), where); + return test(m_flags & (CONTAINS_DYNAMIC_SQL|MULTI_RESULTS)); + } private: MEM_ROOT *m_thd_root; // Temp. store for thd's mem_root @@ -290,9 +308,6 @@ private: */ HASH m_sptabs; - /* Used for tracking of routine invocations and preventing recursion. */ - bool m_is_invoked; - int execute(THD *thd); |