WL#4179: Stored programs: validation of stored program statements
Affects: Server-5.6
—
Status: Complete
Currently there is a problem in handling meta-data changes of the objects (tables, views, ...) which are used in a stored program. The meta-data information of such objects is fixed at the compilation time, and is not updated when the objects are changed (by DDL statements). Next stored program executions use outdated meta-data information, which leads to wrong-data-errors or even a crash. This WL task is about fixing that problem following the approach, previously implemented for Prepared Statements (WL#4166). The idea is to remember the original query for SQL-statement within a Stored Programs and re-parse it when meta-data has changed. There are a number of P1/P2 bugs which will be fixed by this WL task, in particular: - Bug#11747537 - 32868: STORED ROUTINES DO NOT DETECT CHANGES IN META-DATA. - Bug#11747580 - 33082: STORED PROCEDURE: CRASH IF TABLE REPLACED WITH A VIEW IN A LOOP - Bug#11747581 - 33083: STORED FUNCTION: ERROR AND CRASH IF A TEMPORARY TABLE IS DROPPED IN A LOO - Bug#11747566 - 33000: TRIGGERS DO NOT DETECT CHANGES IN META-DATA. - Bug#11747626 - 33289: STORED PROCEDURE: BAD DATA IF VIEW IS REPLACED WITHIN A ITERATION - Bug#11745236 - 12257: SELECT * INSIDE PROCEDURE GIVES "UNKNOWN COLUMN" ON SECOND LOOP IF TBL C - Bug#12652835 - 61434: PREPARED STATEMENTS AND TEMPORARY TABLES IN STORED PROCEDURES - Bug#11747619 - 33255: TRIGGER USING VIEWS AND VIEW DDL : CORRUPTED TRIGGERS All bugs fixed by this WL task are tagged with "WL#4179" in the Oracle BugDB. In order to get the complete list of the bugs fixed by this WL task, one can use 'Bugs_4179' saved search (on http://clustra.no.oracle.com/orabugs/save-search.php). This WL task is a pre-requisite for WL#4299 (Stored Routines: use the new metadata cache). Bug#11748352 (36002: PREPARED STATEMENTS: IF A VIEW USED IN A STATEMENT IS REPLACED, BAD DATA) seems to be related, but actually a different issue. A bugfix for Bug#11748352/36002 is needed to fix bugs from the list above.
Overview ======== Traditional SP-execution ------------------------ Prior to WL#4179 SP-instruction execution was as follows: - During first execution, a Stored Program is parsed, meaning every SQL-statement with the Stored Program is translated into the binary representation (LEX-object). - Binary binary representation has expanded wild-characters and established references to the data-objects (tables, views, ...). - During subsequent executions, the server just executes that binary representation (calls mysql_execute_command() against that LEX-object). Overview of Prepared Statement invalidation ------------------------------------------- WL#4166 introduced automatic re-preparation of a prepared statement when the meta-data used by the prepared statement is changed. For example: if we have a prepared statement like the following PREPARE s1 FROM 'SELECT * FROM table1'; the statement 's1; will be automatically re-prepared when meta-data of the 'table1' table is changed (e.g. a column is added or dropped, or its definition is changed). When a prepared statement is re-prepared, it starts to use up-to-date meta-data information of the underlying objects. Thus, the user-visible effect of automatic re-preparation is that the prepared statement produces correct results even after the meta-data of underlying objects is changed. Technically, this is achieved by the the following technique: - an opened table (or a view) has the current meta-data version; - at first execution of prepared statement, meta-data-versions of the underlying objects (tables, views) are remembered in the statement's context; - meta-data-version is changed (increased) when meta-data is changed; - each time a prepared statement is executed, the meta-data-versions remembered in the statement are compared against the current meta-data-versions from the object definitions. - if the current meta-data-version is newer than the saved one, an internal SQL-error is raised, thus, the prepared statement execution aborts; - that SQL-error is internally handled by the prepared statement execution layer up the calling stack in the following way: - the prepared statement is de-allocated (destroyed); - the prepared statement is re-prepared from the original query string; - execution is re-started. - The prepared statement execution layer makes three attempts to execute the prepared statement. If the execution fails three times due to differences in meta-data versions, a user-visible SQL-condition is raised (automatic re-preparation failed). Comparing SP-execution and PS-execution --------------------------------------- Here is more or less technical overview of differences between executing a Stored Program statement, and a Prepared Statement. Background: - There is Reprepare_observer interface, which provides report_error(); - THD class has THD::m_reprepare_observer member, which is a pointer to an object implementing Reprepare_observer interface; - THD::m_reprepare_observer can be NULL. If it is NULL, meta-data change tracking is disabled, the queries are executed "as usual". Every query execution starts with the opening of the objects (tables, views, ...) used by that query. If THD::m_reprepare_observer points to a valid object, the table-opening function will call Reprepare_observer::report_error() method if meta-data of any object has been changed. report_error() throws ER_REPREPARE SQL-condition (this is an internal error), thus the table-opening function fails. SP/PS execution steps: - Parsing phase (PREPARE for PS): - SP/PS: Parse SQL-statement; - SP/PS: Remember the LEX-object (generated for an SQL-statement) for future use; - SP/PS: Remember mem-root and free-item-list used during the parsing (they will form SP-instruction's arena); - Execution phase: - SP/PS: Switch active query arena to the SP-instruction arena - SP/PS: Re-initialise LEX-object before use - PS: Create an object implementing Reprepare_observer and make THD::m_reprepare_observer points to that object; - PS: Call mysql_execute_command() against the stored LEX-object; metadata changes (if any) will be noticed by the Reprepare_observer object, while opening tables. SP: Call mysql_execute_command() against the stored LEX-object; metadata changes will be missed, since the Reprepare Observer has not been set. - PS: Check if the Reprepare_observer-object noticed any meta-data change. If so, throw away current LEX-object and repeat the parsing stage. WL#4179 overview ---------------- WL#4179 alters the SP-execution logic by following PS-execution path: setup a Reprepare_observer object and tracks meta-data changes. When a meta-data change is noticed, the corresponding SQL-statement should be re-parsed (or re-prepared in case of Prepared Statements). The thing is that Stored Programs support SQL-statements, which can not be executed in the conventional mode (outside Stored Programs). For example: RETURN, IF, DECLARE CURSOR, ... The parser is not able to parse such an SQL-statement alone (without existing SP-parsing-context). That means, that in order to re-parse such an SQL-statement, the whole Stored Program has to be re-parsed. This is not what we want. This limitation is lifted as follows: such statements are split to SQL-expressions, which might depend on the meta-data, and the static part, which does not depend on the meta-data. Then, a new auxiliary SELECT-query is constructed using the SQL-expression part. For example: let's say a stored program contains the following SP-specific statement: RETURN (SELECT * FROM t1) It consists of the static part (just 'RETURN'), and the SQL-expression: '(SELECT * FROM t1)'. An auxiliary SELECT-statement would be: SELECT (SELECT * FROM t1) The idea is to (re-)parse that auxiliary SELECT-statement and take its first and only item to evaluate the RETURN-expression. Handling SP-specific statements =============================== As outlined in the 'WL#4179 overview', SP-statements are split into the static part and SQL-expression part(s). The SQL-expression part is used to construct an auxiliary SELECT-statement to re-parse the expression after meta-data changes. Below there is a list of SP-specific statements along with the notes of handling every particular statement. BEGIN...END ----------- BEGIN and END designate the boundaries of a block. The statements themselves do not have any SQL-expressions, thus no special action for them is needed. SQL-statements in a BEGIN..END block, however, are handled as usual. RETURN statement ---------------- Syntax (http://dev.mysql.com/doc/refman/5.6/en/return.html): RETURN expr RETURN-statements are handled by the sp_instr_freturn instruction class. sp_instr_freturn will be modified to store part of the original query, corresponding to the 'expr'. IF statement ------------ Syntax (http://dev.mysql.com/doc/refman/5.6/en/if-statement.html): IF search_condition THEN statement_list [ELSEIF search_condition THEN statement_list] ... [ELSE statement_list] END IF Every branch in IF-statement (IF / ELSEIF) is handled by the sp_instr_jump_if_not instruction class. sp_instr_jump_if_not will be modified to store part of the original query, corresponding to the 'search_condition'. REPEAT statement ---------------- Syntax (http://dev.mysql.com/doc/refman/5.6/en/repeat-statement.html): [begin_label:] REPEAT statement_list UNTIL search_condition END REPEAT [end_label] REPEAT-statements are handled by the sp_instr_jump_if_not instruction class. sp_instr_jump_if_not should store part of the original query, corresponding to the 'search_condition'. WHILE statement --------------- Syntax (http://dev.mysql.com/doc/refman/5.6/en/while-statement.html): [begin_label:] WHILE search_condition DO statement_list END WHILE [end_label] WHILE-statements are handled by the sp_instr_jump_if_not instruction class. sp_instr_jump_if_not should store part of the original query, corresponding to the 'search_condition'. CASE statement -------------- Syntax (http://dev.mysql.com/doc/refman/5.6/en/case-statement.html): CASE case_value WHEN when_value THEN statement_list [WHEN when_value THEN statement_list] ... [ELSE statement_list] END CASE or: CASE WHEN search_condition THEN statement_list [WHEN search_condition THEN statement_list] ... [ELSE statement_list] END CASE As it is shown above, there are actually two different forms of CASE-statements, which are handled differently from the technical point of view. Handling "simple CASE-statement" ++++++++++++++++++++++++++++++++ (that's how this CASE-variant is named internally). CASE case_value WHEN when_value THEN statement_list [WHEN when_value THEN statement_list] ... [ELSE statement_list] END CASE There are the following instructions used to handle that statement: - sp_instr_set_case_expr -- it evaluates 'case_value' expression and stores the result into sp_rcontext internal table. - sp_instr_jump_if_not -- it creates auxillary Item-tree, corresponding to the following expression: 'case_value = when_value' In order to be able to reprepare case_value and when_value expressions, the following changes will be done: - sp_instr_set_case_expr will store part of the original query, corresponding to the 'case_value' expression; - a new instruction class will be introduced, with the following behaviour: - store part of the original query corresponding to the 'when_value' expression; - when meta-data change occurred: - re-parse 'when_value' expression when meta-data change occurred; - re-build 'case_value = when_value' internal expression; - use 'case_value = when_value' internal expression as the condition to jump It must be guaranteed, that in case of meta-data change: - 'case_value' expression is evaluated once - 'when_value' expressions, which have already been evaluated and were false, are not evaluated again. Handling "searched CASE-statement" ++++++++++++++++++++++++++++++++++ (that's how this CASE-variant is named internally) CASE WHEN search_condition THEN statement_list [WHEN search_condition THEN statement_list] ... [ELSE statement_list] END CASE This form of the CASE-statement is more like traditional IF/ELSEIF statement. It is handled by the sp_instr_jump_if_not instruction class. sp_instr_jump_if_not should store part of the original query, corresponding to the 'search_condition'. It must be guaranteed, that in case of meta-data change: - 'when_value' expressions, which have already been evaluated and were false, are not evaluated again. SET statement ------------- Syntax (http://dev.mysql.com/doc/refman/5.6/en/set-statement.html): SET variable_assignment [, variable_assignment] ... variable_assignment: user_var_name = expr | [GLOBAL | SESSION] system_var_name = expr | [@@global. | @@session. | @@]system_var_name = expr There are actually three forms of the SET-statement: - SET for user variables -- this is a regular statement, supported for conventional execution; - SET for SP-variables -- this is an SP-specific statement, handled by sp_instr_set instruction class; - SET for NEW/OLD trigger pseudo-rows -- this is an SP-specific statement, handled by sp_instr_set_trigger_field instruction class. sp_instr_set and sp_instr_set_trigger_field should be modified to store part of the original query, corresponding to the 'expr'. DECLARE for SP-variables ------------------------ Syntax (http://dev.mysql.com/doc/refman/5.6/en/declare-local-variable.html): DECLARE var_name [, var_name] ... type [DEFAULT value] The thing is that 'value' in the DEFAULT-clause might be an expression, which depends on the meta-data. Setting default values to stored program variables is handled by the sp_instr_set instruction class. Thus, it will be done in the way SET-statement does it for SP-variables. Note, that MySQL supports the following non-documented feature: SET x = DEFAULT; i.e. a stored program variable can be set to its default value somewhere after the initial declaration. The current implementation of this feature does not work well -- it crashes the server under some circumstances (see Bug#13727199 - STORED PROGRAMS USING SET AND DEFAULT IN SOME COMBINATION CRASH THE SERVER). In particular, if DEFAULT expression contains a stored function reference, or a sub-query, the server will crash. It's been decided to not fix that in scope of WL#4179, as this is a side and legacy problem. Thus, 'SET x = DEFAULT' will not detect changes in meta-data of the objects, used in the DEFAULT expression. For example, the following code will not detect meta-data changes (now, it does not even execute -- it crashes the server): CREATE PROCEDURE p1() BEGIN DECLARE v INT DEFAULT (SELECT * FROM t1); # -- Here meta-data changes *will* # -- be noticed. ... SET v = DEFAULT; # -- Here meta-data changes will *not* # -- be noticed (the server crashes now). END Another note: DEFAULT-value-expression is re-evaluated every time, the assignment happens. DECLARE for handlers -------------------- DECLARE keyword may be used to introduce an SQL-condition or a stored program handler: http://dev.mysql.com/doc/refman/5.6/en/declare-condition.html http://dev.mysql.com/doc/refman/5.6/en/declare-handler.html DECLARE-condition does not deal with data objects, nor can it contain an expression referencing data objects. DECLARE for cursors ------------------- Syntax (http://dev.mysql.com/doc/refman/5.6/en/declare-cursor.html): DECLARE cursor_name CURSOR FOR select_statement DECLARE CURSOR statements are handled by the sp_instr_cpush instruction class. sp_instr_cpush will be modified to store part of the original query, corresponding to the 'select_statement'. Getting query string of statement ================================= In order to make a prepared statement out of an SQL-statement in a stored program, the statement's query string needs to be clearly identified. It's proposed to use the current parser (sql_yacc.yy) to extract query string for statements for now. In the future, this could be implemented by means of the "Bison locations" feature (WL#5967), which provides more straightforward way to get query strings from the parser. Re-execution ============ Like with the execution of the Prepared Statements, there are 3 attempts to re-parse a SP-statememnt. If the parsing failed three times, an SQL-condition (an error) is raised. It is a regular SQL-condition, which can be handled according to the standard rules. Other SQL-conditions are also preserved in the Diagnostics Area. For example, let's say, there is a stored procedure with two statements: - one statement updates a table, and generates a warning/SQL-condition (type conversion, ..); - the other statement fails to re-parse. The 'CALL' statement will fail, Diagnostics Area will also contain the warning generated by the first statement. If meta-data change is incompatible, re-parsing fails and Diagnostics Area contains the corresponding error state. For example: create table t(a int); create procedure P() begin ... select a from t; ... end; call P(); -- OK alter table t rename a to b; call P(); -- Error The second 'CALL' fails with the 'unknown column' error. Performance impact ================== Not more than 1% overhead with two different kinds of load: Load 1: A CPU-intensive procedure that is not affected by meta-data changes. Load 2: A stored procedure that executes a subquery and assigns the result to a local variable. Overhead is measured without metadata changes. Alternatives ============ Use internal Prepared Statements -------------------------------- The first implementation of WL#4179 was using internal Prepared Statements: every statement within a Stored Program is converted into a Prepared Statement. That approach worked more or less Ok with the traditional SQL-statements, but it turned to be pretty ugly when things come to supporting SP-specific statements (IF/CASE/..., DECLARE CURSOR, RETURN, ...). The approach was to convert SP-specific statement to a pair: - an instruction with SET with user variable, which can be turn into an internal prepared statement - actual instruction for SP-specific statement. For example, IF (SELECT * FROM t1) THEN ... would be converted into: PREPARE s1 FROM 'SET @__v1 = (SELECT * FROM t1)'; EXECUTE s1; IF (@__v1) THEN ... However, that didn't work for RETURN-statement, which must follow strict type-conversion rules. Thus, for RETURN-statement, a new auxillary field in the sp_rcontext-object was introduced, and RETURN-statement was converted to something like: PREPARE s1 FROM 'SET __aux_return_field = (SELECT * FROM t1)'; EXECUTE s1; RETURN __aux_return_field; Those transformation were not obvious in some tricky cases and lead to numerous errors. Also, the performance impact was questionable. Get an exhaustive set of the used objects ----------------------------------------- We could try to make an exhaustive set of the objects a stored program is using, lock those objects at the beginning of the stored program and detect theirs meta-data changes. Although this approach seems to be more natural and easier to implement, there are the following conceptual problems, which make it hardly possible: - Stored functions and triggers are Ok, because they are executed in scope of outer transaction. Stored procedures and events are not. Thus, we're actually changing the locking scheme. - If all the objects are locked at the beginning of a stored procedure / event, the following problem appear: how to handle DDL statements and other statements that cause implicit commit? When commit happens, we need to re-take all the locks. It's not clear how to handle meta-data changes, happened in the middle of this process. - It's hard to support Dynamic SQL within stored procedures / events, because: - dynamic query string might eventually contain DDL-statement, or other statement causing implicit COMMIT (the previous problem). - it's not possible to determine full set of objects to pre-lock from the dynamic string. - Auto-commit mode. When auto-commit is on, stored procedure is executed statement by statement, and commit is issued after every statement. Impact on replication ===================== The current state (the state before WL#4179) is the following: - sp_instr_stmt substitutes all SP-variables in a statement by NAME_CONST()-expressions and writes the expanded query into the binary log; - a stored program call is logged only if it has modified the data (the stored program has a side effect): - stored procedure calls are logged per-statement (every statement in a stored procedure is logged); - stored function calls are logged as calls -- usually, by SELECT-statement; WL#4179 does not introduce significant changes in replication. Before executing prepared statement, the server should generate expanded query (with SP-variables translated into NAME_CONST()-expressions) and write it to the binary log. Other notes =========== Bug#11744945 (Stored procedure declared variable used instead of column) ------------------------------------------------------------------------ This bug most likely will not be fixed by this WL task. The essence of this bug is resolving ambiguity when a stored-program-variable, a stored-program-parameter and a table column have the same name. Tentative specification from Peter (though it's not clear yet if it is possible to achieve this behavior): Error for ambiguous column | parameter | variable name ------------------------------------------------------ Suppose I have a column named X and I have a variable named X and a parameter named X (the same name for all three items). Suppose I refer to X in an SQL statement, e.g. "SELECT X FROM t". MySQL thinks I am referring to the variable. Some other DBMSs would think I am referring to the column. But according to Peter Gulutzan's email to Paul DuBois in 2005 http://vilje01.no.oracle.com/mailarchive/mail.php?folder=51&mail=2207 in standard SQL ambiguity should cause a syntax error. Therefore If the name is qualified, for example t.X, there is no possible ambiguity, X is a column name. This is correct until we implement WL#5975 (Qualified variable and parameter names). Otherwise, if the name can refer to any two of (a column, a parameter, a variable), Error. SQLSTATE = 42000. Message = Ambiguity. X is the name of both a (column|parameter|variable) name and a (column|parameter|variable) name. This error may happen during a routine invocation, rather than during a routine creation. This will fix BUG#5967 (Stored procedure declared variable used instead of column) although it will not do what BUG#5967 asks for. See also - MySQL Reference Manual 12.7.3.4. Scope and Resolution of Local Variables http://dev.mysql.com/doc/refman/5.6/en/local-variable-scope.html - dev-private email thread re BUG#5967 Re: BUG#5967 Stored procedure declared variable used instead of column http://vilje01.no.oracle.com/mailarchive/mail.php?folder=4&mail=24912 - dev-private email thread Limitation of name resolving of stored routines variables, starting http://vilje01.no.oracle.com/mailarchive/mail.php?folder=51&mail=2123 Functional requirements ======================= Definitions ----------- a. A stored program is either a stored procedure or a stored function, or an event, or a trigger; b. Successful execution means that the server returns OK status and the result of stored program execution is as expected by the user. Requirements ------------ 1. Stored program must be re-executed successfully if the table that this program is referenced to has been modified. 1.1 Stored program that uses query like 'SELECT * FROM t' must be re-executed successfully if some columns were added into table 't' by ALTER TABLE; 1.2 Stored program that uses query like 'SELECT * FROM t' must be re-executed successfully if some columns were removed from table 't' by ALTER TABLE; 1.3 Stored program that uses query like 'SELECT * FROM t' must be re-executed successfully if a type of some table's columns were changed by ALTER TABLE; 1.4 Stored program that uses query like 'SELECT * FROM t' must be re-executed successfully if the table 't' was dropped and created again with the same definition; 1.5 Stored program that uses query like 'SELECT * FROM t' must be re-executed successfully if the table 't' was dropped and created again with different, but compatible definition. 2. Stored program must be successfully re-executed if the view that this program is referenced to has been modified. 2.1 Stored program that uses query like 'SELECT * FROM v' must be re-executed successfully if some columns were added into the view definition by ALTER VIEW; 2.2 Stored program that uses query like 'SELECT * FROM v' must be re-executed successfully if some columns were removed from the view definition by ALTER VIEW; 2.3 Stored program that uses query like 'SELECT * FROM v' must be re-executed successfully if a base table for the view being used was extended by new columns (by ALTER TABLE); 2.4 Stored program that uses query like 'SELECT * FROM v' must be re-executed successfully if not used columns were removed from the base table of this view (by ALTER TABLE); 2.5 Stored program that uses query like 'SELECT * FROM v' must be re-executed successfully if a type of some base table's columns were changed (by ALTER TABLE); 2.6 Stored program that uses query like 'SELECT * FROM v' must be re-executed successfully if the view 'v' was dropped and created again with the same definition; 2.7 Stored program that uses query like 'SELECT * FROM v' must be re-executed successfully if the view 'v' was dropped and created again with different, but compatible definition. 2.8 Stored program that uses query like 'SELECT * FROM v' must be re-executed successfully if the view base tables have been re-created using the same or compatible definition. 3. Stored program must be re-executed successfully if a temporary table that this program is referenced to has been modified. 3.1 Stored program that uses query like 'SELECT * FROM t' must be re-executed successfully if some columns were added into temporary table table 't' (by ALTER TABLE); 3.2 Stored program that uses query like 'SELECT * FROM t' must be re-executed successfully if some columns were removed from temporary table 't' (by ALTER TABLE); 3.3 Stored program that uses query like 'SELECT * FROM t' must be re-executed successfully if a type of some temporary table's columns were changed (by ALTER TABLE); 3.4 Stored program that uses query like 'SELECT * FROM t' must be re-executed successfully if the temporary table 't' was dropped and created again with the same definition; 3.5 Stored program that uses query like 'SELECT * FROM t' must be re-executed successfully if the temporary table 't' was dropped and created again with different, but compatible definition. 4. Stored program must fail when it is re-executed after the definitions of the objects being used have changed in an incompatible way or have been dropped. 4.1 Stored program must be fail when it is re-executed after a table's column that this program is referenced to has been removed; 4.2 Stored program must be fail when it is re-executed after a temporary table's column that this program is referenced to has been removed; 4.3 Stored program must be fail when it is re-executed after a view's column that this program is referenced to has been removed; 4.4 Stored program must be fail when it is re-executed after a regular table that this program referenced to was removed; 4.5 Stored program must be fail when it is re-executed after a view that this program referenced to was removed; 4.6 Stored program must be fail when it is re-executed after a temporary table that this program referenced to was removed; 4.7 Stored program must be fail if the program executes some SQL-statement and afterwards re-executes it again when some table 't' referenced by the statement was dropped in the period between statement execution; 5. A stored program must be successfully re-executed if it references an object (a table, a temporary table, a view), which type has changed between two executions of the function. 5.1 Regular table -> View 5.1 Regular table -> Temporary table 5.1 View -> Regular table 5.1 View -> Temporary table 5.1 Temporary table -> View 5.1 Temporary table -> Regular table 6. Triggers must handle changes in the base table definition correctly when the base tables are accessed via NEW/OLD pseudo-variables. 6.1 Trigger that uses column 'a' of table 't' via pseudo-variable NEW must be re-executed successfully if the table definition has been changed in a compatible way. "Compatible way" in this case is that if the table 't' still has a column named 'a' and the column type is compatible with the operation that NEW.a takes part of. 6.2 Trigger that uses column 'a' of table 't' via pseudo-variable OLD must be re-executed successfully if the table definition has been changed in a compatible way. "Compatible way" in this case is that if the table 't' still has a column named 'a' and the column type is compatible with the operation that OLD.a takes part of. 6.3 Re-execution of a trigger that uses column 'a' of table 't' via pseudo-variable NEW must fail if the table definition has been changed in the way that the column 'a' does not exist anymore. 6.4 Re-execution of a trigger that uses column 'a' of table 't' via pseudo-variable OLD must fail if the table definition has been changed in the way that the column 'a' does not exist anymore. 7. Changes in definition of table/temporary table/view must be handled in a correct way in case of dependency call of stored programs 7.1 Setup: - stored program 'a', which alters regular table 't' in a compatible way; - stored program 'b', which calls 'a' and uses 't' before and after the call; Stored program 'b' must be executed successfully. 7.2 Setup: - stored program 'a', which alters temporary table 't' in a compatible way; - stored program 'b', which calls 'a' and uses 't' before and after the call; Stored program 'b' must be executed successfully. 7.3 Setup: - stored program 'a', which re-creates regular table 't' in a compatible way; - stored program 'b', which calls 'a' and uses 't' before and after the call; Stored program 'b' must be executed successfully. 7.4 Setup: - stored program 'a', which re-creates temporary table 't' in a compatible way; - stored program 'b', which calls 'a' and uses 't' before and after the call; Stored program 'b' must be executed successfully. 7.5 Setup: - stored program 'a', which re-creates view 'v' in a compatible way; - stored program 'b', which calls 'a' and uses 'v' before and after the call; Stored program 'b' must be executed successfully. 7.6 Setup: - stored program 'a', which alters regular table 't' in an incompatible way; - stored program 'b', which calls 'a' and uses 't' before and after the call; Stored program 'b' must fail on access to the table after its modification. 7.7 Setup: - stored program 'a', which alters temporary table 't' in an incompatible way; - stored program 'b', which calls 'a' and uses 't' before and after the call; Stored program 'b' must fail on access to the table after its modification. 7.8 Setup: - stored program 'a', which re-creates regular table 't' in an incompatible way; - stored program 'b', which calls 'a' and uses 't' before and after the call; Stored program 'b' must fail on access to the table after its modification. 7.9 Setup: - stored program 'a', which re-creates temporary table 't' in an incompatible way; - stored program 'b', which calls 'a' and uses 't' before and after the call; Stored program 'b' must fail on access to the table after its modification. 7.10 Setup: - stored program 'a', which re-creates view 'v' in an incompatible way; - stored program 'b', which calls 'a' and uses 'v' before and after the call; Stored program 'b' must fail on access to the view after its modification. 8. Stored program must be executed successfully when: a. the program uses a table/view/temporary table that doesn't exist at the time of start program execution b. failed reference to the missed table/view/temporary table handled by stored program c. this table/view/temporary table is created as part of the program execution d. stored program gets access to newly created table/view/temporary table from some SQL-statement during subsequent stored program execution. 9. Stored program must be executed successfully when - the stored program has an expression in one of the following statements - RETURN - IF - CASE - WHILE - UNTIL - SET - the expression depends on the meta-data of some table/view/temporary table; - the meta-data of dependent object has changed in a compatible way. Note, that CASE-expression must be evaluated once even if (some) CASE-expressions need to be re-parsed. 10. Subsequent executions of a stored program must fail when - the stored program has an expression in one of the following statements - RETURN - IF - CASE - WHILE - UNTIL - SET - the expression depends on the meta-data of some table/view/temporary table; - the meta-data of dependent object has changed in a non-compatible way. Note, that CASE-expression must be evaluated once even if (some) CASE-expressions need to be re-parsed. 11. Metadata changes should be properly handled by SELECT-statement used for cursor declarations. 11.1 If metadata of the objects (regular tables, temporary tables, views), used in SELECT-statement changed between DECLARE CURSOR and OPEN statements, the SELECT-statement should be re-parsed to use up-to-date metadata. 11.2 If the metadata changed between OPEN and FETCH or CLOSE statements, those changes should not be noticed. 11.3 Re-parsing of the SELECT-statement should be made correctly (in the correct parsing context) if the metadata changed between DECLARE CURSOR and OPEN statements, and those statements reside in different parsing contexts.
Copyright (c) 2000, 2024, Oracle Corporation and/or its affiliates. All rights reserved.