Commit 3bf609b7 authored by kostja@bodhi.local's avatar kostja@bodhi.local

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.
parent cb4ea78c
...@@ -422,3 +422,34 @@ DROP TABLE IF EXISTS t1; ...@@ -422,3 +422,34 @@ DROP TABLE IF EXISTS t1;
CREATE TABLE t1(f1 CHAR(100) DEFAULT 'test'); CREATE TABLE t1(f1 CHAR(100) DEFAULT 'test');
INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3)); INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3));
DROP TABLE IF EXISTS t1; 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;
This diff was suppressed by a .gitattributes entry.
...@@ -146,3 +146,44 @@ DROP TABLE IF EXISTS t1; ...@@ -146,3 +146,44 @@ DROP TABLE IF EXISTS t1;
CREATE TABLE t1(f1 CHAR(100) DEFAULT 'test'); CREATE TABLE t1(f1 CHAR(100) DEFAULT 'test');
INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3)); INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3));
DROP TABLE IF EXISTS t1; 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;
...@@ -6154,15 +6154,26 @@ Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table, ...@@ -6154,15 +6154,26 @@ Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table,
Field *new_field; Field *new_field;
if (type() != MYSQL_TYPE_VAR_STRING || keep_type) 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 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 This is done to ensure that ALTER TABLE will convert old VARCHAR fields
to now 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()); 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;
} }
/**************************************************************************** /****************************************************************************
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment