diff options
author | unknown <peter@mysql.com> | 2002-12-04 16:26:29 +0300 |
---|---|---|
committer | unknown <peter@mysql.com> | 2002-12-04 16:26:29 +0300 |
commit | 577cb3238b59ab9f885e9c892d137da3b6c8b599 (patch) | |
tree | dd20822cd74c5e54197d66226784622a58842177 | |
parent | 526ff493bcc374952ca8d66157e48033d21268a1 (diff) | |
parent | 265bf238951c3a123c4d6f7fea600175a399cf96 (diff) | |
download | mariadb-git-577cb3238b59ab9f885e9c892d137da3b6c8b599.tar.gz |
Merge mysql.com:/home/pz/mysql/mysql-4.1-root
into mysql.com:/home/pz/mysql/mysql-4.1
sql/mysql_priv.h:
Auto merged
sql/sql_class.h:
Auto merged
sql/sql_parse.cc:
Auto merged
sql/sql_yacc.yy:
Auto merged
54 files changed, 418 insertions, 232 deletions
diff --git a/heap/hp_create.c b/heap/hp_create.c index 40b8202d94f..5265607ce53 100644 --- a/heap/hp_create.c +++ b/heap/hp_create.c @@ -140,6 +140,7 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef, share->auto_key= create_info->auto_key; share->auto_key_type= create_info->auto_key_type; share->auto_increment= create_info->auto_increment; + /* Must be allocated separately for rename to work */ if (!(share->name= my_strdup(name,MYF(0)))) { my_free((gptr) share,MYF(0)); diff --git a/heap/hp_update.c b/heap/hp_update.c index dd7374f506c..b789ab82b84 100644 --- a/heap/hp_update.c +++ b/heap/hp_update.c @@ -62,7 +62,8 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new) /* we don't need to delete non-inserted key from rb-tree */ if ((*keydef->write_key)(info, keydef, old, pos)) { - if (++(share->records) == share->blength) share->blength+= share->blength; + if (++(share->records) == share->blength) + share->blength+= share->blength; DBUG_RETURN(my_errno); } keydef--; @@ -78,6 +79,7 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new) keydef--; } } - if (++(share->records) == share->blength) share->blength+= share->blength; + if (++(share->records) == share->blength) + share->blength+= share->blength; DBUG_RETURN(my_errno); } /* heap_update */ diff --git a/heap/hp_write.c b/heap/hp_write.c index 9edd897eb34..87211d4c224 100644 --- a/heap/hp_write.c +++ b/heap/hp_write.c @@ -155,7 +155,7 @@ static byte *next_free_record_pos(HP_SHARE *info) /* Write a hash-key to the hash-index */ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, - const byte *record, byte *recpos) + const byte *record, byte *recpos) { HP_SHARE *share = info->s; int flag; diff --git a/include/mysqld_error.h b/include/mysqld_error.h index 7c77d229b81..81a24e89164 100644 --- a/include/mysqld_error.h +++ b/include/mysqld_error.h @@ -109,7 +109,7 @@ #define ER_CANT_REMOVE_ALL_FIELDS 1090 #define ER_CANT_DROP_FIELD_OR_KEY 1091 #define ER_INSERT_INFO 1092 -#define ER_INSERT_TABLE_USED 1093 +#define ER_UPDATE_TABLE_USED 1093 #define ER_NO_SUCH_THREAD 1094 #define ER_KILL_DENIED_ERROR 1095 #define ER_NO_TABLES_USED 1096 @@ -264,4 +264,5 @@ #define ER_ILLEGAL_REFERENCE 1245 #define ER_DERIVED_MUST_HAVE_ALIAS 1246 #define ER_SELECT_REDUCED 1247 -#define ER_ERROR_MESSAGES 248 +#define ER_TABLENAME_NOT_ALLOWED_HERE 1248 +#define ER_ERROR_MESSAGES 249 diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index d585243c6bc..745cde325f9 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -19,7 +19,7 @@ TZ=GMT-3; export TZ # for UNIX_TIMESTAMP tests to work # Program Definitions #-- -PATH=/bin:/usr/bin:/usr/local/bin:/usr/bsd:/usr/X11R6/bin:/usr/openwin/bin:/usr/bin/X11 +PATH=/bin:/usr/bin:/usr/local/bin:/usr/bsd:/usr/X11R6/bin:/usr/openwin/bin:/usr/bin/X11:$PATH MASTER_40_ARGS="--rpl-recovery-rank=1 --init-rpl-role=master" # Standard functions @@ -319,8 +319,8 @@ while test $# -gt 0; do VALGRIND="valgrind --alignment=8 --leak-check=yes" EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --skip-safemalloc" EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --skip-safemalloc" - SLEEP_TIME_AFTER_RESTART=120 - SLEEP_TIME_FOR_DELETE=120 + SLEEP_TIME_AFTER_RESTART=60 + SLEEP_TIME_FOR_DELETE=60 ;; --valgrind-options=*) TMP=`$ECHO "$1" | $SED -e "s;--valgrind-options=;;"` diff --git a/mysql-test/r/insert_update.result b/mysql-test/r/insert_update.result new file mode 100644 index 00000000000..8cc79564679 --- /dev/null +++ b/mysql-test/r/insert_update.result @@ -0,0 +1,51 @@ +DROP TABLE IF EXISTS t1; +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 (5,6,30) ON DUPLICATE KEY UPDATE c=c+100; +SELECT * FROM t1; +a b c +1 2 10 +3 4 20 +5 6 30 +INSERT t1 VALUES (5,7,40) ON DUPLICATE KEY UPDATE c=c+100; +SELECT * FROM t1; +a b c +1 2 10 +3 4 20 +5 6 130 +INSERT t1 VALUES (8,4,50) ON DUPLICATE KEY UPDATE c=c+1000; +SELECT * FROM t1; +a b c +1 2 10 +3 4 1020 +5 6 130 +INSERT t1 VALUES (1,4,60) ON DUPLICATE KEY UPDATE c=c+10000; +SELECT * FROM t1; +a b c +1 2 10010 +3 4 1020 +5 6 130 +INSERT t1 VALUES (1,9,70) ON DUPLICATE KEY UPDATE c=c+100000, b=4; +Duplicate entry '4' for key 2 +SELECT * FROM t1; +a b c +1 2 10010 +3 4 1020 +5 6 130 +TRUNCATE TABLE t1; +INSERT t1 VALUES (1,2,10), (3,4,20); +INSERT t1 VALUES (5,6,30), (7,4,40), (8,9,60) ON DUPLICATE KEY UPDATE c=c+100; +SELECT * FROM t1; +a b c +1 2 10 +3 4 120 +5 6 30 +8 9 60 +INSERT t1 SET a=5 ON DUPLICATE KEY UPDATE b=0; +SELECT * FROM t1; +a b c +1 2 10 +3 4 120 +5 0 30 +8 9 60 +DROP TABLE t1; diff --git a/mysql-test/r/row_test.result b/mysql-test/r/row_test.result index f5bf9856a60..f6e989789c7 100644 --- a/mysql-test/r/row_test.result +++ b/mysql-test/r/row_test.result @@ -1,60 +1,60 @@ -SELECT (1,2,3)=(1,2,3); -(1,2,3)=(1,2,3) +SELECT ROW(1,2,3)=ROW(1,2,3); +ROW(1,2,3)=ROW(1,2,3) 1 -SELECT (2,2,3)=(1+1,2,3); -(2,2,3)=(1+1,2,3) +SELECT ROW(2,2,3)=ROW(1+1,2,3); +ROW(2,2,3)=ROW(1+1,2,3) 1 -SELECT (1,2,3)=(1+1,2,3); -(1,2,3)=(1+1,2,3) +SELECT ROW(1,2,3)=ROW(1+1,2,3); +ROW(1,2,3)=ROW(1+1,2,3) 0 -SELECT (1,2,3)<(1+1,2,3); -(1,2,3)<(1+1,2,3) +SELECT ROW(1,2,3)<ROW(1+1,2,3); +ROW(1,2,3)<ROW(1+1,2,3) 1 -SELECT (1,2,3)>(1+1,2,3); -(1,2,3)>(1+1,2,3) +SELECT ROW(1,2,3)>ROW(1+1,2,3); +ROW(1,2,3)>ROW(1+1,2,3) 0 -SELECT (1,2,3)<=(1+1,2,3); -(1,2,3)<=(1+1,2,3) +SELECT ROW(1,2,3)<=ROW(1+1,2,3); +ROW(1,2,3)<=ROW(1+1,2,3) 1 -SELECT (1,2,3)>=(1+1,2,3); -(1,2,3)>=(1+1,2,3) +SELECT ROW(1,2,3)>=ROW(1+1,2,3); +ROW(1,2,3)>=ROW(1+1,2,3) 0 -SELECT (1,2,3)<>(1+1,2,3); -(1,2,3)<>(1+1,2,3) +SELECT ROW(1,2,3)<>ROW(1+1,2,3); +ROW(1,2,3)<>ROW(1+1,2,3) 1 -SELECT (NULL,2,3)=(NULL,2,3); -(NULL,2,3)=(NULL,2,3) +SELECT ROW(NULL,2,3)=ROW(NULL,2,3); +ROW(NULL,2,3)=ROW(NULL,2,3) NULL -SELECT (NULL,2,3)<=>(NULL,2,3); -(NULL,2,3)<=>(NULL,2,3) +SELECT ROW(NULL,2,3)<=>ROW(NULL,2,3); +ROW(NULL,2,3)<=>ROW(NULL,2,3) 1 -SELECT (1,2,(3,4,5))=(1,2,(3,4,5)); -(1,2,(3,4,5))=(1,2,(3,4,5)) +SELECT ROW(1,2,ROW(3,4,5))=ROW(1,2,ROW(3,4,5)); +ROW(1,2,ROW(3,4,5))=ROW(1,2,ROW(3,4,5)) 1 -SELECT ('test',2,3.33)=('test',2,3.33); -('test',2,3.33)=('test',2,3.33) +SELECT ROW('test',2,3.33)=ROW('test',2,3.33); +ROW('test',2,3.33)=ROW('test',2,3.33) 1 -SELECT ('test',2,3.33)=('test',2,3.33,4); +SELECT ROW('test',2,3.33)=ROW('test',2,3.33,4); Cardinality error (more/less than 3 columns) drop table if exists t1; create table t1 ( a int, b int, c int); insert into t1 values (1,2,3), (2,3,1), (3,2,1); -select * from t1 where (1,2,3)=(a,b,c); +select * from t1 where ROW(1,2,3)=ROW(a,b,c); a b c 1 2 3 -select * from t1 where (0,2,3)=(a,b,c); +select * from t1 where ROW(0,2,3)=ROW(a,b,c); a b c -select * from t1 where (1,2,3)<(a,b,c); +select * from t1 where ROW(1,2,3)<ROW(a,b,c); a b c 2 3 1 3 2 1 drop table t1; -select (1,1); +select ROW(1,1); Cardinality error (more/less than 1 columns) drop table if exists t1; create table t1 (i int); -select 1 from t1 where (1,1); +select 1 from t1 where ROW(1,1); Cardinality error (more/less than 1 columns) -select count(*) from t1 order by (1,1); +select count(*) from t1 order by ROW(1,1); Cardinality error (more/less than 1 columns) drop table t1; diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 42e9ff7012f..d198575deb5 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -412,7 +412,7 @@ a b 1 11 2 12 update t1 set b= (select b from t1); -INSERT TABLE 't1' isn't allowed in FROM table list +You can't specify target table 't1' for update in FROM clause update t1 set b= (select b from t2); Subselect returns more than 1 record update t1 set b= (select b from t2 where t1.a = t2.a); @@ -435,7 +435,7 @@ select * from t1 where b = (select b from t2 where t1.a = t2.a); a b 2 12 delete from t1 where b = (select b from t1); -INSERT TABLE 't1' isn't allowed in FROM table list +You can't specify target table 't1' for update in FROM clause delete from t1 where b = (select b from t2); Subselect returns more than 1 record delete from t1 where b = (select b from t2 where t1.a = t2.a); @@ -462,7 +462,7 @@ a b 22 11 2 12 delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t12 where t11.a = t12.a); -INSERT TABLE 't12' isn't allowed in FROM table list +You can't specify target table 't12' for update in FROM clause delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2); Subselect returns more than 1 record delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2 where t11.a = t2.a); @@ -481,7 +481,7 @@ create table t3 (a int); insert into t2 values (1); insert into t3 values (1),(2); INSERT INTO t1 (x) VALUES ((SELECT x FROM t1)); -INSERT TABLE 't1' isn't allowed in FROM table list +You can't specify target table 't1' for update in FROM clause INSERT INTO t1 (x) VALUES ((SELECT a FROM t3)); Subselect returns more than 1 record INSERT INTO t1 (x) VALUES ((SELECT a FROM t2)); @@ -502,7 +502,7 @@ x 3 3 INSERT INTO t1 (x) select (SELECT SUM(x)+2 FROM t1) FROM t2; -INSERT TABLE 't1' isn't allowed in FROM table list +You can't specify target table 't1' for update in FROM clause INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(x) FROM t2)); select * from t1; x @@ -520,7 +520,7 @@ insert into t3 values (1),(2); select * from t1; x y replace into t1 (x, y) VALUES ((SELECT x FROM t1), (SELECT a+1 FROM t2)); -INSERT TABLE 't1' isn't allowed in FROM table list +You can't specify target table 't1' for update in FROM clause replace into t1 (x, y) VALUES ((SELECT a FROM t3), (SELECT a+1 FROM t2)); Subselect returns more than 1 record replace into t1 (x, y) VALUES ((SELECT a FROM t2), (SELECT a+1 FROM t2)); @@ -584,7 +584,7 @@ SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 2); id 2 INSERT INTO t VALUES ((SELECT * FROM t)); -INSERT TABLE 't' isn't allowed in FROM table list +You can't specify target table 't' for update in FROM clause SELECT * FROM t; id 1 diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 0745f082993..02dda58d48f 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -84,6 +84,8 @@ a b 3 c 2 b 1 a +(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by t1.b; +Table 't1' from one of SELECT's can not be used in order clause explain (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 4 diff --git a/mysql-test/t/insert_update.test b/mysql-test/t/insert_update.test new file mode 100644 index 00000000000..6c92774113a --- /dev/null +++ b/mysql-test/t/insert_update.test @@ -0,0 +1,21 @@ +DROP TABLE IF EXISTS t1; +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 (5,6,30) ON DUPLICATE KEY UPDATE c=c+100; +SELECT * FROM t1; +INSERT t1 VALUES (5,7,40) ON DUPLICATE KEY UPDATE c=c+100; +SELECT * FROM t1; +INSERT t1 VALUES (8,4,50) ON DUPLICATE KEY UPDATE c=c+1000; +SELECT * FROM t1; +INSERT t1 VALUES (1,4,60) ON DUPLICATE KEY UPDATE c=c+10000; +SELECT * FROM t1; +-- error 1062 +INSERT t1 VALUES (1,9,70) ON DUPLICATE KEY UPDATE c=c+100000, b=4; +SELECT * FROM t1; +TRUNCATE TABLE t1; +INSERT t1 VALUES (1,2,10), (3,4,20); +INSERT t1 VALUES (5,6,30), (7,4,40), (8,9,60) ON DUPLICATE KEY UPDATE c=c+100; +SELECT * FROM t1; +INSERT t1 SET a=5 ON DUPLICATE KEY UPDATE b=0; +SELECT * FROM t1; +DROP TABLE t1; diff --git a/mysql-test/t/row_test.test b/mysql-test/t/row_test.test index db65e6bd157..5daacaa1ee6 100644 --- a/mysql-test/t/row_test.test +++ b/mysql-test/t/row_test.test @@ -1,33 +1,33 @@ -SELECT (1,2,3)=(1,2,3); -SELECT (2,2,3)=(1+1,2,3); -SELECT (1,2,3)=(1+1,2,3); -SELECT (1,2,3)<(1+1,2,3); -SELECT (1,2,3)>(1+1,2,3); -SELECT (1,2,3)<=(1+1,2,3); -SELECT (1,2,3)>=(1+1,2,3); -SELECT (1,2,3)<>(1+1,2,3); -SELECT (NULL,2,3)=(NULL,2,3); -SELECT (NULL,2,3)<=>(NULL,2,3); -SELECT (1,2,(3,4,5))=(1,2,(3,4,5)); -SELECT ('test',2,3.33)=('test',2,3.33); +SELECT ROW(1,2,3)=ROW(1,2,3); +SELECT ROW(2,2,3)=ROW(1+1,2,3); +SELECT ROW(1,2,3)=ROW(1+1,2,3); +SELECT ROW(1,2,3)<ROW(1+1,2,3); +SELECT ROW(1,2,3)>ROW(1+1,2,3); +SELECT ROW(1,2,3)<=ROW(1+1,2,3); +SELECT ROW(1,2,3)>=ROW(1+1,2,3); +SELECT ROW(1,2,3)<>ROW(1+1,2,3); +SELECT ROW(NULL,2,3)=ROW(NULL,2,3); +SELECT ROW(NULL,2,3)<=>ROW(NULL,2,3); +SELECT ROW(1,2,ROW(3,4,5))=ROW(1,2,ROW(3,4,5)); +SELECT ROW('test',2,3.33)=ROW('test',2,3.33); -- error 1239 -SELECT ('test',2,3.33)=('test',2,3.33,4); +SELECT ROW('test',2,3.33)=ROW('test',2,3.33,4); drop table if exists t1; create table t1 ( a int, b int, c int); insert into t1 values (1,2,3), (2,3,1), (3,2,1); -select * from t1 where (1,2,3)=(a,b,c); -select * from t1 where (0,2,3)=(a,b,c); -select * from t1 where (1,2,3)<(a,b,c); +select * from t1 where ROW(1,2,3)=ROW(a,b,c); +select * from t1 where ROW(0,2,3)=ROW(a,b,c); +select * from t1 where ROW(1,2,3)<ROW(a,b,c); drop table t1; -- error 1239 -select (1,1); +select ROW(1,1); drop table if exists t1; create table t1 (i int); -- error 1239 -select 1 from t1 where (1,1); +select 1 from t1 where ROW(1,1); -- error 1239 -select count(*) from t1 order by (1,1); +select count(*) from t1 order by ROW(1,1); #TODO remove comments after parser fixing #-- error 1239 #select count(*) from t1 order by i having (1,1); diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index f43308f2f55..9ddfda7872f 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -20,6 +20,8 @@ select 't1',b,count(*) from t1 group by b UNION select 't2',b,count(*) from t2 g (select a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 4; (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1); (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc; +--error 1248 +(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by t1.b; explain (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc; #(select sql_calc_found_rows a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 2; select found_rows(); diff --git a/sql/item.cc b/sql/item.cc index 2dd5de0e896..1c46f9abb7e 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -536,8 +536,9 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) Item **refer= (Item **)not_found_item; // Prevent using outer fields in subselects, that is not supported now - if (thd->lex.current_select->linkage != DERIVED_TABLE_TYPE) - for (SELECT_LEX *sl= thd->lex.current_select->outer_select(); + SELECT_LEX *cursel=(SELECT_LEX *) thd->lex.current_select; + if (cursel->linkage != DERIVED_TABLE_TYPE) + for (SELECT_LEX *sl=cursel->outer_select(); sl; sl= sl->outer_select()) { @@ -573,7 +574,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) if (r->check_cols(1) || r->fix_fields(thd, tables, ref)) return 1; r->depended_from= last; - thd->lex.current_select->mark_as_dependent(last); + cursel->mark_as_dependent(last); thd->add_possible_loop(r); return 0; } diff --git a/sql/item.h b/sql/item.h index 11b141613f3..ae671c5141c 100644 --- a/sql/item.h +++ b/sql/item.h @@ -98,6 +98,7 @@ public: // Row emulation virtual uint cols() { return 1; } virtual Item* el(uint i) { return this; } + virtual Item** addr(uint i) { return 0; } virtual bool check_cols(uint c); }; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 146758600c0..055dad2781a 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -106,7 +106,8 @@ void Item_bool_func2::fix_length_and_dec() { if (convert_constant_item(field,&args[1])) { - arg_store.set_compare_func(this, INT_RESULT); // Works for all types. + cmp.set_cmp_func(this, tmp_arg, tmp_arg+1, + INT_RESULT); // Works for all types. return; } } @@ -118,7 +119,8 @@ void Item_bool_func2::fix_length_and_dec() { if (convert_constant_item(field,&args[0])) { - arg_store.set_compare_func(this, INT_RESULT); // Works for all types. + cmp.set_cmp_func(this, tmp_arg, tmp_arg+1, + INT_RESULT); // Works for all types. return; } } @@ -133,8 +135,8 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) 1:0]; if (type == ROW_RESULT) { - uint n= args[0]->cols(); - if (n != args[1]->cols()) + uint n= (*a)->cols(); + if (n != (*b)->cols()) { my_error(ER_CARDINALITY_COL, MYF(0), n); comparators= 0; @@ -142,11 +144,7 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) } if ((comparators= (Arg_comparator *) sql_alloc(sizeof(Arg_comparator)*n))) for (uint i=0; i < n; i++) - { - comparators[i].set_arg(0, args[0]->el(i)); - comparators[i].set_arg(1, args[1]->el(i)); - comparators[i].set_compare_func(owner); - } + comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i)); else { my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); @@ -160,9 +158,9 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) int Arg_comparator::compare_string() { String *res1,*res2; - if ((res1= args[0]->val_str(&owner->tmp_value1))) + if ((res1= (*a)->val_str(&owner->tmp_value1))) { - if ((res2= args[1]->val_str(&owner->tmp_value2))) + if ((res2= (*b)->val_str(&owner->tmp_value2))) { owner->null_value= 0; return owner->binary() ? stringcmp(res1,res2) : sortcmp(res1,res2); @@ -175,8 +173,8 @@ int Arg_comparator::compare_string() int Arg_comparator::compare_e_string() { String *res1,*res2; - res1= args[0]->val_str(&owner->tmp_value1); - res2= args[1]->val_str(&owner->tmp_value2); + res1= (*a)->val_str(&owner->tmp_value1); + res2= (*b)->val_str(&owner->tmp_value2); if (!res1 || !res2) return test(res1 == res2); return (owner->binary() ? test(stringcmp(res1, res2) == 0) : @@ -186,11 +184,11 @@ int Arg_comparator::compare_e_string() int Arg_comparator::compare_real() { - double val1= args[0]->val(); - if (!args[0]->null_value) + double val1= (*a)->val(); + if (!(*a)->null_value) { - double val2= args[1]->val(); - if (!args[1]->null_value) + double val2= (*b)->val(); + if (!(*b)->null_value) { owner->null_value= 0; if (val1 < val2) return -1; @@ -204,20 +202,20 @@ int Arg_comparator::compare_real() int Arg_comparator::compare_e_real() { - double val1= args[0]->val(); - double val2= args[1]->val(); - if (args[0]->null_value || args[1]->null_value) - return test(args[0]->null_value && args[1]->null_value); + double val1= (*a)->val(); + double val2= (*b)->val(); + if ((*a)->null_value || (*b)->null_value) + return test((*a)->null_value && (*b)->null_value); return test(val1 == val2); } int Arg_comparator::compare_int() { - longlong val1= args[0]->val_int(); - if (!args[0]->null_value) + longlong val1= (*a)->val_int(); + if (!(*a)->null_value) { - longlong val2= args[1]->val_int(); - if (!args[1]->null_value) + longlong val2= (*b)->val_int(); + if (!(*b)->null_value) { owner->null_value= 0; if (val1 < val2) return -1; @@ -231,10 +229,10 @@ int Arg_comparator::compare_int() int Arg_comparator::compare_e_int() { - longlong val1= args[0]->val_int(); - longlong val2= args[1]->val_int(); - if (args[0]->null_value || args[1]->null_value) - return test(args[0]->null_value && args[1]->null_value); + longlong val1= (*a)->val_int(); + longlong val2= (*b)->val_int(); + if ((*a)->null_value || (*b)->null_value) + return test((*a)->null_value && (*b)->null_value); return test(val1 == val2); } @@ -242,7 +240,7 @@ int Arg_comparator::compare_e_int() int Arg_comparator::compare_row() { int res= 0; - uint n= args[0]->cols(); + uint n= (*a)->cols(); for (uint i= 0; i<n; i++) { if ((res= comparators[i].compare())) @@ -256,7 +254,7 @@ int Arg_comparator::compare_row() int Arg_comparator::compare_e_row() { int res= 0; - uint n= args[0]->cols(); + uint n= (*a)->cols(); for (uint i= 0; i<n; i++) { if ((res= comparators[i].compare())) @@ -268,7 +266,7 @@ int Arg_comparator::compare_e_row() longlong Item_func_eq::val_int() { - int value= arg_store.compare(); + int value= cmp.compare(); return value == 0 ? 1 : 0; } @@ -283,39 +281,39 @@ void Item_func_equal::fix_length_and_dec() longlong Item_func_equal::val_int() { - return arg_store.compare(); + return cmp.compare(); } longlong Item_func_ne::val_int() { - int value= arg_store.compare(); + int value= cmp.compare(); return value != 0 && !null_value ? 1 : 0; } longlong Item_func_ge::val_int() { - int value= arg_store.compare(); + int value= cmp.compare(); return value >= 0 ? 1 : 0; } longlong Item_func_gt::val_int() { - int value= arg_store.compare(); + int value= cmp.compare(); return value > 0 ? 1 : 0; } longlong Item_func_le::val_int() { - int value= arg_store.compare(); + int value= cmp.compare(); return value <= 0 && !null_value ? 1 : 0; } longlong Item_func_lt::val_int() { - int value= arg_store.compare(); + int value= cmp.compare(); return value < 0 && !null_value ? 1 : 0; } @@ -664,7 +662,7 @@ double Item_func_nullif::val() { double value; - if (!arg_store.compare() || null_value) + if (!cmp.compare() || null_value) { null_value=1; return 0.0; @@ -678,7 +676,7 @@ longlong Item_func_nullif::val_int() { longlong value; - if (!arg_store.compare() || null_value) + if (!cmp.compare() || null_value) { null_value=1; return 0; @@ -692,7 +690,7 @@ String * Item_func_nullif::val_str(String *str) { String *res; - if (!arg_store.compare() || null_value) + if (!cmp.compare() || null_value) { null_value=1; return 0; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 74c9dec7ef8..83d1050dd9c 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -21,6 +21,63 @@ #pragma interface /* gcc class implementation */ #endif +extern Item_result item_cmp_type(Item_result a,Item_result b); +class Item_bool_func2; +class Arg_comparator; + +typedef int (Arg_comparator::*arg_cmp_func)(); + +class Arg_comparator: public Sql_alloc +{ + Item **a, **b; + arg_cmp_func func; + Item_bool_func2 *owner; + Arg_comparator *comparators; // used only for compare_row() + +public: + Arg_comparator() {}; + Arg_comparator(Item **a1, Item **a2): a(a1), b(a2) {}; + + inline void seta(Item **item) { a= item; } + inline void setb(Item **item) { b= item; } + + int set_compare_func(Item_bool_func2 *owner, Item_result type); + inline int set_compare_func(Item_bool_func2 *owner) + { + return set_compare_func(owner, item_cmp_type((*a)->result_type(), + (*b)->result_type())); + } + + inline int set_cmp_func(Item_bool_func2 *owner, + Item **a1, Item **a2, + Item_result type) + { + a= a1; + b= a2; + return set_compare_func(owner, type); + } + inline int set_cmp_func(Item_bool_func2 *owner, + Item **a1, Item **a2) + { + return set_cmp_func(owner, a1, a2, item_cmp_type((*a1)->result_type(), + (*a2)->result_type())); + } + inline int compare() { return (this->*func)(); } + + int compare_string(); // compare args[0] & args[1] + int compare_real(); // compare args[0] & args[1] + int compare_int(); // compare args[0] & args[1] + int compare_row(); // compare args[0] & args[1] + int compare_e_string(); // compare args[0] & args[1] + int compare_e_real(); // compare args[0] & args[1] + int compare_e_int(); // compare args[0] & args[1] + int compare_e_row(); // compare args[0] & args[1] + + static arg_cmp_func comparator_matrix [4][2]; + + friend class Item_func; +}; + class Item_bool_func :public Item_int_func { public: @@ -33,13 +90,15 @@ public: class Item_bool_func2 :public Item_int_func { /* Bool with 2 string args */ protected: + Arg_comparator cmp; String tmp_value1,tmp_value2; public: - Item_bool_func2(Item *a,Item *b) :Item_int_func(a,b) {} + Item_bool_func2(Item *a,Item *b): + Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1) {} void fix_length_and_dec(); void set_cmp_func() { - arg_store.set_compare_func(this); + cmp.set_cmp_func(this, tmp_arg, tmp_arg+1); } optimize_type select_optimize() const { return OPTIMIZE_OP; } virtual enum Functype rev_functype() const { return UNKNOWN_FUNC; } diff --git a/sql/item_func.h b/sql/item_func.h index 67c088f2bd9..faed8d5f4be 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -28,48 +28,10 @@ extern "C" /* Bug in BSDI include file */ } #endif -extern Item_result item_cmp_type(Item_result a,Item_result b); -class Item_bool_func2; -class Arg_comparator; - -typedef int (Arg_comparator::*arg_cmp_func)(); - -class Arg_comparator: public Sql_alloc -{ - Item *args[2]; - arg_cmp_func func; - Item_bool_func2 *owner; - Arg_comparator *comparators; // used only for compare_row() - -public: - inline void set_arg(int i, Item *item) { args[i]= item; } - int set_compare_func(Item_bool_func2 *owner, Item_result type); - inline int set_compare_func(Item_bool_func2 *owner) - { - return set_compare_func(owner, item_cmp_type(args[0]->result_type(), - args[1]->result_type())); - } - inline int compare() { return (this->*func)(); } - - int compare_string(); // compare args[0] & args[1] - int compare_real(); // compare args[0] & args[1] - int compare_int(); // compare args[0] & args[1] - int compare_row(); // compare args[0] & args[1] - int compare_e_string(); // compare args[0] & args[1] - int compare_e_real(); // compare args[0] & args[1] - int compare_e_int(); // compare args[0] & args[1] - int compare_e_row(); // compare args[0] & args[1] - - static arg_cmp_func comparator_matrix [4][2]; - - friend class Item_func; -}; - class Item_func :public Item_result_field { protected: - Item **args; - Arg_comparator arg_store; + Item **args, *tmp_arg[2]; uint allowed_arg_cols; public: uint arg_count; @@ -96,14 +58,14 @@ public: Item_func(Item *a): allowed_arg_cols(1), arg_count(1) { - args= arg_store.args; + args= tmp_arg; args[0]= a; with_sum_func= a->with_sum_func; } Item_func(Item *a,Item *b): allowed_arg_cols(1), arg_count(2) { - args= arg_store.args; + args= tmp_arg; args[0]= a; args[1]= b; with_sum_func= a->with_sum_func || b->with_sum_func; } diff --git a/sql/item_row.h b/sql/item_row.h index 6970b240b31..5580250b4fb 100644 --- a/sql/item_row.h +++ b/sql/item_row.h @@ -61,5 +61,6 @@ public: virtual uint cols() { return arg_count; } virtual Item* el(uint i) { return items[i]; } + virtual Item** addr(uint i) { return items + i; } virtual bool check_cols(uint c); }; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 63329cd3823..fe7523a5fc5 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -41,7 +41,7 @@ Item_sum::Item_sum(List<Item> &list) list.empty(); // Fields are used } -inline void Item_sum::mark_as_sum_func() +void Item_sum::mark_as_sum_func() { current_thd->lex.current_select->with_sum_func= with_sum_func= 1; } diff --git a/sql/item_sum.h b/sql/item_sum.h index 56b36b615f4..23b8482d41a 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -34,7 +34,7 @@ public: uint arg_count; bool quick_group; /* If incremental update of fields */ - inline void mark_as_sum_func(); + void mark_as_sum_func(); Item_sum() : arg_count(0),quick_group(1) { mark_as_sum_func(); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 1bb66c2a766..0b4759fd388 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -431,7 +431,7 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name, bool drop_primary, enum enum_duplicates handle_duplicates, enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS, - bool simple_alter=0); + bool simple_alter=0); bool mysql_rename_table(enum db_type base, const char *old_db, const char * old_name, @@ -442,11 +442,12 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys); int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop_list); int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields, - List<Item> &values,COND *conds, + List<Item> &values,COND *conds, ORDER *order, ha_rows limit, enum enum_duplicates handle_duplicates); int mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields, - List<List_item> &values, enum_duplicates flag); + List<List_item> &values, List<Item> &update_fields, + List<Item> &update_values, enum_duplicates flag); void kill_delayed_threads(void); int mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, ORDER *order, ha_rows rows, ulong options); diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 31d47b821e0..6c1a6db674b 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -103,7 +103,7 @@ v/* "Nen-Bí mo¾né vymazat v¹echny polo¾ky s ALTER TABLE. Pou¾ijte DROP TABLE", "Nemohu zru-B¹it '%-.64s' (provést DROP). Zkontrolujte, zda neexistují záznamy/klíèe", "Z-Báznamù: %ld Zdvojených: %ld Varování: %ld", -"INSERT TABLE '%-.64s' nen-Bí dovoleno v seznamu tabulek FROM", +"You can't specify target table '%-.64s' for update in FROM clause", "Nezn-Bámá identifikace threadu: %lu", "Nejste vlastn-Bíkem threadu %lu", "Nejsou pou-B¾ity ¾ádné tabulky", @@ -258,3 +258,4 @@ v/* "Reference '%-.64s' not supported (%s)", "Every derived table must have it's own alias" "Select %u was reduced during optimisation", +"Table '%-.64s' from one of SELECT's can not be used in %-.32s" diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index ca5a6918517..2067f13d593 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -97,7 +97,7 @@ "Man kan ikke slette alle felter med ALTER TABLE. Brug DROP TABLE i stedet.", "Kan ikke udføre DROP '%-.64s'. Undersøg om feltet/nøglen eksisterer.", "Poster: %ld Ens: %ld Advarsler: %ld", -"INSERT TABLE '%-.64s' er ikke tilladt i FROM tabel liste", +"You can't specify target table '%-.64s' for update in FROM clause", "Ukendt tråd id: %lu", "Du er ikke ejer af tråden %lu", "Ingen tabeller i brug", @@ -252,3 +252,4 @@ "Reference '%-.64s' not supported (%s)", "Every derived table must have it's own alias" "Select %u was reduced during optimisation", +"Table '%-.64s' from one of SELECT's can not be used in %-.32s" diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 6f5754dee76..0c8d652653f 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -105,7 +105,7 @@ "Het is niet mogelijk alle velden te verwijderen met ALTER TABLE. Gebruik a.u.b. DROP TABLE hiervoor!", "Kan '%-.64s' niet weggooien. Controleer of het veld of de zoeksleutel daadwerkelijk bestaat.", "Records: %ld Dubbel: %ld Waarschuwing: %ld", -"INSERT TABLE '%-.64s' is niet toegestaan in de FROM tabel-lijst", +"You can't specify target table '%-.64s' for update in FROM clause", "Onbekend thread id: %lu", "U bent geen bezitter van thread %lu", "Geen tabellen gebruikt.", @@ -260,3 +260,4 @@ "Reference '%-.64s' not supported (%s)", "Every derived table must have it's own alias" "Select %u was reduced during optimisation", +"Table '%-.64s' from one of SELECT's can not be used in %-.32s" diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index 66ca9eab596..68e4f07f246 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -94,7 +94,7 @@ "You can't delete all columns with ALTER TABLE. Use DROP TABLE instead", "Can't DROP '%-.64s'. Check that column/key exists", "Records: %ld Duplicates: %ld Warnings: %ld", -"INSERT TABLE '%-.64s' isn't allowed in FROM table list", +"You can't specify target table '%-.64s' for update in FROM clause", "Unknown thread id: %lu", "You are not owner of thread %lu", "No tables used", @@ -247,5 +247,6 @@ "Cyclic reference on subqueries", "Converting column '%s' from %s to %s", "Reference '%-.64s' not supported (%s)", -"Every derived table must have it's own alias" +"Every derived table must have it's own alias", "Select %u was reduced during optimisation", +"Table '%-.64s' from one of SELECT's can not be used in %-.32s" diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index 757ae5b6443..13663cca8e2 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -99,7 +99,7 @@ "ALTER TABLE kasutades ei saa kustutada kõiki tulpasid. Kustuta tabel DROP TABLE abil", "Ei suuda kustutada '%-.64s'. Kontrolli kas tulp/võti eksisteerib", "Kirjeid: %ld Kattuvaid: %ld Hoiatusi: %ld", -"INSERT TABLE '%-.64s' ei ole lubatud FROM tabelite nimekirjas", +"You can't specify target table '%-.64s' for update in FROM clause", "Tundmatu lõim: %lu", "Ei ole lõime %lu omanik", "Ühtegi tabelit pole kasutusel", @@ -254,3 +254,4 @@ "Reference '%-.64s' not supported (%s)", "Every derived table must have it's own alias" "Select %u was reduced during optimisation", +"Table '%-.64s' from one of SELECT's can not be used in %-.32s" diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 43952d848c4..ac1764aa7eb 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -94,7 +94,7 @@ "Vous ne pouvez effacer tous les champs avec ALTER TABLE. Utilisez DROP TABLE", "Ne peut effacer (DROP) '%-.64s'. Vérifiez s'il existe", "Enregistrements: %ld Doublons: %ld Avertissements: %ld", -"INSERT TABLE '%-.64s' n'est pas permis dans FROM liste des tables", +"You can't specify target table '%-.64s' for update in FROM clause", "Numéro de tâche inconnu: %lu", "Vous n'êtes pas propriétaire de la tâche no: %lu", "Aucune table utilisée", @@ -249,3 +249,4 @@ "Reference '%-.64s' not supported (%s)", "Every derived table must have it's own alias" "Select %u was reduced during optimisation", +"Table '%-.64s' from one of SELECT's can not be used in %-.32s" diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index f9a70feb549..6b19034ae59 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -97,7 +97,7 @@ "Mit ALTER TABLE können nicht alle Felder auf einmal gelöscht werden. Verwende DROP TABLE stattdessen.", "Kann '%-.64s' nicht löschen (DROP). Existiert das Feld/der Schlüssel?", "Datensätze: %ld Duplikate: %ld Warnungen: %ld", -"INSERT TABLE '%-.64s' nicht erlaubt im FROM Abschnitt.", +"You can't specify target table '%-.64s' for update in FROM clause", "Unbekannte Thread-ID: %lu", "Nicht Besitzer des Threads %lu.", "Keine Tabellen in Verwendung.", @@ -252,3 +252,4 @@ "Reference '%-.64s' not supported (%s)", "Every derived table must have it's own alias" "Select %u was reduced during optimisation", +"Table '%-.64s' from one of SELECT's can not be used in %-.32s" diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index 9410c3d69bb..7e680216b3e 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -94,7 +94,7 @@ "Äåí åßíáé äõíáôÞ ç äéáãñáöÞ üëùí ôùí ðåäßùí ìå ALTER TABLE. Ðáñáêáëþ ÷ñçóéìïðïéåßóôå DROP TABLE", "Áäýíáôç ç äéáãñáöÞ (DROP) '%-.64s'. Ðáñáêáëþ åëÝãîôå áí ôï ðåäßï/êëåéäß õðÜñ÷åé", "ÅããñáöÝò: %ld ÅðáíáëÞøåéò: %ld ÐñïåéäïðïéÞóåéò: %ld", -"INSERT TABLE '%-.64s' äåí åðéôñÝðåôáé óôï FROM table list", +"You can't specify target table '%-.64s' for update in FROM clause", "Áãíùóôï thread id: %lu", "Äåí åßóèå owner ôïõ thread %lu", "Äåí ÷ñçóéìïðïéÞèçêáí ðßíáêåò", @@ -249,3 +249,4 @@ "Reference '%-.64s' not supported (%s)", "Every derived table must have it's own alias" "Select %u was reduced during optimisation", +"Table '%-.64s' from one of SELECT's can not be used in %-.32s" diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 1410a88af4a..747d2be5a3b 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -96,7 +96,7 @@ "Az osszes mezo nem torolheto az ALTER TABLE-lel. Hasznalja a DROP TABLE-t helyette", "A DROP '%-.64s' nem lehetseges. Ellenorizze, hogy a mezo/kulcs letezik-e", "Rekordok: %ld Duplikalva: %ld Warnings: %ld", -"INSERT TABLE '%-.64s' nem engedelyezett a FROM table listabol", +"You can't specify target table '%-.64s' for update in FROM clause", "Ervenytelen szal (thread) id: %lu", "A %lu thread-nek mas a tulajdonosa", "Nincs hasznalt tabla", @@ -251,3 +251,4 @@ "Reference '%-.64s' not supported (%s)", "Every derived table must have it's own alias" "Select %u was reduced during optimisation", +"Table '%-.64s' from one of SELECT's can not be used in %-.32s" diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 499c06e64dc..ef7efa925af 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -94,7 +94,7 @@ "Non si possono cancellare tutti i campi con una ALTER TABLE. Utilizzare DROP TABLE", "Impossibile cancellare '%-.64s'. Controllare che il campo chiave esista", "Records: %ld Duplicati: %ld Avvertimenti: %ld", -"INSERT TABLE '%-.64s' non e` permesso nella FROM table list", +"You can't specify target table '%-.64s' for update in FROM clause", "Thread id: %lu sconosciuto", "Utente non proprietario del thread %lu", "Nessuna tabella usata", @@ -249,3 +249,4 @@ "Reference '%-.64s' not supported (%s)", "Every derived table must have it's own alias" "Select %u was reduced during optimisation", +"Table '%-.64s' from one of SELECT's can not be used in %-.32s" diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index 90a6e23efbd..61b69000473 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -96,7 +96,7 @@ "ALTER TABLE ¤ÇÁ´¤Æ¤Î column ¤Ïºï½ü¤Ç¤¤Þ¤»¤ó. DROP TABLE ¤ò»ÈÍѤ·¤Æ¤¯¤À¤µ¤¤", "'%-.64s' ¤òÇË´þ¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿. Check that column/key exists", "¥ì¥³¡¼¥É¿ô: %ld ½ÅÊ£¿ô: %ld Warnings: %ld", -"INSERT TABLE '%-.64s' isn't allowed in FROM table list", +"You can't specify target table '%-.64s' for update in FROM clause", "thread id: %lu ¤Ï¤¢¤ê¤Þ¤»¤ó", "thread %lu ¤Î¥ª¡¼¥Ê¡¼¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó", "No tables used", @@ -251,3 +251,4 @@ "Reference '%-.64s' not supported (%s)", "Every derived table must have it's own alias" "Select %u was reduced during optimisation", +"Table '%-.64s' from one of SELECT's can not be used in %-.32s" diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index f05ab3148eb..9c367c43551 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -94,7 +94,7 @@ "ALTER TABLE ¸í·ÉÀ¸·Î´Â ¸ðµç Ä®·³À» Áö¿ï ¼ö ¾ø½À´Ï´Ù. DROP TABLE ¸í·ÉÀ» ÀÌ¿ëÇϼ¼¿ä.", "'%-.64s'¸¦ DROPÇÒ ¼ö ¾ø½À´Ï´Ù. Ä®·³À̳ª Å°°¡ Á¸ÀçÇÏ´ÂÁö äũÇϼ¼¿ä.", "·¹ÄÚµå: %ld°³ Áߺ¹: %ld°³ °æ°í: %ld°³", -"INSERT TABLE '%-.64s' ´Â FROM Å×À̺í list¿¡¼ Çã°¡µÇÁö ¾Ê¾Ò½À´Ï´Ù.", +"You can't specify target table '%-.64s' for update in FROM clause", "¾Ë¼ö ¾ø´Â ¾²·¹µå id: %lu", "¾²·¹µå(Thread) %luÀÇ ¼ÒÀ¯ÀÚ°¡ ¾Æ´Õ´Ï´Ù.", "¾î¶² Å×ÀÌºíµµ »ç¿ëµÇÁö ¾Ê¾Ò½À´Ï´Ù.", @@ -249,3 +249,4 @@ "Reference '%-.64s' not supported (%s)", "Every derived table must have it's own alias" "Select %u was reduced during optimisation", +"Table '%-.64s' from one of SELECT's can not be used in %-.32s" diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index 5e75877145c..a3fed98e81a 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -96,7 +96,7 @@ "Ein kan ikkje slette alle felt med ALTER TABLE. Bruk DROP TABLE istadenfor.", "Kan ikkje DROP '%-.64s'. Undersøk om felt/nøkkel eksisterar.", "Postar: %ld Like: %ld Åtvaringar: %ld", -"INSERT TABLE '%-.64s' er ikkje tillate i FROM tabell liste", +"You can't specify target table '%-.64s' for update in FROM clause", "Ukjent tråd id: %lu", "Du er ikkje eigar av tråd %lu", "Ingen tabellar i bruk", @@ -251,3 +251,4 @@ "Reference '%-.64s' not supported (%s)", "Every derived table must have it's own alias" "Select %u was reduced during optimisation", +"Table '%-.64s' from one of SELECT's can not be used in %-.32s" diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 4330827fe1c..26eabe3b91f 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -96,7 +96,7 @@ "En kan ikke slette alle felt med ALTER TABLE. Bruk DROP TABLE isteden.", "Kan ikke DROP '%-.64s'. Undersøk om felt/nøkkel eksisterer.", "Poster: %ld Like: %ld Advarsler: %ld", -"INSERT TABLE '%-.64s' er ikke tillatt i FROM tabell liste", +"You can't specify target table '%-.64s' for update in FROM clause", "Ukjent tråd id: %lu", "Du er ikke eier av tråden %lu", "Ingen tabeller i bruk", @@ -251,3 +251,4 @@ "Reference '%-.64s' not supported (%s)", "Every derived table must have it's own alias" "Select %u was reduced during optimisation", +"Table '%-.64s' from one of SELECT's can not be used in %-.32s" diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index db5b97554ff..616a5d4919b 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -98,7 +98,7 @@ "Nie mo¿na usun?æ wszystkich pól wykorzystuj?c ALTER TABLE. W zamian u¿yj DROP TABLE", "Nie mo¿na wykonaæ operacji DROP '%-.64s'. Sprawd¥, czy to pole/klucz istnieje", "Rekordów: %ld Duplikatów: %ld Ostrze¿eñ: %ld", -"Operacja INSERT TABLE '%-.64s' nie jest dozwolona w li?cie tabel w FROM", +"You can't specify target table '%-.64s' for update in FROM clause", "Nieznany identyfikator w?tku: %lu", "Nie jeste? w³a?cicielem w?tku %lu", "Nie ma ¿adej u¿ytej tabeli", @@ -253,3 +253,4 @@ "Reference '%-.64s' not supported (%s)", "Every derived table must have it's own alias" "Select %u was reduced during optimisation", +"Table '%-.64s' from one of SELECT's can not be used in %-.32s" diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index 80c1b498345..04a9afaa808 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -94,7 +94,7 @@ "Você não pode deletar todas as colunas com ALTER TABLE. Use DROP TABLE em seu lugar", "Não se pode fazer DROP '%-.64s'. Confira se esta coluna/chave existe", "Registros: %ld - Duplicados: %ld - Avisos: %ld", -"INSERT TABLE '%-.64s' não é permitido na lista de tabelas contidas em FROM", +"You can't specify target table '%-.64s' for update in FROM clause", "'Id' de 'thread' %lu desconhecido", "Você não é proprietário da 'thread' %lu", "Nenhuma tabela usada", @@ -249,3 +249,4 @@ "Reference '%-.64s' not supported (%s)", "Every derived table must have it's own alias" "Select %u was reduced during optimisation", +"Table '%-.64s' from one of SELECT's can not be used in %-.32s" diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 59f6e550650..0ae6fc8e51a 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -98,7 +98,7 @@ "Nu poti sterge toate coloanele cu ALTER TABLE. Foloseste DROP TABLE in schimb", "Nu pot sa DROP '%-.64s'. Verifica daca coloana/cheia exista", "Recorduri: %ld Duplicate: %ld Atentionari (warnings): %ld", -"INSERT TABLE '%-.64s' nu este permis in lista FROM de tabele", +"You can't specify target table '%-.64s' for update in FROM clause", "Id-ul: %lu thread-ului este necunoscut", "Nu sinteti proprietarul threadului %lu", "Nici o tabela folosita", @@ -253,3 +253,4 @@ "Reference '%-.64s' not supported (%s)", "Every derived table must have it's own alias" "Select %u was reduced during optimisation", +"Table '%-.64s' from one of SELECT's can not be used in %-.32s" diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index fafcc61f60a..343178b3118 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -97,7 +97,7 @@ "îÅÌØÚÑ ÕÄÁÌÉÔØ ×ÓÅ ÐÏÌÑ ÞÅÒÅÚ ALTER TABLE. ÷ÏÓÐÏÌØÚÕÊÔÅÓØ DROP TABLE", "îÅ ÍÏÇÕ ÓÂÒÏÓÉÔØ '%-.64s'. ðÒÏ×ÅÒØÔÅ, ÞÔÏ ÜÔÏ ÐÏÌÅ/ËÌÀÞ ÓÕÝÅÓÔ×ÕÀÔ", "úÁÐÉÓÅÊ: %ld äÕÂÌÅÊ: %ld ðÒÅÄÕÐÒÅÖÄÅÎÉÊ: %ld", -"INSERT TABLE '%-.64s' ÎÅ ÒÁÚÒÅÛÅÎÏ × ÓÐÉÓËÅ FROM TABLE", +"÷Ù ÎÅ ÍÏÖÅÔÅ ÕËÁÚÁÔØ ÉÚÍÅÎÅÑÍÕÀ ÔÁÂÌÉÃÕ '%-.64s' × ÓÐÉÓËÅ ÔÁÂÌÉà FROM", "îÅÉÚ×ÅÓÔÎÁÑ ÎÉÔØ: %lu", "÷Ù ÎÅ ×ÌÁÄÅÌÅà ÎÉÔÉ %lu", "ôÁÂÌÉÃÙ ÎÅ ÉÓÐÏÌØÚÏ×ÁÎÙ", @@ -252,3 +252,4 @@ "óÓÙÌËÁ '%-.64s' ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ (%s)", "Every derived table must have it's own alias" "Select %u ÂÙÌ ÕÐÒÁÚÄÎÅÎ × ÐÒÏÃÅÓÓÅ ÏÐÔÉÍÉÚÁÃÉÉ", +"Table '%-.64s' from one of SELECT's can not be used in %-.32s" diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index 6bcecf9e4c9..b04b94b82e8 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -100,7 +100,7 @@ "Ne možete da izbrišete sve kolone pomoæu komande 'ALTER TABLE'. Upotrebite komandu 'DROP TABLE' ako želite to da uradite", "Ne mogu da izvršim komandu drop 'DROP' na '%-.64s'. Proverite da li ta kolona (odnosno kljuè) postoji", "Slogova: %ld Duplikata: %ld Upozorenja: %ld", -"Komanda 'INSERT TABLE' na '%-.64s' nije dozvoljena u listi 'FROM' tabela", +"You can't specify target table '%-.64s' for update in FROM clause", "Nepoznat thread identifikator: %lu", "Vi niste vlasnik thread-a %lu", "Nema upotrebljenih tabela", @@ -245,3 +245,4 @@ "Reference '%-.64s' not supported (%s)", "Every derived table must have it's own alias" "Select %u was reduced during optimisation", +"Table '%-.64s' from one of SELECT's can not be used in %-.32s" diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 55ead96545c..f8f52f86b6a 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -102,7 +102,7 @@ "One nemô¾em zmaza» all fields with ALTER TABLE. Use DROP TABLE instead", "Nemô¾em zru¹i» (DROP) '%-.64s'. Skontrolujte, èi neexistujú záznamy/kµúèe", "Záznamov: %ld Opakovaných: %ld Varovania: %ld", -"INSERT TABLE '%-.64s' nie je dovolené v zozname tabuliek FROM", +"You can't specify target table '%-.64s' for update in FROM clause", "Neznáma identifikácia vlákna: %lu", "Nie ste vlastníkom vlákna %lu", "Nie je pou¾itá ¾iadna tabuµka", @@ -257,3 +257,4 @@ "Reference '%-.64s' not supported (%s)", "Every derived table must have it's own alias" "Select %u was reduced during optimisation", +"Table '%-.64s' from one of SELECT's can not be used in %-.32s" diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 93a0abeed39..674d36e9d8c 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -95,7 +95,7 @@ "No puede borrar todos los campos con ALTER TABLE. Usa DROP TABLE para hacerlo", "No puedo ELIMINAR '%-.64s'. compuebe que el campo/clave existe", "Registros: %ld Duplicados: %ld Peligros: %ld", -"INSERT TABLE '%-.64s' no esta permitido en FROM tabla lista", +"You can't specify target table '%-.64s' for update in FROM clause", "Identificador del thread: %lu desconocido", "Tu no eres el propietario del thread%lu", "No ha tablas usadas", @@ -250,3 +250,4 @@ "Reference '%-.64s' not supported (%s)", "Every derived table must have it's own alias" "Select %u was reduced during optimisation", +"Table '%-.64s' from one of SELECT's can not be used in %-.32s" diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index a996898446e..052568ac30d 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -94,7 +94,7 @@ "Man kan inte radera alla fält med ALTER TABLE. Använd DROP TABLE istället", "Kan inte ta bort '%-.64s'. Kontrollera att fältet/nyckel finns", "Rader: %ld Dubletter: %ld Varningar: %ld", -"INSERT table '%-.64s' får inte finnas i FROM tabell-listan", +"You can't specify target table '%-.64s' for update in FROM clause", "Finns inget thread med id %lu", "Du är inte ägare till thread %lu", "Inga tabeller angivna", @@ -249,3 +249,4 @@ "Reference '%-.64s' not supported (%s)", "Every derived table must have it's own alias" "Select %u was reduced during optimisation", +"Table '%-.64s' from one of SELECT's can not be used in %-.32s" diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index 0ec1d88e601..122506f17cf 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -99,7 +99,7 @@ "îÅ ÍÏÖÌÉ×Ï ×ÉÄÁÌÉÔÉ ×Ó¦ ÓÔÏ×Âæ ÚÁ ÄÏÐÏÍÏÇÏÀ ALTER TABLE. äÌÑ ÃØÏÇÏ ÓËÏÒÉÓÔÁÊÔÅÓÑ DROP TABLE", "îÅ ÍÏÖÕ DROP '%-.64s'. ðÅÒÅצÒÔÅ, ÞÉ ÃÅÊ ÓÔÏ×ÂÅÃØ/ËÌÀÞ ¦ÓÎÕ¤", "úÁÐÉÓ¦×: %ld äÕÂ̦ËÁÔ¦×: %ld úÁÓÔÅÒÅÖÅÎØ: %ld", -"INSERT TABLE '%-.64s' ÎÅ ÄÏÚ×ÏÌÅÎÏ Õ ÐÅÒÅ̦ËÕ FROM TABLE", +"ôÁÂÌÉÃÑ '%-.64s' ÝÏ ÚͦÎÀ¤ÔØÓÑ ÎÅ ÄÏÚ×ÏÌÅÎÁ Õ ÐÅÒÅ̦ËÕ ÔÁÂÌÉÃØ FROM", "îÅצÄÏÍÉÊ ¦ÄÅÎÔÉƦËÁÔÏÒ Ç¦ÌËÉ: %lu", "÷É ÎÅ ×ÏÌÏÄÁÒ Ç¦ÌËÉ %lu", "îÅ ×ÉËÏÒÉÓÔÁÎÏ ÔÁÂÌÉÃØ", @@ -254,3 +254,4 @@ "ðÏÓÉÌÁÎÎÑ '%-.64s' ÎÅ ÐiÄÔÒÉÍÕÅÔÓÑ (%s)", "Every derived table must have it's own alias" "Select %u was ÓËÁÓÏ×ÁÎÏ ÐÒÉ ÏÐÔÉÍiÚÁÃii", +"Table '%-.64s' from one of SELECT's can not be used in %-.32s" diff --git a/sql/sql_base.cc b/sql/sql_base.cc index fc7629caae3..63affe5fde6 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1957,8 +1957,14 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, table_name=buff; } if (report_error) - my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0), - table_name, thd->where); + { + if (thd->lex.current_select->get_master()->order_list.elements) + my_printf_error(ER_TABLENAME_NOT_ALLOWED_HERE, ER(ER_TABLENAME_NOT_ALLOWED_HERE), + MYF(0), table_name, thd->where); + else + my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0), + table_name, thd->where); + } else return (Field*) not_found_field; } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 9bca7245cba..57cd0e7a13d 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -142,8 +142,6 @@ THD::THD():user_time(0), fatal_error(0), bzero((char*) &con_root,sizeof(con_root)); bzero((char*) &warn_root,sizeof(warn_root)); init_alloc_root(&warn_root, 1024, 0); - bzero((char*) warn_count, sizeof(warn_count)); - warn_list.empty(); user_connect=(USER_CONN *)0; hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0, (hash_get_key) get_var_key, @@ -187,17 +185,20 @@ THD::THD():user_time(0), fatal_error(0), void THD::init(void) { + pthread_mutex_lock(&LOCK_global_system_variables); + variables= global_system_variables; + pthread_mutex_unlock(&LOCK_global_system_variables); server_status= SERVER_STATUS_AUTOCOMMIT; - update_lock_default= (variables.low_priority_updates ? - TL_WRITE_LOW_PRIORITY : - TL_WRITE); options= thd_startup_options; sql_mode=(uint) opt_sql_mode; open_options=ha_open_options; - pthread_mutex_lock(&LOCK_global_system_variables); - variables= global_system_variables; - pthread_mutex_unlock(&LOCK_global_system_variables); + update_lock_default= (variables.low_priority_updates ? + TL_WRITE_LOW_PRIORITY : + TL_WRITE); session_tx_isolation= (enum_tx_isolation) variables.tx_isolation; + warn_list.empty(); + bzero((char*) warn_count, sizeof(warn_count)); + total_warn_count= 0; } /* @@ -228,6 +229,7 @@ void THD::cleanup(void) { DBUG_ENTER("THD::cleanup"); ha_rollback(this); + delete_tree(&prepared_statements); if (locked_tables) { lock=locked_tables; locked_tables=0; @@ -289,7 +291,6 @@ THD::~THD() free_root(&con_root,MYF(0)); free_root(&warn_root,MYF(0)); free_root(&transaction.mem_root,MYF(0)); - delete_tree(&prepared_statements); mysys_var=0; // Safety (shouldn't be needed) pthread_mutex_destroy(&LOCK_delete); #ifndef DBUG_OFF diff --git a/sql/sql_class.h b/sql/sql_class.h index 89be4741e5d..4de0ad7baf3 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -29,12 +29,12 @@ class Slave_log_event; enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE }; enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY }; -enum enum_duplicates { DUP_ERROR, DUP_REPLACE, DUP_IGNORE }; +enum enum_duplicates { DUP_ERROR, DUP_REPLACE, DUP_IGNORE, DUP_UPDATE }; enum enum_log_type { LOG_CLOSED, LOG_NORMAL, LOG_NEW, LOG_BIN }; enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON, DELAY_KEY_WRITE_ALL }; -// log info errors +// log info errors #define LOG_INFO_EOF -1 #define LOG_INFO_IO -2 #define LOG_INFO_INVALID -3 @@ -188,6 +188,9 @@ typedef struct st_copy_info { ha_rows error_count; enum enum_duplicates handle_duplicates; int escape_char, last_errno; +/* for INSERT ... UPDATE */ + List<Item> *update_fields; + List<Item> *update_values; } COPY_INFO; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index d35790da1b0..f22911ea2bb 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -54,7 +54,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, if (find_real_table_in_list(table_list->next, table_list->db, table_list->real_name)) { - my_error(ER_INSERT_TABLE_USED, MYF(0), table_list->real_name); + my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name); DBUG_RETURN(-1); } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 9ee824d0e2c..92221126096 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -97,8 +97,12 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields, } -int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, - List<List_item> &values_list,enum_duplicates duplic) +int mysql_insert(THD *thd,TABLE_LIST *table_list, + List<Item> &fields, + List<List_item> &values_list, + List<Item> &update_fields, + List<Item> &update_values, + enum_duplicates duplic) { int error; bool log_on= ((thd->options & OPTION_UPDATE_LOG) || @@ -126,7 +130,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, if ((lock_type == TL_WRITE_DELAYED && ((specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) || thd->slave_thread)) || - (lock_type == TL_WRITE_CONCURRENT_INSERT && duplic == DUP_REPLACE)) + (lock_type == TL_WRITE_CONCURRENT_INSERT && duplic == DUP_REPLACE) || + (duplic == DUP_UPDATE)) lock_type=TL_WRITE; table_list->lock_type= lock_type; @@ -166,7 +171,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, values= its++; if (check_insert_fields(thd,table,fields,*values,1) || setup_tables(insert_table_list) || - setup_fields(thd, insert_table_list, *values, 0, 0, 0)) + setup_fields(thd, insert_table_list, *values, 0, 0, 0) || + (duplic == DUP_UPDATE && + (setup_fields(thd, insert_table_list, update_fields, 0, 0, 0) || + setup_fields(thd, insert_table_list, update_values, 0, 0, 0)))) { table->time_stamp= save_time_stamp; goto abort; @@ -174,7 +182,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, if (find_real_table_in_list(table_list->next, table_list->db, table_list->real_name)) { - my_error(ER_INSERT_TABLE_USED, MYF(0), table_list->real_name); + my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name); goto abort; } @@ -203,6 +211,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, info.records=info.deleted=info.copied=0; info.handle_duplicates=duplic; + info.update_fields=&update_fields; + info.update_values=&update_values; // Don't count warnings for simple inserts if (values_list.elements > 1 || (thd->options & OPTION_WARNINGS)) thd->count_cuted_fields = 1; @@ -212,7 +222,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, error=0; id=0; thd->proc_info="update"; - if (duplic == DUP_IGNORE || duplic == DUP_REPLACE) + if (duplic != DUP_ERROR) table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); if ((bulk_insert= (values_list.elements >= MIN_ROWS_TO_USE_BULK_INSERT && lock_type != TL_WRITE_DELAYED && @@ -358,7 +368,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, table->next_number_field=0; thd->count_cuted_fields=0; thd->next_insert_id=0; // Reset this if wrongly used - if (duplic == DUP_IGNORE || duplic == DUP_REPLACE) + if (duplic != DUP_ERROR) table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); if (error) goto abort; @@ -410,7 +420,8 @@ int write_record(TABLE *table,COPY_INFO *info) char *key=0; info->records++; - if (info->handle_duplicates == DUP_REPLACE) + if (info->handle_duplicates == DUP_REPLACE || + info->handle_duplicates == DUP_UPDATE) { while ((error=table->file->write_row(table->record[0]))) { @@ -427,7 +438,9 @@ int write_record(TABLE *table,COPY_INFO *info) was used. This ensures that we don't get a problem when the whole range of the key has been used. */ - if (table->next_number_field && key_nr == table->next_number_index && + if (info->handle_duplicates == DUP_REPLACE && + table->next_number_field && + key_nr == table->next_number_index && table->file->auto_increment_column_changed) goto err; if (table->file->table_flags() & HA_DUPP_POS) @@ -459,16 +472,33 @@ int write_record(TABLE *table,COPY_INFO *info) HA_READ_KEY_EXACT)))) goto err; } - if (last_uniq_key(table,key_nr)) + if (info->handle_duplicates == DUP_UPDATE) { - if ((error=table->file->update_row(table->record[1],table->record[0]))) - goto err; - info->deleted++; - break; /* Update logfile and count */ + /* we don't check for other UNIQUE keys - the first row + that matches, is updated. If update causes a conflict again, + an error is returned + */ + restore_record(table,1); + if (fill_record(*info->update_fields,*info->update_values)) + goto err; + if ((error=table->file->update_row(table->record[1],table->record[0]))) + goto err; + info->deleted++; + break; + } + else /* DUP_REPLACE */ + { + if (last_uniq_key(table,key_nr)) + { + if ((error=table->file->update_row(table->record[1],table->record[0]))) + goto err; + info->deleted++; + break; /* Update logfile and count */ + } + else if ((error=table->file->delete_row(table->record[1]))) + goto err; + info->deleted++; } - else if ((error=table->file->delete_row(table->record[1]))) - goto err; - info->deleted++; } info->copied++; } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index d765c741932..54f28668644 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -458,7 +458,7 @@ int yylex(void *arg, void *yythd) LINT_INIT(c); for (;;) { - switch(state) { + switch (state) { case STATE_OPERATOR_OR_IDENT: // Next is operator or keyword case STATE_START: // Start of token // Skip startspace @@ -900,7 +900,8 @@ int yylex(void *arg, void *yythd) return((int) '@'); case STATE_HOSTNAME: // end '@' of user@hostname for (c=yyGet() ; - my_isalnum(system_charset_info,c) || c == '.' || c == '_' || c == '$'; + my_isalnum(system_charset_info,c) || c == '.' || c == '_' || + c == '$'; c= yyGet()) ; yylval->lex_str=get_token(lex,yyLength()); return(LEX_HOSTNAME); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ac5e06fe87c..be4c791c71d 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1804,7 +1804,7 @@ mysql_execute_command(THD *thd) if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) && find_real_table_in_list(tables->next, tables->db, tables->real_name)) { - net_printf(thd,ER_INSERT_TABLE_USED,tables->real_name); + net_printf(thd,ER_UPDATE_TABLE_USED,tables->real_name); DBUG_VOID_RETURN; } if (tables->next) @@ -2130,14 +2130,21 @@ mysql_execute_command(THD *thd) case SQLCOM_REPLACE: case SQLCOM_INSERT: { + my_bool update=(lex->value_list.elements ? UPDATE_ACL : 0); ulong privilege= (lex->duplicates == DUP_REPLACE ? - INSERT_ACL | DELETE_ACL : INSERT_ACL); + INSERT_ACL | DELETE_ACL : INSERT_ACL | update); if (check_access(thd,privilege,tables->db,&tables->grant.privilege)) goto error; /* purecov: inspected */ if (grant_option && check_grant(thd,privilege,tables)) goto error; + if (select_lex->item_list.elements != lex->value_list.elements) + { + send_error(thd,ER_WRONG_VALUE_COUNT); + DBUG_VOID_RETURN; + } res = mysql_insert(thd,tables,lex->field_list,lex->many_values, - lex->duplicates); + select_lex->item_list, lex->value_list, + (update ? DUP_UPDATE : lex->duplicates)); if (thd->net.report_error) res= -1; break; @@ -2172,7 +2179,7 @@ mysql_execute_command(THD *thd) if (find_real_table_in_list(tables->next, tables->db, tables->real_name)) { - net_printf(thd,ER_INSERT_TABLE_USED,tables->real_name); + net_printf(thd,ER_UPDATE_TABLE_USED,tables->real_name); DBUG_VOID_RETURN; } @@ -2273,7 +2280,7 @@ mysql_execute_command(THD *thd) { if (find_real_table_in_list(t->table_list->next, t->db, t->real_name)) { - my_error(ER_INSERT_TABLE_USED, MYF(0), t->real_name); + my_error(ER_UPDATE_TABLE_USED, MYF(0), t->real_name); res= -1; break; } @@ -2460,7 +2467,7 @@ mysql_execute_command(THD *thd) case SQLCOM_LOAD: { uint privilege= (lex->duplicates == DUP_REPLACE ? - INSERT_ACL | UPDATE_ACL | DELETE_ACL : INSERT_ACL); + INSERT_ACL | DELETE_ACL : INSERT_ACL); if (!lex->local_file) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index c1f7e8272bc..50820b931b6 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -4115,6 +4115,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, keyinfo->usable_key_parts=keyinfo->key_parts= param->group_parts; keyinfo->key_length=0; keyinfo->rec_per_key=0; + keyinfo->algorithm= HA_KEY_ALG_UNDEF; for (; group ; group=group->next,key_part_info++) { Field *field=(*group->item)->tmp_table_field(); @@ -4191,6 +4192,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, keyinfo->flags=HA_NOSAME | HA_NULL_ARE_EQUAL; keyinfo->key_length=(uint16) reclength; keyinfo->name=(char*) "tmp"; + keyinfo->algorithm= HA_KEY_ALG_UNDEF; if (null_pack_length) { key_part_info->null_bit=0; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index c3ae435d851..9aab347ff6a 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -89,7 +89,7 @@ int mysql_update(THD *thd, if (find_real_table_in_list(table_list->next, table_list->db, table_list->real_name)) { - my_error(ER_INSERT_TABLE_USED, MYF(0), table_list->real_name); + my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name); DBUG_RETURN(-1); } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 70a1ebc79ec..a56ed20f7be 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1461,7 +1461,7 @@ alter_list_item: lex->simple_alter=0; } | RENAME opt_to table_ident - { + { LEX *lex=Lex; lex->select_lex.db=$3->db.str; lex->name= $3->table.str; @@ -1979,10 +1979,12 @@ simple_expr: | NOT expr %prec NEG { $$= new Item_func_not($2); } | '!' expr %prec NEG { $$= new Item_func_not($2); } | '(' expr ')' { $$= $2; } - | '(' expr ',' expr_list ')' + /* Note: In SQL-99 "ROW" is optional, but not having it mandatory + causes conflicts with the INTERVAL syntax. */ + | ROW_SYM '(' expr ',' expr_list ')' { - $4->push_front($2); - $$= new Item_row(*$4); + $5->push_front($3); + $$= new Item_row(*$5); } | EXISTS exists_subselect { $$= $2; } | singleval_subselect { $$= $1; } @@ -2680,7 +2682,11 @@ order_dir: opt_limit_clause: /* empty */ {} - | LIMIT + | limit_clause {} + ; + +limit_clause: + LIMIT { LEX *lex= Lex; if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE && @@ -3047,7 +3053,7 @@ expr_or_default: opt_insert_update: /* empty */ - | ON DUPLICATE KEY_SYM UPDATE_SYM SET update_list + | ON DUPLICATE { /* for simplisity, let's forget about INSERT ... SELECT ... UPDATE for a moment */ @@ -3057,6 +3063,7 @@ opt_insert_update: YYABORT; } } + KEY_SYM UPDATE_SYM update_list ; /* Update rows in a table */ @@ -4378,10 +4385,7 @@ union_opt: ; optional_order_or_limit: - /* empty - intentional reduce/reduce conflict here !!! - { code } below should not be executed - when neither ORDER BY nor LIMIT are used */ {} + /* Empty */ {} | { LEX *lex=Lex; @@ -4397,7 +4401,13 @@ optional_order_or_limit: lex->current_select->select_limit= lex->thd->variables.select_limit; } - opt_order_clause opt_limit_clause + order_or_limit + ; + +order_or_limit: + order_clause opt_limit_clause + | + limit_clause ; union_option: |