summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/field_conv.cc17
-rw-r--r--sql/filesort.cc18
-rw-r--r--sql/item.cc12
-rw-r--r--sql/item_subselect.cc3
-rw-r--r--sql/item_sum.cc4
-rw-r--r--sql/item_sum.h9
-rw-r--r--sql/sql_class.h1
-rw-r--r--sql/sql_insert.cc92
-rw-r--r--sql/sql_select.cc54
-rw-r--r--sql/sql_select.h4
-rw-r--r--sql/sql_sort.h9
-rw-r--r--sql/table.cc14
-rw-r--r--sql/uniques.cc13
13 files changed, 164 insertions, 86 deletions
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index 410db357510..a286255ec23 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -307,6 +307,15 @@ static void do_field_string(Copy_field *copy)
}
+static void do_field_enum(Copy_field *copy)
+{
+ if (copy->from_field->val_int() == 0)
+ ((Field_enum *) copy->to_field)->store_type((ulonglong) 0);
+ else
+ do_field_string(copy);
+}
+
+
static void do_field_varbinary_pre50(Copy_field *copy)
{
char buff[MAX_FIELD_WIDTH];
@@ -662,7 +671,13 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*)
to->real_type() == FIELD_TYPE_SET)
{
if (!to->eq_def(from))
- return do_field_string;
+ {
+ if (from->real_type() == MYSQL_TYPE_ENUM &&
+ to->real_type() == MYSQL_TYPE_ENUM)
+ return do_field_enum;
+ else
+ return do_field_string;
+ }
}
else if (to->charset() != from->charset())
return do_field_string;
diff --git a/sql/filesort.cc b/sql/filesort.cc
index d518ddbb117..f8868ed6927 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -1052,6 +1052,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
BUFFPEK *buffpek;
QUEUE queue;
qsort2_cmp cmp;
+ void *first_cmp_arg;
volatile THD::killed_state *killed= &current_thd->killed;
THD::killed_state not_killable;
DBUG_ENTER("merge_buffers");
@@ -1077,9 +1078,18 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
/* The following will fire if there is not enough space in sort_buffer */
DBUG_ASSERT(maxcount!=0);
+ if (param->unique_buff)
+ {
+ cmp= param->compare;
+ first_cmp_arg= (void *) &param->cmp_context;
+ }
+ else
+ {
+ cmp= get_ptr_compare(sort_length);
+ first_cmp_arg= (void*) &sort_length;
+ }
if (init_queue(&queue, (uint) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
- (queue_compare) (cmp= get_ptr_compare(sort_length)),
- (void*) &sort_length))
+ (queue_compare) cmp, first_cmp_arg))
DBUG_RETURN(1); /* purecov: inspected */
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
{
@@ -1132,7 +1142,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
buffpek= (BUFFPEK*) queue_top(&queue);
if (cmp) // Remove duplicates
{
- if (!(*cmp)(&sort_length, &(param->unique_buff),
+ if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
(uchar**) &buffpek->key))
goto skip_duplicate;
memcpy(param->unique_buff, (uchar*) buffpek->key, rec_length);
@@ -1184,7 +1194,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
*/
if (cmp)
{
- if (!(*cmp)(&sort_length, &(param->unique_buff), (uchar**) &buffpek->key))
+ if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (uchar**) &buffpek->key))
{
buffpek->key+= rec_length; // Remove duplicate
--buffpek->mem_count;
diff --git a/sql/item.cc b/sql/item.cc
index a334028fd64..52389eece10 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -6595,9 +6595,15 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
expansion of the size of the values because of character set
conversions.
*/
- max_length= max(old_max_chars * collation.collation->mbmaxlen,
- display_length(item) / item->collation.collation->mbmaxlen *
- collation.collation->mbmaxlen);
+ if (collation.collation != &my_charset_bin)
+ {
+ max_length= max(old_max_chars * collation.collation->mbmaxlen,
+ display_length(item) /
+ item->collation.collation->mbmaxlen *
+ collation.collation->mbmaxlen);
+ }
+ else
+ set_if_bigger(max_length, display_length(item));
break;
}
case REAL_RESULT:
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 3f4ba16a18d..0020dd35c61 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -942,7 +942,8 @@ Item_in_subselect::single_value_transformer(JOIN *join,
DBUG_RETURN(RES_ERROR);
thd->lex->allow_sum_func= save_allow_sum_func;
/* we added aggregate function => we have to change statistic */
- count_field_types(&join->tmp_table_param, join->all_fields, 0);
+ count_field_types(select_lex, &join->tmp_table_param, join->all_fields,
+ 0);
subs= new Item_singlerow_subselect(select_lex);
}
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index ea2a14ffb63..e5b0f2721b1 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -2461,7 +2461,7 @@ bool Item_sum_count_distinct::setup(THD *thd)
}
if (always_null)
return FALSE;
- count_field_types(tmp_table_param,list,0);
+ count_field_types(select_lex, tmp_table_param, list, 0);
tmp_table_param->force_copy_fields= force_copy_fields;
DBUG_ASSERT(table == 0);
if (!(table= create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1,
@@ -3265,7 +3265,7 @@ bool Item_func_group_concat::setup(THD *thd)
setup_order(thd, args, context->table_list, list, all_fields, *order))
DBUG_RETURN(TRUE);
- count_field_types(tmp_table_param,all_fields,0);
+ count_field_types(select_lex, tmp_table_param, all_fields, 0);
tmp_table_param->force_copy_fields= force_copy_fields;
DBUG_ASSERT(table == 0);
/*
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 66c73e1d416..d18454cc3b8 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -966,8 +966,15 @@ public:
bool fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
+
+ if (init_sum_func_check(thd))
+ return TRUE;
+
fixed= 1;
- return udf.fix_fields(thd, this, this->arg_count, this->args);
+ if (udf.fix_fields(thd, this, this->arg_count, this->args))
+ return TRUE;
+
+ return check_sum_func(thd, ref);
}
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
virtual bool have_field_update(void) const { return 0; }
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 50c45d461e0..b005f956c28 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1959,6 +1959,7 @@ class select_insert :public select_result_interceptor {
virtual void store_values(List<Item> &values);
void send_error(uint errcode,const char *err);
bool send_eof();
+ void abort();
/* not implemented: select_insert is never re-used in prepared statements */
void cleanup();
};
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 228fc8860ae..9e094c31dce 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -2892,41 +2892,6 @@ void select_insert::send_error(uint errcode,const char *err)
my_message(errcode, err, MYF(0));
- if (!table)
- {
- /*
- This can only happen when using CREATE ... SELECT and the table was not
- created becasue of an syntax error
- */
- DBUG_VOID_RETURN;
- }
- if (!thd->prelocked_mode)
- table->file->end_bulk_insert();
- /*
- If at least one row has been inserted/modified and will stay in the table
- (the table doesn't have transactions) (example: we got a duplicate key
- error while inserting into a MyISAM table) we must write to the binlog (and
- the error code will make the slave stop).
- */
- if ((info.copied || info.deleted || info.updated) &&
- !table->file->has_transactions())
- {
- if (last_insert_id)
- thd->insert_id(last_insert_id); // For binary log
- if (mysql_bin_log.is_open())
- {
- Query_log_event qinfo(thd, thd->query, thd->query_length,
- table->file->has_transactions(), FALSE);
- mysql_bin_log.write(&qinfo);
- }
- if (!table->s->tmp_table)
- thd->no_trans_update.all= TRUE;
- }
- if (info.copied || info.deleted || info.updated)
- {
- query_cache_invalidate3(thd, table, 1);
- }
- ha_rollback_stmt(thd);
DBUG_VOID_RETURN;
}
@@ -2984,6 +2949,49 @@ bool select_insert::send_eof()
DBUG_RETURN(0);
}
+void select_insert::abort()
+{
+ DBUG_ENTER("select_insert::abort");
+
+ if (!table)
+ {
+ /*
+ This can only happen when using CREATE ... SELECT and the table was not
+ created becasue of an syntax error
+ */
+ DBUG_VOID_RETURN;
+ }
+ if (!thd->prelocked_mode)
+ table->file->end_bulk_insert();
+ /*
+ If at least one row has been inserted/modified and will stay in the table
+ (the table doesn't have transactions) (example: we got a duplicate key
+ error while inserting into a MyISAM table) we must write to the binlog (and
+ the error code will make the slave stop).
+ */
+ if ((info.copied || info.deleted || info.updated) &&
+ !table->file->has_transactions())
+ {
+ if (last_insert_id)
+ thd->insert_id(last_insert_id); // For binary log
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ table->file->has_transactions(), FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+ if (!table->s->tmp_table)
+ thd->no_trans_update.all= TRUE;
+ }
+ if (info.copied || info.deleted || info.updated)
+ {
+ query_cache_invalidate3(thd, table, 1);
+ }
+ ha_rollback_stmt(thd);
+
+ DBUG_VOID_RETURN;
+
+}
/***************************************************************************
CREATE TABLE (SELECT) ...
@@ -3241,13 +3249,7 @@ void select_create::store_values(List<Item> &values)
void select_create::send_error(uint errcode,const char *err)
{
- /*
- Disable binlog, because we "roll back" partial inserts in ::abort
- by removing the table, even for non-transactional tables.
- */
- tmp_disable_binlog(thd);
select_insert::send_error(errcode, err);
- reenable_binlog(thd);
}
@@ -3272,6 +3274,14 @@ bool select_create::send_eof()
void select_create::abort()
{
+ /*
+ Disable binlog, because we "roll back" partial inserts in ::abort
+ by removing the table, even for non-transactional tables.
+ */
+ tmp_disable_binlog(thd);
+ select_insert::abort();
+ reenable_binlog(thd);
+
if (lock)
{
mysql_unlock_tables(thd, lock);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 118de99bc6e..9d27ab4bb4e 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -258,11 +258,8 @@ bool handle_select(THD *thd, LEX *lex, select_result *result,
thd->net.report_error));
res|= thd->net.report_error;
if (unlikely(res))
- {
- /* If we had a another error reported earlier then this will be ignored */
- result->send_error(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR));
result->abort();
- }
+
DBUG_RETURN(res);
}
@@ -614,7 +611,7 @@ JOIN::prepare(Item ***rref_pointer_array,
goto err; /* purecov: inspected */
/* Init join struct */
- count_field_types(&tmp_table_param, all_fields, 0);
+ count_field_types(select_lex, &tmp_table_param, all_fields, 0);
ref_pointer_array_size= all_fields.elements*sizeof(Item*);
this->group= group_list != 0;
unit= unit_arg;
@@ -1769,7 +1766,7 @@ JOIN::exec()
if (make_simple_join(curr_join, curr_tmp_table))
DBUG_VOID_RETURN;
calc_group_buffer(curr_join, group_list);
- count_field_types(&curr_join->tmp_table_param,
+ count_field_types(select_lex, &curr_join->tmp_table_param,
curr_join->tmp_all_fields1,
curr_join->select_distinct && !curr_join->group_list);
curr_join->tmp_table_param.hidden_field_count=
@@ -1889,11 +1886,13 @@ JOIN::exec()
if (make_simple_join(curr_join, curr_tmp_table))
DBUG_VOID_RETURN;
calc_group_buffer(curr_join, curr_join->group_list);
- count_field_types(&curr_join->tmp_table_param, *curr_all_fields, 0);
+ count_field_types(select_lex, &curr_join->tmp_table_param,
+ *curr_all_fields, 0);
}
if (procedure)
- count_field_types(&curr_join->tmp_table_param, *curr_all_fields, 0);
+ count_field_types(select_lex, &curr_join->tmp_table_param,
+ *curr_all_fields, 0);
if (curr_join->group || curr_join->tmp_table_param.sum_func_count ||
(procedure && (procedure->flags & PROC_GROUP)))
@@ -13681,8 +13680,8 @@ next_item:
*****************************************************************************/
void
-count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
- bool reset_with_sum_func)
+count_field_types(SELECT_LEX *select_lex, TMP_TABLE_PARAM *param,
+ List<Item> &fields, bool reset_with_sum_func)
{
List_iterator<Item> li(fields);
Item *field;
@@ -13700,18 +13699,22 @@ count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
if (! field->const_item())
{
Item_sum *sum_item=(Item_sum*) field->real_item();
- if (!sum_item->quick_group)
- param->quick_group=0; // UDF SUM function
- param->sum_func_count++;
- param->func_count++;
+ if (!sum_item->depended_from() ||
+ sum_item->depended_from() == select_lex)
+ {
+ if (!sum_item->quick_group)
+ param->quick_group=0; // UDF SUM function
+ param->sum_func_count++;
- for (uint i=0 ; i < sum_item->arg_count ; i++)
- {
- if (sum_item->args[0]->real_item()->type() == Item::FIELD_ITEM)
- param->field_count++;
- else
- param->func_count++;
- }
+ for (uint i=0 ; i < sum_item->arg_count ; i++)
+ {
+ if (sum_item->args[0]->real_item()->type() == Item::FIELD_ITEM)
+ param->field_count++;
+ else
+ param->func_count++;
+ }
+ }
+ param->func_count++;
}
}
else
@@ -14173,7 +14176,9 @@ bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_fields,
func= sum_funcs;
while ((item=it++))
{
- if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item())
+ if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item() &&
+ (!((Item_sum*) item)->depended_from() ||
+ ((Item_sum *)item)->depended_from() == select_lex))
*func++= (Item_sum*) item;
}
if (before_group_by && rollup.state == ROLLUP::STATE_INITED)
@@ -14755,7 +14760,10 @@ bool JOIN::rollup_make_fields(List<Item> &fields_arg, List<Item> &sel_fields,
ref_array= ref_array_start;
}
- if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item())
+ if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item() &&
+ (!((Item_sum*) item)->depended_from() ||
+ ((Item_sum *)item)->depended_from() == select_lex))
+
{
/*
This is a top level summary function that must be replaced with
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 3cdd265df9a..4f9f6e9ed48 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -470,8 +470,8 @@ TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
ulonglong select_options, ha_rows rows_limit,
char* alias);
void free_tmp_table(THD *thd, TABLE *entry);
-void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
- bool reset_with_sum_func);
+void count_field_types(SELECT_LEX *select_lex, TMP_TABLE_PARAM *param,
+ List<Item> &fields, bool reset_with_sum_func);
bool setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
Item **ref_pointer_array,
List<Item> &new_list1, List<Item> &new_list2,
diff --git a/sql/sql_sort.h b/sql/sql_sort.h
index da28ca07e2c..1e9322f7f5b 100644
--- a/sql/sql_sort.h
+++ b/sql/sql_sort.h
@@ -50,6 +50,12 @@ typedef struct st_buffpek { /* Struktur om sorteringsbuffrarna */
ulong max_keys; /* Max keys in buffert */
} BUFFPEK;
+struct BUFFPEK_COMPARE_CONTEXT
+{
+ qsort_cmp2 key_compare;
+ void *key_compare_arg;
+};
+
typedef struct st_sort_param {
uint rec_length; /* Length of sorted records */
uint sort_length; /* Length of sorted columns */
@@ -65,6 +71,9 @@ typedef struct st_sort_param {
uchar *unique_buff;
bool not_killable;
char* tmp_buffer;
+ /* The fields below are used only by Unique class */
+ qsort2_cmp compare;
+ BUFFPEK_COMPARE_CONTEXT cmp_context;
} SORTPARAM;
diff --git a/sql/table.cc b/sql/table.cc
index 9868aa9b9c1..4e0f2b5d287 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1442,7 +1442,19 @@ File create_frm(THD *thd, my_string name, const char *db,
fileinfo[3]= (uchar) ha_checktype(thd,create_info->db_type,0,0);
fileinfo[4]=1;
int2store(fileinfo+6,IO_SIZE); /* Next block starts here */
- key_length=keys*(7+NAME_LEN+MAX_REF_PARTS*9)+16;
+ /*
+ Keep in sync with pack_keys() in unireg.cc
+ For each key:
+ 8 bytes for the key header
+ 9 bytes for each key-part (MAX_REF_PARTS)
+ NAME_LEN bytes for the name
+ 1 byte for the NAMES_SEP_CHAR (before the name)
+ For all keys:
+ 6 bytes for the header
+ 1 byte for the NAMES_SEP_CHAR (after the last name)
+ 9 extra bytes (padding for safety? alignment?)
+ */
+ key_length= keys * (8 + MAX_REF_PARTS * 9 + NAME_LEN + 1) + 16;
length= next_io_size((ulong) (IO_SIZE+key_length+reclength+
create_info->extra_size));
int4store(fileinfo+10,length);
diff --git a/sql/uniques.cc b/sql/uniques.cc
index 9eb827f62a3..7c197d2a2e9 100644
--- a/sql/uniques.cc
+++ b/sql/uniques.cc
@@ -361,17 +361,12 @@ Unique::reset()
}
/*
- The comparison function, passed to queue_init() in merge_walk() must
+ The comparison function, passed to queue_init() in merge_walk() and in
+ merge_buffers() when the latter is called from Uniques::get() must
use comparison function of Uniques::tree, but compare members of struct
BUFFPEK.
*/
-struct BUFFPEK_COMPARE_CONTEXT
-{
- qsort_cmp2 key_compare;
- void *key_compare_arg;
-};
-
C_MODE_START
static int buffpek_compare(void *arg, byte *key_ptr1, byte *key_ptr2)
@@ -630,6 +625,10 @@ bool Unique::get(TABLE *table)
sort_param.unique_buff= sort_buffer+(sort_param.keys*
sort_param.sort_length);
+ sort_param.compare= (qsort2_cmp) buffpek_compare;
+ sort_param.cmp_context.key_compare= tree.compare;
+ sort_param.cmp_context.key_compare_arg= tree.custom_arg;
+
/* Merge the buffers to one file, removing duplicates */
if (merge_many_buff(&sort_param,sort_buffer,file_ptr,&maxbuffer,&file))
goto err;