diff options
author | kaa@polly.local <> | 2007-05-31 14:54:44 +0400 |
---|---|---|
committer | kaa@polly.local <> | 2007-05-31 14:54:44 +0400 |
commit | d435b3ed74c1a610ad27f366d825ddf3609d5038 (patch) | |
tree | c04d9c8f5ce3a42514490e40b731a75e345d2c0b /strings | |
parent | f924d84c918ca7c24740c175c591115958332018 (diff) | |
download | mariadb-git-d435b3ed74c1a610ad27f366d825ddf3609d5038.tar.gz |
Fix for bug #27643 "query failed : 1114 (The table '' is full)
Problem:
HASH indexes on VARCHAR columns with binary collations did not ignore trailing spaces from strings before comparisons. This could result in duplicate records being successfully inserted into a MEMORY table with unique key constraints.
As a direct consequence of the above, internal MEMORY tables used for GROUP BY calculation in testcases for bug #27643 contained duplicate rows which resulted in duplicate key errors when converting those temporary tables to MyISAM. Additionally, that error was incorrectly converted to the 'table is full' error.
Solution:
- ignore trailing spaces in VARCHAR fields with binary collations when calculating hashes.
- return a proper error from create_myisam_from_heap() when conversion fails.
Diffstat (limited to 'strings')
-rw-r--r-- | strings/ctype-bin.c | 25 | ||||
-rw-r--r-- | strings/ctype-mb.c | 7 | ||||
-rw-r--r-- | strings/ctype-ucs2.c | 5 |
3 files changed, 35 insertions, 2 deletions
diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index e9de0ade557..f9d29ca1739 100644 --- a/strings/ctype-bin.c +++ b/strings/ctype-bin.c @@ -271,6 +271,29 @@ static int my_wc_mb_bin(CHARSET_INFO *cs __attribute__((unused)), } +void my_hash_sort_8bit_bin(CHARSET_INFO *cs __attribute__((unused)), + const uchar *key, uint len,ulong *nr1, ulong *nr2) +{ + const uchar *pos = key; + + key+= len; + + /* + Remove trailing spaces. We have to do this to be able to compare + 'A ' and 'A' as identical + */ + while (key > pos && key[-1] == ' ') + key--; + + for (; pos < (uchar*) key ; pos++) + { + nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * + ((uint)*pos)) + (nr1[0] << 8); + nr2[0]+=3; + } +} + + void my_hash_sort_bin(CHARSET_INFO *cs __attribute__((unused)), const uchar *key, uint len,ulong *nr1, ulong *nr2) { @@ -471,7 +494,7 @@ MY_COLLATION_HANDLER my_collation_8bit_bin_handler = my_wildcmp_bin, my_strcasecmp_bin, my_instr_bin, - my_hash_sort_bin, + my_hash_sort_8bit_bin, my_propagate_simple }; diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index 40cec669766..c12426b555f 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -467,6 +467,13 @@ static void my_hash_sort_mb_bin(CHARSET_INFO *cs __attribute__((unused)), key+= len; + /* + Remove trailing spaces. We have to do this to be able to compare + 'A ' and 'A' as identical + */ + while (key > pos && key[-1] == ' ') + key--; + for (; pos < (uchar*) key ; pos++) { nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 6b1ba3c1ef6..f3abbaa6e7e 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1484,7 +1484,10 @@ void my_hash_sort_ucs2_bin(CHARSET_INFO *cs __attribute__((unused)), const uchar *pos = key; key+= len; - + + while (key > pos+1 && key[-1] == ' ' && key[-2] == '\0') + key-= 2; + for (; pos < (uchar*) key ; pos++) { nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * |