From 442c2ba8af29ea77b79500fc9a7e920e2e110f13 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Tue, 21 Feb 2006 19:52:20 +0300 Subject: [PATCH 1/2] A fix and a test case for Bug#13134 "Length of VARCHAR() utf8 column is increasing when table is recreated with PS/SP": make use of create_field::char_length more consistent in the code. Reinit create_field::length from create_field::char_length for every execution of a prepared statement (actually fixes the bug). --- mysql-test/r/ps.result | 17 +++++++++++++++++ mysql-test/t/ps.test | 24 +++++++++++++++++++++++- sql/field.cc | 5 ++--- sql/field.h | 2 +- sql/sql_parse.cc | 2 ++ sql/sql_table.cc | 8 +++++++- 6 files changed, 52 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index ba9336c20bb..5404681e222 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -733,3 +733,20 @@ count(*) 5 deallocate prepare stmt; drop table t1; +drop table if exists t1; +Warnings: +Note 1051 Unknown table 't1' +prepare stmt from 'create table t1 (a varchar(10) character set utf8)'; +execute stmt; +insert into t1 (a) values (repeat('a', 20)); +select length(a) from t1; +length(a) +10 +drop table t1; +execute stmt; +insert into t1 (a) values (repeat('a', 20)); +select length(a) from t1; +length(a) +10 +drop table t1; +deallocate prepare stmt; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index b0755d06414..b1f6be819d4 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -763,5 +763,27 @@ execute stmt using @like; deallocate prepare stmt; drop table t1; -# End of 4.1 tests +# +# Bug#13134 "Length of VARCHAR() utf8 column is increasing when table is +# recreated with PS/SP" +# + +drop table if exists t1; +prepare stmt from 'create table t1 (a varchar(10) character set utf8)'; +execute stmt; +--disable_warnings +insert into t1 (a) values (repeat('a', 20)); +--enable_warnings +select length(a) from t1; +drop table t1; +execute stmt; +--disable_warnings +insert into t1 (a) values (repeat('a', 20)); +--enable_warnings +# Check that the data is truncated to the same length +select length(a) from t1; +drop table t1; +deallocate prepare stmt; + +# End of 4.1 tests diff --git a/sql/field.cc b/sql/field.cc index b1d9167aee2..fd6eba9e492 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -6516,13 +6516,11 @@ bool Field_num::eq_def(Field *field) 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. + Convert create_field::length from number of characters to number of bytes. */ 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: @@ -6775,6 +6773,7 @@ create_field::create_field(Field *old_field,Field *orig_field) break; } + char_length= length; decimals= old_field->decimals(); if (sql_type == FIELD_TYPE_STRING) { diff --git a/sql/field.h b/sql/field.h index 04f1bd68c7a..966549516b1 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1188,7 +1188,7 @@ public: /* The value of 'length' before a call to create_length_to_internal_length */ - uint32 chars_length; + uint32 char_length; uint decimals,flags,pack_length; Field::utype unireg_check; TYPELIB *interval; // Which interval to use diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1daa0a5ffec..21a335637b9 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4480,6 +4480,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, NOT_FIXED_DEC-1) : 0; new_field->sql_type=type; new_field->length=0; + new_field->char_length= 0; new_field->change=change; new_field->interval=0; new_field->pack_length=0; @@ -4750,6 +4751,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, FIELD_TYPE_STRING : new_field->sql_type, new_field->length); + new_field->char_length= new_field->length; lex->create_list.push_back(new_field); lex->last_field=new_field; DBUG_RETURN(0); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 71cbc0be1e3..616db8b0424 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -488,6 +488,12 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, for (field_no=0; (sql_field=it++) ; field_no++) { + /* + Initialize length from its original value (number of characters), + which was set in the parser. This is necessary if we're + executing a prepared statement for the second time. + */ + sql_field->length= sql_field->char_length; if (!sql_field->charset) sql_field->charset= create_info->default_table_charset; /* @@ -665,7 +671,7 @@ 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->chars_length; + sql_field->length= dup_field->char_length; sql_field->pack_length= dup_field->pack_length; sql_field->create_length_to_internal_length(); sql_field->decimals= dup_field->decimals; From 7178f247f531ce3a3dd2faee520027ea8d2fad88 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Thu, 23 Feb 2006 23:41:15 +0300 Subject: [PATCH 2/2] Remove 'delayed' to make the test deterministic (already fixed in 5.0). A post-review fix (Bug#13134) --- mysql-test/r/heap.result | 4 ++-- mysql-test/r/ps.result | 3 --- mysql-test/t/heap.test | 4 ++-- mysql-test/t/ps.test | 1 - 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/heap.result b/mysql-test/r/heap.result index e3b9f7db984..6bb9d0c87ee 100644 --- a/mysql-test/r/heap.result +++ b/mysql-test/r/heap.result @@ -297,11 +297,11 @@ insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd ERROR 23000: Duplicate entry 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl' for key 1 drop table t1; CREATE TABLE t1 (a int, key(a)) engine=heap; -insert delayed into t1 values (0); +insert into t1 values (0); delete from t1; select * from t1; a -insert delayed into t1 values (0), (1); +insert into t1 values (0), (1); select * from t1 where a = 0; a 0 diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 5404681e222..e94c2952893 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -733,9 +733,6 @@ count(*) 5 deallocate prepare stmt; drop table t1; -drop table if exists t1; -Warnings: -Note 1051 Unknown table 't1' prepare stmt from 'create table t1 (a varchar(10) character set utf8)'; execute stmt; insert into t1 (a) values (repeat('a', 20)); diff --git a/mysql-test/t/heap.test b/mysql-test/t/heap.test index a8128b79e3b..50147b4182d 100644 --- a/mysql-test/t/heap.test +++ b/mysql-test/t/heap.test @@ -238,10 +238,10 @@ drop table t1; # Bug 12796: Record doesn't show when selecting through index # CREATE TABLE t1 (a int, key(a)) engine=heap; -insert delayed into t1 values (0); +insert into t1 values (0); delete from t1; select * from t1; -insert delayed into t1 values (0), (1); +insert into t1 values (0), (1); select * from t1 where a = 0; drop table t1; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index b1f6be819d4..af885a5c02f 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -769,7 +769,6 @@ drop table t1; # recreated with PS/SP" # -drop table if exists t1; prepare stmt from 'create table t1 (a varchar(10) character set utf8)'; execute stmt; --disable_warnings