summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/field.cc32
-rw-r--r--sql/field.h32
-rw-r--r--sql/item.cc8
-rw-r--r--sql/item.h44
-rw-r--r--sql/item_xmlfunc.cc2
-rw-r--r--sql/sp_head.cc8
-rw-r--r--sql/sp_head.h2
-rw-r--r--sql/sp_pcontext.h2
-rw-r--r--sql/sp_rcontext.cc23
-rw-r--r--sql/sql_lex.cc27
-rw-r--r--sql/sql_type.cc11
-rw-r--r--sql/sql_type.h12
-rw-r--r--sql/sql_yacc.yy2
13 files changed, 113 insertions, 92 deletions
diff --git a/sql/field.cc b/sql/field.cc
index e7329feecb1..068a7285c8e 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -2272,6 +2272,16 @@ void Field_null::sql_type(String &res) const
/****************************************************************************
+ Field_row, e.g. for ROW-type SP variables
+****************************************************************************/
+
+Field_row::~Field_row()
+{
+ delete m_table;
+}
+
+
+/****************************************************************************
Functions for the Field_decimal class
This is an number stored as a pre-space (or pre-zero) string
****************************************************************************/
@@ -10096,6 +10106,21 @@ Field *make_field(TABLE_SHARE *share,
uchar *UNINIT_VAR(bit_ptr);
uchar UNINIT_VAR(bit_offset);
+ DBUG_PRINT("debug", ("field_type: %s, field_length: %u, interval: %p, pack_flag: %s%s%s%s%s",
+ handler->name().ptr(), field_length, interval,
+ FLAGSTR(pack_flag, FIELDFLAG_BINARY),
+ FLAGSTR(pack_flag, FIELDFLAG_INTERVAL),
+ FLAGSTR(pack_flag, FIELDFLAG_NUMBER),
+ FLAGSTR(pack_flag, FIELDFLAG_PACK),
+ FLAGSTR(pack_flag, FIELDFLAG_BLOB)));
+
+ if (handler == &type_handler_row)
+ {
+ DBUG_ASSERT(field_length == 0);
+ DBUG_ASSERT(f_maybe_null(pack_flag));
+ return new (mem_root) Field_row(ptr, field_name);
+ }
+
if (handler->real_field_type() == MYSQL_TYPE_BIT && !f_bit_as_char(pack_flag))
{
bit_ptr= null_pos;
@@ -10117,13 +10142,6 @@ Field *make_field(TABLE_SHARE *share,
null_bit= ((uchar) 1) << null_bit;
}
- DBUG_PRINT("debug", ("field_type: %s, field_length: %u, interval: %p, pack_flag: %s%s%s%s%s",
- handler->name().ptr(), field_length, interval,
- FLAGSTR(pack_flag, FIELDFLAG_BINARY),
- FLAGSTR(pack_flag, FIELDFLAG_INTERVAL),
- FLAGSTR(pack_flag, FIELDFLAG_NUMBER),
- FLAGSTR(pack_flag, FIELDFLAG_PACK),
- FLAGSTR(pack_flag, FIELDFLAG_BLOB)));
if (f_is_alpha(pack_flag))
{
diff --git a/sql/field.h b/sql/field.h
index 5999f3e0a34..3147374d496 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -44,6 +44,7 @@ class Column_statistics_collected;
class Item_func;
class Item_bool_func;
class Item_equal;
+class Virtual_tmp_table;
enum enum_check_fields
{
@@ -1510,6 +1511,11 @@ public:
/* Mark field in read map. Updates also virtual fields */
void register_field_in_read_map();
+ virtual Virtual_tmp_table **virtual_tmp_table_addr()
+ {
+ return NULL;
+ }
+
friend int cre_myisam(char * name, register TABLE *form, uint options,
ulonglong auto_increment_value);
friend class Copy_field;
@@ -3814,6 +3820,19 @@ public:
};
+class Field_row: public Field_null
+{
+ class Virtual_tmp_table *m_table;
+public:
+ Field_row(uchar *ptr_arg, const LEX_CSTRING *field_name_arg)
+ :Field_null(ptr_arg, 0, Field::NONE, field_name_arg, &my_charset_bin),
+ m_table(NULL)
+ {}
+ ~Field_row();
+ Virtual_tmp_table **virtual_tmp_table_addr() { return &m_table; }
+};
+
+
extern const LEX_CSTRING null_clex_str;
Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root,
@@ -4164,9 +4183,7 @@ public:
{ }
const Type_handler *type_handler() const
{
- return is_row() || is_table_rowtype_ref() || is_cursor_rowtype_ref() ?
- &type_handler_row :
- Type_handler_hybrid_field_type::type_handler();
+ return Type_handler_hybrid_field_type::type_handler();
}
bool is_column_type_ref() const { return m_column_type_ref != 0; }
bool is_table_rowtype_ref() const { return m_table_rowtype_ref != 0; }
@@ -4186,6 +4203,8 @@ public:
}
void set_table_rowtype_ref(class Table_ident *ref)
{
+ DBUG_ASSERT(ref);
+ set_handler(&type_handler_row);
m_table_rowtype_ref= ref;
}
@@ -4193,9 +4212,10 @@ public:
{
return m_cursor_rowtype_offset;
}
- void set_cursor_rowtype_ref(bool ref, uint offset)
+ void set_cursor_rowtype_ref(uint offset)
{
- m_cursor_rowtype_ref= ref;
+ set_handler(&type_handler_row);
+ m_cursor_rowtype_ref= true;
m_cursor_rowtype_offset= offset;
}
@@ -4224,6 +4244,8 @@ public:
}
void set_row_field_definitions(Row_definition_list *list)
{
+ DBUG_ASSERT(list);
+ set_handler(&type_handler_row);
m_row_field_definitions= list;
}
diff --git a/sql/item.cc b/sql/item.cc
index 72703c2f7b0..999b64fcc1e 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1753,17 +1753,15 @@ void Item_sp_variable::make_field(THD *thd, Send_field *field)
Item_splocal::Item_splocal(THD *thd, const LEX_CSTRING *sp_var_name,
uint sp_var_idx,
- enum_field_types sp_var_type,
+ const Type_handler *handler,
uint pos_in_q, uint len_in_q):
Item_sp_variable(thd, sp_var_name),
Rewritable_query_parameter(pos_in_q, len_in_q),
+ Type_handler_hybrid_field_type(handler),
m_var_idx(sp_var_idx)
{
maybe_null= TRUE;
-
- sp_var_type= real_type_to_type(sp_var_type);
- m_type= sp_map_item_type(sp_var_type);
- set_handler_by_field_type(sp_var_type);
+ m_type= sp_map_item_type(handler);
}
diff --git a/sql/item.h b/sql/item.h
index f21c88c69a4..d3636ccc263 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -2093,17 +2093,6 @@ public:
};
-class Item_spvar_args: public Item_args
-{
- Virtual_tmp_table *m_table;
-public:
- Item_spvar_args():Item_args(), m_table(NULL) { }
- ~Item_spvar_args();
- bool row_create_items(THD *thd, List<Spvar_definition> *list);
- Field *get_row_field(uint i) const;
-};
-
-
/*
Class to be used to enumerate all field references in an item tree. This
includes references to outside but not fields of the tables within a
@@ -2337,7 +2326,7 @@ protected:
bool append_value_for_log(THD *thd, String *str);
public:
Item_splocal(THD *thd, const LEX_CSTRING *sp_var_name, uint sp_var_idx,
- enum_field_types sp_var_type,
+ const Type_handler *handler,
uint pos_in_q= 0, uint len_in_q= 0);
bool fix_fields(THD *, Item **);
@@ -2390,20 +2379,6 @@ public:
};
-class Item_splocal_row: public Item_splocal
-{
-public:
- Item_splocal_row(THD *thd, const LEX_CSTRING *sp_var_name,
- uint sp_var_idx, uint pos_in_q, uint len_in_q)
- :Item_splocal(thd, sp_var_name, sp_var_idx, MYSQL_TYPE_NULL,
- pos_in_q, len_in_q)
- {
- set_handler(&type_handler_row);
- }
- enum Type type() const { return ROW_ITEM; }
-};
-
-
/**
An Item_splocal variant whose data type becomes known only at
sp_rcontext creation time, e.g. "DECLARE var1 t1.col1%TYPE".
@@ -2415,7 +2390,7 @@ public:
const LEX_CSTRING *sp_var_name,
uint sp_var_idx,
uint pos_in_q, uint len_in_q)
- :Item_splocal(thd, sp_var_name, sp_var_idx, MYSQL_TYPE_NULL,
+ :Item_splocal(thd, sp_var_name, sp_var_idx, &type_handler_null,
pos_in_q, len_in_q)
{ }
};
@@ -2437,9 +2412,9 @@ public:
const LEX_CSTRING *sp_var_name,
const LEX_CSTRING *sp_field_name,
uint sp_var_idx, uint sp_field_idx,
- enum_field_types sp_var_type,
+ const Type_handler *handler,
uint pos_in_q= 0, uint len_in_q= 0)
- :Item_splocal(thd, sp_var_name, sp_var_idx, sp_var_type,
+ :Item_splocal(thd, sp_var_name, sp_var_idx, handler,
pos_in_q, len_in_q),
m_field_name(*sp_field_name),
m_field_idx(sp_field_idx)
@@ -2461,11 +2436,11 @@ public:
const LEX_CSTRING *sp_var_name,
const LEX_CSTRING *sp_field_name,
uint sp_var_idx,
- enum_field_types sp_var_type,
+ const Type_handler *handler,
uint pos_in_q= 0, uint len_in_q= 0)
:Item_splocal_row_field(thd, sp_var_name, sp_field_name,
sp_var_idx, 0 /* field index will be set later */,
- sp_var_type, pos_in_q, len_in_q)
+ handler, pos_in_q, len_in_q)
{ }
bool fix_fields(THD *thd, Item **it);
void print(String *str, enum_query_type query_type);
@@ -2930,14 +2905,13 @@ public:
Item_field for the ROW data type
*/
class Item_field_row: public Item_field,
- public Item_spvar_args
+ public Item_args
{
public:
Item_field_row(THD *thd, Field *field)
:Item_field(thd, field),
- Item_spvar_args()
+ Item_args()
{ }
-
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_field_row>(thd, mem_root, this); }
@@ -2955,6 +2929,8 @@ public:
}
return false;
}
+ bool row_create_items(THD *thd, List<Spvar_definition> *list);
+ Field *get_row_field(uint i) const;
};
diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc
index 2b3d2374405..8b428a45bee 100644
--- a/sql/item_xmlfunc.cc
+++ b/sql/item_xmlfunc.cc
@@ -2621,7 +2621,7 @@ my_xpath_parse_VariableReference(MY_XPATH *xpath)
(spv= spc->find_variable(&name, false)))
{
Item_splocal *splocal= new (thd->mem_root)
- Item_splocal(thd, &name, spv->offset, spv->sql_type(), 0);
+ Item_splocal(thd, &name, spv->offset, spv->type_handler(), 0);
#ifndef DBUG_OFF
if (splocal)
splocal->m_sp= lex->sphead;
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index ed4b76026a0..82123c6ad6e 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -70,8 +70,12 @@ static void reset_start_time_for_sp(THD *thd)
Item::Type
-sp_map_item_type(enum enum_field_types type)
+sp_map_item_type(const Type_handler *handler)
{
+ if (handler == &type_handler_row)
+ return Item::ROW_ITEM;
+ enum_field_types type= real_type_to_type(handler->real_field_type());
+
switch (type) {
case MYSQL_TYPE_BIT:
case MYSQL_TYPE_TINY:
@@ -4757,11 +4761,11 @@ bool sp_head::spvar_fill_row(THD *thd,
sp_variable *spvar,
Row_definition_list *defs)
{
+ spvar->field_def.set_row_field_definitions(defs);
spvar->field_def.field_name= spvar->name;
if (fill_spvar_definition(thd, &spvar->field_def))
return true;
row_fill_field_definitions(thd, defs);
- spvar->field_def.set_row_field_definitions(defs);
return false;
}
diff --git a/sql/sp_head.h b/sql/sp_head.h
index 272bc5d445c..ac0f406f854 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -41,7 +41,7 @@
*/
Item::Type
-sp_map_item_type(enum enum_field_types type);
+sp_map_item_type(const Type_handler *handler);
uint
sp_get_flags_for_command(LEX *lex);
diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h
index 9c879099410..990ad35cb57 100644
--- a/sql/sp_pcontext.h
+++ b/sql/sp_pcontext.h
@@ -60,8 +60,6 @@ public:
Spvar_definition field_def;
/// Field-type of the SP-variable.
- enum_field_types sql_type() const { return field_def.real_field_type(); }
-
const Type_handler *type_handler() const { return field_def.type_handler(); }
public:
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index 8a86d522e1e..ee13eac6a1c 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -358,10 +358,13 @@ bool sp_rcontext::init_var_items(THD *thd,
}
-bool Item_spvar_args::row_create_items(THD *thd, List<Spvar_definition> *list)
+bool Item_field_row::row_create_items(THD *thd, List<Spvar_definition> *list)
{
DBUG_ASSERT(list);
- if (!(m_table= create_virtual_tmp_table(thd, *list)))
+ DBUG_ASSERT(field);
+ Virtual_tmp_table **ptable= field->virtual_tmp_table_addr();
+ DBUG_ASSERT(ptable);
+ if (!(ptable[0]= create_virtual_tmp_table(thd, *list)))
return true;
if (alloc_arguments(thd, list->elements))
@@ -372,23 +375,19 @@ bool Item_spvar_args::row_create_items(THD *thd, List<Spvar_definition> *list)
for (arg_count= 0; (def= it++); arg_count++)
{
if (!(args[arg_count]= new (thd->mem_root)
- Item_field(thd, m_table->field[arg_count])))
+ Item_field(thd, ptable[0]->field[arg_count])))
return true;
}
return false;
}
-Field *Item_spvar_args::get_row_field(uint i) const
+Field *Item_field_row::get_row_field(uint i) const
{
- DBUG_ASSERT(m_table);
- return m_table->field[i];
-}
-
-
-Item_spvar_args::~Item_spvar_args()
-{
- delete m_table;
+ DBUG_ASSERT(field);
+ Virtual_tmp_table **ptable= field->virtual_tmp_table_addr();
+ DBUG_ASSERT(ptable);
+ return ptable[0]->field[i];
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 938b386a816..831b4ee4ca7 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -5294,7 +5294,11 @@ LEX::sp_variable_declarations_copy_type_finalize(THD *thd, int nvars,
{
sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i);
spvar->field_def.set_type(ref);
- spvar->field_def.set_row_field_definitions(fields);
+ if (fields)
+ {
+ DBUG_ASSERT(ref.type_handler() == &type_handler_row);
+ spvar->field_def.set_row_field_definitions(fields);
+ }
spvar->field_def.field_name= spvar->name;
}
if (sp_variable_declarations_set_default(thd, nvars, default_value))
@@ -5340,9 +5344,9 @@ bool LEX::sp_variable_declarations_row_finalize(THD *thd, int nvars,
for (uint i= 0 ; i < (uint) nvars ; i++)
{
sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i);
+ spvar->field_def.set_row_field_definitions(row);
if (sphead->fill_spvar_definition(thd, &spvar->field_def, &spvar->name))
return true;
- spvar->field_def.set_row_field_definitions(row);
}
if (sp_variable_declarations_set_default(thd, nvars, dflt_value_item))
@@ -5428,7 +5432,7 @@ LEX::sp_variable_declarations_cursor_rowtype_finalize(THD *thd, int nvars,
{
sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i);
- spvar->field_def.set_cursor_rowtype_ref(true, offset);
+ spvar->field_def.set_cursor_rowtype_ref(offset);
sp_instr_cursor_copy_struct *instr=
new (thd->mem_root) sp_instr_cursor_copy_struct(sphead->instructions(),
spcont, pcursor->lex(),
@@ -5592,7 +5596,7 @@ LEX::sp_add_for_loop_cursor_variable(THD *thd,
if (!(spvar->default_value= new (thd->mem_root) Item_null(thd)))
return NULL;
- spvar->field_def.set_cursor_rowtype_ref(true, coffset);
+ spvar->field_def.set_cursor_rowtype_ref(coffset);
if (sphead->add_for_loop_open_cursor(thd, spcont, spvar, pcursor, coffset,
param_lex, parameters))
@@ -5616,7 +5620,7 @@ bool LEX::sp_for_loop_condition(THD *thd, const Lex_for_loop_st &loop)
{
sp_variable *src= i == 0 ? loop.m_index : loop.m_upper_bound;
args[i]= new (thd->mem_root)
- Item_splocal(thd, &src->name, src->offset, src->sql_type());
+ Item_splocal(thd, &src->name, src->offset, src->type_handler());
if (args[i] == NULL)
return true;
#ifndef DBUG_OFF
@@ -5750,7 +5754,7 @@ bool LEX::sp_for_loop_increment(THD *thd, const Lex_for_loop_st &loop)
{
Item_splocal *splocal= new (thd->mem_root)
Item_splocal(thd, &loop.m_index->name, loop.m_index->offset,
- loop.m_index->sql_type());
+ loop.m_index->type_handler());
if (splocal == NULL)
return true;
#ifndef DBUG_OFF
@@ -6521,7 +6525,7 @@ Item_splocal *LEX::create_item_spvar_row_field(THD *thd,
{
if (!(item= new (thd->mem_root)
Item_splocal_row_field_by_name(thd, a, b, spv->offset,
- MYSQL_TYPE_NULL,
+ &type_handler_null,
pos.pos(), pos.length())))
return NULL;
}
@@ -6535,7 +6539,7 @@ Item_splocal *LEX::create_item_spvar_row_field(THD *thd,
if (!(item= new (thd->mem_root)
Item_splocal_row_field(thd, a, b,
spv->offset, row_field_offset,
- def->real_field_type(),
+ def->type_handler(),
pos.pos(), pos.length())))
return NULL;
}
@@ -6704,7 +6708,7 @@ Item *LEX::create_item_limit(THD *thd,
Query_fragment pos(thd, sphead, start, end);
Item_splocal *item;
if (!(item= new (thd->mem_root) Item_splocal(thd, a,
- spv->offset, spv->sql_type(),
+ spv->offset, spv->type_handler(),
pos.pos(), pos.length())))
return NULL;
#ifndef DBUG_OFF
@@ -6823,11 +6827,8 @@ Item *LEX::create_item_ident_sp(THD *thd, LEX_CSTRING *name,
spv->offset,
pos.pos(),
pos.length()) :
- spv->field_def.is_row() || spv->field_def.is_table_rowtype_ref() ?
- new (thd->mem_root) Item_splocal_row(thd, name, spv->offset,
- pos.pos(), pos.length()) :
new (thd->mem_root) Item_splocal(thd, name,
- spv->offset, spv->sql_type(),
+ spv->offset, spv->type_handler(),
pos.pos(), pos.length());
if (splocal == NULL)
return NULL;
diff --git a/sql/sql_type.cc b/sql/sql_type.cc
index 737d01f7b89..d6b861eaaf2 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -1589,6 +1589,17 @@ bool Type_handler_null::
return false;
}
+bool Type_handler_row::
+ Column_definition_prepare_stage1(THD *thd,
+ MEM_ROOT *mem_root,
+ Column_definition *def,
+ handler *file,
+ ulonglong table_flags) const
+{
+ def->create_length_to_internal_length_null();
+ return false;
+}
+
bool Type_handler_newdecimal::
Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
diff --git a/sql/sql_type.h b/sql/sql_type.h
index 910172134fd..c2e2127994a 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -1046,18 +1046,13 @@ public:
}
bool Column_definition_fix_attributes(Column_definition *c) const
{
- DBUG_ASSERT(0);
- return true;
+ return false;
}
bool Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *c,
handler *file,
- ulonglong table_flags) const
- {
- DBUG_ASSERT(0);
- return true;
- }
+ ulonglong table_flags) const;
bool Column_definition_redefine_stage1(Column_definition *def,
const Column_definition *dup,
const handler *file,
@@ -1071,8 +1066,7 @@ public:
handler *file,
ulonglong table_flags) const
{
- DBUG_ASSERT(0);
- return true;
+ return false;
}
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 0a62361e222..8c6c6bb58e8 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -396,7 +396,7 @@ LEX::create_item_for_sp_var(LEX_CSTRING *name, sp_variable *spvar,
len_in_q= (uint)(end_in_q - start_in_q);
item= new (thd->mem_root)
- Item_splocal(thd, name, spvar->offset, spvar->sql_type(),
+ Item_splocal(thd, name, spvar->offset, spvar->type_handler(),
pos_in_q, len_in_q);
#ifndef DBUG_OFF