summaryrefslogtreecommitdiff
path: root/sql/sql_select.cc
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2016-07-03 11:20:46 +0400
committerAlexander Barkov <bar@mariadb.org>2016-07-03 11:20:46 +0400
commit3ccf8218bc03a9cc598cd2da5c5a98ea2412cc05 (patch)
treee8bc6f5b4600582e87466c22bb7da52fe5cb72dc /sql/sql_select.cc
parentf832b47833bd03fbb9e972508097f3f88c0ba184 (diff)
downloadmariadb-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.cc110
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;