summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/item.h30
-rw-r--r--sql/item_cmpfunc.cc5
-rw-r--r--sql/item_cmpfunc.h4
-rw-r--r--sql/item_func.cc51
-rw-r--r--sql/item_func.h15
-rw-r--r--sql/item_geofunc.cc2
-rw-r--r--sql/item_geofunc.h2
-rw-r--r--sql/item_sum.cc38
-rw-r--r--sql/item_sum.h12
-rw-r--r--sql/item_timefunc.h2
-rw-r--r--sql/sql_insert.cc4
-rw-r--r--sql/sql_select.cc116
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;