Skip to content

Commit

Permalink
Partial backporting of 7b50447
Browse files Browse the repository at this point in the history
(MDEV-9407, MDEV-9408) from 10.1

Needed to fix MDEV-10317 easier.
  • Loading branch information
Alexander Barkov committed Jul 3, 2016
1 parent f832b47 commit 3ccf821
Show file tree
Hide file tree
Showing 11 changed files with 87 additions and 127 deletions.
17 changes: 11 additions & 6 deletions sql/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,8 @@ class Item: public Value_source,

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
Expand Down Expand Up @@ -1021,8 +1023,6 @@ class Item: public Value_source,
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 : "???"; }
Expand Down Expand Up @@ -1630,6 +1630,15 @@ class Item: public Value_source,
// 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);
Expand Down Expand Up @@ -2224,7 +2233,6 @@ class Item_result_field :public Item /* Item with result field */
{}
~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
Expand Down Expand Up @@ -3397,8 +3405,6 @@ class Item_temporal_literal :public Item_basic_constant
{ 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); }
};
Expand Down Expand Up @@ -3903,7 +3909,6 @@ class Item_ref :public Item_ident
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();
Expand Down
5 changes: 0 additions & 5 deletions sql/item_cmpfunc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand Down
4 changes: 3 additions & 1 deletion sql/item_cmpfunc.h
Original file line number Diff line number Diff line change
Expand Up @@ -951,7 +951,9 @@ class Item_func_ifnull :public Item_func_case_abbreviation2
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
{
Expand Down
51 changes: 2 additions & 49 deletions sql/item_func.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down
14 changes: 8 additions & 6 deletions sql/item_func.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,10 @@ class Item_func :public Item_func_or_sum
}
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);
Expand Down Expand Up @@ -1765,7 +1763,7 @@ class Item_func_set_user_var :public Item_func_user_var
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
Expand Down Expand Up @@ -2106,8 +2104,12 @@ class Item_func_sp :public Item_func

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;
Expand Down
2 changes: 1 addition & 1 deletion sql/item_geofunc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion sql/item_geofunc.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class Item_geometry_func: public Item_str_func
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
Expand Down
3 changes: 1 addition & 2 deletions sql/item_sum.h
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ class Item_sum :public Item_func_or_sum
}
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);
Expand Down Expand Up @@ -1084,7 +1084,6 @@ class Item_sum_field :public Item
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); }
};
Expand Down
2 changes: 1 addition & 1 deletion sql/item_timefunc.h
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ class Item_temporal_func: public Item_func
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); }
Expand Down
4 changes: 2 additions & 2 deletions sql/sql_insert.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}


Expand Down
110 changes: 57 additions & 53 deletions sql/sql_select.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand Down

2 comments on commit 3ccf821

@iangilfillan
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you mean backporting from 10.2.

@abarkov
Copy link
Contributor

@abarkov abarkov commented on 3ccf821 Aug 1, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops. Right, from 10.2.

Please sign in to comment.