mirror of
https://github.com/MariaDB/server.git
synced 2025-08-05 13:16:09 +03:00
Merge gkodinov@bk-internal.mysql.com:/home/bk/mysql-5.0-opt
into rakia.gmz:/home/kgeorge/mysql/autopush/B25575-5.0-opt
This commit is contained in:
@@ -1605,3 +1605,31 @@ WHERE t1.id='5';
|
|||||||
id ct pc nm
|
id ct pc nm
|
||||||
5 NULL NULL NULL
|
5 NULL NULL NULL
|
||||||
DROP TABLE t1,t2,t3,t4;
|
DROP TABLE t1,t2,t3,t4;
|
||||||
|
CREATE TABLE t1 (a INT, b INT);
|
||||||
|
CREATE TABLE t2 (a INT);
|
||||||
|
CREATE TABLE t3 (a INT, c INT);
|
||||||
|
CREATE TABLE t4 (a INT, c INT);
|
||||||
|
CREATE TABLE t5 (a INT, c INT);
|
||||||
|
SELECT b FROM t1 JOIN (t2 LEFT JOIN t3 USING (a) LEFT JOIN t4 USING (a)
|
||||||
|
LEFT JOIN t5 USING (a)) USING (a);
|
||||||
|
b
|
||||||
|
SELECT c FROM t1 JOIN (t2 LEFT JOIN t3 USING (a) LEFT JOIN t4 USING (a)
|
||||||
|
LEFT JOIN t5 USING (a)) USING (a);
|
||||||
|
ERROR 23000: Column 'c' in field list is ambiguous
|
||||||
|
SELECT b FROM t1 JOIN (t2 JOIN t3 USING (a) JOIN t4 USING (a)
|
||||||
|
JOIN t5 USING (a)) USING (a);
|
||||||
|
b
|
||||||
|
SELECT c FROM t1 JOIN (t2 JOIN t3 USING (a) JOIN t4 USING (a)
|
||||||
|
JOIN t5 USING (a)) USING (a);
|
||||||
|
ERROR 23000: Column 'c' in field list is ambiguous
|
||||||
|
DROP TABLE t1,t2,t3,t4,t5;
|
||||||
|
CREATE TABLE t1 (a INT, b INT);
|
||||||
|
CREATE TABLE t2 (a INT, b INT);
|
||||||
|
CREATE TABLE t3 (a INT, b INT);
|
||||||
|
INSERT INTO t1 VALUES (1,1);
|
||||||
|
INSERT INTO t2 VALUES (1,1);
|
||||||
|
INSERT INTO t3 VALUES (1,1);
|
||||||
|
SELECT * FROM t1 JOIN (t2 JOIN t3 USING (b)) USING (a);
|
||||||
|
ERROR 23000: Column 'a' in from clause is ambiguous
|
||||||
|
DROP TABLE t1,t2,t3;
|
||||||
|
End of 5.0 tests
|
||||||
|
@@ -1045,3 +1045,42 @@ SELECT t1.*, t4.nm
|
|||||||
WHERE t1.id='5';
|
WHERE t1.id='5';
|
||||||
|
|
||||||
DROP TABLE t1,t2,t3,t4;
|
DROP TABLE t1,t2,t3,t4;
|
||||||
|
|
||||||
|
#
|
||||||
|
# BUG#25575: ERROR 1052 (Column in from clause is ambiguous) with sub-join
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a INT, b INT);
|
||||||
|
CREATE TABLE t2 (a INT);
|
||||||
|
CREATE TABLE t3 (a INT, c INT);
|
||||||
|
CREATE TABLE t4 (a INT, c INT);
|
||||||
|
CREATE TABLE t5 (a INT, c INT);
|
||||||
|
|
||||||
|
SELECT b FROM t1 JOIN (t2 LEFT JOIN t3 USING (a) LEFT JOIN t4 USING (a)
|
||||||
|
LEFT JOIN t5 USING (a)) USING (a);
|
||||||
|
|
||||||
|
--error ER_NON_UNIQ_ERROR
|
||||||
|
SELECT c FROM t1 JOIN (t2 LEFT JOIN t3 USING (a) LEFT JOIN t4 USING (a)
|
||||||
|
LEFT JOIN t5 USING (a)) USING (a);
|
||||||
|
|
||||||
|
SELECT b FROM t1 JOIN (t2 JOIN t3 USING (a) JOIN t4 USING (a)
|
||||||
|
JOIN t5 USING (a)) USING (a);
|
||||||
|
|
||||||
|
--error ER_NON_UNIQ_ERROR
|
||||||
|
SELECT c FROM t1 JOIN (t2 JOIN t3 USING (a) JOIN t4 USING (a)
|
||||||
|
JOIN t5 USING (a)) USING (a);
|
||||||
|
|
||||||
|
DROP TABLE t1,t2,t3,t4,t5;
|
||||||
|
CREATE TABLE t1 (a INT, b INT);
|
||||||
|
CREATE TABLE t2 (a INT, b INT);
|
||||||
|
CREATE TABLE t3 (a INT, b INT);
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES (1,1);
|
||||||
|
INSERT INTO t2 VALUES (1,1);
|
||||||
|
INSERT INTO t3 VALUES (1,1);
|
||||||
|
|
||||||
|
--error ER_NON_UNIQ_ERROR
|
||||||
|
SELECT * FROM t1 JOIN (t2 JOIN t3 USING (b)) USING (a);
|
||||||
|
|
||||||
|
DROP TABLE t1,t2,t3;
|
||||||
|
|
||||||
|
--echo End of 5.0 tests
|
||||||
|
@@ -985,7 +985,8 @@ bool push_new_name_resolution_context(THD *thd,
|
|||||||
TABLE_LIST *left_op,
|
TABLE_LIST *left_op,
|
||||||
TABLE_LIST *right_op);
|
TABLE_LIST *right_op);
|
||||||
void add_join_on(TABLE_LIST *b,Item *expr);
|
void add_join_on(TABLE_LIST *b,Item *expr);
|
||||||
void add_join_natural(TABLE_LIST *a,TABLE_LIST *b,List<String> *using_fields);
|
void add_join_natural(TABLE_LIST *a,TABLE_LIST *b,List<String> *using_fields,
|
||||||
|
SELECT_LEX *lex);
|
||||||
bool add_proc_to_list(THD *thd, Item *item);
|
bool add_proc_to_list(THD *thd, Item *item);
|
||||||
TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find);
|
TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find);
|
||||||
void update_non_unique_table_error(TABLE_LIST *update,
|
void update_non_unique_table_error(TABLE_LIST *update,
|
||||||
|
@@ -2945,7 +2945,7 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
|
|||||||
{
|
{
|
||||||
List_iterator_fast<Natural_join_column>
|
List_iterator_fast<Natural_join_column>
|
||||||
field_it(*(table_ref->join_columns));
|
field_it(*(table_ref->join_columns));
|
||||||
Natural_join_column *nj_col;
|
Natural_join_column *nj_col, *curr_nj_col;
|
||||||
Field *found_field;
|
Field *found_field;
|
||||||
Query_arena *arena, backup;
|
Query_arena *arena, backup;
|
||||||
DBUG_ENTER("find_field_in_natural_join");
|
DBUG_ENTER("find_field_in_natural_join");
|
||||||
@@ -2956,14 +2956,21 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
|
|||||||
|
|
||||||
LINT_INIT(found_field);
|
LINT_INIT(found_field);
|
||||||
|
|
||||||
for (;;)
|
for (nj_col= NULL, curr_nj_col= field_it++; curr_nj_col;
|
||||||
|
curr_nj_col= field_it++)
|
||||||
{
|
{
|
||||||
if (!(nj_col= field_it++))
|
if (!my_strcasecmp(system_charset_info, curr_nj_col->name(), name))
|
||||||
DBUG_RETURN(NULL);
|
{
|
||||||
|
if (nj_col)
|
||||||
if (!my_strcasecmp(system_charset_info, nj_col->name(), name))
|
{
|
||||||
break;
|
my_error(ER_NON_UNIQ_ERROR, MYF(0), name, thd->where);
|
||||||
|
DBUG_RETURN(NULL);
|
||||||
|
}
|
||||||
|
nj_col= curr_nj_col;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (!nj_col)
|
||||||
|
DBUG_RETURN(NULL);
|
||||||
|
|
||||||
if (nj_col->view_field)
|
if (nj_col->view_field)
|
||||||
{
|
{
|
||||||
@@ -3774,9 +3781,16 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
|
|||||||
{
|
{
|
||||||
bool found= FALSE;
|
bool found= FALSE;
|
||||||
const char *field_name_1;
|
const char *field_name_1;
|
||||||
|
/* true if field_name_1 is a member of using_fields */
|
||||||
|
bool is_using_column_1;
|
||||||
if (!(nj_col_1= it_1.get_or_create_column_ref(leaf_1)))
|
if (!(nj_col_1= it_1.get_or_create_column_ref(leaf_1)))
|
||||||
goto err;
|
goto err;
|
||||||
field_name_1= nj_col_1->name();
|
field_name_1= nj_col_1->name();
|
||||||
|
is_using_column_1= using_fields &&
|
||||||
|
test_if_string_in_list(field_name_1, using_fields);
|
||||||
|
DBUG_PRINT ("info", ("field_name_1=%s.%s",
|
||||||
|
nj_col_1->table_name() ? nj_col_1->table_name() : "",
|
||||||
|
field_name_1));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Find a field with the same name in table_ref_2.
|
Find a field with the same name in table_ref_2.
|
||||||
@@ -3793,6 +3807,10 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
|
|||||||
if (!(cur_nj_col_2= it_2.get_or_create_column_ref(leaf_2)))
|
if (!(cur_nj_col_2= it_2.get_or_create_column_ref(leaf_2)))
|
||||||
goto err;
|
goto err;
|
||||||
cur_field_name_2= cur_nj_col_2->name();
|
cur_field_name_2= cur_nj_col_2->name();
|
||||||
|
DBUG_PRINT ("info", ("cur_field_name_2=%s.%s",
|
||||||
|
cur_nj_col_2->table_name() ?
|
||||||
|
cur_nj_col_2->table_name() : "",
|
||||||
|
cur_field_name_2));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Compare the two columns and check for duplicate common fields.
|
Compare the two columns and check for duplicate common fields.
|
||||||
@@ -3800,10 +3818,16 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
|
|||||||
table_ref_2 (then found == TRUE), or if a field in table_ref_2
|
table_ref_2 (then found == TRUE), or if a field in table_ref_2
|
||||||
was already matched by some previous field in table_ref_1
|
was already matched by some previous field in table_ref_1
|
||||||
(then cur_nj_col_2->is_common == TRUE).
|
(then cur_nj_col_2->is_common == TRUE).
|
||||||
|
Note that it is too early to check the columns outside of the
|
||||||
|
USING list for ambiguity because they are not actually "referenced"
|
||||||
|
here. These columns must be checked only on unqualified reference
|
||||||
|
by name (e.g. in SELECT list).
|
||||||
*/
|
*/
|
||||||
if (!my_strcasecmp(system_charset_info, field_name_1, cur_field_name_2))
|
if (!my_strcasecmp(system_charset_info, field_name_1, cur_field_name_2))
|
||||||
{
|
{
|
||||||
if (found || cur_nj_col_2->is_common)
|
DBUG_PRINT ("info", ("match c1.is_common=%d", nj_col_1->is_common));
|
||||||
|
if (cur_nj_col_2->is_common ||
|
||||||
|
(found && (!using_fields || is_using_column_1)))
|
||||||
{
|
{
|
||||||
my_error(ER_NON_UNIQ_ERROR, MYF(0), field_name_1, thd->where);
|
my_error(ER_NON_UNIQ_ERROR, MYF(0), field_name_1, thd->where);
|
||||||
goto err;
|
goto err;
|
||||||
@@ -3829,9 +3853,7 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
|
|||||||
clause (if present), mark them as common fields, and add a new
|
clause (if present), mark them as common fields, and add a new
|
||||||
equi-join condition to the ON clause.
|
equi-join condition to the ON clause.
|
||||||
*/
|
*/
|
||||||
if (nj_col_2 &&
|
if (nj_col_2 && (!using_fields ||is_using_column_1))
|
||||||
(!using_fields ||
|
|
||||||
test_if_string_in_list(field_name_1, using_fields)))
|
|
||||||
{
|
{
|
||||||
Item *item_1= nj_col_1->create_item(thd);
|
Item *item_1= nj_col_1->create_item(thd);
|
||||||
Item *item_2= nj_col_2->create_item(thd);
|
Item *item_2= nj_col_2->create_item(thd);
|
||||||
@@ -3886,6 +3908,13 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
|
|||||||
eq_cond);
|
eq_cond);
|
||||||
|
|
||||||
nj_col_1->is_common= nj_col_2->is_common= TRUE;
|
nj_col_1->is_common= nj_col_2->is_common= TRUE;
|
||||||
|
DBUG_PRINT ("info", ("%s.%s and %s.%s are common",
|
||||||
|
nj_col_1->table_name() ?
|
||||||
|
nj_col_1->table_name() : "",
|
||||||
|
nj_col_1->name(),
|
||||||
|
nj_col_2->table_name() ?
|
||||||
|
nj_col_2->table_name() : "",
|
||||||
|
nj_col_2->name()));
|
||||||
|
|
||||||
if (field_1)
|
if (field_1)
|
||||||
{
|
{
|
||||||
|
@@ -586,6 +586,20 @@ public:
|
|||||||
int cur_pos_in_select_list;
|
int cur_pos_in_select_list;
|
||||||
|
|
||||||
List<udf_func> udf_list; /* udf function calls stack */
|
List<udf_func> udf_list; /* udf function calls stack */
|
||||||
|
/*
|
||||||
|
This is a copy of the original JOIN USING list that comes from
|
||||||
|
the parser. The parser :
|
||||||
|
1. Sets the natural_join of the second TABLE_LIST in the join
|
||||||
|
and the st_select_lex::prev_join_using.
|
||||||
|
2. Makes a parent TABLE_LIST and sets its is_natural_join/
|
||||||
|
join_using_fields members.
|
||||||
|
3. Uses the wrapper TABLE_LIST as a table in the upper level.
|
||||||
|
We cannot assign directly to join_using_fields in the parser because
|
||||||
|
at stage (1.) the parent TABLE_LIST is not constructed yet and
|
||||||
|
the assignment will override the JOIN USING fields of the lower level
|
||||||
|
joins on the right.
|
||||||
|
*/
|
||||||
|
List<String> *prev_join_using;
|
||||||
|
|
||||||
void init_query();
|
void init_query();
|
||||||
void init_select();
|
void init_select();
|
||||||
|
@@ -6432,11 +6432,8 @@ TABLE_LIST *st_select_lex::nest_last_join(THD *thd)
|
|||||||
If this is a JOIN ... USING, move the list of joined fields to the
|
If this is a JOIN ... USING, move the list of joined fields to the
|
||||||
table reference that describes the join.
|
table reference that describes the join.
|
||||||
*/
|
*/
|
||||||
if (table->join_using_fields)
|
if (prev_join_using)
|
||||||
{
|
ptr->join_using_fields= prev_join_using;
|
||||||
ptr->join_using_fields= table->join_using_fields;
|
|
||||||
table->join_using_fields= NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
join_list->push_front(ptr);
|
join_list->push_front(ptr);
|
||||||
@@ -6692,6 +6689,7 @@ void add_join_on(TABLE_LIST *b, Item *expr)
|
|||||||
a Left join argument
|
a Left join argument
|
||||||
b Right join argument
|
b Right join argument
|
||||||
using_fields Field names from USING clause
|
using_fields Field names from USING clause
|
||||||
|
lex The current st_select_lex
|
||||||
|
|
||||||
IMPLEMENTATION
|
IMPLEMENTATION
|
||||||
This function marks that table b should be joined with a either via
|
This function marks that table b should be joined with a either via
|
||||||
@@ -6720,10 +6718,11 @@ void add_join_on(TABLE_LIST *b, Item *expr)
|
|||||||
None
|
None
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List<String> *using_fields)
|
void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List<String> *using_fields,
|
||||||
|
SELECT_LEX *lex)
|
||||||
{
|
{
|
||||||
b->natural_join= a;
|
b->natural_join= a;
|
||||||
b->join_using_fields= using_fields;
|
lex->prev_join_using= using_fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -5466,11 +5466,11 @@ join_table:
|
|||||||
YYERROR_UNLESS($1 && $3);
|
YYERROR_UNLESS($1 && $3);
|
||||||
}
|
}
|
||||||
'(' using_list ')'
|
'(' using_list ')'
|
||||||
{ add_join_natural($1,$3,$7); $$=$3; }
|
{ add_join_natural($1,$3,$7,Select); $$=$3; }
|
||||||
| table_ref NATURAL JOIN_SYM table_factor
|
| table_ref NATURAL JOIN_SYM table_factor
|
||||||
{
|
{
|
||||||
YYERROR_UNLESS($1 && ($$=$4));
|
YYERROR_UNLESS($1 && ($$=$4));
|
||||||
add_join_natural($1,$4,NULL);
|
add_join_natural($1,$4,NULL,Select);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* LEFT JOIN variants */
|
/* LEFT JOIN variants */
|
||||||
@@ -5497,11 +5497,15 @@ join_table:
|
|||||||
YYERROR_UNLESS($1 && $5);
|
YYERROR_UNLESS($1 && $5);
|
||||||
}
|
}
|
||||||
USING '(' using_list ')'
|
USING '(' using_list ')'
|
||||||
{ add_join_natural($1,$5,$9); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; }
|
{
|
||||||
|
add_join_natural($1,$5,$9,Select);
|
||||||
|
$5->outer_join|=JOIN_TYPE_LEFT;
|
||||||
|
$$=$5;
|
||||||
|
}
|
||||||
| table_ref NATURAL LEFT opt_outer JOIN_SYM table_factor
|
| table_ref NATURAL LEFT opt_outer JOIN_SYM table_factor
|
||||||
{
|
{
|
||||||
YYERROR_UNLESS($1 && $6);
|
YYERROR_UNLESS($1 && $6);
|
||||||
add_join_natural($1,$6,NULL);
|
add_join_natural($1,$6,NULL,Select);
|
||||||
$6->outer_join|=JOIN_TYPE_LEFT;
|
$6->outer_join|=JOIN_TYPE_LEFT;
|
||||||
$$=$6;
|
$$=$6;
|
||||||
}
|
}
|
||||||
@@ -5535,12 +5539,12 @@ join_table:
|
|||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
if (!($$= lex->current_select->convert_right_join()))
|
if (!($$= lex->current_select->convert_right_join()))
|
||||||
YYABORT;
|
YYABORT;
|
||||||
add_join_natural($$,$5,$9);
|
add_join_natural($$,$5,$9,Select);
|
||||||
}
|
}
|
||||||
| table_ref NATURAL RIGHT opt_outer JOIN_SYM table_factor
|
| table_ref NATURAL RIGHT opt_outer JOIN_SYM table_factor
|
||||||
{
|
{
|
||||||
YYERROR_UNLESS($1 && $6);
|
YYERROR_UNLESS($1 && $6);
|
||||||
add_join_natural($6,$1,NULL);
|
add_join_natural($6,$1,NULL,Select);
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
if (!($$= lex->current_select->convert_right_join()))
|
if (!($$= lex->current_select->convert_right_join()))
|
||||||
YYABORT;
|
YYABORT;
|
||||||
|
@@ -2630,6 +2630,7 @@ Field *Natural_join_column::field()
|
|||||||
|
|
||||||
const char *Natural_join_column::table_name()
|
const char *Natural_join_column::table_name()
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(table_ref);
|
||||||
return table_ref->alias;
|
return table_ref->alias;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user