diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.h | 30 | ||||
-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 | 15 | ||||
-rw-r--r-- | sql/item_geofunc.cc | 2 | ||||
-rw-r--r-- | sql/item_geofunc.h | 2 | ||||
-rw-r--r-- | sql/item_sum.cc | 38 | ||||
-rw-r--r-- | sql/item_sum.h | 12 | ||||
-rw-r--r-- | sql/item_timefunc.h | 2 | ||||
-rw-r--r-- | sql/sql_insert.cc | 4 | ||||
-rw-r--r-- | sql/sql_select.cc | 116 |
12 files changed, 108 insertions, 173 deletions
diff --git a/sql/item.h b/sql/item.h index acc149f9677..94107d897d6 100644 --- a/sql/item.h +++ b/sql/item.h @@ -656,6 +656,14 @@ protected: SEL_TREE *get_mm_tree_for_const(RANGE_OPT_PARAM *param); + virtual Field *make_string_field(TABLE *table); + Field *tmp_table_field_from_field_type(TABLE *table, + bool fixed_length, + bool set_blob_packlength); + Field *create_tmp_field(bool group, TABLE *table, + uint convert_blob_length, + uint convert_int_length); + public: /* Cache val_str() into the own buffer, e.g. to evaluate constant @@ -722,7 +730,6 @@ public: void init_make_field(Send_field *tmp_field,enum enum_field_types type); virtual void cleanup(); virtual void make_field(THD *thd, Send_field *field); - virtual Field *make_string_field(TABLE *table); virtual bool fix_fields(THD *, Item **); /* Fix after some tables has been pulled out. Basically re-calculate all @@ -1046,8 +1053,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(THD *thd, TABLE *table); virtual Field *create_field_for_schema(THD *thd, TABLE *table); virtual const char *full_name() const { return name ? name : "???"; } @@ -1655,9 +1660,18 @@ public: // used in row subselects to get value of elements virtual void bring_value() {} - Field *tmp_table_field_from_field_type(TABLE *table, - bool fixed_length, - bool set_blob_packlength); + virtual Field *create_tmp_field(bool group, TABLE *table, + uint convert_blob_length) + { + /* + 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, + convert_blob_length, + MY_INT32_NUM_DECIMAL_DIGITS - 2); + } + virtual Item_field *field_for_view_update() { return 0; } virtual Item *neg_transformer(THD *thd) { return NULL; } @@ -2252,7 +2266,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 @@ -3440,8 +3453,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); } }; @@ -3947,7 +3958,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 928ca145a79..0c2d241309d 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2300,11 +2300,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 fae1c4358bb..c14ee42016b 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -940,7 +940,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(THD *thd, 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 379c0ecc15a..4b376706500 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) { @@ -2908,10 +2871,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; @@ -6801,16 +6764,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 fd1a1eeb3fa..5e1fa753f34 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -171,12 +171,11 @@ 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(THD *thd, TABLE *table) { + DBUG_ASSERT(thd == table->in_use); return result_type() != STRING_RESULT ? - tmp_table_field(table) : + create_tmp_field(false, table, 0, MY_INT32_NUM_DECIMAL_DIGITS) : tmp_table_field_from_field_type(table, false, false); } Item *get_tmp_table_item(THD *thd); @@ -1767,7 +1766,7 @@ public: Field *create_field_for_create_select(THD *thd, TABLE *table) { return result_type() != STRING_RESULT ? - tmp_table_field(table) : + create_tmp_field(false, table, 0, MY_INT32_NUM_DECIMAL_DIGITS) : tmp_table_field_from_field_type(table, false, true); } table_map used_tables() const @@ -2136,8 +2135,12 @@ public: enum enum_field_types field_type() const; - Field *tmp_table_field(TABLE *t_arg); - + Field *create_field_for_create_select(THD *thd, TABLE *table) + { + return result_type() != STRING_RESULT ? + sp_result_field : + tmp_table_field_from_field_type(table, false, false); + } void make_field(THD *thd, Send_field *tmp_field); Item_result result_type() const; diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 07059fed4be..352c9fd93b9 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -41,7 +41,7 @@ #include "opt_range.h" -Field *Item_geometry_func::tmp_table_field(TABLE *t_arg) +Field *Item_geometry_func::create_field_for_create_select(THD *thd, 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 b72661fe054..56e2a729924 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(THD *thd, TABLE *table); }; class Item_func_geometry_from_text: public Item_geometry_func diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 073bec4eaa0..5b98ea801f0 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -496,44 +496,6 @@ Item *Item_sum::get_tmp_table_item(THD *thd) } -Field *Item_sum::create_tmp_field(bool group, TABLE *table, - uint convert_blob_length) -{ - Field *UNINIT_VAR(field); - MEM_ROOT *mem_root= table->in_use->mem_root; - - switch (result_type()) { - case REAL_RESULT: - field= new (mem_root) - Field_double(max_length, maybe_null, name, decimals, TRUE); - break; - case INT_RESULT: - field= new (mem_root) - Field_longlong(max_length, maybe_null, name, unsigned_flag); - break; - case STRING_RESULT: - if (max_length/collation.collation->mbmaxlen <= 255 || - convert_blob_length > Field_varstring::MAX_SIZE || - !convert_blob_length) - return make_string_field(table); - field= new (mem_root) Field_varstring(convert_blob_length, maybe_null, - name, table->s, collation.collation); - break; - 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 choosen - DBUG_ASSERT(0); - return 0; - } - if (field) - field->init(table); - return field; -} - - void Item_sum::update_used_tables () { if (!Item_sum::const_item()) diff --git a/sql/item_sum.h b/sql/item_sum.h index 49999980b09..68b034c9213 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -481,8 +481,12 @@ 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, - uint convert_blob_length); + Field *create_tmp_field(bool group, TABLE *table, + uint convert_blob_length) + { + return Item::create_tmp_field(group, table, convert_blob_length, + MY_INT32_NUM_DECIMAL_DIGITS); + } virtual bool collect_outer_ref_processor(uchar *param); bool init_sum_func_check(THD *thd); bool check_sum_func(THD *thd, Item **ref); @@ -1093,7 +1097,6 @@ public: } table_map used_tables() const { return (table_map) 1L; } Field *get_tmp_table_field() { DBUG_ASSERT(0); return NULL; } - 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); } }; @@ -1483,6 +1486,8 @@ class Item_func_group_concat : public Item_sum friend int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)), void* item_arg); +protected: + virtual Field *make_string_field(TABLE *table); public: Item_func_group_concat(THD *thd, Name_resolution_context *context_arg, @@ -1497,7 +1502,6 @@ public: const char *func_name() const { return "group_concat"; } virtual Item_result result_type () const { return STRING_RESULT; } virtual Item_result cmp_type () const { return STRING_RESULT; } - virtual Field *make_string_field(TABLE *table); enum_field_types field_type() const { if (too_big_for_varchar()) diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 2bfa31c604d..175f3b06c1a 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -502,7 +502,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(THD *thd, 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 d1db45c446e..e27cc6de073 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -3892,8 +3892,8 @@ void select_insert::abort_result_set() { Field *Item::create_field_for_create_select(THD *thd, TABLE *table) { Field *def_field, *tmp_field; - return create_tmp_field(thd, table, this, type(), - (Item ***) 0, &tmp_field, &def_field, 0, 0, 0, 0, 0); + return ::create_tmp_field(thd, table, this, type(), + (Item ***) 0, &tmp_field, &def_field, 0, 0, 0, 0, 0); } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 91365f03d58..efc710509e7 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -15681,90 +15681,61 @@ Field *create_tmp_field_from_field(THD *thd, Field *org_field, return new_field; } -/** - Create field for temporary table using type of given item. - - @param thd Thread handler - @param item Item to create a field for - @param table Temporary table - @param copy_func If set and item is a function, store copy of - item in this array - @param modify_item 1 if item->result_field should point to new - item. This is relevent for how fill_record() - is going to work: - If modify_item is 1 then fill_record() will - update the record in the original table. - If modify_item is 0 then fill_record() will - update the temporary table - @param convert_blob_length If >0 create a varstring(convert_blob_length) - field instead of blob. - @retval - 0 on error - @retval - new_created field -*/ - -static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, - Item ***copy_func, bool modify_item, - uint convert_blob_length) +Field *Item::create_tmp_field(bool group, TABLE *table, + uint convert_blob_length, + uint convert_int_length) { - bool maybe_null= item->maybe_null; Field *UNINIT_VAR(new_field); - MEM_ROOT *mem_root= thd->mem_root; + MEM_ROOT *mem_root= table->in_use->mem_root; - switch (item->result_type()) { + switch (cmp_type()) { case REAL_RESULT: new_field= new (mem_root) - Field_double(item->max_length, maybe_null, - item->name, item->decimals, TRUE); + Field_double(max_length, maybe_null, name, 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. + convert_int_length is sign inclusive, don't consider the sign. */ - 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); + 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(item->max_length, maybe_null, item->name, - item->unsigned_flag); + 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(item->collation.collation); + DBUG_ASSERT(collation.collation); /* - DATE/TIME and GEOMETRY fields have STRING_RESULT result type. + GEOMETRY fields have STRING_RESULT result type. To preserve type they needed 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); + if (field_type() == MYSQL_TYPE_GEOMETRY) + new_field= tmp_table_field_from_field_type(table, true, false); /* Make sure that the blob fits into a Field_varstring which has 2-byte lenght. */ - else if (item->max_length/item->collation.collation->mbmaxlen > 255 && + else if (max_length / collation.collation->mbmaxlen > 255 && convert_blob_length <= Field_varstring::MAX_SIZE && convert_blob_length) new_field= new (mem_root) Field_varstring(convert_blob_length, maybe_null, - item->name, table->s, - item->collation.collation); + name, table->s, collation.collation); else - new_field= item->make_string_field(table); - new_field->set_derivation(item->collation.derivation); + new_field= make_string_field(table); + new_field->set_derivation(collation.derivation); break; case DECIMAL_RESULT: - new_field= Field_new_decimal::create_from_item(mem_root, item); + new_field= Field_new_decimal::create_from_item(mem_root, this); break; case ROW_RESULT: - default: // This case should never be choosen DBUG_ASSERT(0); new_field= 0; @@ -15772,6 +15743,42 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, } if (new_field) new_field->init(table); + return new_field; +} + + + +/** + Create field for temporary table using type of given item. + + @param thd Thread handler + @param item Item to create a field for + @param table Temporary table + @param copy_func If set and item is a function, store copy of + item in this array + @param modify_item 1 if item->result_field should point to new + item. This is relevent for how fill_record() + is going to work: + If modify_item is 1 then fill_record() will + update the record in the original table. + If modify_item is 0 then fill_record() will + update the temporary table + @param convert_blob_length If >0 create a varstring(convert_blob_length) + field instead of blob. + + @retval + 0 on error + @retval + new_created field +*/ + +static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, + Item ***copy_func, bool modify_item, + uint convert_blob_length) +{ + Field *UNINIT_VAR(new_field); + DBUG_ASSERT(thd == table->in_use); + new_field= item->Item::create_tmp_field(false, table, convert_blob_length); if (copy_func && item->real_item()->is_result_field()) *((*copy_func)++) = item; // Save for copy_funcs @@ -15866,8 +15873,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, convert_blob_length); + result= item->create_tmp_field(group, table, convert_blob_length); if (!result) my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR)); return result; |