summaryrefslogtreecommitdiff
path: root/sql/sp_rcontext.cc
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2017-03-08 23:20:39 +0400
committerAlexander Barkov <bar@mariadb.org>2017-04-05 15:02:59 +0400
commitf429b5a834439e4f0c76e893487e33027d76b74b (patch)
treea06ec92dad05a2820ecd8a9afe73696b103536a3 /sql/sp_rcontext.cc
parent1b8a0c879d80733e3c684080b8c7719c35642e0d (diff)
downloadmariadb-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.cc35
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.
///////////////////////////////////////////////////////////////////////////