diff options
Diffstat (limited to 'sql/filesort.cc')
-rw-r--r-- | sql/filesort.cc | 115 |
1 files changed, 76 insertions, 39 deletions
diff --git a/sql/filesort.cc b/sql/filesort.cc index 6f2a6096aa2..c76295e666a 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -60,9 +60,7 @@ static bool save_index(Sort_param *param, uint count, static uint suffix_length(ulong string_length); static uint sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length, bool *multi_byte_charset); -static SORT_ADDON_FIELD *get_addon_fields(ulong max_length_for_sort_data, - Field **ptabfield, - uint sortlength, +static SORT_ADDON_FIELD *get_addon_fields(TABLE *table, uint sortlength, LEX_STRING *addon_buf); static void unpack_addon_fields(struct st_sort_addon_field *addon_field, uchar *buff, uchar *buff_end); @@ -71,7 +69,6 @@ static bool check_if_pq_applicable(Sort_param *param, SORT_INFO *info, ha_rows records, size_t memory_available); void Sort_param::init_for_filesort(uint sortlen, TABLE *table, - ulong max_length_for_sort_data, ha_rows maxrows, bool sort_positions) { DBUG_ASSERT(addon_field == 0 && addon_buf.length == 0); @@ -85,8 +82,7 @@ void Sort_param::init_for_filesort(uint sortlen, TABLE *table, Get the descriptors of all fields whose values are appended to sorted fields and get its total length in addon_buf.length */ - addon_field= get_addon_fields(max_length_for_sort_data, - table->field, sort_length, &addon_buf); + addon_field= get_addon_fields(table, sort_length, &addon_buf); } if (addon_field) { @@ -190,9 +186,7 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort, param.init_for_filesort(sortlength(thd, filesort->sortorder, s_length, &multi_byte_charset), - table, - thd->variables.max_length_for_sort_data, - max_rows, filesort->sort_positions); + table, max_rows, filesort->sort_positions); sort->addon_buf= param.addon_buf; sort->addon_field= param.addon_field; @@ -1057,7 +1051,10 @@ Type_handler_temporal_result::make_sort_key(uchar *to, Item *item, Sort_param *param) const { MYSQL_TIME buf; - if (item->get_date_result(current_thd, &buf, TIME_INVALID_DATES)) + // This is a temporal type. No nanoseconds. Rounding mode is not important. + DBUG_ASSERT(item->cmp_type() == TIME_RESULT); + static const Temporal::Options opt(TIME_INVALID_DATES, TIME_FRAC_NONE); + if (item->get_date_result(current_thd, &buf, opt)) { DBUG_ASSERT(item->maybe_null); DBUG_ASSERT(item->null_value); @@ -1071,6 +1068,28 @@ Type_handler_temporal_result::make_sort_key(uchar *to, Item *item, void +Type_handler_timestamp_common::make_sort_key(uchar *to, Item *item, + const SORT_FIELD_ATTR *sort_field, + Sort_param *param) const +{ + uint binlen= my_timestamp_binary_length(item->decimals); + Timestamp_or_zero_datetime_native_null native(current_thd, item); + if (native.is_null() || native.is_zero_datetime()) + { + // NULL or '0000-00-00 00:00:00' + bzero(to, item->maybe_null ? binlen + 1 : binlen); + } + else + { + DBUG_ASSERT(native.length() == binlen); + if (item->maybe_null) + *to++= 1; + memcpy((char *) to, native.ptr(), binlen); + } +} + + +void Type_handler::make_sort_key_longlong(uchar *to, bool maybe_null, bool null_value, @@ -1877,6 +1896,15 @@ Type_handler_temporal_result::sortlength(THD *thd, void +Type_handler_timestamp_common::sortlength(THD *thd, + const Type_std_attributes *item, + SORT_FIELD_ATTR *sortorder) const +{ + sortorder->length= my_timestamp_binary_length(item->decimals); +} + + +void Type_handler_int_result::sortlength(THD *thd, const Type_std_attributes *item, SORT_FIELD_ATTR *sortorder) const @@ -1963,6 +1991,30 @@ sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length, return length; } +bool filesort_use_addons(TABLE *table, uint sortlength, + uint *length, uint *fields, uint *null_fields) +{ + Field **pfield, *field; + *length= *fields= *null_fields= 0; + + for (pfield= table->field; (field= *pfield) ; pfield++) + { + if (!bitmap_is_set(table->read_set, field->field_index)) + continue; + if (field->flags & BLOB_FLAG) + return false; + (*length)+= field->max_packed_col_length(field->pack_length()); + if (field->maybe_null()) + (*null_fields)++; + (*fields)++; + } + if (!*fields) + return false; + (*length)+= (*null_fields+7)/8; + + return *length + sortlength < + table->in_use->variables.max_length_for_sort_data; +} /** Get descriptors of fields appended to sorted fields and @@ -1970,7 +2022,7 @@ sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length, The function first finds out what fields are used in the result set. Then it calculates the length of the buffer to store the values of - these fields together with the value of sort values. + these fields together with the value of sort values. If the calculated length is not greater than max_length_for_sort_data the function allocates memory for an array of descriptors containing layouts for the values of the non-sorted fields in the buffer and @@ -1992,16 +2044,13 @@ sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length, */ static SORT_ADDON_FIELD * -get_addon_fields(ulong max_length_for_sort_data, - Field **ptabfield, uint sortlength, LEX_STRING *addon_buf) +get_addon_fields(TABLE *table, uint sortlength, LEX_STRING *addon_buf) { Field **pfield; Field *field; SORT_ADDON_FIELD *addonf; - uint length= 0; - uint fields= 0; - uint null_fields= 0; - MY_BITMAP *read_set= (*ptabfield)->table->read_set; + uint length, fields, null_fields; + MY_BITMAP *read_set= table->read_set; DBUG_ENTER("get_addon_fields"); /* @@ -2010,40 +2059,28 @@ get_addon_fields(ulong max_length_for_sort_data, Note for future refinement: This this a too strong condition. Actually we need only the fields referred in the - result set. And for some of them it makes sense to use + result set. And for some of them it makes sense to use the values directly from sorted fields. But beware the case when item->cmp_type() != item->result_type() */ addon_buf->str= 0; addon_buf->length= 0; - for (pfield= ptabfield; (field= *pfield) ; pfield++) - { - if (!bitmap_is_set(read_set, field->field_index)) - continue; - if (field->flags & BLOB_FLAG) - DBUG_RETURN(0); - length+= field->max_packed_col_length(field->pack_length()); - if (field->maybe_null()) - null_fields++; - fields++; - } - if (!fields) - DBUG_RETURN(0); - length+= (null_fields+7)/8; + // see remove_const() for HA_SLOW_RND_POS explanation + if (table->file->ha_table_flags() & HA_SLOW_RND_POS) + sortlength= 0; - if (length+sortlength > max_length_for_sort_data || - !my_multi_malloc(MYF(MY_WME | MY_THREAD_SPECIFIC), - &addonf, sizeof(SORT_ADDON_FIELD) * (fields+1), - &addon_buf->str, length, - NullS)) + if (!filesort_use_addons(table, sortlength, &length, &fields, &null_fields) || + !my_multi_malloc(MYF(MY_WME | MY_THREAD_SPECIFIC), &addonf, + sizeof(SORT_ADDON_FIELD) * (fields+1), + &addon_buf->str, length, NullS)) DBUG_RETURN(0); addon_buf->length= length; length= (null_fields+7)/8; null_fields= 0; - for (pfield= ptabfield; (field= *pfield) ; pfield++) + for (pfield= table->field; (field= *pfield) ; pfield++) { if (!bitmap_is_set(read_set, field->field_index)) continue; @@ -2065,7 +2102,7 @@ get_addon_fields(ulong max_length_for_sort_data, addonf++; } addonf->field= 0; // Put end marker - + DBUG_PRINT("info",("addon_length: %d",length)); DBUG_RETURN(addonf-fields); } |