diff options
author | Alexander Barkov <bar@mariadb.org> | 2017-03-08 23:20:39 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.org> | 2017-04-05 15:02:59 +0400 |
commit | f429b5a834439e4f0c76e893487e33027d76b74b (patch) | |
tree | a06ec92dad05a2820ecd8a9afe73696b103536a3 /sql/sp_rcontext.cc | |
parent | 1b8a0c879d80733e3c684080b8c7719c35642e0d (diff) | |
download | mariadb-git-f429b5a834439e4f0c76e893487e33027d76b74b.tar.gz |
MDEV-12011 sql_mode=ORACLE: cursor%ROWTYPE in variable declarations
Implementing cursor%ROWTYPE variables, according to the task description.
This patch includes a refactoring in how sp_instr_cpush and sp_instr_copen
work. This is needed to implement MDEV-10598 later easier, to allow variable
declarations go after cursor declarations (which is currently not allowed).
Before this patch, sp_instr_cpush worked as a Query_arena associated with
the cursor. sp_instr_copen::execute() switched to the sp_instr_cpush's
Query_arena when executing the cursor SELECT statement.
Now the Query_arena associated with the cursor is stored inside an instance
of a new class sp_lex_cursor (a LEX descendand) that contains the cursor SELECT
statement.
This simplifies the implementation, because:
- It's easier to follow the code when everything related to execution
of the cursor SELECT statement is stored inside the same sp_lex_cursor
object (rather than distributed between LEX and sp_instr_cpush).
- It's easier to link an sp_instr_cursor_copy_struct to
sp_lex_cursor rather than to sp_instr_cpush.
- Also, it allows to perform sp_instr_cursor_copy_struct::exec_core()
without having a pointer to sp_instr_cpush, using a pointer to sp_lex_cursor
instead. This will be important for MDEV-10598, because sp_instr_cpush will
happen *after* sp_instr_cursor_copy_struct.
After MDEV-10598 is done, this declaration:
DECLARE
CURSOR cur IS SELECT * FROM t1;
rec cur%ROWTYPE;
BEGIN
OPEN cur;
FETCH cur INTO rec;
CLOSE cur;
END;
will generate about this code:
+-----+--------------------------+
| Pos | Instruction |
+-----+--------------------------+
| 0 | cursor_copy_struct rec@0 | Points to sp_cursor_lex through m_lex_keeper
| 1 | set rec@0 NULL |
| 2 | cpush cur@0 | Points to sp_cursor_lex through m_lex_keeper
| 3 | copen cur@0 | Points to sp_cursor_lex through m_cursor
| 4 | cfetch cur@0 rec@0 |
| 5 | cclose cur@0 |
| 6 | cpop 1 |
+-----+--------------------------+
Notice, "cursor_copy_struct" and "set" will go before "cpush".
Instructions at positions 0, 2, 3 point to the same sp_cursor_lex instance.
Diffstat (limited to 'sql/sp_rcontext.cc')
-rw-r--r-- | sql/sp_rcontext.cc | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index b631ad71e49..d60d7f5118f 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -286,6 +286,13 @@ bool sp_rcontext::init_var_items(THD *thd, item->row_create_items(thd, &defs)) return true; } + else if (def->is_cursor_rowtype_ref()) + { + Row_definition_list defs; + Item_field_row *item= new (thd->mem_root) Item_field_row(thd, field); + if (!(m_var_items[idx]= item)) + return true; + } else if (def->is_row()) { Item_field_row *item= new (thd->mem_root) Item_field_row(thd, field); @@ -341,14 +348,13 @@ bool sp_rcontext::set_return_value(THD *thd, Item **return_value_item) } -bool sp_rcontext::push_cursor(THD *thd, sp_lex_keeper *lex_keeper, - sp_instr_cpush *i) +bool sp_rcontext::push_cursor(THD *thd, sp_lex_keeper *lex_keeper) { /* We should create cursors in the callers arena, as it could be (and usually is) used in several instructions. */ - sp_cursor *c= new (callers_arena->mem_root) sp_cursor(thd, lex_keeper, i); + sp_cursor *c= new (callers_arena->mem_root) sp_cursor(thd, lex_keeper); if (c == NULL) return true; @@ -687,11 +693,10 @@ bool sp_rcontext::set_case_expr(THD *thd, int case_expr_id, /////////////////////////////////////////////////////////////////////////// -sp_cursor::sp_cursor(THD *thd_arg, sp_lex_keeper *lex_keeper, sp_instr_cpush *i): +sp_cursor::sp_cursor(THD *thd_arg, sp_lex_keeper *lex_keeper): result(thd_arg), m_lex_keeper(lex_keeper), server_side_cursor(NULL), - m_i(i), m_fetch_count(0), m_row_count(0), m_found(false) @@ -731,6 +736,21 @@ int sp_cursor::open(THD *thd) } +int sp_cursor::open_view_structure_only(THD *thd) +{ + int res; + int thd_no_errors_save= thd->no_errors; + Item *limit_rows_examined= thd->lex->limit_rows_examined; + if (!(thd->lex->limit_rows_examined= new (thd->mem_root) Item_uint(thd, 0))) + return -1; + thd->no_errors= true; // Suppress ER_QUERY_EXCEEDED_ROWS_EXAMINED_LIMIT + res= open(thd); + thd->no_errors= thd_no_errors_save; + thd->lex->limit_rows_examined= limit_rows_examined; + return res; +} + + int sp_cursor::close(THD *thd) { if (! server_side_cursor) @@ -802,6 +822,11 @@ int sp_cursor::fetch(THD *thd, List<sp_variable> *vars) } +bool sp_cursor::export_structure(THD *thd, Row_definition_list *list) +{ + return server_side_cursor->export_structure(thd, list); +} + /////////////////////////////////////////////////////////////////////////// // sp_cursor::Select_fetch_into_spvars implementation. /////////////////////////////////////////////////////////////////////////// |