diff options
author | Vladislav Vaintroub <wlad@mariadb.com> | 2021-08-30 13:28:45 +0200 |
---|---|---|
committer | Vladislav Vaintroub <wlad@mariadb.com> | 2021-10-14 12:13:04 +0200 |
commit | 167d2509249f9e501090ac4a5e985fe014c40932 (patch) | |
tree | 70ecc50c9d793d32acce318e883d77029696bec7 | |
parent | b3cedf63a3981e58d035f94290afaa3eca0b0c99 (diff) | |
download | mariadb-git-167d2509249f9e501090ac4a5e985fe014c40932.tar.gz |
MDEV-4742 additions
- return error from natsort_encode_numeric_key, if it would need
to allocate memory. All needed memory was preallocated much earlier.
- Add test for sort order of leading zero vs numeric strings with suffix.
-rw-r--r-- | mysql-test/main/natural_sort_key.result | 15 | ||||
-rw-r--r-- | mysql-test/main/natural_sort_key.test | 11 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 61 |
3 files changed, 59 insertions, 28 deletions
diff --git a/mysql-test/main/natural_sort_key.result b/mysql-test/main/natural_sort_key.result index 501898fc7d4..1a6cf1cc3ea 100644 --- a/mysql-test/main/natural_sort_key.result +++ b/mysql-test/main/natural_sort_key.result @@ -15,6 +15,11 @@ NATURAL_SORT_KEY(repeat('a1',@@max_allowed_packet/2-1)) NULL Warnings: Warning 1301 Result of natural_sort_key() was larger than max_allowed_packet (16777216) - truncated +SELECT NATURAL_SORT_KEY(repeat('1',@@max_allowed_packet-1)); +NATURAL_SORT_KEY(repeat('1',@@max_allowed_packet-1)) +NULL +Warnings: +Warning 1301 Result of natural_sort_key() was larger than max_allowed_packet (16777216) - truncated CREATE TABLE t1( c VARCHAR(30) CHARACTER SET latin1 COLLATE latin1_bin, k VARCHAR(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci AS (NATURAL_SORT_KEY(CONVERT(c USING utf8mb4))) INVISIBLE, @@ -106,3 +111,13 @@ value sortkey encoding_overhead 10000000000000000000000000 997100000000000000000000000000 4 100000000000000000000000000 9981000000000000000000000000000 4 1000000000000000000000000000 99901271000000000000000000000000000 8 +SELECT val +FROM +( +SELECT 0 val WHERE 0 +UNION VALUES ('1/'),('01'),('1a') +) AS strings ORDER BY NATURAL_SORT_KEY(val); +val +1/ +1a +01 diff --git a/mysql-test/main/natural_sort_key.test b/mysql-test/main/natural_sort_key.test index 50f579c87d0..f918c0e9bdf 100644 --- a/mysql-test/main/natural_sort_key.test +++ b/mysql-test/main/natural_sort_key.test @@ -9,6 +9,7 @@ SELECT '' c WHERE 0 UNION VALUES('a10'),('a9'),('a1000'), ('a0'),('b'),('b0') OR #Test that max packet overflow produces NULL plus warning SELECT NATURAL_SORT_KEY(repeat('a1',@@max_allowed_packet/2-1)); +SELECT NATURAL_SORT_KEY(repeat('1',@@max_allowed_packet-1)); #Test with virtual(index only) key CREATE TABLE t1( @@ -37,3 +38,13 @@ SELECT 0 val UNION VALUES ('1'),('01'),('0001') UNION SELECT CONCAT('1',repeat('0',seq)) FROM seq_1_to_27 ) AS numbers ORDER BY sortkey; + + +#Test that sort order with leading zeros (lead zeros sort larger) +SELECT val +FROM +( +SELECT 0 val WHERE 0 +UNION VALUES ('1/'),('01'),('1a') +) AS strings ORDER BY NATURAL_SORT_KEY(val); + diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 943c459d834..cfacddf62d4 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -5522,7 +5522,13 @@ enum class NATSORT_ERR @param[in] n_lead_zeros - leading zeros count. - @param[out] out - String to write to. + @param[out] out - String to write to. The string should + have enough preallocated space to fit the encoded key. + + @return + NATSORT_ERR::SUCCESS - success + NATSORT_ERR::KEY_TOO_LARGE - out string does not have enough + space left to accomodate the key. Note: Special case, where there are only leading zeros @@ -5544,15 +5550,19 @@ static NATSORT_ERR natsort_encode_numeric_string(const char *in, DBUG_ASSERT(in); DBUG_ASSERT(n_digits); - if (out->append(buf, natsort_encode_length(n_digits - 1, buf))) - return NATSORT_ERR::ALLOC_ERROR; + size_t len; + len= natsort_encode_length(n_digits - 1, buf); - if (out->append(in, n_digits)) - return NATSORT_ERR::ALLOC_ERROR; + if (out->length() + len + n_digits > out->alloced_length()) + return NATSORT_ERR::KEY_TOO_LARGE; - if (out->append(buf, natsort_encode_length(n_leading_zeros, buf))) - return NATSORT_ERR::ALLOC_ERROR; + out->append(buf, len); + out->append(in, n_digits); + len= natsort_encode_length(n_leading_zeros, buf); + if (out->length() + len > out->alloced_length()) + return NATSORT_ERR::KEY_TOO_LARGE; + out->append(buf, len); return NATSORT_ERR::SUCCESS; } @@ -5578,16 +5588,26 @@ static size_t natsort_max_key_size(size_t input_size) Convert a string to natural sort key. @param[in] in - input string @param[out] out - output string - - We assume that memory is preallocated for the output - string, so that appends do not fail. + @param[in] max_key_size - the maximum size of the output + key, in bytes. + @return NATSORT_ERR::SUCCESS - successful completion + NATSORT_ERR::ALLOC_ERROR - memory allocation error + NATSORT_ERR::KEY_TOO_LARGE - resulting key would exceed max_key_size */ static NATSORT_ERR to_natsort_key(const String *in, String *out, - size_t max_key_size= (size_t) -1) + size_t max_key_size) { size_t n_digits= 0; size_t n_lead_zeros= 0; size_t num_start; + size_t reserve_length= std::min(natsort_max_key_size(in->length()), + max_key_size); + + out->length(0); + out->set_charset(in->charset()); + + if (out->alloc((uint32) reserve_length)) + return NATSORT_ERR::ALLOC_ERROR; for (size_t pos= 0;; pos++) { @@ -5608,9 +5628,6 @@ static NATSORT_ERR to_natsort_key(const String *in, String *out, if (err != NATSORT_ERR::SUCCESS) return err; - if (out->length() > max_key_size) - return NATSORT_ERR::KEY_TOO_LARGE; - /* Reset state.*/ n_digits= 0; num_start= size_t(-1); @@ -5622,16 +5639,14 @@ static NATSORT_ERR to_natsort_key(const String *in, String *out, if (!is_digit) { - if (out->append(c)) + if (out->length() == max_key_size) return NATSORT_ERR::KEY_TOO_LARGE; + out->append(c); } else if (c == '0' && !n_digits) n_lead_zeros++; else if (!n_digits++) num_start= pos; - - if (out->length() + n_digits > max_key_size) - return NATSORT_ERR::KEY_TOO_LARGE; } return NATSORT_ERR::SUCCESS; } @@ -5647,8 +5662,6 @@ String *Item_func_natural_sort_key::val_str(String *out) String *in= args[0]->val_str(); CHARSET_INFO *cs= in->charset(); ulong max_allowed_packet= current_thd->variables.max_allowed_packet; - size_t reserve_length= std::max(natsort_max_key_size(in->length()), - (size_t) max_allowed_packet); uint errs; String tmp; /* @@ -5664,14 +5677,6 @@ String *Item_func_natural_sort_key::val_str(String *out) in= &tmp; } - if (out->alloc((uint32) reserve_length)) - { - err= NATSORT_ERR::ALLOC_ERROR; - goto error_exit; - } - out->length(0); - out->set_charset(in->charset()); - err= to_natsort_key(in, out, max_allowed_packet / cs->mbminlen); if (err != NATSORT_ERR::SUCCESS) |