diff options
Diffstat (limited to 'sql/uniques.cc')
-rw-r--r-- | sql/uniques.cc | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/sql/uniques.cc b/sql/uniques.cc index 082bacceff4..3da78f8d5ab 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -374,6 +374,7 @@ Unique_impl::~Unique_impl() close_cached_file(&file); delete_tree(&tree, 0); delete_dynamic(&file_ptrs); + delete m_descriptor; } @@ -876,9 +877,186 @@ int Unique_impl::write_record_to_file(uchar *key) Variable_sized_keys_descriptor::Variable_sized_keys_descriptor(uint length) + :sortorder(NULL), sort_keys(NULL) { key_length= length; flags= (1 << VARIABLE_SIZED_KEYS_WITH_ORIGINAL_VALUES); + packed_rec_ptr= (uchar *)my_malloc(PSI_INSTRUMENT_ME, + length, + MYF(MY_WME | MY_THREAD_SPECIFIC)); + tmp_buffer.alloc(length); +} + + +Variable_sized_keys_descriptor::~Variable_sized_keys_descriptor() +{ + my_free(packed_rec_ptr); +} + + +/* + @brief + Make a record with packed values for a key + + @retval + 0 NULL value + >0 length of the packed record +*/ +uint Variable_sized_keys_descriptor::make_packed_record(bool exclude_nulls) +{ + Field *field; + SORT_FIELD *sort_field; + uint length; + uchar *orig_to, *to; + orig_to= to= packed_rec_ptr; + to+= size_of_length_field; + + for (sort_field=sort_keys->begin() ; + sort_field != sort_keys->end() ; + sort_field++) + { + bool maybe_null=0; + if ((field=sort_field->field)) + { + // Field + length= field->make_packed_sort_key_part(to, sort_field); + } + else + { // Item + Item *item= sort_field->item; + length= item->type_handler()->make_packed_sort_key_part(to, item, + sort_field, + &tmp_buffer); + } + + if ((maybe_null= sort_field->maybe_null)) + { + if (exclude_nulls && length == 0) + return 0; // NULL value + to++; + } + to+= length; + } + + length= static_cast<int>(to - orig_to); + store_packed_length(orig_to, length); + return length; +} + + +/* + @brief + Setup the structures that are used when Unique stores packed values + + @param thd thread structure + @param item item of aggregate function + @param non_const_args number of non constant arguments + @param arg_count total number of arguments + + @note + This implementation is used by GROUP_CONCAT and COUNT_DISTINCT + as it can have more than one arguments in the argument list. + + @retval + TRUE error + FALSE setup successful +*/ + +bool +Variable_sized_keys_descriptor::setup(THD *thd, Item_sum *item, + uint non_const_args, uint arg_count) +{ + SORT_FIELD *sort,*pos; + if (sortorder) + return false; + DBUG_ASSERT(sort_keys == NULL); + sortorder= (SORT_FIELD*) thd->alloc(sizeof(SORT_FIELD) * non_const_args); + pos= sort= sortorder; + if (!pos) + return true; + sort_keys= new Sort_keys(sortorder, non_const_args); + if (!sort_keys) + return true; + sort=pos= sortorder; + for (uint i= 0; i < arg_count; i++) + { + Item *arg= item->get_arg(i); + if (arg->const_item()) + continue; + + if (arg->type() == Item::FIELD_ITEM) + { + Field *field= ((Item_field*)arg)->field; + pos->setup(field, false); + } + else + pos->setup(arg, false); + pos++; + } + return false; +} + + +/* + @brief + Setup the structures that are used when Unique stores packed values + + @param thd thread structure + @param field field structure + + @retval + TRUE error + FALSE setup successful +*/ + +bool Variable_sized_keys_descriptor::setup(THD *thd, Field *field) +{ + SORT_FIELD *sort,*pos; + if (sortorder) + return false; + + DBUG_ASSERT(sort_keys == NULL); + sortorder= (SORT_FIELD*) thd->alloc(sizeof(SORT_FIELD)); + pos= sort= sortorder; + if (!pos) + return true; + sort_keys= new Sort_keys(sortorder, 1); + if (!sort_keys) + return true; + sort=pos= sortorder; + pos->setup(field, false); // Nulls are always excluded + + return false; +} + + +/* + @brief + Compare two packed keys inside the Unique tree + + @param a_ptr packed sort key + @param b_ptr packed sort key + + @retval + >0 key a_ptr greater than b_ptr + =0 key a_ptr equal to b_ptr + <0 key a_ptr less than b_ptr + +*/ + +int Variable_sized_keys_descriptor::compare_keys(uchar *a_ptr, + uchar *b_ptr) +{ + return sort_keys->compare_keys(a_ptr + size_of_length_field, + b_ptr + size_of_length_field); +} + + +int Variable_sized_keys_descriptor::compare_keys_for_single_arg(uchar *a, + uchar *b) +{ + return sort_keys->compare_keys_for_single_arg(a + size_of_length_field, + b + size_of_length_field); } |