From 45293fc346e0294a33f35e09575da8ca14f062b9 Mon Sep 17 00:00:00 2001 From: "bar@mysql.com" <> Date: Thu, 13 Apr 2006 10:55:48 +0500 Subject: [PATCH 1/5] Bug#18691: Converting number to UNICODE string returns invalid result. Conversion from int and real numbers to UCS2 didn't work fine: CONVERT(100, CHAR(50) UNICODE) CONVERT(103.9, CHAR(50) UNICODE) The problem appeared because numbers have binary charset, so, simple charset recast binary->ucs2 was performed instead of real conversion. Fixed to make numbers pretend to be non-binary. --- mysql-test/r/ctype_ucs.result | 12 ++++++++++++ mysql-test/t/ctype_ucs.test | 8 ++++++++ sql/item_timefunc.cc | 28 +++++++++++++++++++++++----- sql/item_timefunc.h | 2 +- 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 0e12ec88662..8869604b128 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -666,6 +666,18 @@ Warnings: Warning 1265 Data truncated for column 'Field1' at row 1 DROP TABLE t1; SET NAMES latin1; +SELECT CONVERT(103, CHAR(50) UNICODE); +CONVERT(103, CHAR(50) UNICODE) +103 +SELECT CONVERT(103.0, CHAR(50) UNICODE); +CONVERT(103.0, CHAR(50) UNICODE) +103.0 +SELECT CONVERT(-103, CHAR(50) UNICODE); +CONVERT(-103, CHAR(50) UNICODE) +-103 +SELECT CONVERT(-103.0, CHAR(50) UNICODE); +CONVERT(-103.0, CHAR(50) UNICODE) +-103.0 CREATE TABLE t1 ( a varchar(255) NOT NULL default '', KEY a (a) diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index bd37d008173..2cbabf88ee0 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -407,6 +407,14 @@ INSERT INTO t1 VALUES ('-1'); DROP TABLE t1; SET NAMES latin1; +# +# Bug#18691 Converting number to UNICODE string returns invalid result +# +SELECT CONVERT(103, CHAR(50) UNICODE); +SELECT CONVERT(103.0, CHAR(50) UNICODE); +SELECT CONVERT(-103, CHAR(50) UNICODE); +SELECT CONVERT(-103.0, CHAR(50) UNICODE); + # # Bug#9557 MyISAM utf8 table crash # diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index d6b57464d59..f3d6858755c 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2221,8 +2221,8 @@ String *Item_char_typecast::val_str(String *str) // Convert character set if differ uint dummy_errors; if (!(res= args[0]->val_str(&tmp_value)) || - str->copy(res->ptr(), res->length(), res->charset(), - cast_cs, &dummy_errors)) + str->copy(res->ptr(), res->length(), from_cs, + cast_cs, &dummy_errors)) { null_value= 1; return 0; @@ -2261,14 +2261,32 @@ void Item_char_typecast::fix_length_and_dec() For single-byte character sets we allow just to copy from the argument. A single-byte character sets string is always well-formed. + + There is a special trick to convert form a number to ucs2. + As numbers have my_charset_bin as their character set, + it wouldn't do conversion to ucs2 without an additional action. + To force conversion, we should pretend to be non-binary. + Let's choose from_cs this way: + - If the argument in a number and cast_cs is ucs2 (i.e. mbminlen > 1), + then from_cs is set to latin1, to perform latin1 -> ucs2 conversion. + - If the argument is a number and cast_cs is ASCII-compatible + (i.e. mbminlen == 1), then from_cs is set to cast_cs, + which allows just to take over the args[0]->val_str() result + and thus avoid unnecessary character set conversion. + - If the argument is not a number, then from_cs is set to + the argument's charset. */ + from_cs= (args[0]->result_type() == INT_RESULT || + args[0]->result_type() == REAL_RESULT) ? + (cast_cs->mbminlen == 1 ? cast_cs : &my_charset_latin1) : + args[0]->collation.collation; charset_conversion= (cast_cs->mbmaxlen > 1) || - !my_charset_same(args[0]->collation.collation, cast_cs) && - args[0]->collation.collation != &my_charset_bin && + !my_charset_same(from_cs, cast_cs) && + from_cs != &my_charset_bin && cast_cs != &my_charset_bin; collation.set(cast_cs, DERIVATION_IMPLICIT); char_length= (cast_length >= 0) ? cast_length : - args[0]->max_length/args[0]->collation.collation->mbmaxlen; + args[0]->max_length/from_cs->mbmaxlen; max_length= char_length * cast_cs->mbmaxlen; } diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index ce9d6b0a7aa..163b1591e52 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -681,7 +681,7 @@ public: class Item_char_typecast :public Item_typecast { int cast_length; - CHARSET_INFO *cast_cs; + CHARSET_INFO *cast_cs, *from_cs; bool charset_conversion; String tmp_value; public: From 7412db5e565e50db0df1b4208de4e7999c59bf56 Mon Sep 17 00:00:00 2001 From: "svoj@april.(none)" <> Date: Thu, 13 Apr 2006 14:37:03 +0500 Subject: [PATCH 2/5] BUG#17917 - SELECT from compressed MyISAM table crashes MySQL server Retrieving data from compressed MyISAM table which is bigger than 4G on 32-bit box with mmap() support results in server crash. mmap() accepts length of bytes to be mapped in second param, which is 32-bit size_t. But we pass data_file_length, which is 64-bit my_off_t. As a result only first data_file_length % 4G were mapped. This fix adds additional condition for mmap() usage, that is use mmap() for compressed table which size is no more than 4G on 32-bit platform. --- myisam/mi_packrec.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/myisam/mi_packrec.c b/myisam/mi_packrec.c index 322420b71db..bd2d162d100 100644 --- a/myisam/mi_packrec.c +++ b/myisam/mi_packrec.c @@ -1158,16 +1158,22 @@ my_bool _mi_memmap_file(MI_INFO *info) MYISAM_SHARE *share=info->s; DBUG_ENTER("mi_memmap_file"); - if (!info->s->file_map) + if (!share->file_map) { + my_off_t data_file_length= share->state.state.data_file_length; + if (data_file_length > (my_off_t) (~((size_t) 0)) - MEMMAP_EXTRA_MARGIN) + { + DBUG_PRINT("warning", ("File is too large for mmap")); + DBUG_RETURN(0); + } if (my_seek(info->dfile,0L,MY_SEEK_END,MYF(0)) < - share->state.state.data_file_length+MEMMAP_EXTRA_MARGIN) + data_file_length + MEMMAP_EXTRA_MARGIN) { DBUG_PRINT("warning",("File isn't extended for memmap")); DBUG_RETURN(0); } file_map=(byte*) - mmap(0,share->state.state.data_file_length+MEMMAP_EXTRA_MARGIN,PROT_READ, + mmap(0, data_file_length + MEMMAP_EXTRA_MARGIN, PROT_READ, MAP_SHARED | MAP_NORESERVE,info->dfile,0L); if (file_map == (byte*) MAP_FAILED) { @@ -1175,7 +1181,7 @@ my_bool _mi_memmap_file(MI_INFO *info) my_errno=errno; DBUG_RETURN(0); } - info->s->file_map=file_map; + share->file_map= file_map; } info->opt_flag|= MEMMAP_USED; info->read_record=share->read_record=_mi_read_mempack_record; From b915f054cf918f82327993d464c8c709d5e0a041 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Thu, 13 Apr 2006 14:06:46 +0400 Subject: [PATCH 3/5] Fix a typo in the help message. --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index e68762868a4..740e1a419c7 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5253,7 +5253,7 @@ The minimum value for this variable is 4096.", (gptr*) &max_system_variables.max_length_for_sort_data, 0, GET_ULONG, REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0}, {"max_prepared_stmt_count", OPT_MAX_PREPARED_STMT_COUNT, - "Maximum numbrer of prepared statements in the server.", + "Maximum number of prepared statements in the server.", (gptr*) &max_prepared_stmt_count, (gptr*) &max_prepared_stmt_count, 0, GET_ULONG, REQUIRED_ARG, 16382, 0, 1*1024*1024, 0, 1, 0}, {"max_relay_log_size", OPT_MAX_RELAY_LOG_SIZE, From b033da87fabf47a441aa9544333b217a6fbc34ae Mon Sep 17 00:00:00 2001 From: "aelkin@mysql.com" <> Date: Fri, 14 Apr 2006 12:13:26 +0300 Subject: [PATCH 4/5] Bug#19097: rpl_view failed on some platforms removing comments from the opt file. --- mysql-test/t/rpl_view-slave.opt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/mysql-test/t/rpl_view-slave.opt b/mysql-test/t/rpl_view-slave.opt index 55b3aeb3bda..79b3bf6174b 100644 --- a/mysql-test/t/rpl_view-slave.opt +++ b/mysql-test/t/rpl_view-slave.opt @@ -1,5 +1 @@ -# -# BUG18715 create view with replicate*ignore-table -# The option is needed to force slave executes tables_ok -# which must return OK in conditions of this tests (no table foo is used) --replicate-ignore-table=test.foo From a9e309210284763e0678d7f4138ed40dac2e8337 Mon Sep 17 00:00:00 2001 From: "bar@mysql.com" <> Date: Mon, 17 Apr 2006 15:36:25 +0500 Subject: [PATCH 5/5] item_timefunc.cc: 5.0 additional fix for b#18691 Handle DECIMAL the same with INT and REAL. --- sql/item_timefunc.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 84e532ba4bc..200541f22a7 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2457,6 +2457,7 @@ void Item_char_typecast::fix_length_and_dec() the argument's charset. */ from_cs= (args[0]->result_type() == INT_RESULT || + args[0]->result_type() == DECIMAL_RESULT || args[0]->result_type() == REAL_RESULT) ? (cast_cs->mbminlen == 1 ? cast_cs : &my_charset_latin1) : args[0]->collation.collation;