summaryrefslogtreecommitdiff
path: root/sql/sp_rcontext.cc
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2017-02-02 22:59:07 +0400
committerAlexander Barkov <bar@mariadb.org>2017-04-05 15:02:56 +0400
commit72f43df623261d5fe579cb355451d84216c8882d (patch)
tree6d2921d9e807e624244af9273b2332e184a5bc60 /sql/sp_rcontext.cc
parentffbb2bbc09e7fc8c0f60d5c42ce521b4c31c94a7 (diff)
downloadmariadb-git-72f43df623261d5fe579cb355451d84216c8882d.tar.gz
MDEV-10914 ROW data type for stored routine variables
Diffstat (limited to 'sql/sp_rcontext.cc')
-rw-r--r--sql/sp_rcontext.cc122
1 files changed, 117 insertions, 5 deletions
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index 5fcdbf42313..17c91b09727 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -222,23 +222,65 @@ bool sp_rcontext::init_var_items(THD *thd,
if (!m_var_items.array())
return true;
- for (uint idx = 0; idx < num_vars; ++idx)
+ DBUG_ASSERT(field_def_lst.elements == num_vars);
+ List_iterator<Spvar_definition> it(field_def_lst);
+ Spvar_definition *def= it++;
+
+ for (uint idx= 0; idx < num_vars; ++idx, def= it++)
{
- if (!(m_var_items[idx]= new (thd->mem_root) Item_field(thd, m_var_table->field[idx])))
- return true;
+ Field *field= m_var_table->field[idx];
+ if (def->is_row())
+ {
+ Item_field_row *item= new (thd->mem_root) Item_field_row(thd, field);
+ if (!(m_var_items[idx]= item) ||
+ item->row_create_items(thd, def->row_field_definitions()))
+ return true;
+ }
+ else
+ {
+ if (!(m_var_items[idx]= new (thd->mem_root) Item_field(thd, field)))
+ return true;
+ }
}
+ return false;
+}
+
+
+bool Item_spvar_args::row_create_items(THD *thd, List<Spvar_definition> *list)
+{
+ DBUG_ASSERT(list);
+ if (!(m_table= create_virtual_tmp_table(thd, *list)))
+ return true;
+
+ if (alloc_arguments(thd, list->elements))
+ return true;
+ List_iterator<Spvar_definition> it(*list);
+ Spvar_definition *def;
+ for (arg_count= 0; (def= it++); arg_count++)
+ {
+ if (!(args[arg_count]= new (thd->mem_root)
+ Item_field(thd, m_table->field[arg_count])))
+ return true;
+ }
return false;
}
+Item_spvar_args::~Item_spvar_args()
+{
+ if (m_table)
+ free_blobs(m_table);
+}
+
+
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, m_return_value_fld, return_value_item);
+ return sp_eval_expr(thd, NULL, m_return_value_fld, return_value_item);
}
@@ -455,8 +497,78 @@ int sp_rcontext::set_variable(THD *thd, uint idx, Item **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();
+}
+
- return sp_eval_expr(thd, field, value);
+int sp_rcontext::set_variable_row_field(THD *thd, uint var_idx, uint field_idx,
+ Item **value)
+{
+ 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;
+
+ 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);
}