Commit 6c937d71 authored by unknown's avatar unknown

Fix for the bug #2976: NATURAL JOIN produces duplicate columns.

Improvement natural join code in the setup_conds(). 


mysql-test/r/join.result:
  Fix for the bug #2976: NATURAL JOIN produces duplicate columns
mysql-test/r/join_outer.result:
  Fix for the bug #2976: NATURAL JOIN produces duplicate columns
mysql-test/r/select.result:
  Fix for the bug #2976: NATURAL JOIN produces duplicate columns
parent bf4e1d46
...@@ -277,11 +277,11 @@ CREATE TABLE t2 (ID INTEGER NOT NULL PRIMARY KEY, Value2 VARCHAR(255)); ...@@ -277,11 +277,11 @@ CREATE TABLE t2 (ID INTEGER NOT NULL PRIMARY KEY, Value2 VARCHAR(255));
INSERT INTO t1 VALUES (1, 'A'); INSERT INTO t1 VALUES (1, 'A');
INSERT INTO t2 VALUES (1, 'B'); INSERT INTO t2 VALUES (1, 'B');
SELECT * FROM t1 NATURAL JOIN t2 WHERE 1 AND (Value1 = 'A' AND Value2 <> 'B'); SELECT * FROM t1 NATURAL JOIN t2 WHERE 1 AND (Value1 = 'A' AND Value2 <> 'B');
ID Value1 ID Value2 ID Value1 Value2
SELECT * FROM t1 NATURAL JOIN t2 WHERE 1 AND Value1 = 'A' AND Value2 <> 'B'; SELECT * FROM t1 NATURAL JOIN t2 WHERE 1 AND Value1 = 'A' AND Value2 <> 'B';
ID Value1 ID Value2 ID Value1 Value2
SELECT * FROM t1 NATURAL JOIN t2 WHERE (Value1 = 'A' AND Value2 <> 'B') AND 1; SELECT * FROM t1 NATURAL JOIN t2 WHERE (Value1 = 'A' AND Value2 <> 'B') AND 1;
ID Value1 ID Value2 ID Value1 Value2
drop table t1,t2; drop table t1,t2;
create table t1 (i int); create table t1 (i int);
create table t2 (i int); create table t2 (i int);
......
...@@ -124,8 +124,8 @@ grp a c id a c d ...@@ -124,8 +124,8 @@ grp a c id a c d
3 5 C 3 5 B 5 3 5 C 3 5 B 5
3 6 D 3 6 C 6 3 6 D 3 6 C 6
select t1.*,t2.* from t1 natural join t2; select t1.*,t2.* from t1 natural join t2;
grp a c id a c d grp a c id d
1 1 a 1 1 a 1 1 1 a 1 1
drop table t1,t2; drop table t1,t2;
CREATE TABLE t1 ( CREATE TABLE t1 (
usr_id INT unsigned NOT NULL, usr_id INT unsigned NOT NULL,
...@@ -467,10 +467,10 @@ count color ...@@ -467,10 +467,10 @@ count color
15 white 15 white
7 green 7 green
select * from t2 natural join t1; select * from t2 natural join t1;
count color color name count color name
10 green green lime 10 green lime
7 green green lime 7 green lime
5 black black grape 5 black grape
select t2.count, t1.name from t2 natural join t1; select t2.count, t1.name from t2 natural join t1;
count name count name
10 lime 10 lime
......
...@@ -2279,10 +2279,10 @@ a a a ...@@ -2279,10 +2279,10 @@ a a a
2 2 2 2 2 2
3 3 3 3 3 3
select * from t1 natural join (t1 as t2 left join t1 as t3 using (a)); select * from t1 natural join (t1 as t2 left join t1 as t3 using (a));
a a a a a
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
select * from (t1 as t2 left join t1 as t3 using (a)) natural join t1; select * from (t1 as t2 left join t1 as t3 using (a)) natural join t1;
a a a a a a
1 1 1 1 1 1
......
...@@ -2292,12 +2292,21 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, ...@@ -2292,12 +2292,21 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
Field **ptr=table->field,*field; Field **ptr=table->field,*field;
thd->used_tables|=table->map; thd->used_tables|=table->map;
while ((field = *ptr++)) while ((field = *ptr++))
{
/* Skip duplicate field names if NATURAL JOIN is used */
if (table->outer_join ||
!tables->natural_join ||
tables->natural_join->table->outer_join ||
!find_field_in_table(thd, tables->natural_join->table,
field->field_name, strlen(field->field_name),
0, 0))
{ {
Item_field *item= new Item_field(field); Item_field *item= new Item_field(field);
if (!found++) if (!found++)
(void) it->replace(item); // Replace '*' (void) it->replace(item); // Replace '*'
else else
it->after(item); it->after(item);
}
/* /*
Mark if field used before in this select. Mark if field used before in this select.
Used by 'insert' to verify if a field name is used twice Used by 'insert' to verify if a field name is used twice
...@@ -2377,29 +2386,25 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) ...@@ -2377,29 +2386,25 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
DBUG_RETURN(1); DBUG_RETURN(1);
cond_and->top_level_item(); cond_and->top_level_item();
uint i,j; Field **t1_field, *t2_field;
for (i=0 ; i < t1->fields ; i++) for (t1_field= t1->field; (*t1_field); t1_field++)
{
// TODO: This could be optimized to use hashed names if t2 had a hash
for (j=0 ; j < t2->fields ; j++)
{ {
if (!my_strcasecmp(system_charset_info, const char *t1_field_name= (*t1_field)->field_name;
t1->field[i]->field_name,
t2->field[j]->field_name)) if ((t2_field= find_field_in_table(thd, t2, t1_field_name,
strlen(t1_field_name), 0, 0)))
{ {
Item_func_eq *tmp=new Item_func_eq(new Item_field(t1->field[i]), Item_func_eq *tmp=new Item_func_eq(new Item_field(*t1_field),
new Item_field(t2->field[j])); new Item_field(t2_field));
if (!tmp) if (!tmp)
DBUG_RETURN(1); DBUG_RETURN(1);
tmp->fix_length_and_dec(); // Update cmp_type tmp->fix_length_and_dec(); // Update cmp_type
tmp->const_item_cache=0; tmp->const_item_cache= 0;
/* Mark field used for table cache */ /* Mark field used for table cache */
t1->field[i]->query_id=t2->field[j]->query_id=thd->query_id; (*t1_field)->query_id= t2_field->query_id= thd->query_id;
cond_and->list.push_back(tmp); cond_and->list.push_back(tmp);
t1->used_keys.intersect(t1->field[i]->part_of_key); t1->used_keys.intersect((*t1_field)->part_of_key);
t2->used_keys.intersect(t2->field[j]->part_of_key); t2->used_keys.intersect(t2_field->part_of_key);
break;
}
} }
} }
cond_and->used_tables_cache= t1->map | t2->map; cond_and->used_tables_cache= t1->map | t2->map;
......
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