summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2017-03-24 17:52:55 +0400
committerAlexander Barkov <bar@mariadb.org>2017-03-24 17:52:55 +0400
commit48c59f394bb9bd4dfd34be19ff4cf933557eb017 (patch)
treee94ad81afab772d6913502cc155d1a51a043c11c /sql
parent1b3bd00c6b517dec73b35672875aeda9f2143bed (diff)
downloadmariadb-git-48c59f394bb9bd4dfd34be19ff4cf933557eb017.tar.gz
MDEV-12338 Split Item_type_holder::get_real_type() into virtual Item::real_type_handler()
Diffstat (limited to 'sql')
-rw-r--r--sql/item.cc134
-rw-r--r--sql/item.h28
-rw-r--r--sql/item_sum.h8
-rw-r--r--sql/item_windowfunc.h2
-rw-r--r--sql/sql_type.cc6
-rw-r--r--sql/sql_type.h18
6 files changed, 70 insertions, 126 deletions
diff --git a/sql/item.cc b/sql/item.cc
index b0337efff9e..2f2b773b795 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -5670,6 +5670,25 @@ error:
return TRUE;
}
+
+const Type_handler *Item_field::real_type_handler() const
+{
+ /*
+ Item_field::field_type ask Field_type() but sometimes field return
+ a different type, like for enum/set, so we need to ask real type.
+ */
+ if (field->is_created_from_null_item)
+ return &type_handler_null;
+ /* work around about varchar type field detection */
+ enum_field_types type= field->real_type();
+ // TODO: We should add Field::real_type_handler() eventually
+ if (type == MYSQL_TYPE_STRING && field->type() == MYSQL_TYPE_VAR_STRING)
+ type= MYSQL_TYPE_VAR_STRING;
+ return Type_handler::get_handler_by_real_type(type);
+
+}
+
+
/*
@brief
Mark virtual columns as used in a partitioning expression
@@ -10009,7 +10028,7 @@ void Item_cache_row::set_null()
Item_type_holder::Item_type_holder(THD *thd, Item *item)
:Item(thd, item),
- Type_handler_hybrid_real_field_type(get_real_type(item)),
+ Type_handler_hybrid_field_type(item->real_type_handler()),
enum_set_typelib(0)
{
DBUG_ASSERT(item->fixed);
@@ -10025,87 +10044,6 @@ Item_type_holder::Item_type_holder(THD *thd, Item *item)
/**
- Find real field type of item.
-
- @return
- type of field which should be created to store item value
-*/
-
-enum_field_types Item_type_holder::get_real_type(Item *item)
-{
- if (item->type() == REF_ITEM)
- item= item->real_item();
- switch(item->type())
- {
- case FIELD_ITEM:
- {
- /*
- Item_field::field_type ask Field_type() but sometimes field return
- a different type, like for enum/set, so we need to ask real type.
- */
- Field *field= ((Item_field *) item)->field;
- enum_field_types type= field->real_type();
- if (field->is_created_from_null_item)
- return MYSQL_TYPE_NULL;
- /* work around about varchar type field detection */
- if (type == MYSQL_TYPE_STRING && field->type() == MYSQL_TYPE_VAR_STRING)
- return MYSQL_TYPE_VAR_STRING;
- return type;
- }
- case SUM_FUNC_ITEM:
- {
- /*
- Argument of aggregate function sometimes should be asked about field
- type
- */
- Item_sum *item_sum= (Item_sum *) item;
- if (item_sum->keep_field_type())
- return get_real_type(item_sum->get_arg(0));
- break;
- }
- case FUNC_ITEM:
- if (((Item_func *) item)->functype() == Item_func::GUSERVAR_FUNC)
- {
- /*
- There are work around of problem with changing variable type on the
- fly and variable always report "string" as field type to get
- acceptable information for client in send_field, so we make field
- type from expression type.
- */
- switch (item->result_type()) {
- case STRING_RESULT:
- return MYSQL_TYPE_VARCHAR;
- case INT_RESULT:
- return MYSQL_TYPE_LONGLONG;
- case REAL_RESULT:
- return MYSQL_TYPE_DOUBLE;
- case DECIMAL_RESULT:
- return MYSQL_TYPE_NEWDECIMAL;
- case ROW_RESULT:
- case TIME_RESULT:
- DBUG_ASSERT(0);
- return MYSQL_TYPE_VARCHAR;
- }
- }
- break;
- case TYPE_HOLDER:
- /*
- Item_type_holder and Item_blob should not appear in this context.
- In case they for some reasons do, returning field_type() is wrong anyway.
- They must return Item_type_holder::real_field_type() instead, to make
- the code in sql_type.cc and sql_type.h happy, as it expectes
- Field::real_type()-compatible rather than Field::field_type()-compatible
- valies in some places, and may in the future add some asserts preventing
- use of field_type() instead of real_type() and the other way around.
- */
- DBUG_ASSERT(0);
- default:
- break;
- }
- return item->field_type();
-}
-
-/**
Find field type which can carry current Item_type_holder type and
type of given Item.
@@ -10123,14 +10061,13 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
uint max_length_orig= max_length;
uint decimals_orig= decimals;
DBUG_ENTER("Item_type_holder::join_types");
- DBUG_PRINT("info:", ("was type %d len %d, dec %d name %s",
- real_field_type(), max_length, decimals,
+ DBUG_PRINT("info:", ("was type %s len %d, dec %d name %s",
+ real_type_handler()->name().ptr(), max_length, decimals,
(name ? name : "<NULL>")));
- DBUG_PRINT("info:", ("in type %d len %d, dec %d",
- get_real_type(item),
+ DBUG_PRINT("info:", ("in type %s len %d, dec %d",
+ item->real_type_handler()->name().ptr(),
item->max_length, item->decimals));
- const Type_handler *item_type_handler=
- Type_handler::get_handler_by_real_type(get_real_type(item));
+ const Type_handler *item_type_handler= item->real_type_handler();
if (aggregate_for_result(item_type_handler))
{
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
@@ -10218,13 +10155,13 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
int delta1= max_length_orig - decimals_orig;
int delta2= item->max_length - item->decimals;
max_length= MY_MAX(delta1, delta2) + decimals;
- if (Item_type_holder::real_field_type() == MYSQL_TYPE_FLOAT &&
+ if (Item_type_holder::real_type_handler() == &type_handler_float &&
max_length > FLT_DIG + 2)
{
max_length= MAX_FLOAT_STR_LENGTH;
decimals= NOT_FIXED_DEC;
}
- else if (Item_type_holder::real_field_type() == MYSQL_TYPE_DOUBLE &&
+ else if (Item_type_holder::real_type_handler() == &type_handler_double &&
max_length > DBL_DIG + 2)
{
max_length= MAX_DOUBLE_STR_LENGTH;
@@ -10245,8 +10182,9 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
/* Remember decimal integer part to be used in DECIMAL_RESULT handleng */
prev_decimal_int_part= decimal_int_part();
- DBUG_PRINT("info", ("become type: %d len: %u dec: %u",
- (int) real_field_type(), max_length, (uint) decimals));
+ DBUG_PRINT("info", ("become type: %s len: %u dec: %u",
+ real_type_handler()->name().ptr(),
+ max_length, (uint) decimals));
DBUG_RETURN(FALSE);
}
@@ -10269,7 +10207,7 @@ Field *Item_type_holder::make_field_by_type(TABLE *table)
uchar *null_ptr= maybe_null ? (uchar*) "" : 0;
Field *field;
- switch (Item_type_holder::real_field_type()) {
+ switch (Item_type_holder::real_type_handler()->real_field_type()) {
case MYSQL_TYPE_ENUM:
DBUG_ASSERT(enum_set_typelib);
field= new Field_enum((uchar *) 0, max_length, null_ptr, 0,
@@ -10305,8 +10243,8 @@ Field *Item_type_holder::make_field_by_type(TABLE *table)
*/
void Item_type_holder::get_full_info(Item *item)
{
- if (Item_type_holder::real_field_type() == MYSQL_TYPE_ENUM ||
- Item_type_holder::real_field_type() == MYSQL_TYPE_SET)
+ if (Item_type_holder::real_type_handler() == &type_handler_enum ||
+ Item_type_holder::real_type_handler() == &type_handler_set)
{
if (item->type() == Item::SUM_FUNC_ITEM &&
(((Item_sum*)item)->sum_func() == Item_sum::MAX_FUNC ||
@@ -10317,11 +10255,11 @@ void Item_type_holder::get_full_info(Item *item)
field (or MIN|MAX(enum|set field)) and number of NULL fields
*/
DBUG_ASSERT((enum_set_typelib &&
- get_real_type(item) == MYSQL_TYPE_NULL) ||
+ item->real_type_handler() == &type_handler_null) ||
(!enum_set_typelib &&
item->real_item()->type() == Item::FIELD_ITEM &&
- (get_real_type(item->real_item()) == MYSQL_TYPE_ENUM ||
- get_real_type(item->real_item()) == MYSQL_TYPE_SET) &&
+ (item->real_type_handler() == &type_handler_enum ||
+ item->real_type_handler() == &type_handler_set) &&
((Field_enum*)((Item_field *) item->real_item())->field)->typelib));
if (!enum_set_typelib)
{
diff --git a/sql/item.h b/sql/item.h
index d3b1189f80f..e7086a5cbb3 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -699,6 +699,10 @@ public:
{
return Type_handler::get_handler_by_field_type(field_type());
}
+ virtual const Type_handler *real_type_handler() const
+ {
+ return type_handler();
+ }
virtual const Type_handler *cast_to_int_type_handler() const
{
return type_handler();
@@ -2409,6 +2413,7 @@ public:
{
return field->type();
}
+ const Type_handler *real_type_handler() const;
enum_monotonicity_info get_monotonicity_info() const
{
return MONOTONIC_STRICT_INCREASING;
@@ -3355,6 +3360,12 @@ public:
{ max_length= length; }
enum Type type() const { return TYPE_HOLDER; }
enum_field_types field_type() const { return MYSQL_TYPE_BLOB; }
+ const Type_handler *real_type_handler() const
+ {
+ // Should not be called, Item_blob is used for SHOW purposes only.
+ DBUG_ASSERT(0);
+ return &type_handler_varchar;
+ }
Field *create_field_for_schema(THD *thd, TABLE *table)
{ return tmp_table_field_from_field_type(table, false, true); }
};
@@ -4072,6 +4083,8 @@ public:
{ return (*ref)->setup_fast_field_copier(field); }
enum Item_result result_type () const { return (*ref)->result_type(); }
enum_field_types field_type() const { return (*ref)->field_type(); }
+ const Type_handler *real_type_handler() const
+ { return (*ref)->real_type_handler(); }
Field *get_tmp_table_field()
{ return result_field ? result_field : (*ref)->get_tmp_table_field(); }
Item *get_tmp_table_item(THD *thd);
@@ -5602,7 +5615,7 @@ public:
single SP/PS execution.
*/
class Item_type_holder: public Item,
- public Type_handler_hybrid_real_field_type
+ public Type_handler_hybrid_field_type
{
protected:
TYPELIB *enum_set_typelib;
@@ -5616,11 +5629,11 @@ public:
Item_type_holder(THD*, Item*);
const Type_handler *type_handler() const
- { return Type_handler_hybrid_real_field_type::type_handler(); }
+ { return Type_handler_hybrid_field_type::type_handler(); }
enum_field_types field_type() const
- { return Type_handler_hybrid_real_field_type::field_type(); }
+ { return Type_handler_hybrid_field_type::field_type(); }
enum_field_types real_field_type() const
- { return Type_handler_hybrid_real_field_type::real_field_type(); }
+ { return Type_handler_hybrid_field_type::real_field_type(); }
enum Item_result result_type () const
{
/*
@@ -5635,7 +5648,11 @@ public:
As soon as we get BIT as one of the joined types, the result field
type cannot be numeric: it's either BIT, or VARBINARY.
*/
- return Type_handler_hybrid_real_field_type::result_type();
+ return Type_handler_hybrid_field_type::result_type();
+ }
+ const Type_handler *real_type_handler() const
+ {
+ return Item_type_holder::type_handler();
}
enum Type type() const { return TYPE_HOLDER; }
@@ -5645,7 +5662,6 @@ public:
String *val_str(String*);
bool join_types(THD *thd, Item *);
Field *make_field_by_type(TABLE *table);
- static enum_field_types get_real_type(Item *);
Field::geometry_type get_geometry_type() const { return geometry_type; };
Item* get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; }
};
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 3ceb2a04dcc..ee1c10f9fbe 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -456,7 +456,6 @@ public:
Updated value is then saved in the field.
*/
virtual void update_field()=0;
- virtual bool keep_field_type(void) const { return 0; }
virtual void fix_length_and_dec() { maybe_null=1; null_value=1; }
virtual Item *result_item(THD *thd, Field *field);
@@ -520,7 +519,7 @@ public:
st_select_lex *depended_from()
{ return (nest_level == aggr_level ? 0 : aggr_sel); }
- Item *get_arg(uint i) { return args[i]; }
+ Item *get_arg(uint i) const { return args[i]; }
Item *set_arg(uint i, THD *thd, Item *new_val);
uint get_arg_count() const { return arg_count; }
@@ -1047,7 +1046,10 @@ protected:
my_decimal *val_decimal(my_decimal *);
void reset_field();
String *val_str(String *);
- bool keep_field_type(void) const { return 1; }
+ const Type_handler *real_type_handler() const
+ {
+ return get_arg(0)->real_type_handler();
+ }
const Type_handler *type_handler() const
{ return Type_handler_hybrid_field_type::type_handler(); }
enum Item_result result_type () const
diff --git a/sql/item_windowfunc.h b/sql/item_windowfunc.h
index b4953c8a6ac..193ac04b315 100644
--- a/sql/item_windowfunc.h
+++ b/sql/item_windowfunc.h
@@ -303,8 +303,6 @@ class Item_sum_hybrid_simple : public Item_sum,
my_decimal *val_decimal(my_decimal *);
void reset_field();
String *val_str(String *);
- /* TODO(cvicentiu) copied from Item_sum_hybrid, what does it do? */
- bool keep_field_type(void) const { return 1; }
enum Item_result result_type() const
{ return Type_handler_hybrid_field_type::result_type(); }
enum Item_result cmp_type() const
diff --git a/sql/sql_type.cc b/sql/sql_type.cc
index f9d7586f784..67ecd2af45e 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -25,7 +25,6 @@ static Type_handler_short type_handler_short;
static Type_handler_long type_handler_long;
static Type_handler_int24 type_handler_int24;
static Type_handler_year type_handler_year;
-static Type_handler_float type_handler_float;
static Type_handler_time type_handler_time;
static Type_handler_time2 type_handler_time2;
static Type_handler_date type_handler_date;
@@ -39,18 +38,19 @@ static Type_handler_tiny_blob type_handler_tiny_blob;
static Type_handler_medium_blob type_handler_medium_blob;
static Type_handler_long_blob type_handler_long_blob;
static Type_handler_blob type_handler_blob;
-static Type_handler_enum type_handler_enum;
-static Type_handler_set type_handler_set;
Type_handler_null type_handler_null;
Type_handler_row type_handler_row;
Type_handler_varchar type_handler_varchar;
Type_handler_longlong type_handler_longlong;
+Type_handler_float type_handler_float;
Type_handler_double type_handler_double;
Type_handler_newdecimal type_handler_newdecimal;
Type_handler_datetime type_handler_datetime;
Type_handler_bit type_handler_bit;
+Type_handler_enum type_handler_enum;
+Type_handler_set type_handler_set;
#ifdef HAVE_SPATIAL
Type_handler_geometry type_handler_geometry;
diff --git a/sql/sql_type.h b/sql/sql_type.h
index 963e10a57a7..189b1b0dc27 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -1450,29 +1450,19 @@ public:
};
-/**
- This class is used for Item_type_holder, which preserves real_type.
-*/
-class Type_handler_hybrid_real_field_type:
- public Type_handler_hybrid_field_type
-{
-public:
- Type_handler_hybrid_real_field_type(enum_field_types type)
- :Type_handler_hybrid_field_type(Type_handler::
- get_handler_by_real_type(type))
- { }
-};
-
-
extern Type_handler_row type_handler_row;
extern Type_handler_null type_handler_null;
extern Type_handler_varchar type_handler_varchar;
extern Type_handler_longlong type_handler_longlong;
+extern Type_handler_float type_handler_float;
extern Type_handler_double type_handler_double;
extern Type_handler_newdecimal type_handler_newdecimal;
extern Type_handler_datetime type_handler_datetime;
extern Type_handler_longlong type_handler_longlong;
extern Type_handler_bit type_handler_bit;
+extern Type_handler_enum type_handler_enum;
+extern Type_handler_set type_handler_set;
+
class Type_aggregator
{