From 115bf43602424f2bba326efab6d7ec51c66ac4e5 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 26 Oct 2005 00:56:17 +0400 Subject: [PATCH 1/3] BUG#14139: When handling "CREATE TABLE(field_X type_spec,...) SELECT smth AS field_X, ...." avoid multiplying length of field_X by charset->mbmaxlen twice when calculating space required for field_X in the new table. mysql-test/r/create.result: Testcase for BUG#14139 mysql-test/t/create.test: Testcase for BUG#14139 sql/field.cc: BUG#14139: Make create_length_to_internal_length() save length-in-characters in create_field::chars_length. sql/field.h: BUG#14139: Add create_length::chars_length where we save length-in-characters, added comments. sql/sql_table.cc: BUG#14139: When handling "CREATE TABLE(field_X type_spec,...) SELECT smth AS field_X, ...." we get two instances of create_field: (1) is occurence of field_X in create list, and (2) is in select list. If we figure they both refer to the same field, we "join" them according to some rule that is not explicitly specified anywhere. When we do this "join", create_field::length already contains length-in-bytes for both, so when we transfer field length (in characters) from (1) to (2), use length-in-characters that we have saved in create_length::chars_length. --- mysql-test/r/create.result | 11 +++++++++++ mysql-test/t/create.test | 8 ++++++++ sql/field.cc | 12 ++++++++++++ sql/field.h | 8 ++++++++ sql/sql_table.cc | 4 ++-- 5 files changed, 41 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 6edd4cbc48f..55ad6e3304a 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -621,3 +621,14 @@ create table if not exists t1 (a int); Warnings: Note 1050 Table 't1' already exists drop table t1; +create table t1 ( +a varchar(112) charset utf8 collate utf8_bin not null, +primary key (a) +) select 'test' as a ; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varchar(112) character set utf8 collate utf8_bin NOT NULL default '', + PRIMARY KEY (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 73184853d1a..966be8b58a3 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -526,4 +526,12 @@ create table t1 (a int); create table if not exists t1 (a int); drop table t1; +# BUG#14139 +create table t1 ( + a varchar(112) charset utf8 collate utf8_bin not null, + primary key (a) +) select 'test' as a ; +show create table t1; +drop table t1; + # End of 4.1 tests diff --git a/sql/field.cc b/sql/field.cc index 6d2f92e27ea..35dfa4cac18 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -6511,8 +6511,20 @@ bool Field_num::eq_def(Field *field) ** Handling of field and create_field *****************************************************************************/ +/* + Convert create_field::length from number of characters to number of bytes + + SYNOPSIS + create_field::create_length_to_internal_length() + + DESCRIPTION + Convert create_field::length from number of characters to number of bytes, + save original value in chars_length. +*/ + void create_field::create_length_to_internal_length(void) { + chars_length= length; switch (sql_type) { case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: diff --git a/sql/field.h b/sql/field.h index ba963418c7a..04f1bd68c7a 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1180,7 +1180,15 @@ public: LEX_STRING comment; // Comment for field Item *def; // Default value enum enum_field_types sql_type; + /* + At various stages in execution this can be length of field in bytes or + max number of characters. + */ uint32 length; + /* + The value of 'length' before a call to create_length_to_internal_length + */ + uint32 chars_length; uint decimals,flags,pack_length; Field::utype unireg_check; TYPELIB *interval; // Which interval to use diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 01126043764..dcbc2018b49 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -643,8 +643,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, sql_field->charset= (dup_field->charset ? dup_field->charset : create_info->default_table_charset); - sql_field->length= dup_field->length; - sql_field->pack_length= dup_field->pack_length; + sql_field->length= dup_field->chars_length; + sql_field->pack_length= dup_field->pack_length; sql_field->create_length_to_internal_length(); sql_field->decimals= dup_field->decimals; sql_field->flags= dup_field->flags; From 8db3252fa6fbcf7615815a19ae740bc83b3a605d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 28 Oct 2005 14:01:00 +0300 Subject: [PATCH 2/3] NetWare specific change to use a LibC API instead of a kernel function to prevent CPU hogs. --- include/config-netware.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/config-netware.h b/include/config-netware.h index 310c9bb7db8..e07e972ba4b 100644 --- a/include/config-netware.h +++ b/include/config-netware.h @@ -116,15 +116,12 @@ extern "C" { /* do not use the extended time in LibC sys\stat.h */ #define _POSIX_SOURCE -/* Kernel call on NetWare that will only yield if our time slice is up */ -void kYieldIfTimeSliceUp(void); - /* Some macros for portability */ #define set_timespec(ABSTIME,SEC) { (ABSTIME).tv_sec=time(NULL)+(SEC); (ABSTIME).tv_nsec=0; } /* extra protection against CPU Hogs on NetWare */ -#define NETWARE_YIELD kYieldIfTimeSliceUp() +#define NETWARE_YIELD pthread_yield() /* Screen mode for help texts */ #define NETWARE_SET_SCREEN_MODE(A) setscreenmode(A) From 00a275e53ccf0fd38fa159ef3e172faf52ffbf38 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 28 Oct 2005 17:16:22 +0400 Subject: [PATCH 3/3] Fix BUG#10511: Wrong padding of UCS2 CHAR columns in ON UPDATE CASCADE innobase/row/row0ins.c: Patch from Marko is applied --- innobase/row/row0ins.c | 46 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index 5ca1ee51cbd..456bb51d424 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -522,20 +522,50 @@ row_ins_cascade_calc_update_vec( && ufield->new_val.len < dtype_get_fixed_size(type)) { + ulint cset; + ufield->new_val.data = mem_heap_alloc(heap, dtype_get_fixed_size(type)); ufield->new_val.len = dtype_get_fixed_size(type); - ut_a(dtype_get_pad_char(type) - != ULINT_UNDEFINED); - memset(ufield->new_val.data, - (byte)dtype_get_pad_char(type), - dtype_get_fixed_size(type)); - ut_memcpy(ufield->new_val.data, - parent_ufield->new_val.data, - parent_ufield->new_val.len); + /* Handle UCS2 strings differently. + As no new collations will be + introduced in 4.1, we hardcode the + charset-collation codes here. + In 5.0, the logic is based on + mbminlen. */ + cset = dtype_get_charset_coll( + dtype_get_prtype(type)); + + if (cset == 35/*ucs2_general_ci*/ + || cset == 90/*ucs2_bin*/ + || (cset >= 128/*ucs2_unicode_ci*/ + && cset <= 144 + /*ucs2_persian_ci*/)) { + /* space=0x0020 */ + ulint i; + for (i = 0; + i < ufield->new_val.len; + i += 2) { + mach_write_to_2(((byte*) + ufield->new_val.data) + + i, 0x0020); + } + } else { + ut_a(dtype_get_pad_char(type) + != ULINT_UNDEFINED); + + memset(ufield->new_val.data, + (byte)dtype_get_pad_char( + type), + ufield->new_val.len); + } + + memcpy(ufield->new_val.data, + parent_ufield->new_val.data, + parent_ufield->new_val.len); } ufield->extern_storage = FALSE;