summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <peter@mysql.com>2002-12-04 16:26:29 +0300
committerunknown <peter@mysql.com>2002-12-04 16:26:29 +0300
commit577cb3238b59ab9f885e9c892d137da3b6c8b599 (patch)
treedd20822cd74c5e54197d66226784622a58842177
parent526ff493bcc374952ca8d66157e48033d21268a1 (diff)
parent265bf238951c3a123c4d6f7fea600175a399cf96 (diff)
downloadmariadb-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
-rw-r--r--heap/hp_create.c1
-rw-r--r--heap/hp_update.c6
-rw-r--r--heap/hp_write.c2
-rw-r--r--include/mysqld_error.h5
-rw-r--r--mysql-test/mysql-test-run.sh6
-rw-r--r--mysql-test/r/insert_update.result51
-rw-r--r--mysql-test/r/row_test.result62
-rw-r--r--mysql-test/r/subselect.result14
-rw-r--r--mysql-test/r/union.result2
-rw-r--r--mysql-test/t/insert_update.test21
-rw-r--r--mysql-test/t/row_test.test38
-rw-r--r--mysql-test/t/union.test2
-rw-r--r--sql/item.cc7
-rw-r--r--sql/item.h1
-rw-r--r--sql/item_cmpfunc.cc80
-rw-r--r--sql/item_cmpfunc.h63
-rw-r--r--sql/item_func.h44
-rw-r--r--sql/item_row.h1
-rw-r--r--sql/item_sum.cc2
-rw-r--r--sql/item_sum.h2
-rw-r--r--sql/mysql_priv.h7
-rw-r--r--sql/share/czech/errmsg.txt3
-rw-r--r--sql/share/danish/errmsg.txt3
-rw-r--r--sql/share/dutch/errmsg.txt3
-rw-r--r--sql/share/english/errmsg.txt5
-rw-r--r--sql/share/estonian/errmsg.txt3
-rw-r--r--sql/share/french/errmsg.txt3
-rw-r--r--sql/share/german/errmsg.txt3
-rw-r--r--sql/share/greek/errmsg.txt3
-rw-r--r--sql/share/hungarian/errmsg.txt3
-rw-r--r--sql/share/italian/errmsg.txt3
-rw-r--r--sql/share/japanese/errmsg.txt3
-rw-r--r--sql/share/korean/errmsg.txt3
-rw-r--r--sql/share/norwegian-ny/errmsg.txt3
-rw-r--r--sql/share/norwegian/errmsg.txt3
-rw-r--r--sql/share/polish/errmsg.txt3
-rw-r--r--sql/share/portuguese/errmsg.txt3
-rw-r--r--sql/share/romanian/errmsg.txt3
-rw-r--r--sql/share/russian/errmsg.txt3
-rw-r--r--sql/share/serbian/errmsg.txt3
-rw-r--r--sql/share/slovak/errmsg.txt3
-rw-r--r--sql/share/spanish/errmsg.txt3
-rw-r--r--sql/share/swedish/errmsg.txt3
-rw-r--r--sql/share/ukrainian/errmsg.txt3
-rw-r--r--sql/sql_base.cc10
-rw-r--r--sql/sql_class.cc19
-rw-r--r--sql/sql_class.h7
-rw-r--r--sql/sql_delete.cc2
-rw-r--r--sql/sql_insert.cc64
-rw-r--r--sql/sql_lex.cc5
-rw-r--r--sql/sql_parse.cc19
-rw-r--r--sql/sql_select.cc2
-rw-r--r--sql/sql_update.cc2
-rw-r--r--sql/sql_yacc.yy32
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: