summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <evgen@sunlight.local>2007-09-24 17:23:40 +0400
committerunknown <evgen@sunlight.local>2007-09-24 17:23:40 +0400
commite4cbbcf8a970b854bfbc34f77571afdb0b247814 (patch)
treedff8e299e24252baed98de65a5a6435bbbfcf1c4 /sql
parentc2c760bdb60eaa22165b518c209381010d489604 (diff)
parent17df0d648ca86d7074805228ba50d0f137b486d4 (diff)
downloadmariadb-git-e4cbbcf8a970b854bfbc34f77571afdb0b247814.tar.gz
Merge sunlight.local:/local_work/27216-bug-5.0-opt-mysql
into sunlight.local:/local_work/merge-5.1-opt-mysql libmysql/libmysql.c: Auto merged mysql-test/r/date_formats.result: Auto merged mysql-test/r/insert_select.result: Auto merged mysql-test/t/insert_select.test: Auto merged sql/item_func.cc: Auto merged sql/item_func.h: Auto merged sql/item_timefunc.cc: Auto merged sql/mysql_priv.h: Auto merged sql/protocol.cc: Auto merged sql/sql_class.h: Auto merged mysql-test/r/type_datetime.result: Manually merged mysql-test/t/type_datetime.test: Manually merged sql/item_cmpfunc.cc: Manually merged sql/item_cmpfunc.h: Manually merged sql/sql_insert.cc: Manually merged
Diffstat (limited to 'sql')
-rw-r--r--sql/item_cmpfunc.cc39
-rw-r--r--sql/item_cmpfunc.h7
-rw-r--r--sql/item_func.cc1
-rw-r--r--sql/item_func.h4
-rw-r--r--sql/item_timefunc.cc2
-rw-r--r--sql/mysql_priv.h1
-rw-r--r--sql/protocol.cc1
-rw-r--r--sql/sql_class.h2
-rw-r--r--sql/sql_insert.cc17
9 files changed, 63 insertions, 11 deletions
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 8f5ff050dd6..690661bc513 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -146,6 +146,35 @@ static int agg_cmp_type(Item_result *type, Item **items, uint nitems)
}
+/**
+ @brief Aggregates field types from the array of items.
+
+ @param[in] items array of items to aggregate the type from
+ @paran[in] nitems number of items in the array
+
+ @details This function aggregates field types from the array of items.
+ Found type is supposed to be used later as the result field type
+ of a multi-argument function.
+ Aggregation itself is performed by the Field::field_type_merge()
+ function.
+
+ @note The term "aggregation" is used here in the sense of inferring the
+ result type of a function from its argument types.
+
+ @return aggregated field type.
+*/
+
+enum_field_types agg_field_type(Item **items, uint nitems)
+{
+ uint i;
+ if (!nitems || items[0]->result_type() == ROW_RESULT )
+ return (enum_field_types)-1;
+ enum_field_types res= items[0]->field_type();
+ for (i= 1 ; i < nitems ; i++)
+ res= Field::field_type_merge(res, items[i]->field_type());
+ return res;
+}
+
/*
Collects different types for comparison of first item with each other items
@@ -2065,9 +2094,7 @@ Item_func_ifnull::fix_length_and_dec()
default:
DBUG_ASSERT(0);
}
- cached_field_type= args[0]->field_type();
- if (cached_field_type != args[1]->field_type())
- cached_field_type= Item_func::field_type();
+ cached_field_type= agg_field_type(args, 2);
}
@@ -2215,11 +2242,13 @@ Item_func_if::fix_length_and_dec()
{
cached_result_type= arg2_type;
collation.set(args[2]->collation.collation);
+ cached_field_type= args[2]->field_type();
}
else if (null2)
{
cached_result_type= arg1_type;
collation.set(args[1]->collation.collation);
+ cached_field_type= args[1]->field_type();
}
else
{
@@ -2233,6 +2262,7 @@ Item_func_if::fix_length_and_dec()
{
collation.set(&my_charset_bin); // Number
}
+ cached_field_type= agg_field_type(args + 1, 2);
}
if ((cached_result_type == DECIMAL_RESULT )
@@ -2582,7 +2612,7 @@ void Item_func_case::fix_length_and_dec()
agg_arg_charsets(collation, agg, nagg, MY_COLL_ALLOW_CONV, 1))
return;
-
+ cached_field_type= agg_field_type(agg, nagg);
/*
Aggregate first expression and all THEN expression types
and collations when string comparison
@@ -2751,6 +2781,7 @@ my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value)
void Item_func_coalesce::fix_length_and_dec()
{
+ cached_field_type= agg_field_type(args, arg_count);
agg_result_type(&hybrid_type, args, arg_count);
switch (hybrid_type) {
case STRING_RESULT:
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 40d0c2dfe91..1a64f9c4211 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -640,6 +640,7 @@ public:
class Item_func_coalesce :public Item_func_numhybrid
{
protected:
+ enum_field_types cached_field_type;
Item_func_coalesce(Item *a, Item *b) :Item_func_numhybrid(a, b) {}
public:
Item_func_coalesce(List<Item> &list) :Item_func_numhybrid(list) {}
@@ -652,13 +653,13 @@ public:
enum Item_result result_type () const { return hybrid_type; }
const char *func_name() const { return "coalesce"; }
table_map not_null_tables() const { return 0; }
+ enum_field_types field_type() const { return cached_field_type; }
};
class Item_func_ifnull :public Item_func_coalesce
{
protected:
- enum_field_types cached_field_type;
bool field_type_defined;
public:
Item_func_ifnull(Item *a, Item *b) :Item_func_coalesce(a,b) {}
@@ -677,6 +678,7 @@ public:
class Item_func_if :public Item_func
{
enum Item_result cached_result_type;
+ enum_field_types cached_field_type;
public:
Item_func_if(Item *a,Item *b,Item *c)
:Item_func(a,b,c), cached_result_type(INT_RESULT)
@@ -686,6 +688,7 @@ public:
String *val_str(String *str);
my_decimal *val_decimal(my_decimal *);
enum Item_result result_type () const { return cached_result_type; }
+ enum_field_types field_type() const { return cached_field_type; }
bool fix_fields(THD *, Item **);
void fix_length_and_dec();
uint decimal_precision() const;
@@ -713,6 +716,7 @@ public:
bool is_null();
};
+
/* Functions to handle the optimized IN */
@@ -1442,6 +1446,7 @@ public:
Item *transform(Item_transformer transformer, uchar *arg);
void traverse_cond(Cond_traverser, void *arg, traverse_order order);
void neg_arguments(THD *thd);
+ enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
bool subst_argument_checker(uchar **arg) { return TRUE; }
Item *compile(Item_analyzer analyzer, uchar **arg_p,
Item_transformer transformer, uchar *arg_t);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index efc42c1b73f..6b1c0e340a5 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2238,6 +2238,7 @@ void Item_func_min_max::fix_length_and_dec()
else if ((cmp_type == DECIMAL_RESULT) || (cmp_type == INT_RESULT))
max_length= my_decimal_precision_to_length(max_int_part+decimals, decimals,
unsigned_flag);
+ cached_field_type= agg_field_type(args, arg_count);
}
diff --git a/sql/item_func.h b/sql/item_func.h
index ea22e35773d..602c1c86f01 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -699,7 +699,8 @@ class Item_func_min_max :public Item_func
/* An item used for issuing warnings while string to DATETIME conversion. */
Item *datetime_item;
THD *thd;
-
+protected:
+ enum_field_types cached_field_type;
public:
Item_func_min_max(List<Item> &list,int cmp_sign_arg) :Item_func(list),
cmp_type(INT_RESULT), cmp_sign(cmp_sign_arg), compare_as_dates(FALSE),
@@ -712,6 +713,7 @@ public:
enum Item_result result_type () const { return cmp_type; }
bool result_as_longlong() { return compare_as_dates; };
uint cmp_datetimes(ulonglong *value);
+ enum_field_types field_type() const { return cached_field_type; }
};
class Item_func_min :public Item_func_min_max
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 300d0788f55..59e1777f542 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -3239,7 +3239,7 @@ void Item_func_str_to_date::fix_length_and_dec()
String format_str(format_buff, sizeof(format_buff), &my_charset_bin), *format;
maybe_null= 1;
decimals=0;
- cached_field_type= MYSQL_TYPE_STRING;
+ cached_field_type= MYSQL_TYPE_DATETIME;
max_length= MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
cached_timestamp_type= MYSQL_TIMESTAMP_NONE;
format= args[1]->val_str(&format_str);
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 47a42354423..3aaee71bd42 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -1673,6 +1673,7 @@ void flush_thread_cache();
/* item_func.cc */
extern bool check_reserved_words(LEX_STRING *name);
+extern enum_field_types agg_field_type(Item **items, uint nitems);
/* strfunc.cc */
ulonglong find_set(TYPELIB *lib, const char *x, uint length, CHARSET_INFO *cs,
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 2ed241c4c98..839109ef964 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -827,6 +827,7 @@ bool Protocol_text::store(const char *from, size_t length,
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
field_types[field_pos] == MYSQL_TYPE_BIT ||
field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
+ field_types[field_pos] == MYSQL_TYPE_NEWDATE ||
(field_types[field_pos] >= MYSQL_TYPE_ENUM &&
field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
field_pos++;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 7875870bd1a..95338d7f151 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -2107,7 +2107,7 @@ class select_insert :public select_result_interceptor {
ulonglong autoinc_value_of_last_inserted_row; // autogenerated or not
COPY_INFO info;
bool insert_into_view;
-
+ bool is_bulk_insert_mode;
select_insert(TABLE_LIST *table_list_par,
TABLE *table_par, List<Item> *fields_par,
List<Item> *update_fields, List<Item> *update_values,
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index ebbf4cafb19..4bac5f9c9da 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -2778,7 +2778,8 @@ select_insert::select_insert(TABLE_LIST *table_list_par, TABLE *table_par,
bool ignore_check_option_errors)
:table_list(table_list_par), table(table_par), fields(fields_par),
autoinc_value_of_last_inserted_row(0),
- insert_into_view(table_list_par && table_list_par->view != 0)
+ insert_into_view(table_list_par && table_list_par->view != 0),
+ is_bulk_insert_mode(FALSE)
{
bzero((char*) &info,sizeof(info));
info.handle_duplicates= duplic;
@@ -2964,8 +2965,11 @@ int select_insert::prepare2(void)
{
DBUG_ENTER("select_insert::prepare2");
if (thd->lex->current_select->options & OPTION_BUFFER_RESULT &&
- !thd->prelocked_mode)
+ !thd->prelocked_mode && !is_bulk_insert_mode)
+ {
table->file->ha_start_bulk_insert((ha_rows) 0);
+ is_bulk_insert_mode= TRUE;
+ }
DBUG_RETURN(0);
}
@@ -3084,6 +3088,7 @@ bool select_insert::send_eof()
trans_table, table->file->table_type()));
error= (!thd->prelocked_mode) ? table->file->ha_end_bulk_insert():0;
+ is_bulk_insert_mode= FALSE;
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
@@ -3307,7 +3312,10 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
Create_field *cr_field;
Field *field, *def_field;
if (item->type() == Item::FUNC_ITEM)
- field= item->tmp_table_field(&tmp_table);
+ if (item->result_type() != STRING_RESULT)
+ field= item->tmp_table_field(&tmp_table);
+ else
+ field= item->tmp_table_field_from_field_type(&tmp_table);
else
field= create_tmp_field(thd, &tmp_table, item, item->type(),
(Item ***) 0, &tmp_field, &def_field, 0, 0, 0, 0,
@@ -3518,7 +3526,10 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
if (info.handle_duplicates == DUP_UPDATE)
table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE);
if (!thd->prelocked_mode)
+ {
table->file->ha_start_bulk_insert((ha_rows) 0);
+ is_bulk_insert_mode= TRUE;
+ }
thd->abort_on_warning= (!info.ignore &&
(thd->variables.sql_mode &
(MODE_STRICT_TRANS_TABLES |