Commit 371eeef0 authored by unknown's avatar unknown

Merge epotemkin@bk-internal.mysql.com:/home/bk/mysql-5.0

into moonbone.local:/work/mysql-5.0-merge

parents 2c14bd9a 55718473
...@@ -2,8 +2,17 @@ This directory contains a test suite for mysql daemon. To run ...@@ -2,8 +2,17 @@ This directory contains a test suite for mysql daemon. To run
the currently existing test cases, simply execute ./mysql-test-run in the currently existing test cases, simply execute ./mysql-test-run in
this directory. It will fire up the newly built mysqld and test it. this directory. It will fire up the newly built mysqld and test it.
If you want to run the test with a running MySQL server use the --external If you want to run a test with a running MySQL server use the --extern
option to mysql-test-run. option to mysql-test-run. Please note that in this mode the test suite
expects user to specify test names to run. Otherwise it falls back to the
normal "non-extern" behaviour. The reason is that some tests
could not run with external server. Here is the sample command
to test "alias" and "analyze" tests on external server:
mysql-test-run --extern alias analyze
To match your setup you might also need to provide --socket, --user and
other relevant options.
Note that you do not have to have to do make install, and you could Note that you do not have to have to do make install, and you could
actually have a co-existing MySQL installation - the tests will not actually have a co-existing MySQL installation - the tests will not
......
...@@ -634,3 +634,18 @@ ff1 ff2 ...@@ -634,3 +634,18 @@ ff1 ff2
1 2 1 2
2 1 2 1
drop table t1, t2; drop table t1, t2;
create table t1 (a int unique);
create table t2 (a int, b int);
insert into t1 values (1),(2);
insert into t2 values (1,2);
select * from t1;
a
1
2
insert into t1 select t2.a from t2 on duplicate key update a= a + t2.b;
select * from t1;
a
2
3
drop table t1;
drop table t2;
DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t1, t2;
CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B)); CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B));
INSERT t1 VALUES (1,2,10), (3,4,20); INSERT t1 VALUES (1,2,10), (3,4,20);
INSERT t1 VALUES (5,6,30) ON DUPLICATE KEY UPDATE c=c+100; INSERT t1 VALUES (5,6,30) ON DUPLICATE KEY UPDATE c=c+100;
......
...@@ -173,3 +173,17 @@ insert into t1 values (1),(1),(2); ...@@ -173,3 +173,17 @@ insert into t1 values (1),(1),(2);
insert into t2(ff1) select f1 from t1 on duplicate key update ff2=ff2+1; insert into t2(ff1) select f1 from t1 on duplicate key update ff2=ff2+1;
select * from t2; select * from t2;
drop table t1, t2; drop table t1, t2;
#
# BUGS #9728 - 'Decreased functionality in "on duplicate key update"'
# #8147 - 'a column proclaimed ambigous in INSERT ... SELECT .. ON
# DUPLICATE'
#
create table t1 (a int unique);
create table t2 (a int, b int);
insert into t1 values (1),(2);
insert into t2 values (1,2);
select * from t1;
insert into t1 select t2.a from t2 on duplicate key update a= a + t2.b;
select * from t1;
drop table t1;
drop table t2;
--disable_warnings --disable_warnings
DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t1, t2;
--enable_warnings --enable_warnings
CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B)); CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B));
......
...@@ -338,6 +338,7 @@ Item::Item(): ...@@ -338,6 +338,7 @@ Item::Item():
place == IN_HAVING) place == IN_HAVING)
thd->lex->current_select->select_n_having_items++; thd->lex->current_select->select_n_having_items++;
} }
item_flags= 0;
} }
/* /*
...@@ -358,7 +359,8 @@ Item::Item(THD *thd, Item *item): ...@@ -358,7 +359,8 @@ Item::Item(THD *thd, Item *item):
unsigned_flag(item->unsigned_flag), unsigned_flag(item->unsigned_flag),
with_sum_func(item->with_sum_func), with_sum_func(item->with_sum_func),
fixed(item->fixed), fixed(item->fixed),
collation(item->collation) collation(item->collation),
item_flags(item->item_flags)
{ {
next= thd->free_list; // Put in free list next= thd->free_list; // Put in free list
thd->free_list= this; thd->free_list= this;
......
...@@ -225,6 +225,11 @@ typedef Item* (Item::*Item_transformer) (byte *arg); ...@@ -225,6 +225,11 @@ typedef Item* (Item::*Item_transformer) (byte *arg);
typedef void (*Cond_traverser) (const Item *item, void *arg); typedef void (*Cond_traverser) (const Item *item, void *arg);
/*
See comments for sql_yacc.yy: insert_update_elem rule
*/
#define MY_ITEM_PREFER_1ST_TABLE 1
class Item { class Item {
Item(const Item &); /* Prevent use of these */ Item(const Item &); /* Prevent use of these */
void operator=(Item &); void operator=(Item &);
...@@ -272,6 +277,7 @@ public: ...@@ -272,6 +277,7 @@ public:
my_bool is_autogenerated_name; /* indicate was name of this Item my_bool is_autogenerated_name; /* indicate was name of this Item
autogenerated or set by user */ autogenerated or set by user */
DTCollation collation; DTCollation collation;
uint8 item_flags; /* Flags on how item should be processed */
// alloc & destruct is done as start of select using sql_alloc // alloc & destruct is done as start of select using sql_alloc
Item(); Item();
...@@ -584,6 +590,11 @@ public: ...@@ -584,6 +590,11 @@ public:
cleanup(); cleanup();
delete this; delete this;
} }
virtual bool set_flags_processor(byte *args)
{
this->item_flags|= *((uint8*)args);
return false;
}
virtual bool is_splocal() { return 0; } /* Needed for error checking */ virtual bool is_splocal() { return 0; } /* Needed for error checking */
}; };
......
...@@ -2626,7 +2626,6 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, ...@@ -2626,7 +2626,6 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
uint length=(uint) strlen(name); uint length=(uint) strlen(name);
char name_buff[NAME_LEN+1]; char name_buff[NAME_LEN+1];
if (item->cached_table) if (item->cached_table)
{ {
/* /*
...@@ -2693,10 +2692,13 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, ...@@ -2693,10 +2692,13 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
db= name_buff; db= name_buff;
} }
bool search_global= item->item_flags & MY_ITEM_PREFER_1ST_TABLE;
if (table_name && table_name[0]) if (table_name && table_name[0])
{ /* Qualified field */ { /* Qualified field */
bool found_table=0; bool found_table=0;
for (; tables; tables= tables->next_local) uint table_idx= 0;
for (; tables; tables= search_global?tables->next_global:tables->next_local,
table_idx++)
{ {
/* TODO; Ensure that db and tables->db always points to something ! */ /* TODO; Ensure that db and tables->db always points to something ! */
if (!my_strcasecmp(table_alias_charset, tables->alias, table_name) && if (!my_strcasecmp(table_alias_charset, tables->alias, table_name) &&
...@@ -2732,6 +2734,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, ...@@ -2732,6 +2734,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
return (Field*) 0; return (Field*) 0;
} }
found=find; found=find;
if (table_idx == 0 && item->item_flags & MY_ITEM_PREFER_1ST_TABLE)
break;
} }
} }
} }
...@@ -2756,9 +2760,10 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, ...@@ -2756,9 +2760,10 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
return (Field*) not_found_field; return (Field*) not_found_field;
return (Field*) 0; return (Field*) 0;
} }
bool allow_rowid= tables && !tables->next_local; // Only one table bool allow_rowid= tables && !tables->next_local; // Only one table
for (; tables ; tables= tables->next_local) uint table_idx= 0;
for (; tables ; tables= search_global?tables->next_global:tables->next_local,
table_idx++)
{ {
if (!tables->table && !tables->ancestor) if (!tables->table && !tables->ancestor)
{ {
...@@ -2793,7 +2798,9 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, ...@@ -2793,7 +2798,9 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
my_error(ER_NON_UNIQ_ERROR, MYF(0), name, thd->where); my_error(ER_NON_UNIQ_ERROR, MYF(0), name, thd->where);
return (Field*) 0; return (Field*) 0;
} }
found=field; found= field;
if (table_idx == 0 && item->item_flags & MY_ITEM_PREFER_1ST_TABLE)
break;
} }
} }
if (found) if (found)
......
...@@ -6120,9 +6120,24 @@ insert_update_elem: ...@@ -6120,9 +6120,24 @@ insert_update_elem:
simple_ident_nospvar equal expr_or_default simple_ident_nospvar equal expr_or_default
{ {
LEX *lex= Lex; LEX *lex= Lex;
uint8 tmp= MY_ITEM_PREFER_1ST_TABLE;
if (lex->update_list.push_back($1) || if (lex->update_list.push_back($1) ||
lex->value_list.push_back($3)) lex->value_list.push_back($3))
YYABORT; YYABORT;
/*
INSERT INTO a1(a) SELECT b1.a FROM b1 ON DUPLICATE KEY
UPDATE a= a + b1.b
Set MY_ITEM_PREFER_1ST_TABLE flag to $1 and $3 items
to prevent find_field_in_tables() doing further item searching
if it finds item occurence in first table in insert_table_list.
This allows to avoid ambiguity in resolving 'a' field in
example above.
*/
$1->walk(&Item::set_flags_processor,
(byte *) &tmp);
$3->walk(&Item::set_flags_processor,
(byte *) &tmp);
}; };
opt_low_priority: opt_low_priority:
......
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