diff options
author | Alexander Barkov <bar@mariadb.org> | 2016-07-03 11:20:46 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.org> | 2016-07-03 11:20:46 +0400 |
commit | 3ccf8218bc03a9cc598cd2da5c5a98ea2412cc05 (patch) | |
tree | e8bc6f5b4600582e87466c22bb7da52fe5cb72dc /sql | |
parent | f832b47833bd03fbb9e972508097f3f88c0ba184 (diff) | |
download | mariadb-git-3ccf8218bc03a9cc598cd2da5c5a98ea2412cc05.tar.gz |
Partial backporting of 7b50447aa6d051b8d14bb01ef14802cb8ffee223
(MDEV-9407, MDEV-9408) from 10.1
Needed to fix MDEV-10317 easier.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.h | 17 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 5 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 4 | ||||
-rw-r--r-- | sql/item_func.cc | 51 | ||||
-rw-r--r-- | sql/item_func.h | 14 | ||||
-rw-r--r-- | sql/item_geofunc.cc | 2 | ||||
-rw-r--r-- | sql/item_geofunc.h | 2 | ||||
-rw-r--r-- | sql/item_sum.h | 3 | ||||
-rw-r--r-- | sql/item_timefunc.h | 2 | ||||
-rw-r--r-- | sql/sql_insert.cc | 4 | ||||
-rw-r--r-- | sql/sql_select.cc | 110 |
11 files changed, 87 insertions, 127 deletions
diff --git a/sql/item.h b/sql/item.h index 8650eb9382c..1905e0f1216 100644 --- a/sql/item.h +++ b/sql/item.h @@ -657,6 +657,8 @@ protected: SEL_TREE *get_mm_tree_for_const(RANGE_OPT_PARAM *param); + Field *create_tmp_field(bool group, TABLE *table, uint convert_int_length); + public: /* Cache val_str() into the own buffer, e.g. to evaluate constant @@ -1021,8 +1023,6 @@ public: int save_str_value_in_field(Field *field, String *result); virtual Field *get_tmp_table_field() { return 0; } - /* This is also used to create fields in CREATE ... SELECT: */ - virtual Field *tmp_table_field(TABLE *t_arg) { return 0; } virtual Field *create_field_for_create_select(TABLE *table); virtual Field *create_field_for_schema(THD *thd, TABLE *table); virtual const char *full_name() const { return name ? name : "???"; } @@ -1630,6 +1630,15 @@ public: // used in row subselects to get value of elements virtual void bring_value() {} + virtual Field *create_tmp_field(bool group, TABLE *table) + { + /* + Values with MY_INT32_NUM_DECIMAL_DIGITS digits may or may not fit into + Field_long : make them Field_longlong. + */ + return create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS - 2); + } + Field *tmp_table_field_from_field_type(TABLE *table, bool fixed_length, bool set_blob_packlength); @@ -2224,7 +2233,6 @@ public: {} ~Item_result_field() {} /* Required with gcc 2.95 */ Field *get_tmp_table_field() { return result_field; } - Field *tmp_table_field(TABLE *t_arg) { return result_field; } /* This implementation of used_tables() used by Item_avg_field and Item_variance_field which work when only temporary table left, so theu @@ -3397,8 +3405,6 @@ public: { return val_real_from_date(); } my_decimal *val_decimal(my_decimal *decimal_value) { return val_decimal_from_date(decimal_value); } - Field *tmp_table_field(TABLE *table) - { return tmp_table_field_from_field_type(table, false, false); } int save_in_field(Field *field, bool no_conversions) { return save_date_in_field(field); } }; @@ -3903,7 +3909,6 @@ public: enum_field_types field_type() const { return (*ref)->field_type(); } Field *get_tmp_table_field() { return result_field ? result_field : (*ref)->get_tmp_table_field(); } - Field *tmp_table_field(TABLE *t_arg) { return 0; } Item *get_tmp_table_item(THD *thd); table_map used_tables() const; void update_used_tables(); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index f3196c55873..bd1e8b72157 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2263,11 +2263,6 @@ uint Item_func_case_abbreviation2::decimal_precision2(Item **args) const } -Field *Item_func_ifnull::tmp_table_field(TABLE *table) -{ - return tmp_table_field_from_field_type(table, false, false); -} - double Item_func_ifnull::real_op() { diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 2f66382941d..2e066b895e9 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -951,7 +951,9 @@ public: maybe_null= args[1]->maybe_null; } const char *func_name() const { return "ifnull"; } - Field *tmp_table_field(TABLE *table); + Field *create_field_for_create_select(TABLE *table) + { return tmp_table_field_from_field_type(table, false, false); } + table_map not_null_tables() const { return 0; } uint decimal_precision() const { diff --git a/sql/item_func.cc b/sql/item_func.cc index 6edb276ca20..0d21183cac8 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -509,43 +509,6 @@ bool Item_func::eq(const Item *item, bool binary_cmp) const } -Field *Item_func::tmp_table_field(TABLE *table) -{ - Field *field= NULL; - MEM_ROOT *mem_root= table->in_use->mem_root; - - switch (result_type()) { - case INT_RESULT: - if (max_char_length() > MY_INT32_NUM_DECIMAL_DIGITS) - field= new (mem_root) - Field_longlong(max_char_length(), maybe_null, name, - unsigned_flag); - else - field= new (mem_root) - Field_long(max_char_length(), maybe_null, name, - unsigned_flag); - break; - case REAL_RESULT: - field= new (mem_root) - Field_double(max_char_length(), maybe_null, name, decimals); - break; - case STRING_RESULT: - return make_string_field(table); - case DECIMAL_RESULT: - field= Field_new_decimal::create_from_item(mem_root, this); - break; - case ROW_RESULT: - case TIME_RESULT: - // This case should never be chosen - DBUG_ASSERT(0); - field= 0; - break; - } - if (field) - field->init(table); - return field; -} - /* bool Item_func::is_expensive_processor(uchar *arg) { @@ -2910,10 +2873,10 @@ void Item_func_min_max::fix_length_and_dec() collation.set_numeric(); fix_char_length(float_length(decimals)); /* - Set type to DOUBLE, as Item_func::tmp_table_field() does not + Set type to DOUBLE, as Item_func::create_tmp_field() does not distinguish between DOUBLE and FLOAT and always creates Field_double. Perhaps we should eventually change this to use agg_field_type() here, - and fix Item_func::tmp_table_field() to create Field_float when possible. + and fix Item_func::create_tmp_field() to create Field_float when possible. */ set_handler_by_field_type(MYSQL_TYPE_DOUBLE); break; @@ -6805,16 +6768,6 @@ longlong Item_func_found_rows::val_int() } -Field * -Item_func_sp::tmp_table_field(TABLE *t_arg) -{ - DBUG_ENTER("Item_func_sp::tmp_table_field"); - - DBUG_ASSERT(sp_result_field); - DBUG_RETURN(sp_result_field); -} - - /** @brief Checks if requested access to function can be granted to user. If function isn't found yet, it searches function first. diff --git a/sql/item_func.h b/sql/item_func.h index a6d0374d491..47af2a3f898 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -173,12 +173,10 @@ public: } void signal_divide_by_null(); friend class udf_handler; - Field *tmp_table_field() { return result_field; } - Field *tmp_table_field(TABLE *t_arg); Field *create_field_for_create_select(TABLE *table) { return result_type() != STRING_RESULT ? - tmp_table_field(table) : + create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS) : tmp_table_field_from_field_type(table, false, false); } Item *get_tmp_table_item(THD *thd); @@ -1765,7 +1763,7 @@ public: Field *create_field_for_create_select(TABLE *table) { return result_type() != STRING_RESULT ? - tmp_table_field(table) : + create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS) : tmp_table_field_from_field_type(table, false, true); } table_map used_tables() const @@ -2106,8 +2104,12 @@ public: enum enum_field_types field_type() const; - Field *tmp_table_field(TABLE *t_arg); - + Field *create_field_for_create_select(TABLE *table) + { + return result_type() != STRING_RESULT ? + sp_result_field : + tmp_table_field_from_field_type(table, false, false); + } void make_field(Send_field *tmp_field); Item_result result_type() const; diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 76e4a85e865..c856aa985b3 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -40,7 +40,7 @@ #include "opt_range.h" -Field *Item_geometry_func::tmp_table_field(TABLE *t_arg) +Field *Item_geometry_func::create_field_for_create_select(TABLE *t_arg) { Field *result; if ((result= new Field_geom(max_length, maybe_null, name, t_arg->s, diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index 6b991a1b643..121e122d939 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -40,7 +40,7 @@ public: Item_geometry_func(THD *thd, List<Item> &list): Item_str_func(thd, list) {} void fix_length_and_dec(); enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; } - Field *tmp_table_field(TABLE *t_arg); + Field *create_field_for_create_select(TABLE *table); }; class Item_func_geometry_from_text: public Item_geometry_func diff --git a/sql/item_sum.h b/sql/item_sum.h index 11d2f802af7..8568eaae907 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -481,7 +481,7 @@ public: } virtual void make_unique() { force_copy_fields= TRUE; } Item *get_tmp_table_item(THD *thd); - virtual Field *create_tmp_field(bool group, TABLE *table); + Field *create_tmp_field(bool group, TABLE *table); virtual bool collect_outer_ref_processor(uchar *param); bool init_sum_func_check(THD *thd); bool check_sum_func(THD *thd, Item **ref); @@ -1084,7 +1084,6 @@ public: fixed= true; } table_map used_tables() const { return (table_map) 1L; } - Field *tmp_table_field(TABLE *) { DBUG_ASSERT(0); return NULL; } void set_result_field(Field *) { DBUG_ASSERT(0); } void save_in_result_field(bool no_conversions) { DBUG_ASSERT(0); } }; diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index bb840987089..2c1a0943699 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -500,7 +500,7 @@ public: bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date) { DBUG_ASSERT(0); return 1; } my_decimal *val_decimal(my_decimal *decimal_value) { return val_decimal_from_date(decimal_value); } - Field *tmp_table_field(TABLE *table) + Field *create_field_for_create_select(TABLE *table) { return tmp_table_field_from_field_type(table, false, false); } int save_in_field(Field *field, bool no_conversions) { return save_date_in_field(field); } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 3efdd2535c2..b97bae6b23c 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -3927,8 +3927,8 @@ void select_insert::abort_result_set() { Field *Item::create_field_for_create_select(TABLE *table) { Field *def_field, *tmp_field; - return create_tmp_field(table->in_use, table, this, type(), - (Item ***) 0, &tmp_field, &def_field, 0, 0, 0, 0); + return ::create_tmp_field(table->in_use, table, this, type(), + (Item ***) 0, &tmp_field, &def_field, 0, 0, 0, 0); } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 86a7309315a..387e0403f96 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -15837,6 +15837,60 @@ Field *create_tmp_field_from_field(THD *thd, Field *org_field, return new_field; } + +Field *Item::create_tmp_field(bool group, TABLE *table, uint convert_int_length) +{ + Field *UNINIT_VAR(new_field); + MEM_ROOT *mem_root= table->in_use->mem_root; + + switch (cmp_type()) { + case REAL_RESULT: + new_field= new (mem_root) + Field_double(max_length, maybe_null, name, decimals, TRUE); + break; + case INT_RESULT: + /* + Select an integer type with the minimal fit precision. + convert_int_length is sign inclusive, don't consider the sign. + */ + if (max_char_length() > convert_int_length) + new_field= new (mem_root) + Field_longlong(max_char_length(), maybe_null, name, unsigned_flag); + else + new_field= new (mem_root) + Field_long(max_char_length(), maybe_null, name, unsigned_flag); + break; + case TIME_RESULT: + new_field= tmp_table_field_from_field_type(table, true, false); + break; + case STRING_RESULT: + DBUG_ASSERT(collation.collation); + /* + GEOMETRY fields have STRING_RESULT result type. + To preserve type they needed to be handled separately. + */ + if (field_type() == MYSQL_TYPE_GEOMETRY) + new_field= tmp_table_field_from_field_type(table, true, false); + else + new_field= make_string_field(table); + new_field->set_derivation(collation.derivation, collation.repertoire); + break; + case DECIMAL_RESULT: + new_field= Field_new_decimal::create_from_item(mem_root, this); + break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + new_field= 0; + break; + } + if (new_field) + new_field->init(table); + return new_field; +} + + + /** Create field for temporary table using type of given item. @@ -15862,58 +15916,9 @@ Field *create_tmp_field_from_field(THD *thd, Field *org_field, static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, Item ***copy_func, bool modify_item) { - bool maybe_null= item->maybe_null; Field *UNINIT_VAR(new_field); - MEM_ROOT *mem_root= thd->mem_root; - - /* - To preserve type or DATE/TIME and GEOMETRY fields, - they need to be handled separately. - */ - if (item->cmp_type() == TIME_RESULT || - item->field_type() == MYSQL_TYPE_GEOMETRY) - new_field= item->tmp_table_field_from_field_type(table, true, false); - else - switch (item->result_type()) { - case REAL_RESULT: - new_field= new (mem_root) - Field_double(item->max_length, maybe_null, - item->name, item->decimals, TRUE); - break; - case INT_RESULT: - /* - Select an integer type with the minimal fit precision. - MY_INT32_NUM_DECIMAL_DIGITS is sign inclusive, don't consider the sign. - Values with MY_INT32_NUM_DECIMAL_DIGITS digits may or may not fit into - Field_long : make them Field_longlong. - */ - if (item->max_length >= (MY_INT32_NUM_DECIMAL_DIGITS - 1)) - new_field=new (mem_root) - Field_longlong(item->max_length, maybe_null, - item->name, item->unsigned_flag); - else - new_field=new (mem_root) - Field_long(item->max_length, maybe_null, item->name, - item->unsigned_flag); - break; - case STRING_RESULT: - DBUG_ASSERT(item->collation.collation); - new_field= item->make_string_field(table); - new_field->set_derivation(item->collation.derivation, - item->collation.repertoire); - break; - case DECIMAL_RESULT: - new_field= Field_new_decimal::create_from_item(mem_root, item); - break; - case ROW_RESULT: - default: - // This case should never be choosen - DBUG_ASSERT(0); - new_field= 0; - break; - } - if (new_field) - new_field->init(table); + DBUG_ASSERT(thd == table->in_use); + new_field= item->Item::create_tmp_field(false, table); if (copy_func && item->real_item()->is_result_field()) *((*copy_func)++) = item; // Save for copy_funcs @@ -16005,8 +16010,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, switch (type) { case Item::SUM_FUNC_ITEM: { - Item_sum *item_sum=(Item_sum*) item; - result= item_sum->create_tmp_field(group, table); + result= item->create_tmp_field(group, table); if (!result) my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR)); return result; |