summaryrefslogtreecommitdiff
path: root/sql/sp_rcontext.cc
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2018-01-29 12:01:17 +0400
committerAlexander Barkov <bar@mariadb.org>2018-01-29 12:01:17 +0400
commitb12430adc716be51810953920448563c87fe0521 (patch)
tree30721264c8545f03807db6c3de3d91eb21ca03b2 /sql/sp_rcontext.cc
parentffcedfab46a7b2fad9b309aa1930e14068d968aa (diff)
downloadmariadb-git-b12430adc716be51810953920448563c87fe0521.tar.gz
MDEV-15107 Add virtual Field::sp_prepare_and_store_item(), make sp_rcontext symmetric for scalar and ROW
After MDEV-14212, the Virtual_tmp_table instance that stores a ROW variable elements is accessible from the underlying Field_row (rather than Item_field_row). This patch makes some further changes by moving the code from sp_instr_xxx, sp_rcontext, Item_xxx to Virtual_tmp_table and Field_xxx. The data type specific code (scalar vs ROW) now resides in a new virtual method Field_xxx::sp_prepare_and_store_item(). The the code in sp_rcontext::set_variable() and sp_eval_expr() is now symmetric for scalar and ROW values. The code in sp_rcontext::set_variable_row_field(), sp_rcontext::set_variable_row_field(), sp_rcontext::set_variable_row() is now symmetric for ROW elements (i.e. scalar and ROW elements inside a ROW). Rationale: Prepare the code to implement these tasks soon easier: - MDEV-12252 ROW data type for stored function return values - MDEV-12307 ROW data type for built-in function return values - MDEV-6121 Data type: Array - MDEV-10593 sql_mode=ORACLE: TYPE .. AS OBJECT: basic functionality - ROW with ROW fields (no MDEV yet) Details: 1. Moving the code in sp_eval_expr() responsible to backup/restore thd->count_cuted_fields, thd->abort_on_warning, thd->transaction.stmt.modified_non_trans_table into a new helper class Sp_eval_expr_state, to reuse it easier. Fixing sp_eval_expr() to use this new class. 2. Moving sp_eval_expr() and sp_prepare_func_item() from public functions to methods in THD, so they can be reused in *.cc files easier without a need to include "sp_head.h". Splitting sp_prepare_func_item() into two parts. Adding a new function sp_fix_func_item(), which fixes the underlying items, but does not do check_cols() for them. Reusing sp_fix_func_item() in Field_row::sp_prepare_and_store_item(). 3. Moving the code to find ROW fields by name from Item to Virtual_tmp_table Moving the code searching for ROW fields by their names from Item_field_row::element_index_by_name() to a new method Item_field_row to Virtual_tmp_table::sp_find_field_by_name(). Adding wrapper methods sp_rcontext::find_row_field_by_name() and find_row_field_by_name_or_error(), to search for a ROW variable fields by the variable offset and its field name. Changing Item_splocal_row_field_by_name::fix_fields() to do use sp_rcontext::find_row_field_by_name_or_error(). Removing virtual Item::element_index_by_name(). 4. Splitting sp_rcontext::set_variable() Adding a new virtual method Field::sp_prepare_and_store_item(). Spliting the two branches of the code in sp_rcontext::set_variable() into two virtual implementations of Field::sp_prepare_and_store_item(), (for Field and for Field_row). Moving the former part of sp_rcontext::set_variable() with the loop doing set_null() for all ROW fields into a new method Virtual_tmp_table::set_all_fields_to_null() and using it in Field_row::sp_prepare_and_store_item(). Moving the former part of sp_rcontext::set_variable() with the loop doing set_variable_row_field() into a new method Virtual_tmp_table::set_all_fields_from_item() and using it in Field_row::sp_prepare_and_store_item(). The loop in the new method now uses sp_prepare_and_store_item() instead of set_variable_row_field(), because saving/restoring THD flags is now done on the upper level. No needs to save/restore on every iteration. 5. Fixing sp_eval_expr() to simply do two things: - backup/restore THD flags - call result_field->sp_prepare_and_store_item() So now sp_eval_expr() can be used for both scalar and ROW variables. Reusing it in sp_rcontext::set_variable*(). 6. Moving the loop in sp_rcontext::set_variable_row() into a new method Virtual_tmp_table::sp_set_all_fields_from_item_list(). Changing the loop body to call field->sp_prepare_and_store_item() instead of doing set_variable_row_field(). This removes saving/restoring of the THD flags from every interation. Instead, adding the code to save/restore the flags around the entire loop in set_variable_row(), using Sp_eval_expr_state. So now saving/restoring is done only once for the entire ROW (a slight performance improvement). 7. Removing the code in sp_instr_set::exec_core() that sets a variable to NULL if the value evaluation failed. sp_rcontext::set_variable() now makes sure to reset the variable properly by effectively calling sp_eval_expr(), which calls virtual Field::sp_prepare_and_store_item(). Removing the similar code from sp_instr_set_row_field::exec_core() and sp_instr_set_row_field_by_name::exec_core(). Removing the method sp_rcontext::set_variable_row_field_to_null(), as it's not used any more. 8. Removing the call for sp_prepare_func_item() from sp_rcontext::set_variable_row_field(), as it was duplicate: it was done inside sp_eval_expr(). Now it's done inside virtual Field::sp_prepare_and_store_item(). 9. Moving the code from sp_instr_set_row_field_by_name::exec_core() into sp_rcontext::set_variable_row_field_by_name(), for symmetry with other sp_instr_set*::exec_core()/sp_rcontext::set_variable*() pairs. Now sp_instr_set_row_field_by_name::exec_core() calls sp_rcontext::set_variable_row_field_by_name(). 10. Misc: - Adding a helper private method sp_rcontext::virtual_tmp_table_for_row(), reusing it in a new sp_rcontext methods. - Removing Item_field_row::get_row_field(), as it's not used any more. - Removing the "Item *result_item" from sp_eval_expr(), as it's not needed any more.
Diffstat (limited to 'sql/sp_rcontext.cc')
-rw-r--r--sql/sp_rcontext.cc135
1 files changed, 45 insertions, 90 deletions
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index 62b5439d84d..43d033ad83e 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -388,22 +388,13 @@ bool Item_field_row::row_create_items(THD *thd, List<Spvar_definition> *list)
}
-Field *Item_field_row::get_row_field(uint i) const
-{
- DBUG_ASSERT(field);
- Virtual_tmp_table **ptable= field->virtual_tmp_table_addr();
- DBUG_ASSERT(ptable);
- return ptable[0]->field[i];
-}
-
-
bool sp_rcontext::set_return_value(THD *thd, Item **return_value_item)
{
DBUG_ASSERT(m_return_value_fld);
m_return_value_set = true;
- return sp_eval_expr(thd, NULL, m_return_value_fld, return_value_item);
+ return thd->sp_eval_expr(m_return_value_fld, return_value_item);
}
@@ -612,84 +603,31 @@ uint sp_rcontext::exit_handler(Diagnostics_area *da)
int sp_rcontext::set_variable(THD *thd, uint idx, Item **value)
{
- Field *field= m_var_table->field[idx];
- if (!value)
- {
- field->set_null();
- return 0;
- }
- Item *dst= m_var_items[idx];
-
- if (dst->cmp_type() != ROW_RESULT)
- return sp_eval_expr(thd, dst, m_var_table->field[idx], value);
-
- DBUG_ASSERT(dst->type() == Item::FIELD_ITEM);
- if (value[0]->type() == Item::NULL_ITEM)
- {
- /*
- We're in a auto-generated sp_inst_set, to assign
- the explicit default NULL value to a ROW variable.
- */
- for (uint i= 0; i < dst->cols(); i++)
- {
- Item_field_row *item_field_row= (Item_field_row*) dst;
- item_field_row->get_row_field(i)->set_null();
- }
- return false;
- }
-
- /**
- - In case if we're assigning a ROW variable from another ROW variable,
- value[0] points to Item_splocal. sp_prepare_func_item() will return the
- fixed underlying Item_field_spvar with ROW members in its aguments().
- - In case if we're assigning from a ROW() value, src and value[0] will
- point to the same Item_row.
- */
- Item *src;
- if (!(src= sp_prepare_func_item(thd, value, dst->cols())) ||
- src->cmp_type() != ROW_RESULT)
- {
- my_error(ER_OPERAND_COLUMNS, MYF(0), dst->cols());
- return true;
- }
- DBUG_ASSERT(dst->cols() == src->cols());
- for (uint i= 0; i < src->cols(); i++)
- set_variable_row_field(thd, idx, i, src->addr(i));
- return false;
-}
-
-
-void sp_rcontext::set_variable_row_field_to_null(THD *thd,
- uint var_idx,
- uint field_idx)
-{
- Item *dst= get_item(var_idx);
- DBUG_ASSERT(dst->type() == Item::FIELD_ITEM);
- DBUG_ASSERT(dst->cmp_type() == ROW_RESULT);
- Item_field_row *item_field_row= (Item_field_row*) dst;
- item_field_row->get_row_field(field_idx)->set_null();
+ DBUG_ENTER("sp_rcontext::set_variable");
+ DBUG_ASSERT(value);
+ DBUG_RETURN(thd->sp_eval_expr(m_var_table->field[idx], value));
}
int sp_rcontext::set_variable_row_field(THD *thd, uint var_idx, uint field_idx,
Item **value)
{
+ DBUG_ENTER("sp_rcontext::set_variable_row_field");
DBUG_ASSERT(value);
- Item *dst= get_item(var_idx);
- DBUG_ASSERT(dst->type() == Item::FIELD_ITEM);
- DBUG_ASSERT(dst->cmp_type() == ROW_RESULT);
- Item_field_row *item_field_row= (Item_field_row*) dst;
+ Virtual_tmp_table *vtable= virtual_tmp_table_for_row(var_idx);
+ DBUG_RETURN(thd->sp_eval_expr(vtable->field[field_idx], value));
+}
- Item *expr_item= sp_prepare_func_item(thd, value);
- if (!expr_item)
- {
- DBUG_ASSERT(thd->is_error());
- return true;
- }
- return sp_eval_expr(thd,
- item_field_row->arguments()[field_idx],
- item_field_row->get_row_field(field_idx),
- value);
+
+int sp_rcontext::set_variable_row_field_by_name(THD *thd, uint var_idx,
+ const LEX_CSTRING &field_name,
+ Item **value)
+{
+ DBUG_ENTER("sp_rcontext::set_variable_row_field_by_name");
+ uint field_idx;
+ if (find_row_field_by_name_or_error(&field_idx, var_idx, field_name))
+ DBUG_RETURN(1);
+ DBUG_RETURN(set_variable_row_field(thd, var_idx, field_idx, value));
}
@@ -697,15 +635,32 @@ int sp_rcontext::set_variable_row(THD *thd, uint var_idx, List<Item> &items)
{
DBUG_ENTER("sp_rcontext::set_variable_row");
DBUG_ASSERT(get_item(var_idx)->cols() == items.elements);
- List_iterator<Item> it(items);
- Item *item;
- for (uint i= 0 ; (item= it++) ; i++)
- {
- int rc;
- if ((rc= set_variable_row_field(thd, var_idx, i, &item)))
- DBUG_RETURN(rc);
- }
- DBUG_RETURN(0);
+ Virtual_tmp_table *vtable= virtual_tmp_table_for_row(var_idx);
+ Sp_eval_expr_state state(thd);
+ DBUG_RETURN(vtable->sp_set_all_fields_from_item_list(thd, items));
+}
+
+
+Virtual_tmp_table *sp_rcontext::virtual_tmp_table_for_row(uint var_idx)
+{
+ DBUG_ASSERT(get_item(var_idx)->type() == Item::FIELD_ITEM);
+ DBUG_ASSERT(get_item(var_idx)->cmp_type() == ROW_RESULT);
+ Field *field= m_var_table->field[var_idx];
+ Virtual_tmp_table **ptable= field->virtual_tmp_table_addr();
+ DBUG_ASSERT(ptable);
+ DBUG_ASSERT(ptable[0]);
+ return ptable[0];
+}
+
+
+bool sp_rcontext::find_row_field_by_name_or_error(uint *field_idx,
+ uint var_idx,
+ const LEX_CSTRING &field_name)
+{
+ Virtual_tmp_table *vtable= virtual_tmp_table_for_row(var_idx);
+ Field *row= m_var_table->field[var_idx];
+ return vtable->sp_find_field_by_name_or_error(field_idx,
+ row->field_name, field_name);
}
@@ -728,7 +683,7 @@ Item_cache *sp_rcontext::create_case_expr_holder(THD *thd,
bool sp_rcontext::set_case_expr(THD *thd, int case_expr_id,
Item **case_expr_item_ptr)
{
- Item *case_expr_item= sp_prepare_func_item(thd, case_expr_item_ptr);
+ Item *case_expr_item= thd->sp_prepare_func_item(case_expr_item_ptr);
if (!case_expr_item)
return true;