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/sql_select.cc | |
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/sql_select.cc')
-rw-r--r-- | sql/sql_select.cc | 110 |
1 files changed, 57 insertions, 53 deletions
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; |