diff --git a/sql/field.h b/sql/field.h index 448eee9b04db4..9559ba789b14c 100644 --- a/sql/field.h +++ b/sql/field.h @@ -3987,16 +3987,6 @@ class Row_definition_list: public List }; -class Cursor_rowtype: public Sql_alloc -{ -public: - uint m_cursor; - Cursor_rowtype(uint cursor) - :m_cursor(cursor) - { } -}; - - /** This class is used during a stored routine or a trigger execution, at sp_rcontext::create() time. @@ -4020,20 +4010,20 @@ class Spvar_definition: public Column_definition { class Qualified_column_ident *m_column_type_ref; // for %TYPE class Table_ident *m_table_rowtype_ref; // for table%ROWTYPE - class Cursor_rowtype *m_cursor_rowtype_ref; // for cursor%ROWTYPE + bool m_cursor_rowtype_ref; // for cursor%ROWTYPE Row_definition_list *m_row_field_definitions; // for ROW public: Spvar_definition() :m_column_type_ref(NULL), m_table_rowtype_ref(NULL), - m_cursor_rowtype_ref(NULL), + m_cursor_rowtype_ref(false), m_row_field_definitions(NULL) { } Spvar_definition(THD *thd, Field *field) :Column_definition(thd, field, NULL), m_column_type_ref(NULL), m_table_rowtype_ref(NULL), - m_cursor_rowtype_ref(NULL), + m_cursor_rowtype_ref(false), m_row_field_definitions(NULL) { } const Type_handler *type_handler() const @@ -4044,7 +4034,7 @@ class Spvar_definition: public Column_definition } bool is_column_type_ref() const { return m_column_type_ref != 0; } bool is_table_rowtype_ref() const { return m_table_rowtype_ref != 0; } - bool is_cursor_rowtype_ref() const { return m_cursor_rowtype_ref != NULL; } + bool is_cursor_rowtype_ref() const { return m_cursor_rowtype_ref; } class Qualified_column_ident *column_type_ref() const { return m_column_type_ref; @@ -4062,11 +4052,7 @@ class Spvar_definition: public Column_definition { m_table_rowtype_ref= ref; } - class Cursor_rowtype *cursor_rowtype_ref() const - { - return m_cursor_rowtype_ref; - } - void set_cursor_rowtype_ref(class Cursor_rowtype *ref) + void set_cursor_rowtype_ref(bool ref) { m_cursor_rowtype_ref= ref; } diff --git a/sql/sp_head.cc b/sql/sp_head.cc index d819112dbfc69..9376ada40bae5 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -3183,8 +3183,7 @@ int sp_lex_keeper::cursor_reset_lex_and_exec_core(THD *thd, uint *nextp, */ thd->stmt_arena= m_lex->query_arena(); int res= reset_lex_and_exec_core(thd, nextp, open_tables, instr); - if (thd->stmt_arena->free_list) - cleanup_items(thd->stmt_arena->free_list); + cleanup_items(thd->stmt_arena->free_list); thd->stmt_arena= old_arena; return res; } @@ -4170,10 +4169,18 @@ sp_instr_cfetch::print(String *str) sp_instr_cursor_copy_struct class functions */ +/** + This methods processes cursor %ROWTYPE declarations, e.g.: + CURSOR cur IS SELECT * FROM t1; + rec cur%ROWTYPE; + and does the following: + - opens the cursor without copying data (materialization). + - copies the cursor structure to the associated %ROWTYPE variable. +*/ int sp_instr_cursor_copy_struct::exec_core(THD *thd, uint *nextp) { - DBUG_ENTER("sp_instr_cusrot_copy_struct::exec_core"); + DBUG_ENTER("sp_instr_cursor_copy_struct::exec_core"); int ret= 0; Item_field_row *row= (Item_field_row*) thd->spcont->get_item(m_var); DBUG_ASSERT(row->type_handler() == &type_handler_row); @@ -4188,6 +4195,7 @@ sp_instr_cursor_copy_struct::exec_core(THD *thd, uint *nextp) if (!row->arguments()) { sp_cursor tmp(thd, &m_lex_keeper); + // Open the cursor without copying data if (!(ret= tmp.open_view_structure_only(thd))) { Row_definition_list defs; diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index 18f603f932dbc..fcbe5ddf75714 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -743,11 +743,17 @@ int sp_cursor::open(THD *thd) } +/** + Open the cursor, but do not copy data. + This method is used to fetch the cursor structure + to cursor%ROWTYPE routine variables. + Data copying is suppressed by setting thd->lex->limit_rows_examined to 0. +*/ 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; + Item *limit_rows_examined= thd->lex->limit_rows_examined; // No data copying 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 diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index dca203863e2d3..655c0872eebca 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -5303,10 +5303,7 @@ LEX::sp_variable_declarations_rowtype_finalize(THD *thd, int nvars, if (pcursor) { - Cursor_rowtype *ref; - if (!(ref= new (thd->mem_root) Cursor_rowtype(coffp))) - return true; - spvar->field_def.set_cursor_rowtype_ref(ref); + spvar->field_def.set_cursor_rowtype_ref(true); sp_instr_cursor_copy_struct *instr= new (thd->mem_root) sp_instr_cursor_copy_struct(sphead->instructions(), spcont, pcursor->lex(), @@ -5435,10 +5432,7 @@ LEX::sp_add_for_loop_cursor_variable(THD *thd, sphead->fill_spvar_definition(thd, &spvar->field_def, spvar->name.str); spvar->default_value= new (thd->mem_root) Item_null(thd); - Cursor_rowtype *ref; - if (!(ref= new (thd->mem_root) Cursor_rowtype(coffset))) - return NULL; - spvar->field_def.set_cursor_rowtype_ref(ref); + spvar->field_def.set_cursor_rowtype_ref(true); if (sphead->add_for_loop_open_cursor(thd, spcont, spvar, pcursor, coffset, param_lex, parameters))