Commit 4355ea5a authored by unknown's avatar unknown
Browse files

A fix for Bug#14897 "ResultSet.getString("table.column") sometimes

doesn't find the column"

When a user was using 4.1 tables with VARCHAR column and 5.0 server
and a query that used a temporary table to resolve itself, the
table metadata for the varchar column sent to client was incorrect:
MYSQL_FIELD::table member was empty.

The bug was caused by implicit "upgrade" from old VARCHAR to new
VARCHAR hard-coded in Field::new_field, which did not preserve
the information about the original table. Thus, the field metadata
of the "upgraded" field pointed to an auxiliary temporary table
created for query execution.

The fix is to copy the pointer to the original table to the new field.


mysql-test/r/type_varchar.result:
  Update test results (Bug#14897)
mysql-test/t/type_varchar.test:
  Add a test case for Bug#14897 "ResultSet.getString("table.column") 
  sometimes doesn't find the column"
sql/field.cc:
  Preserve the original table name when converting fields from 
  old VARCHAR to new VARCHAR.
mysql-test/std_data/14897.frm:
  New BitKeeper file ``mysql-test/std_data/14897.frm''
parent c923270f
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -422,3 +422,34 @@ DROP TABLE IF EXISTS t1;
CREATE TABLE t1(f1 CHAR(100) DEFAULT 'test');
INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3));
DROP TABLE IF EXISTS t1;
drop table if exists t1, t2, t3;
create table t3 (
id int(11),
en varchar(255) character set utf8,
cz varchar(255) character set utf8
);
truncate table t3;
insert into t3 (id, en, cz) values 
(1,'en string 1','cz string 1'),
(2,'en string 2','cz string 2'),
(3,'en string 3','cz string 3');
create table t1 ( 
id int(11),
name_id int(11)
);
insert into t1 (id, name_id) values (1,1), (2,3), (3,3);
create table t2 (id int(11));
insert into t2 (id) values (1), (2), (3);
select t1.*, t2.id, t3.en, t3.cz from t1 left join t2 on t1.id=t2.id
left join t3 on t1.id=t3.id order by t3.id;
Catalog	Database	Table	Table_alias	Column	Column_alias	Type	Length	Max length	Is_null	Flags	Decimals	Charsetnr
def	test	t1	t1	id	id	3	11	1	Y	32768	0	63
def	test	t1	t1	name_id	name_id	3	11	1	Y	32768	0	63
def	test	t2	t2	id	id	3	11	1	Y	32768	0	63
def	test	t3	t3	en	en	253	255	11	Y	0	0	8
def	test	t3	t3	cz	cz	253	255	11	Y	0	0	8
id	name_id	id	en	cz
1	1	1	en string 1	cz string 1
2	3	2	en string 2	cz string 2
3	3	3	en string 3	cz string 3
drop table t1, t2, t3;
+8.41 KiB

File added.

Preview suppressed by a .gitattributes entry or the file's encoding is unsupported.

+41 −0
Original line number Diff line number Diff line
@@ -146,3 +146,44 @@ DROP TABLE IF EXISTS t1;
CREATE TABLE t1(f1 CHAR(100) DEFAULT 'test');
INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3));
DROP TABLE IF EXISTS t1;

#
# Bug#14897 "ResultSet.getString("table.column") sometimes doesn't find the
# column"
# Test that after upgrading an old 4.1 VARCHAR column to 5.0 VARCHAR we preserve
# the original column metadata.
#
--disable_warnings
drop table if exists t1, t2, t3;
--enable_warnings

create table t3 (
  id int(11),
  en varchar(255) character set utf8,
  cz varchar(255) character set utf8
);
system cp $MYSQL_TEST_DIR/std_data/14897.frm $MYSQLTEST_VARDIR/master-data/test/t3.frm;
truncate table t3;
insert into t3 (id, en, cz) values 
(1,'en string 1','cz string 1'),
(2,'en string 2','cz string 2'),
(3,'en string 3','cz string 3');

create table t1 ( 
  id int(11),
  name_id int(11)
);
insert into t1 (id, name_id) values (1,1), (2,3), (3,3);

create table t2 (id int(11));
insert into t2 (id) values (1), (2), (3);

# max_length is different for varchar fields in ps-protocol and we can't 
# replace a single metadata column, disable PS protocol
--disable_ps_protocol
--enable_metadata
select t1.*, t2.id, t3.en, t3.cz from t1 left join t2 on t1.id=t2.id
left join t3 on t1.id=t3.id order by t3.id;
--disable_metadata
--enable_ps_protocol
drop table t1, t2, t3;
+19 −8
Original line number Diff line number Diff line
@@ -6154,15 +6154,26 @@ Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table,
  Field *new_field;

  if (type() != MYSQL_TYPE_VAR_STRING || keep_type)
    return Field::new_field(root, new_table, keep_type);
    new_field= Field::new_field(root, new_table, keep_type);
  else
  {

    /*
      Old VARCHAR field which should be modified to a VARCHAR on copy
      This is done to ensure that ALTER TABLE will convert old VARCHAR fields
      to now VARCHAR fields.
    */
  return new Field_varstring(field_length, maybe_null(),
    new_field= new Field_varstring(field_length, maybe_null(),
                                   field_name, new_table, charset());
    /*
      Normally orig_table is different from table only if field was created
      via ::new_field.  Here we alter the type of field, so ::new_field is
      not applicable. But we still need to preserve the original field
      metadata for the client-server protocol.
    */
    new_field->orig_table= orig_table;
  }
  return new_field;
}

/****************************************************************************