mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
committed by
Sergei Golubchik
parent
57a09a72a3
commit
837ad9ab97
@ -10,6 +10,7 @@ Feature_delay_key_write 0
|
|||||||
Feature_dynamic_columns 0
|
Feature_dynamic_columns 0
|
||||||
Feature_fulltext 0
|
Feature_fulltext 0
|
||||||
Feature_gis 0
|
Feature_gis 0
|
||||||
|
Feature_insert_returning 0
|
||||||
Feature_invisible_columns 0
|
Feature_invisible_columns 0
|
||||||
Feature_json 0
|
Feature_json 0
|
||||||
Feature_locale 0
|
Feature_locale 0
|
||||||
@ -165,9 +166,24 @@ drop table t1;
|
|||||||
show status like "feature_delay_key_write";
|
show status like "feature_delay_key_write";
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
Feature_delay_key_write 2
|
Feature_delay_key_write 2
|
||||||
|
#
|
||||||
|
# Feature CHECK CONSTRAINT
|
||||||
|
#
|
||||||
create table t1 (a int check (a > 5));
|
create table t1 (a int check (a > 5));
|
||||||
create table t2 (b int, constraint foo check (b < 10));
|
create table t2 (b int, constraint foo check (b < 10));
|
||||||
drop table t1, t2;
|
drop table t1, t2;
|
||||||
show status like "feature_check_constraint";
|
show status like "feature_check_constraint";
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
Feature_check_constraint 2
|
Feature_check_constraint 2
|
||||||
|
#
|
||||||
|
# Feature insert...returning
|
||||||
|
#
|
||||||
|
create table t1(id1 int);
|
||||||
|
insert into t1 values (1),(2) returning *;
|
||||||
|
id1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
drop table t1;
|
||||||
|
show status like "feature_insert_returning";
|
||||||
|
Variable_name Value
|
||||||
|
Feature_insert_returning 1
|
||||||
|
@ -132,10 +132,18 @@ drop table t1;
|
|||||||
|
|
||||||
show status like "feature_delay_key_write";
|
show status like "feature_delay_key_write";
|
||||||
|
|
||||||
#
|
--echo #
|
||||||
# Feature CHECK CONSTRAINT
|
--echo # Feature CHECK CONSTRAINT
|
||||||
#
|
--echo #
|
||||||
create table t1 (a int check (a > 5));
|
create table t1 (a int check (a > 5));
|
||||||
create table t2 (b int, constraint foo check (b < 10));
|
create table t2 (b int, constraint foo check (b < 10));
|
||||||
drop table t1, t2;
|
drop table t1, t2;
|
||||||
show status like "feature_check_constraint";
|
show status like "feature_check_constraint";
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Feature insert...returning
|
||||||
|
--echo #
|
||||||
|
create table t1(id1 int);
|
||||||
|
insert into t1 values (1),(2) returning *;
|
||||||
|
drop table t1;
|
||||||
|
show status like "feature_insert_returning";
|
||||||
|
560
mysql-test/main/insert_returning.result
Normal file
560
mysql-test/main/insert_returning.result
Normal file
@ -0,0 +1,560 @@
|
|||||||
|
# Test for INSERT...RETURNING
|
||||||
|
CREATE TABLE t1(id1 INT PRIMARY KEY AUTO_INCREMENT, val1 VARCHAR(1));
|
||||||
|
CREATE TABLE t2(id2 INT PRIMARY KEY AUTO_INCREMENT, val2 VARCHAR(1));
|
||||||
|
CREATE VIEW v1 AS SELECT id1, val1 FROM t1;
|
||||||
|
CREATE VIEW v2 AS SELECT id2,val2 FROM t2;
|
||||||
|
INSERT INTO t2 VALUES (1,'a'),(2,'b'),(3,'c');
|
||||||
|
CREATE FUNCTION f(arg INT) RETURNS TEXT
|
||||||
|
BEGIN
|
||||||
|
RETURN (SELECT arg+arg);
|
||||||
|
END|
|
||||||
|
#
|
||||||
|
# Simple insert statement...RETURNING
|
||||||
|
#
|
||||||
|
INSERT INTO t1 (id1, val1) VALUES (1, 'a');
|
||||||
|
INSERT INTO t1 (id1, val1) VALUES (2, 'b') RETURNING *;
|
||||||
|
id1 val1
|
||||||
|
2 b
|
||||||
|
INSERT INTO t1 (id1, val1) VALUES (3, 'c') RETURNING id1+id1 as total,val1,
|
||||||
|
id1 && id1, id1 | id1, UPPER(val1),f(id1);
|
||||||
|
total val1 id1 && id1 id1 | id1 UPPER(val1) f(id1)
|
||||||
|
6 c 1 3 C 6
|
||||||
|
INSERT INTO t1(id1,val1) VALUES (4,'d') RETURNING(SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 WHERE id2=1);
|
||||||
|
(SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 WHERE id2=1)
|
||||||
|
a
|
||||||
|
INSERT INTO t1(id1,val1) VALUES(5,'e') RETURNING(SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 GROUP BY id2 HAVING id2=id2+1);
|
||||||
|
(SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 GROUP BY id2 HAVING id2=id2+1)
|
||||||
|
NULL
|
||||||
|
PREPARE stmt FROM "INSERT INTO t1 (id1,val1) VALUES (6,'f') RETURNING (SELECT id2 FROM t2 WHERE val2='b')";
|
||||||
|
EXECUTE stmt;
|
||||||
|
(SELECT id2 FROM t2 WHERE val2='b')
|
||||||
|
2
|
||||||
|
DELETE FROM t1 WHERE id1=6;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
id1 val1
|
||||||
|
1 a
|
||||||
|
2 b
|
||||||
|
3 c
|
||||||
|
4 d
|
||||||
|
5 e
|
||||||
|
EXECUTE stmt;
|
||||||
|
(SELECT id2 FROM t2 WHERE val2='b')
|
||||||
|
2
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
INSERT IGNORE INTO t1(id1,val1) VALUES (7,'h') RETURNING *;
|
||||||
|
id1 val1
|
||||||
|
7 h
|
||||||
|
SELECT * FROM t1;
|
||||||
|
id1 val1
|
||||||
|
1 a
|
||||||
|
2 b
|
||||||
|
3 c
|
||||||
|
4 d
|
||||||
|
5 e
|
||||||
|
6 f
|
||||||
|
7 h
|
||||||
|
EXPLAIN INSERT INTO t1(id1,val1) VALUES (8,'i') RETURNING *;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 INSERT t1 ALL NULL NULL NULL NULL NULL NULL
|
||||||
|
EXPLAIN EXTENDED INSERT INTO t1(id1,val1) VALUES(9,'j') RETURNING id1;
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 INSERT t1 ALL NULL NULL NULL NULL NULL 100.00 NULL
|
||||||
|
EXPLAIN FORMAT="json" INSERT INTO t1(id1,val1) VALUES (10,'k') RETURNING id1;
|
||||||
|
EXPLAIN
|
||||||
|
{
|
||||||
|
"query_block": {
|
||||||
|
"select_id": 1,
|
||||||
|
"table": {
|
||||||
|
"table_name": "t1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SELECT * FROM t1;
|
||||||
|
id1 val1
|
||||||
|
1 a
|
||||||
|
2 b
|
||||||
|
3 c
|
||||||
|
4 d
|
||||||
|
5 e
|
||||||
|
6 f
|
||||||
|
7 h
|
||||||
|
INSERT INTO v1(id1, val1) VALUES (12, 'a') RETURNING id1+id1 as total,val1,
|
||||||
|
id1 && id1, id1 id1, UPPER(val1),f(id1);
|
||||||
|
total val1 id1 && id1 id1 UPPER(val1) f(id1)
|
||||||
|
24 a 1 12 A 24
|
||||||
|
ANALYZE INSERT INTO t1(id1,val1) VALUES(13,'l') RETURNING *;
|
||||||
|
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
|
||||||
|
1 INSERT t1 ALL NULL NULL NULL NULL NULL NULL 100.00 100.00 NULL
|
||||||
|
TRUNCATE TABLE t1;
|
||||||
|
#
|
||||||
|
# Multiple values in one insert statement...RETURNING
|
||||||
|
#
|
||||||
|
INSERT INTO t1 VALUES (1,'a'),(2,'b');
|
||||||
|
INSERT INTO t1 VALUES (3,'c'),(4,'d') RETURNING *;
|
||||||
|
id1 val1
|
||||||
|
3 c
|
||||||
|
4 d
|
||||||
|
INSERT INTO t1 VALUES (5,'e'),(6,'f') RETURNING id1 as id,val1,
|
||||||
|
id1 && id1, id1|id1, UPPER(val1),f(id1);
|
||||||
|
id val1 id1 && id1 id1|id1 UPPER(val1) f(id1)
|
||||||
|
5 e 1 5 E 10
|
||||||
|
6 f 1 6 F 12
|
||||||
|
INSERT INTO t1 VALUES (7,'g'),(8,'h') RETURNING(SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 WHERE id2=1);
|
||||||
|
(SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 WHERE id2=1)
|
||||||
|
a
|
||||||
|
a
|
||||||
|
INSERT INTO t1 VALUES (9,'i'),(10,'j') RETURNING(SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 GROUP BY id2 HAVING id2=id2+1);
|
||||||
|
(SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 GROUP BY id2 HAVING id2=id2+1)
|
||||||
|
NULL
|
||||||
|
NULL
|
||||||
|
PREPARE stmt FROM "INSERT INTO t1 VALUES (11,'k'),(12,'l') RETURNING (SELECT id2 FROM t2 WHERE val2='b')";
|
||||||
|
EXECUTE stmt;
|
||||||
|
(SELECT id2 FROM t2 WHERE val2='b')
|
||||||
|
2
|
||||||
|
2
|
||||||
|
DELETE FROM t1 WHERE val1 IN ('k','l');
|
||||||
|
SELECT * FROM t1;
|
||||||
|
id1 val1
|
||||||
|
1 a
|
||||||
|
2 b
|
||||||
|
3 c
|
||||||
|
4 d
|
||||||
|
5 e
|
||||||
|
6 f
|
||||||
|
7 g
|
||||||
|
8 h
|
||||||
|
9 i
|
||||||
|
10 j
|
||||||
|
EXECUTE stmt;
|
||||||
|
(SELECT id2 FROM t2 WHERE val2='b')
|
||||||
|
2
|
||||||
|
2
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
INSERT IGNORE INTO t1 VALUES(13,'o'),(14,'p') RETURNING *;
|
||||||
|
id1 val1
|
||||||
|
13 o
|
||||||
|
14 p
|
||||||
|
EXPLAIN INSERT INTO t1 VALUES(15,'q'),(16,'r') RETURNING *;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 INSERT t1 ALL NULL NULL NULL NULL NULL NULL
|
||||||
|
EXPLAIN EXTENDED INSERT INTO t1 VALUES (17,'s'),(18,'t') RETURNING *;
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 INSERT t1 ALL NULL NULL NULL NULL NULL 100.00 NULL
|
||||||
|
EXPLAIN FORMAT="json" INSERT INTO t1 VALUES(19,'u'),(20,'v') RETURNING id1;
|
||||||
|
EXPLAIN
|
||||||
|
{
|
||||||
|
"query_block": {
|
||||||
|
"select_id": 1,
|
||||||
|
"table": {
|
||||||
|
"table_name": "t1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SELECT * FROM t1;
|
||||||
|
id1 val1
|
||||||
|
1 a
|
||||||
|
2 b
|
||||||
|
3 c
|
||||||
|
4 d
|
||||||
|
5 e
|
||||||
|
6 f
|
||||||
|
7 g
|
||||||
|
8 h
|
||||||
|
9 i
|
||||||
|
10 j
|
||||||
|
12 l
|
||||||
|
11 k
|
||||||
|
13 o
|
||||||
|
14 p
|
||||||
|
INSERT INTO v1 VALUES(23,'y'),(24,'z') RETURNING id1 as id,val1,
|
||||||
|
id1 && id1, id1|id1, UPPER(val1),f(id1);
|
||||||
|
id val1 id1 && id1 id1|id1 UPPER(val1) f(id1)
|
||||||
|
23 y 1 23 Y 46
|
||||||
|
24 z 1 24 Z 48
|
||||||
|
ANALYZE INSERT INTO t1 VALUES(25,'a'),(26,'b') RETURNING *;
|
||||||
|
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
|
||||||
|
1 INSERT t1 ALL NULL NULL NULL NULL NULL NULL 100.00 100.00 NULL
|
||||||
|
#
|
||||||
|
# INSERT...ON DUPLICATE KEY UPDATE...RETURNING
|
||||||
|
#
|
||||||
|
CREATE TABLE ins_duplicate (id INT PRIMARY KEY AUTO_INCREMENT, val VARCHAR(1));
|
||||||
|
INSERT INTO ins_duplicate VALUES (1,'a');
|
||||||
|
INSERT INTO ins_duplicate VALUES (2,'b') ON DUPLICATE KEY UPDATE val='b'
|
||||||
|
RETURNING *;
|
||||||
|
id val
|
||||||
|
2 b
|
||||||
|
INSERT INTO ins_duplicate VALUES (2,'b') ON DUPLICATE KEY UPDATE val='c'
|
||||||
|
RETURNING id+id AS total, val, id && id, id|id, UPPER(val),f(id);
|
||||||
|
total val id && id id|id UPPER(val) f(id)
|
||||||
|
4 c 1 2 C 4
|
||||||
|
INSERT INTO ins_duplicate VALUES (2,'b') ON DUPLICATE KEY UPDATE val='d'
|
||||||
|
RETURNING (SELECT GROUP_CONCAT(val2) FROM t2 WHERE id2=1);
|
||||||
|
(SELECT GROUP_CONCAT(val2) FROM t2 WHERE id2=1)
|
||||||
|
a
|
||||||
|
INSERT INTO ins_duplicate VALUES (2,'b') ON DUPLICATE KEY UPDATE val='e'
|
||||||
|
RETURNING (SELECT GROUP_CONCAT(val2) FROM t2 GROUP BY id2 HAVING id2=id2+1);
|
||||||
|
(SELECT GROUP_CONCAT(val2) FROM t2 GROUP BY id2 HAVING id2=id2+1)
|
||||||
|
NULL
|
||||||
|
PREPARE stmt FROM "INSERT INTO ins_duplicate VALUES (2,'b') ON DUPLICATE
|
||||||
|
KEY UPDATE val='f' RETURNING (SELECT id2 FROM t2 WHERE val2='b')";
|
||||||
|
EXECUTE stmt;
|
||||||
|
(SELECT id2 FROM t2 WHERE val2='b')
|
||||||
|
2
|
||||||
|
SELECT * FROM t2;
|
||||||
|
id2 val2
|
||||||
|
1 a
|
||||||
|
2 b
|
||||||
|
3 c
|
||||||
|
EXECUTE stmt;
|
||||||
|
(SELECT id2 FROM t2 WHERE val2='b')
|
||||||
|
2
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
INSERT IGNORE INTO ins_duplicate(id,val) VALUES (3,'c'),(4,'d') ON DUPLICATE
|
||||||
|
KEY UPDATE val='g' RETURNING id;
|
||||||
|
id
|
||||||
|
3
|
||||||
|
4
|
||||||
|
EXPLAIN INSERT INTO ins_duplicate(id,val) VALUES (2,'b') ON DUPLICATE KEY
|
||||||
|
UPDATE val='h' RETURNING val;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 INSERT ins_duplicate ALL NULL NULL NULL NULL NULL NULL
|
||||||
|
EXPLAIN EXTENDED INSERT INTO ins_duplicate(id,val) VALUES (2,'b')
|
||||||
|
ON DUPLICATE KEY UPDATE val='i' RETURNING val;
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 INSERT ins_duplicate ALL NULL NULL NULL NULL NULL 100.00 NULL
|
||||||
|
EXPLAIN FORMAT="json" INSERT INTO ins_duplicate(id,val) VALUES (2,'b')
|
||||||
|
ON DUPLICATE KEY UPDATE val='j' RETURNING val;
|
||||||
|
EXPLAIN
|
||||||
|
{
|
||||||
|
"query_block": {
|
||||||
|
"select_id": 1,
|
||||||
|
"table": {
|
||||||
|
"table_name": "ins_duplicate"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
INSERT INTO v1(id1, val1) VALUES (2,'d') ON DUPLICATE KEY UPDATE
|
||||||
|
val1='d' RETURNING id1+id1 AS total, val1, id1 && id1, id1|id1, UPPER(val1),
|
||||||
|
f(id1);
|
||||||
|
total val1 id1 && id1 id1|id1 UPPER(val1) f(id1)
|
||||||
|
4 d 1 2 D 4
|
||||||
|
ANALYZE INSERT INTO ins_duplicate(id,val) VALUES(2,'b') ON DUPLICATE KEY UPDATE
|
||||||
|
val='k' RETURNING *;
|
||||||
|
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
|
||||||
|
1 INSERT ins_duplicate ALL NULL NULL NULL NULL NULL NULL 100.00 100.00 NULL
|
||||||
|
SELECT * FROM ins_duplicate;
|
||||||
|
id val
|
||||||
|
1 a
|
||||||
|
2 k
|
||||||
|
3 c
|
||||||
|
4 d
|
||||||
|
#
|
||||||
|
# INSERT...SET...RETURNING
|
||||||
|
#
|
||||||
|
TRUNCATE TABLE t1;
|
||||||
|
INSERT INTO t1 SET id1= 1, val1= 'a';
|
||||||
|
INSERT INTO t1 SET id1= 2, val1= 'b' RETURNING *;
|
||||||
|
id1 val1
|
||||||
|
2 b
|
||||||
|
INSERT INTO t1 SET id1= 3, val1= 'c' RETURNING id1+id1 AS total,val1,
|
||||||
|
id1 && id1, id1|id1, UPPER(val1),f(id1);
|
||||||
|
total val1 id1 && id1 id1|id1 UPPER(val1) f(id1)
|
||||||
|
6 c 1 3 C 6
|
||||||
|
INSERT INTO t1 SET id1= 4, val1= 'd' RETURNING (SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 WHERE id2=1);
|
||||||
|
(SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 WHERE id2=1)
|
||||||
|
a
|
||||||
|
INSERT INTO t1 SET id1= 5, val1='e' RETURNING (SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 GROUP BY id2 HAVING id2=id2+1);
|
||||||
|
(SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 GROUP BY id2 HAVING id2=id2+1)
|
||||||
|
NULL
|
||||||
|
PREPARE stmt FROM "INSERT INTO t1 SET id1= 6, val1='f' RETURNING (SELECT id2 FROM t2 WHERE val2='b')";
|
||||||
|
EXECUTE stmt;
|
||||||
|
(SELECT id2 FROM t2 WHERE val2='b')
|
||||||
|
2
|
||||||
|
DELETE FROM t1 WHERE val1='f';
|
||||||
|
SELECT * FROM t1;
|
||||||
|
id1 val1
|
||||||
|
1 a
|
||||||
|
2 b
|
||||||
|
3 c
|
||||||
|
4 d
|
||||||
|
5 e
|
||||||
|
EXECUTE stmt;
|
||||||
|
(SELECT id2 FROM t2 WHERE val2='b')
|
||||||
|
2
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
INSERT INTO t1 SET id1= 7, val1= 'g' RETURNING f(id1);
|
||||||
|
f(id1)
|
||||||
|
14
|
||||||
|
INSERT INTO t1 SET val1= 'n' RETURNING *;
|
||||||
|
id1 val1
|
||||||
|
8 n
|
||||||
|
INSERT IGNORE INTO t1 SET id1= 8, val1= 'h' RETURNING *;
|
||||||
|
id1 val1
|
||||||
|
8 h
|
||||||
|
Warnings:
|
||||||
|
Warning 1062 Duplicate entry '8' for key 'PRIMARY'
|
||||||
|
EXPLAIN INSERT INTO t1 SET id1=9, val1='i' RETURNING id1;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 INSERT t1 ALL NULL NULL NULL NULL NULL NULL
|
||||||
|
EXPLAIN EXTENDED INSERT INTO t1 SET id1=10, val1='j' RETURNING val1;
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 INSERT t1 ALL NULL NULL NULL NULL NULL 100.00 NULL
|
||||||
|
EXPLAIN FORMAT="json" INSERT INTO t1 SET id1=11, val1='k' RETURNING val1;
|
||||||
|
EXPLAIN
|
||||||
|
{
|
||||||
|
"query_block": {
|
||||||
|
"select_id": 1,
|
||||||
|
"table": {
|
||||||
|
"table_name": "t1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
INSERT INTO v1 SET id1=26, val1='Z' RETURNING id1+id1 AS total,val1,
|
||||||
|
id1 && id1, id1|id1, UPPER(val1),f(id1);
|
||||||
|
total val1 id1 && id1 id1|id1 UPPER(val1) f(id1)
|
||||||
|
52 Z 1 26 Z 52
|
||||||
|
ANALYZE INSERT INTO t1 SET id1=12, val1='l' RETURNING *;
|
||||||
|
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
|
||||||
|
1 INSERT t1 ALL NULL NULL NULL NULL NULL NULL 100.00 100.00 NULL
|
||||||
|
SELECT * FROM t1;
|
||||||
|
id1 val1
|
||||||
|
1 a
|
||||||
|
2 b
|
||||||
|
3 c
|
||||||
|
4 d
|
||||||
|
5 e
|
||||||
|
6 f
|
||||||
|
7 g
|
||||||
|
8 n
|
||||||
|
26 Z
|
||||||
|
12 l
|
||||||
|
#
|
||||||
|
# INSERT...SELECT...RETURNING
|
||||||
|
#
|
||||||
|
TRUNCATE TABLE t2;
|
||||||
|
INSERT INTO t2(id2,val2) SELECT * FROM t1;
|
||||||
|
TRUNCATE TABLE t2;
|
||||||
|
INSERT INTO t2 SELECT * FROM t1 WHERE id1=1 RETURNING *;
|
||||||
|
id2 val2
|
||||||
|
1 a
|
||||||
|
INSERT INTO t2 SELECT * FROM t1 WHERE id1=2 RETURNING id2+id2 AS total,
|
||||||
|
val2,id2 && id2, id2|id2, UPPER(val2),f(id2);
|
||||||
|
total val2 id2 && id2 id2|id2 UPPER(val2) f(id2)
|
||||||
|
4 b 1 2 B 4
|
||||||
|
INSERT INTO t2 SELECT * FROM t1 WHERE id1=3 RETURNING (SELECT GROUP_CONCAT(val1) FROM t1 GROUP BY id1 HAVING id1=id1+1);
|
||||||
|
(SELECT GROUP_CONCAT(val1) FROM t1 GROUP BY id1 HAVING id1=id1+1)
|
||||||
|
NULL
|
||||||
|
PREPARE stmt FROM "INSERT INTO t2 SELECT * FROM t1 WHERE id1=4 RETURNING (SELECT id1 FROM t1 WHERE val1='b')";
|
||||||
|
EXECUTE stmt;
|
||||||
|
(SELECT id1 FROM t1 WHERE val1='b')
|
||||||
|
2
|
||||||
|
DELETE FROM t2 WHERE id2=4;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
id1 val1
|
||||||
|
1 a
|
||||||
|
2 b
|
||||||
|
3 c
|
||||||
|
4 d
|
||||||
|
5 e
|
||||||
|
6 f
|
||||||
|
7 g
|
||||||
|
8 n
|
||||||
|
26 Z
|
||||||
|
12 l
|
||||||
|
EXECUTE stmt;
|
||||||
|
(SELECT id1 FROM t1 WHERE val1='b')
|
||||||
|
2
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
INSERT INTO t2 SELECT * FROM t1 WHERE id1=6 RETURNING
|
||||||
|
(SELECT id1+id2 FROM t1 WHERE id1=1);
|
||||||
|
(SELECT id1+id2 FROM t1 WHERE id1=1)
|
||||||
|
7
|
||||||
|
INSERT INTO t2 SELECT * FROM t1 WHERE id1=7 RETURNING f(id2);
|
||||||
|
f(id2)
|
||||||
|
14
|
||||||
|
EXPLAIN INSERT INTO t2 SELECT * FROM t1 WHERE id1=8 RETURNING id2;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 const PRIMARY PRIMARY 4 const 1
|
||||||
|
EXPLAIN EXTENDED INSERT INTO t1 SELECT * FROM t1 WHERE id1=9 RETURNING val1;
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
|
EXPLAIN FORMAT="json" INSERT INTO t1 SELECT * FROM t1 WHERE id1=10 RETURNING val1;
|
||||||
|
EXPLAIN
|
||||||
|
{
|
||||||
|
"query_block": {
|
||||||
|
"select_id": 1,
|
||||||
|
"table": {
|
||||||
|
"message": "Impossible WHERE noticed after reading const tables"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
INSERT IGNORE INTO t2 SELECT * FROM t1 WHERE id1=8 RETURNING *;
|
||||||
|
id2 val2
|
||||||
|
8 n
|
||||||
|
INSERT IGNORE INTO v2 SELECT * FROM v1 RETURNING *;
|
||||||
|
id2 val2
|
||||||
|
1 a
|
||||||
|
2 b
|
||||||
|
3 c
|
||||||
|
4 d
|
||||||
|
5 e
|
||||||
|
6 f
|
||||||
|
7 g
|
||||||
|
8 n
|
||||||
|
26 Z
|
||||||
|
12 l
|
||||||
|
Warnings:
|
||||||
|
Warning 1062 Duplicate entry '1' for key 'PRIMARY'
|
||||||
|
Warning 1062 Duplicate entry '2' for key 'PRIMARY'
|
||||||
|
Warning 1062 Duplicate entry '3' for key 'PRIMARY'
|
||||||
|
Warning 1062 Duplicate entry '4' for key 'PRIMARY'
|
||||||
|
Warning 1062 Duplicate entry '6' for key 'PRIMARY'
|
||||||
|
Warning 1062 Duplicate entry '7' for key 'PRIMARY'
|
||||||
|
Warning 1062 Duplicate entry '8' for key 'PRIMARY'
|
||||||
|
ANALYZE INSERT INTO t2 SELECT * FROM t1 WHERE id1=11 RETURNING *;
|
||||||
|
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
|
||||||
|
SELECT * FROM t2;
|
||||||
|
id2 val2
|
||||||
|
1 a
|
||||||
|
2 b
|
||||||
|
3 c
|
||||||
|
4 d
|
||||||
|
6 f
|
||||||
|
7 g
|
||||||
|
8 n
|
||||||
|
5 e
|
||||||
|
26 Z
|
||||||
|
12 l
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP TABLE t2;
|
||||||
|
DROP TABLE ins_duplicate;
|
||||||
|
#
|
||||||
|
# Error message test
|
||||||
|
#
|
||||||
|
CREATE TABLE t1(id1 INT,val1 VARCHAR(1));
|
||||||
|
CREATE TABLE t2(id2 INT,val2 VARCHAR(1));
|
||||||
|
CREATE TABLE ins_duplicate (id INT PRIMARY KEY, val VARCHAR(1));
|
||||||
|
INSERT INTO t1 VALUES(1,'a'),(2,'b'),(3,'c');
|
||||||
|
#
|
||||||
|
# SIMLPE INSERT STATEMENT
|
||||||
|
#
|
||||||
|
INSERT INTO t2(id2,val2) VALUES(1,'a') RETURNING id1;
|
||||||
|
ERROR 42S22: Unknown column 'id1' in 'field list'
|
||||||
|
INSERT INTO t2(id2,val2) values(2,'b') RETURNING SUM(id2);
|
||||||
|
ERROR HY000: Invalid use of group function
|
||||||
|
INSERT INTO t2(id2,val2) VALUES(3,'c') RETURNING (SELECT id1 FROM t1);
|
||||||
|
ERROR 21000: Subquery returns more than 1 row
|
||||||
|
INSERT INTO t2(id2,val2) VALUES(4,'d') RETURNING (SELECT * FROM t1);
|
||||||
|
ERROR 21000: Operand should contain 1 column(s)
|
||||||
|
INSERT INTO t2(id2,val2) VALUES(4,'d') RETURNING (SELECT * FROM t2);
|
||||||
|
ERROR 21000: Operand should contain 1 column(s)
|
||||||
|
INSERT INTO t2(id2,val2) VALUES(5,'e') RETURNING id2, (SELECT id1+id2 FROM
|
||||||
|
t1 WHERE id1=1);
|
||||||
|
id2 (SELECT id1+id2 FROM
|
||||||
|
t1 WHERE id1=1)
|
||||||
|
5 6
|
||||||
|
INSERT INTO t2(id2,val2) VALUES(5,'f') RETURNING (SELECT id2 FROM t2);
|
||||||
|
ERROR HY000: Table 't2' is specified twice, both as a target for 'INSERT' and as a separate source for data
|
||||||
|
#
|
||||||
|
# Multiple rows in single insert statement
|
||||||
|
#
|
||||||
|
INSERT INTO t2 VALUES(1,'a'),(2,'b') RETURNING id1;
|
||||||
|
ERROR 42S22: Unknown column 'id1' in 'field list'
|
||||||
|
INSERT INTO t2 VALUES(3,'c'),(4,'d') RETURNING MAX(id2);
|
||||||
|
ERROR HY000: Invalid use of group function
|
||||||
|
INSERT INTO t2 VALUES(5,'c'),(6,'f') RETURNING (SELECT id1 FROM t1);
|
||||||
|
ERROR 21000: Subquery returns more than 1 row
|
||||||
|
INSERT INTO t2 VALUES(7,'g'),(8,'h') RETURNING (SELECT * FROM t1);
|
||||||
|
ERROR 21000: Operand should contain 1 column(s)
|
||||||
|
INSERT INTO t2 VALUES(9,'g'),(10,'h') RETURNING (SELECT * FROM t2);
|
||||||
|
ERROR 21000: Operand should contain 1 column(s)
|
||||||
|
INSERT INTO t2 VALUES(11,'e'),(12,'f') RETURNING id2, (SELECT id1+id2 FROM
|
||||||
|
t1 WHERE id1=1);
|
||||||
|
id2 (SELECT id1+id2 FROM
|
||||||
|
t1 WHERE id1=1)
|
||||||
|
11 12
|
||||||
|
12 13
|
||||||
|
INSERT INTO t2 VALUES(13,'f'),(14,'g') RETURNING (SELECT id2 FROM t2);
|
||||||
|
ERROR HY000: Table 't2' is specified twice, both as a target for 'INSERT' and as a separate source for data
|
||||||
|
#
|
||||||
|
# INSERT ... SET
|
||||||
|
#
|
||||||
|
INSERT INTO t2 SET id2=1, val2='a' RETURNING id1;
|
||||||
|
ERROR 42S22: Unknown column 'id1' in 'field list'
|
||||||
|
INSERT INTO t2 SET id2=2, val2='b' RETURNING COUNT(id2);
|
||||||
|
ERROR HY000: Invalid use of group function
|
||||||
|
INSERT INTO t2 SET id2=3, val2='c' RETURNING (SELECT id1 FROM t1);
|
||||||
|
ERROR 21000: Subquery returns more than 1 row
|
||||||
|
INSERT INTO t2 SET id2=4, val2='d' RETURNING (SELECT * FROM t1);
|
||||||
|
ERROR 21000: Operand should contain 1 column(s)
|
||||||
|
INSERT INTO t2 SET id2=4, val2='d' RETURNING (SELECT * FROM t2);
|
||||||
|
ERROR 21000: Operand should contain 1 column(s)
|
||||||
|
INSERT INTO t2 SET id2=5, val2='e' RETURNING id2, (SELECT id1+id2 FROM t1
|
||||||
|
WHERE id1=1);
|
||||||
|
id2 (SELECT id1+id2 FROM t1
|
||||||
|
WHERE id1=1)
|
||||||
|
5 6
|
||||||
|
INSERT INTO t2 SET id2=5, val2='f' RETURNING (SELECT id2 FROM t2);
|
||||||
|
ERROR HY000: Table 't2' is specified twice, both as a target for 'INSERT' and as a separate source for data
|
||||||
|
#
|
||||||
|
# INSERT...ON DUPLICATE KEY UPDATE
|
||||||
|
#
|
||||||
|
INSERT INTO ins_duplicate VALUES (2,'b') ON DUPLICATE KEY UPDATE val='b'
|
||||||
|
RETURNING id1;
|
||||||
|
ERROR 42S22: Unknown column 'id1' in 'field list'
|
||||||
|
INSERT INTO ins_duplicate VALUES (2,'b') ON DUPLICATE KEY UPDATE val='b'
|
||||||
|
RETURNING MAX(id);
|
||||||
|
ERROR HY000: Invalid use of group function
|
||||||
|
INSERT INTO ins_duplicate VALUES (2,'b') ON DUPLICATE KEY UPDATE val='b'
|
||||||
|
RETURNING (SELECT id1 FROM t1);
|
||||||
|
ERROR 21000: Subquery returns more than 1 row
|
||||||
|
INSERT INTO ins_duplicate VALUES (2,'b') ON DUPLICATE KEY UPDATE val='b'
|
||||||
|
RETURNING (SELECT * FROM t1);
|
||||||
|
ERROR 21000: Operand should contain 1 column(s)
|
||||||
|
INSERT INTO ins_duplicate VALUES (2,'b') ON DUPLICATE KEY UPDATE val='b'
|
||||||
|
RETURNING (SELECT * FROM ins_duplicate);
|
||||||
|
ERROR 21000: Operand should contain 1 column(s)
|
||||||
|
INSERT INTO ins_duplicate VALUES(2,'b') ON DUPLICATE KEY UPDATE val='b'
|
||||||
|
RETURNING id2, (SELECT id1+id FROM t1 WHERE id1=1);
|
||||||
|
ERROR 42S22: Unknown column 'id2' in 'field list'
|
||||||
|
INSERT INTO ins_duplicate VALUES(2,'b') ON DUPLICATE KEY UPDATE val='b'
|
||||||
|
RETURNING (SELECT id FROM ins_duplicate);
|
||||||
|
ERROR HY000: Table 'ins_duplicate' is specified twice, both as a target for 'INSERT' and as a separate source for data
|
||||||
|
#
|
||||||
|
# INSERT...SELECT
|
||||||
|
#
|
||||||
|
INSERT INTO t2(id2, val2) SELECT * FROM t1 WHERE id1=1 RETURNING id1;
|
||||||
|
ERROR 42S22: Unknown column 'id1' in 'field list'
|
||||||
|
INSERT INTO t2(id2, val2) SELECT * FROM t1 WHERE id1=2 RETURNING MAX(id2);
|
||||||
|
ERROR HY000: Invalid use of group function
|
||||||
|
INSERT INTO t2(id2, val2) SELECT * FROM t1 WHERE id1=2 RETURNING (SELECT
|
||||||
|
id1 FROM t1);
|
||||||
|
ERROR 21000: Subquery returns more than 1 row
|
||||||
|
INSERT INTO t2(id2, val2) SELECT * FROM t1 WHERE id1=2 RETURNING (SELECT
|
||||||
|
* FROM t1);
|
||||||
|
ERROR 21000: Operand should contain 1 column(s)
|
||||||
|
INSERT INTO t2(id2, val2) SELECT * FROM t1 WHERE id1=2 RETURNING(SELECT
|
||||||
|
* FROM t2);
|
||||||
|
ERROR 21000: Operand should contain 1 column(s)
|
||||||
|
INSERT INTO t2(id2,val2) SELECT * FROM t1 WHERE id1=2 RETURNING (SELECT
|
||||||
|
id2 FROM t2);
|
||||||
|
ERROR 21000: Subquery returns more than 1 row
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP TABLE t2;
|
||||||
|
DROP TABLE ins_duplicate;
|
||||||
|
DROP VIEW v1;
|
||||||
|
DROP VIEW v2;
|
||||||
|
DROP FUNCTION f;
|
280
mysql-test/main/insert_returning.test
Normal file
280
mysql-test/main/insert_returning.test
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
--echo # Test for INSERT...RETURNING
|
||||||
|
|
||||||
|
CREATE TABLE t1(id1 INT PRIMARY KEY AUTO_INCREMENT, val1 VARCHAR(1));
|
||||||
|
CREATE TABLE t2(id2 INT PRIMARY KEY AUTO_INCREMENT, val2 VARCHAR(1));
|
||||||
|
CREATE VIEW v1 AS SELECT id1, val1 FROM t1;
|
||||||
|
CREATE VIEW v2 AS SELECT id2,val2 FROM t2;
|
||||||
|
INSERT INTO t2 VALUES (1,'a'),(2,'b'),(3,'c');
|
||||||
|
|
||||||
|
DELIMITER |;
|
||||||
|
|
||||||
|
CREATE FUNCTION f(arg INT) RETURNS TEXT
|
||||||
|
BEGIN
|
||||||
|
RETURN (SELECT arg+arg);
|
||||||
|
END|
|
||||||
|
|
||||||
|
DELIMITER ;|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Simple insert statement...RETURNING
|
||||||
|
--echo #
|
||||||
|
INSERT INTO t1 (id1, val1) VALUES (1, 'a');
|
||||||
|
INSERT INTO t1 (id1, val1) VALUES (2, 'b') RETURNING *;
|
||||||
|
INSERT INTO t1 (id1, val1) VALUES (3, 'c') RETURNING id1+id1 as total,val1,
|
||||||
|
id1 && id1, id1 | id1, UPPER(val1),f(id1);
|
||||||
|
INSERT INTO t1(id1,val1) VALUES (4,'d') RETURNING(SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 WHERE id2=1);
|
||||||
|
INSERT INTO t1(id1,val1) VALUES(5,'e') RETURNING(SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 GROUP BY id2 HAVING id2=id2+1);
|
||||||
|
PREPARE stmt FROM "INSERT INTO t1 (id1,val1) VALUES (6,'f') RETURNING (SELECT id2 FROM t2 WHERE val2='b')";
|
||||||
|
EXECUTE stmt;
|
||||||
|
DELETE FROM t1 WHERE id1=6;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
INSERT IGNORE INTO t1(id1,val1) VALUES (7,'h') RETURNING *;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
EXPLAIN INSERT INTO t1(id1,val1) VALUES (8,'i') RETURNING *;
|
||||||
|
EXPLAIN EXTENDED INSERT INTO t1(id1,val1) VALUES(9,'j') RETURNING id1;
|
||||||
|
EXPLAIN FORMAT="json" INSERT INTO t1(id1,val1) VALUES (10,'k') RETURNING id1;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
INSERT INTO v1(id1, val1) VALUES (12, 'a') RETURNING id1+id1 as total,val1,
|
||||||
|
id1 && id1, id1 id1, UPPER(val1),f(id1);
|
||||||
|
ANALYZE INSERT INTO t1(id1,val1) VALUES(13,'l') RETURNING *;
|
||||||
|
TRUNCATE TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Multiple values in one insert statement...RETURNING
|
||||||
|
--echo #
|
||||||
|
INSERT INTO t1 VALUES (1,'a'),(2,'b');
|
||||||
|
INSERT INTO t1 VALUES (3,'c'),(4,'d') RETURNING *;
|
||||||
|
INSERT INTO t1 VALUES (5,'e'),(6,'f') RETURNING id1 as id,val1,
|
||||||
|
id1 && id1, id1|id1, UPPER(val1),f(id1);
|
||||||
|
INSERT INTO t1 VALUES (7,'g'),(8,'h') RETURNING(SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 WHERE id2=1);
|
||||||
|
INSERT INTO t1 VALUES (9,'i'),(10,'j') RETURNING(SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 GROUP BY id2 HAVING id2=id2+1);
|
||||||
|
PREPARE stmt FROM "INSERT INTO t1 VALUES (11,'k'),(12,'l') RETURNING (SELECT id2 FROM t2 WHERE val2='b')";
|
||||||
|
EXECUTE stmt;
|
||||||
|
DELETE FROM t1 WHERE val1 IN ('k','l');
|
||||||
|
SELECT * FROM t1;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
INSERT IGNORE INTO t1 VALUES(13,'o'),(14,'p') RETURNING *;
|
||||||
|
EXPLAIN INSERT INTO t1 VALUES(15,'q'),(16,'r') RETURNING *;
|
||||||
|
EXPLAIN EXTENDED INSERT INTO t1 VALUES (17,'s'),(18,'t') RETURNING *;
|
||||||
|
EXPLAIN FORMAT="json" INSERT INTO t1 VALUES(19,'u'),(20,'v') RETURNING id1;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
INSERT INTO v1 VALUES(23,'y'),(24,'z') RETURNING id1 as id,val1,
|
||||||
|
id1 && id1, id1|id1, UPPER(val1),f(id1);
|
||||||
|
ANALYZE INSERT INTO t1 VALUES(25,'a'),(26,'b') RETURNING *;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # INSERT...ON DUPLICATE KEY UPDATE...RETURNING
|
||||||
|
--echo #
|
||||||
|
CREATE TABLE ins_duplicate (id INT PRIMARY KEY AUTO_INCREMENT, val VARCHAR(1));
|
||||||
|
INSERT INTO ins_duplicate VALUES (1,'a');
|
||||||
|
INSERT INTO ins_duplicate VALUES (2,'b') ON DUPLICATE KEY UPDATE val='b'
|
||||||
|
RETURNING *;
|
||||||
|
INSERT INTO ins_duplicate VALUES (2,'b') ON DUPLICATE KEY UPDATE val='c'
|
||||||
|
RETURNING id+id AS total, val, id && id, id|id, UPPER(val),f(id);
|
||||||
|
INSERT INTO ins_duplicate VALUES (2,'b') ON DUPLICATE KEY UPDATE val='d'
|
||||||
|
RETURNING (SELECT GROUP_CONCAT(val2) FROM t2 WHERE id2=1);
|
||||||
|
INSERT INTO ins_duplicate VALUES (2,'b') ON DUPLICATE KEY UPDATE val='e'
|
||||||
|
RETURNING (SELECT GROUP_CONCAT(val2) FROM t2 GROUP BY id2 HAVING id2=id2+1);
|
||||||
|
PREPARE stmt FROM "INSERT INTO ins_duplicate VALUES (2,'b') ON DUPLICATE
|
||||||
|
KEY UPDATE val='f' RETURNING (SELECT id2 FROM t2 WHERE val2='b')";
|
||||||
|
EXECUTE stmt;
|
||||||
|
SELECT * FROM t2;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
INSERT IGNORE INTO ins_duplicate(id,val) VALUES (3,'c'),(4,'d') ON DUPLICATE
|
||||||
|
KEY UPDATE val='g' RETURNING id;
|
||||||
|
EXPLAIN INSERT INTO ins_duplicate(id,val) VALUES (2,'b') ON DUPLICATE KEY
|
||||||
|
UPDATE val='h' RETURNING val;
|
||||||
|
EXPLAIN EXTENDED INSERT INTO ins_duplicate(id,val) VALUES (2,'b')
|
||||||
|
ON DUPLICATE KEY UPDATE val='i' RETURNING val;
|
||||||
|
EXPLAIN FORMAT="json" INSERT INTO ins_duplicate(id,val) VALUES (2,'b')
|
||||||
|
ON DUPLICATE KEY UPDATE val='j' RETURNING val;
|
||||||
|
INSERT INTO v1(id1, val1) VALUES (2,'d') ON DUPLICATE KEY UPDATE
|
||||||
|
val1='d' RETURNING id1+id1 AS total, val1, id1 && id1, id1|id1, UPPER(val1),
|
||||||
|
f(id1);
|
||||||
|
ANALYZE INSERT INTO ins_duplicate(id,val) VALUES(2,'b') ON DUPLICATE KEY UPDATE
|
||||||
|
val='k' RETURNING *;
|
||||||
|
SELECT * FROM ins_duplicate;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # INSERT...SET...RETURNING
|
||||||
|
--echo #
|
||||||
|
TRUNCATE TABLE t1;
|
||||||
|
INSERT INTO t1 SET id1= 1, val1= 'a';
|
||||||
|
INSERT INTO t1 SET id1= 2, val1= 'b' RETURNING *;
|
||||||
|
INSERT INTO t1 SET id1= 3, val1= 'c' RETURNING id1+id1 AS total,val1,
|
||||||
|
id1 && id1, id1|id1, UPPER(val1),f(id1);
|
||||||
|
INSERT INTO t1 SET id1= 4, val1= 'd' RETURNING (SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 WHERE id2=1);
|
||||||
|
INSERT INTO t1 SET id1= 5, val1='e' RETURNING (SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 GROUP BY id2 HAVING id2=id2+1);
|
||||||
|
PREPARE stmt FROM "INSERT INTO t1 SET id1= 6, val1='f' RETURNING (SELECT id2 FROM t2 WHERE val2='b')";
|
||||||
|
EXECUTE stmt;
|
||||||
|
DELETE FROM t1 WHERE val1='f';
|
||||||
|
SELECT * FROM t1;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
INSERT INTO t1 SET id1= 7, val1= 'g' RETURNING f(id1);
|
||||||
|
INSERT INTO t1 SET val1= 'n' RETURNING *;
|
||||||
|
INSERT IGNORE INTO t1 SET id1= 8, val1= 'h' RETURNING *;
|
||||||
|
EXPLAIN INSERT INTO t1 SET id1=9, val1='i' RETURNING id1;
|
||||||
|
EXPLAIN EXTENDED INSERT INTO t1 SET id1=10, val1='j' RETURNING val1;
|
||||||
|
EXPLAIN FORMAT="json" INSERT INTO t1 SET id1=11, val1='k' RETURNING val1;
|
||||||
|
INSERT INTO v1 SET id1=26, val1='Z' RETURNING id1+id1 AS total,val1,
|
||||||
|
id1 && id1, id1|id1, UPPER(val1),f(id1);
|
||||||
|
ANALYZE INSERT INTO t1 SET id1=12, val1='l' RETURNING *;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # INSERT...SELECT...RETURNING
|
||||||
|
--echo #
|
||||||
|
TRUNCATE TABLE t2;
|
||||||
|
INSERT INTO t2(id2,val2) SELECT * FROM t1;
|
||||||
|
TRUNCATE TABLE t2;
|
||||||
|
INSERT INTO t2 SELECT * FROM t1 WHERE id1=1 RETURNING *;
|
||||||
|
INSERT INTO t2 SELECT * FROM t1 WHERE id1=2 RETURNING id2+id2 AS total,
|
||||||
|
val2,id2 && id2, id2|id2, UPPER(val2),f(id2);
|
||||||
|
INSERT INTO t2 SELECT * FROM t1 WHERE id1=3 RETURNING (SELECT GROUP_CONCAT(val1) FROM t1 GROUP BY id1 HAVING id1=id1+1);
|
||||||
|
PREPARE stmt FROM "INSERT INTO t2 SELECT * FROM t1 WHERE id1=4 RETURNING (SELECT id1 FROM t1 WHERE val1='b')";
|
||||||
|
EXECUTE stmt;
|
||||||
|
DELETE FROM t2 WHERE id2=4;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
INSERT INTO t2 SELECT * FROM t1 WHERE id1=6 RETURNING
|
||||||
|
(SELECT id1+id2 FROM t1 WHERE id1=1);
|
||||||
|
INSERT INTO t2 SELECT * FROM t1 WHERE id1=7 RETURNING f(id2);
|
||||||
|
EXPLAIN INSERT INTO t2 SELECT * FROM t1 WHERE id1=8 RETURNING id2;
|
||||||
|
EXPLAIN EXTENDED INSERT INTO t1 SELECT * FROM t1 WHERE id1=9 RETURNING val1;
|
||||||
|
EXPLAIN FORMAT="json" INSERT INTO t1 SELECT * FROM t1 WHERE id1=10 RETURNING val1;
|
||||||
|
INSERT IGNORE INTO t2 SELECT * FROM t1 WHERE id1=8 RETURNING *;
|
||||||
|
INSERT IGNORE INTO v2 SELECT * FROM v1 RETURNING *;
|
||||||
|
ANALYZE INSERT INTO t2 SELECT * FROM t1 WHERE id1=11 RETURNING *;
|
||||||
|
SELECT * FROM t2;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP TABLE t2;
|
||||||
|
DROP TABLE ins_duplicate;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Error message test
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1(id1 INT,val1 VARCHAR(1));
|
||||||
|
CREATE TABLE t2(id2 INT,val2 VARCHAR(1));
|
||||||
|
CREATE TABLE ins_duplicate (id INT PRIMARY KEY, val VARCHAR(1));
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES(1,'a'),(2,'b'),(3,'c');
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # SIMLPE INSERT STATEMENT
|
||||||
|
--echo #
|
||||||
|
--error ER_BAD_FIELD_ERROR
|
||||||
|
INSERT INTO t2(id2,val2) VALUES(1,'a') RETURNING id1;
|
||||||
|
--error ER_INVALID_GROUP_FUNC_USE
|
||||||
|
INSERT INTO t2(id2,val2) values(2,'b') RETURNING SUM(id2);
|
||||||
|
--error ER_SUBQUERY_NO_1_ROW
|
||||||
|
INSERT INTO t2(id2,val2) VALUES(3,'c') RETURNING (SELECT id1 FROM t1);
|
||||||
|
--error ER_OPERAND_COLUMNS
|
||||||
|
INSERT INTO t2(id2,val2) VALUES(4,'d') RETURNING (SELECT * FROM t1);
|
||||||
|
--error ER_OPERAND_COLUMNS
|
||||||
|
INSERT INTO t2(id2,val2) VALUES(4,'d') RETURNING (SELECT * FROM t2);
|
||||||
|
INSERT INTO t2(id2,val2) VALUES(5,'e') RETURNING id2, (SELECT id1+id2 FROM
|
||||||
|
t1 WHERE id1=1);
|
||||||
|
--error ER_UPDATE_TABLE_USED
|
||||||
|
INSERT INTO t2(id2,val2) VALUES(5,'f') RETURNING (SELECT id2 FROM t2);
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Multiple rows in single insert statement
|
||||||
|
--echo #
|
||||||
|
--error ER_BAD_FIELD_ERROR
|
||||||
|
INSERT INTO t2 VALUES(1,'a'),(2,'b') RETURNING id1;
|
||||||
|
--error ER_INVALID_GROUP_FUNC_USE
|
||||||
|
INSERT INTO t2 VALUES(3,'c'),(4,'d') RETURNING MAX(id2);
|
||||||
|
--error ER_SUBQUERY_NO_1_ROW
|
||||||
|
INSERT INTO t2 VALUES(5,'c'),(6,'f') RETURNING (SELECT id1 FROM t1);
|
||||||
|
--error ER_OPERAND_COLUMNS
|
||||||
|
INSERT INTO t2 VALUES(7,'g'),(8,'h') RETURNING (SELECT * FROM t1);
|
||||||
|
--error ER_OPERAND_COLUMNS
|
||||||
|
INSERT INTO t2 VALUES(9,'g'),(10,'h') RETURNING (SELECT * FROM t2);
|
||||||
|
INSERT INTO t2 VALUES(11,'e'),(12,'f') RETURNING id2, (SELECT id1+id2 FROM
|
||||||
|
t1 WHERE id1=1);
|
||||||
|
--error ER_UPDATE_TABLE_USED
|
||||||
|
INSERT INTO t2 VALUES(13,'f'),(14,'g') RETURNING (SELECT id2 FROM t2);
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # INSERT ... SET
|
||||||
|
--echo #
|
||||||
|
--error ER_BAD_FIELD_ERROR
|
||||||
|
INSERT INTO t2 SET id2=1, val2='a' RETURNING id1;
|
||||||
|
--error ER_INVALID_GROUP_FUNC_USE
|
||||||
|
INSERT INTO t2 SET id2=2, val2='b' RETURNING COUNT(id2);
|
||||||
|
--error ER_SUBQUERY_NO_1_ROW
|
||||||
|
INSERT INTO t2 SET id2=3, val2='c' RETURNING (SELECT id1 FROM t1);
|
||||||
|
--error ER_OPERAND_COLUMNS
|
||||||
|
INSERT INTO t2 SET id2=4, val2='d' RETURNING (SELECT * FROM t1);
|
||||||
|
--error ER_OPERAND_COLUMNS
|
||||||
|
INSERT INTO t2 SET id2=4, val2='d' RETURNING (SELECT * FROM t2);
|
||||||
|
INSERT INTO t2 SET id2=5, val2='e' RETURNING id2, (SELECT id1+id2 FROM t1
|
||||||
|
WHERE id1=1);
|
||||||
|
--error ER_UPDATE_TABLE_USED
|
||||||
|
INSERT INTO t2 SET id2=5, val2='f' RETURNING (SELECT id2 FROM t2);
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # INSERT...ON DUPLICATE KEY UPDATE
|
||||||
|
--echo #
|
||||||
|
--error ER_BAD_FIELD_ERROR
|
||||||
|
INSERT INTO ins_duplicate VALUES (2,'b') ON DUPLICATE KEY UPDATE val='b'
|
||||||
|
RETURNING id1;
|
||||||
|
--error ER_INVALID_GROUP_FUNC_USE
|
||||||
|
INSERT INTO ins_duplicate VALUES (2,'b') ON DUPLICATE KEY UPDATE val='b'
|
||||||
|
RETURNING MAX(id);
|
||||||
|
--error ER_SUBQUERY_NO_1_ROW
|
||||||
|
INSERT INTO ins_duplicate VALUES (2,'b') ON DUPLICATE KEY UPDATE val='b'
|
||||||
|
RETURNING (SELECT id1 FROM t1);
|
||||||
|
--error ER_OPERAND_COLUMNS
|
||||||
|
INSERT INTO ins_duplicate VALUES (2,'b') ON DUPLICATE KEY UPDATE val='b'
|
||||||
|
RETURNING (SELECT * FROM t1);
|
||||||
|
--error ER_OPERAND_COLUMNS
|
||||||
|
INSERT INTO ins_duplicate VALUES (2,'b') ON DUPLICATE KEY UPDATE val='b'
|
||||||
|
RETURNING (SELECT * FROM ins_duplicate);
|
||||||
|
--error ER_BAD_FIELD_ERROR
|
||||||
|
INSERT INTO ins_duplicate VALUES(2,'b') ON DUPLICATE KEY UPDATE val='b'
|
||||||
|
RETURNING id2, (SELECT id1+id FROM t1 WHERE id1=1);
|
||||||
|
--error ER_UPDATE_TABLE_USED
|
||||||
|
INSERT INTO ins_duplicate VALUES(2,'b') ON DUPLICATE KEY UPDATE val='b'
|
||||||
|
RETURNING (SELECT id FROM ins_duplicate);
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # INSERT...SELECT
|
||||||
|
--echo #
|
||||||
|
--error ER_BAD_FIELD_ERROR
|
||||||
|
INSERT INTO t2(id2, val2) SELECT * FROM t1 WHERE id1=1 RETURNING id1;
|
||||||
|
--error ER_INVALID_GROUP_FUNC_USE
|
||||||
|
INSERT INTO t2(id2, val2) SELECT * FROM t1 WHERE id1=2 RETURNING MAX(id2);
|
||||||
|
--error ER_SUBQUERY_NO_1_ROW
|
||||||
|
INSERT INTO t2(id2, val2) SELECT * FROM t1 WHERE id1=2 RETURNING (SELECT
|
||||||
|
id1 FROM t1);
|
||||||
|
--error ER_OPERAND_COLUMNS
|
||||||
|
INSERT INTO t2(id2, val2) SELECT * FROM t1 WHERE id1=2 RETURNING (SELECT
|
||||||
|
* FROM t1);
|
||||||
|
--error ER_OPERAND_COLUMNS
|
||||||
|
INSERT INTO t2(id2, val2) SELECT * FROM t1 WHERE id1=2 RETURNING(SELECT
|
||||||
|
* FROM t2);
|
||||||
|
--error ER_SUBQUERY_NO_1_ROW
|
||||||
|
INSERT INTO t2(id2,val2) SELECT * FROM t1 WHERE id1=2 RETURNING (SELECT
|
||||||
|
id2 FROM t2);
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP TABLE t2;
|
||||||
|
DROP TABLE ins_duplicate;
|
||||||
|
DROP VIEW v1;
|
||||||
|
DROP VIEW v2;
|
||||||
|
DROP FUNCTION f;
|
72
mysql-test/main/insert_returning_datatypes.result
Normal file
72
mysql-test/main/insert_returning_datatypes.result
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
CREATE TABLE t1(num_int1 INT(2) PRIMARY KEY,
|
||||||
|
num_bit1 BIT(8),
|
||||||
|
num_float1 FLOAT(5,2),
|
||||||
|
num_double1 DOUBLE(5,2),
|
||||||
|
char_enum1 ENUM('A','B','C','D'),
|
||||||
|
char_set1 SET('a','b','c','d','e'),
|
||||||
|
str_varchar1 VARCHAR(2),
|
||||||
|
d1 DATE,
|
||||||
|
dt1 DATETIME,
|
||||||
|
ts1 TIMESTAMP,
|
||||||
|
y1 YEAR,
|
||||||
|
b1 BOOL);
|
||||||
|
CREATE TABLE t2(num_int2 INT(2) PRIMARY KEY,
|
||||||
|
num_bit2 BIT(8),
|
||||||
|
num_float2 FLOAT(5,2),
|
||||||
|
num_double2 DOUBLE(5,2),
|
||||||
|
char_enum2 ENUM('A','B','C','D'),
|
||||||
|
char_set2 SET('a','b','c','d','e'),
|
||||||
|
str_varchar2 VARCHAR(2),
|
||||||
|
d2 DATE,
|
||||||
|
dt2 DATETIME,
|
||||||
|
ts2 TIMESTAMP,
|
||||||
|
y2 YEAR,
|
||||||
|
b2 BOOL);
|
||||||
|
#
|
||||||
|
# SIMLPE INSERT STATEMENT
|
||||||
|
#
|
||||||
|
INSERT INTO t1(num_int1,num_bit1,num_float1,num_double1,char_enum1,char_set1,
|
||||||
|
str_varchar1, d1,dt1,ts1,y1,b1) VALUES(1,b'1000011', 123.45, 123.55,
|
||||||
|
'A','b,e', 'V','120314',"2012-04-19 13:08:22", '2001-07-22 12:12:12',
|
||||||
|
2012,0) RETURNING *;
|
||||||
|
num_int1 num_bit1 num_float1 num_double1 char_enum1 char_set1 str_varchar1 d1 dt1 ts1 y1 b1
|
||||||
|
1 C 123.45 123.55 A b,e V 2012-03-14 2012-04-19 13:08:22 2001-07-22 12:12:12 2012 0
|
||||||
|
#
|
||||||
|
# MULTIPLE ROWS IN SINGLE STATEMENT
|
||||||
|
#
|
||||||
|
INSERT INTO t1 VALUES(2,b'1000011', 123.45, 123.55, 'A','b,e', 'V',
|
||||||
|
'120314',"2012-04-19 13:08:22", '2001-07-22 12:12:12',2012,0),(3,b'1000011',
|
||||||
|
123.45, 123.55, 'A','b,e', 'V','120314',"2012-04-19 13:08:22",
|
||||||
|
'2001-07-22 12:12:12',2012,1) RETURNING *;
|
||||||
|
num_int1 num_bit1 num_float1 num_double1 char_enum1 char_set1 str_varchar1 d1 dt1 ts1 y1 b1
|
||||||
|
2 C 123.45 123.55 A b,e V 2012-03-14 2012-04-19 13:08:22 2001-07-22 12:12:12 2012 0
|
||||||
|
3 C 123.45 123.55 A b,e V 2012-03-14 2012-04-19 13:08:22 2001-07-22 12:12:12 2012 1
|
||||||
|
#
|
||||||
|
# INSERT...SET...RETURNING
|
||||||
|
#
|
||||||
|
INSERT INTO t1 SET num_int1=4,num_bit1=b'1000011',num_float1=124.67,
|
||||||
|
num_double1=231.12,char_enum1='B',char_set1='a,d,e',
|
||||||
|
str_varchar1='AB',d1='120314',dt1="2012-04-19 13:08:22",
|
||||||
|
ts1='2001-07-22 12:12:1',y1=2014,b1=1 RETURNING *;
|
||||||
|
num_int1 num_bit1 num_float1 num_double1 char_enum1 char_set1 str_varchar1 d1 dt1 ts1 y1 b1
|
||||||
|
4 C 124.67 231.12 B a,d,e AB 2012-03-14 2012-04-19 13:08:22 2001-07-22 12:12:01 2014 1
|
||||||
|
#
|
||||||
|
# INSERT...ON DUPLICATE KEY UPDATE
|
||||||
|
#
|
||||||
|
INSERT INTO t1 VALUES (5,b'1000011', 123.45, 123.55,'C','b,e', 'V',
|
||||||
|
'120314',"2012-04-19 13:08:22", '2001-07-22 12:12:12',2012,0)
|
||||||
|
ON DUPLICATE KEY UPDATE num_float1=111.111 RETURNING *;
|
||||||
|
num_int1 num_bit1 num_float1 num_double1 char_enum1 char_set1 str_varchar1 d1 dt1 ts1 y1 b1
|
||||||
|
5 C 123.45 123.55 C b,e V 2012-03-14 2012-04-19 13:08:22 2001-07-22 12:12:12 2012 0
|
||||||
|
#
|
||||||
|
# INSERT...SELECT...RETURNING
|
||||||
|
#
|
||||||
|
INSERT INTO t2 SELECT * FROM t1 RETURNING *;
|
||||||
|
num_int2 num_bit2 num_float2 num_double2 char_enum2 char_set2 str_varchar2 d2 dt2 ts2 y2 b2
|
||||||
|
1 C 123.45 123.55 A b,e V 2012-03-14 2012-04-19 13:08:22 2001-07-22 12:12:12 2012 0
|
||||||
|
2 C 123.45 123.55 A b,e V 2012-03-14 2012-04-19 13:08:22 2001-07-22 12:12:12 2012 0
|
||||||
|
3 C 123.45 123.55 A b,e V 2012-03-14 2012-04-19 13:08:22 2001-07-22 12:12:12 2012 1
|
||||||
|
4 C 124.67 231.12 B a,d,e AB 2012-03-14 2012-04-19 13:08:22 2001-07-22 12:12:01 2014 1
|
||||||
|
5 C 123.45 123.55 C b,e V 2012-03-14 2012-04-19 13:08:22 2001-07-22 12:12:12 2012 0
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP TABLE t2;
|
74
mysql-test/main/insert_returning_datatypes.test
Normal file
74
mysql-test/main/insert_returning_datatypes.test
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#Test for checking all dataypes are returned
|
||||||
|
|
||||||
|
CREATE TABLE t1(num_int1 INT(2) PRIMARY KEY,
|
||||||
|
num_bit1 BIT(8),
|
||||||
|
num_float1 FLOAT(5,2),
|
||||||
|
num_double1 DOUBLE(5,2),
|
||||||
|
char_enum1 ENUM('A','B','C','D'),
|
||||||
|
char_set1 SET('a','b','c','d','e'),
|
||||||
|
str_varchar1 VARCHAR(2),
|
||||||
|
d1 DATE,
|
||||||
|
dt1 DATETIME,
|
||||||
|
ts1 TIMESTAMP,
|
||||||
|
y1 YEAR,
|
||||||
|
b1 BOOL);
|
||||||
|
|
||||||
|
CREATE TABLE t2(num_int2 INT(2) PRIMARY KEY,
|
||||||
|
num_bit2 BIT(8),
|
||||||
|
num_float2 FLOAT(5,2),
|
||||||
|
num_double2 DOUBLE(5,2),
|
||||||
|
char_enum2 ENUM('A','B','C','D'),
|
||||||
|
char_set2 SET('a','b','c','d','e'),
|
||||||
|
str_varchar2 VARCHAR(2),
|
||||||
|
d2 DATE,
|
||||||
|
dt2 DATETIME,
|
||||||
|
ts2 TIMESTAMP,
|
||||||
|
y2 YEAR,
|
||||||
|
b2 BOOL);
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # SIMLPE INSERT STATEMENT
|
||||||
|
--echo #
|
||||||
|
INSERT INTO t1(num_int1,num_bit1,num_float1,num_double1,char_enum1,char_set1,
|
||||||
|
str_varchar1, d1,dt1,ts1,y1,b1) VALUES(1,b'1000011', 123.45, 123.55,
|
||||||
|
'A','b,e', 'V','120314',"2012-04-19 13:08:22", '2001-07-22 12:12:12',
|
||||||
|
2012,0) RETURNING *;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MULTIPLE ROWS IN SINGLE STATEMENT
|
||||||
|
--echo #
|
||||||
|
INSERT INTO t1 VALUES(2,b'1000011', 123.45, 123.55, 'A','b,e', 'V',
|
||||||
|
'120314',"2012-04-19 13:08:22", '2001-07-22 12:12:12',2012,0),(3,b'1000011',
|
||||||
|
123.45, 123.55, 'A','b,e', 'V','120314',"2012-04-19 13:08:22",
|
||||||
|
'2001-07-22 12:12:12',2012,1) RETURNING *;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # INSERT...SET...RETURNING
|
||||||
|
--echo #
|
||||||
|
INSERT INTO t1 SET num_int1=4,num_bit1=b'1000011',num_float1=124.67,
|
||||||
|
num_double1=231.12,char_enum1='B',char_set1='a,d,e',
|
||||||
|
str_varchar1='AB',d1='120314',dt1="2012-04-19 13:08:22",
|
||||||
|
ts1='2001-07-22 12:12:1',y1=2014,b1=1 RETURNING *;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # INSERT...ON DUPLICATE KEY UPDATE
|
||||||
|
--echo #
|
||||||
|
INSERT INTO t1 VALUES (5,b'1000011', 123.45, 123.55,'C','b,e', 'V',
|
||||||
|
'120314',"2012-04-19 13:08:22", '2001-07-22 12:12:12',2012,0)
|
||||||
|
ON DUPLICATE KEY UPDATE num_float1=111.111 RETURNING *;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # INSERT...SELECT...RETURNING
|
||||||
|
--echo #
|
||||||
|
INSERT INTO t2 SELECT * FROM t1 RETURNING *;
|
||||||
|
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP TABLE t2;
|
154
mysql-test/main/replace_returning.result
Normal file
154
mysql-test/main/replace_returning.result
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
# Test for REPLACE...RETURNING
|
||||||
|
CREATE TABLE t1(id1 INT PRIMARY KEY, val1 VARCHAR(1));
|
||||||
|
CREATE TABLE t2(id2 INT PRIMARY KEY, val2 VARCHAR(1));
|
||||||
|
INSERT INTO t2 VALUES (1,'a'),(2,'b'),(3,'c');
|
||||||
|
CREATE FUNCTION f(arg INT) RETURNS INT
|
||||||
|
BEGIN
|
||||||
|
RETURN (SELECT arg+arg);
|
||||||
|
END|
|
||||||
|
#
|
||||||
|
# Simple replace statement...RETURNING
|
||||||
|
#
|
||||||
|
REPLACE INTO t1 (id1, val1) VALUES (1, 'a');
|
||||||
|
REPLACE INTO t1 (id1, val1) VALUES (1, 'b') RETURNING *;
|
||||||
|
id1 val1
|
||||||
|
1 b
|
||||||
|
REPLACE INTO t1 (id1, val1) VALUES (1, 'c') RETURNING id1+id1 AS total,
|
||||||
|
id1&&id1, id1|id1,UPPER(val1),f(id1);
|
||||||
|
total id1&&id1 id1|id1 UPPER(val1) f(id1)
|
||||||
|
2 1 1 C 2
|
||||||
|
REPLACE INTO t1(id1,val1) VALUES (1,'d') RETURNING (SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 WHERE id2=1);
|
||||||
|
(SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 WHERE id2=1)
|
||||||
|
a
|
||||||
|
REPLACE INTO t1(id1,val1) VALUES(1,'e') RETURNING (SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 GROUP BY id2 HAVING id2=id2+1);
|
||||||
|
(SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 GROUP BY id2 HAVING id2=id2+1)
|
||||||
|
NULL
|
||||||
|
PREPARE stmt FROM "REPLACE INTO t1 (id1,val1) VALUES (1,'f') RETURNING
|
||||||
|
id1,(SELECT id2 FROM t2 WHERE val2='b')";
|
||||||
|
EXECUTE stmt;
|
||||||
|
id1 (SELECT id2 FROM t2 WHERE val2='b')
|
||||||
|
1 2
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
id1 val1
|
||||||
|
1 f
|
||||||
|
TRUNCATE TABLE t1;
|
||||||
|
#
|
||||||
|
# Multiple values in one replace statement...RETURNING
|
||||||
|
#
|
||||||
|
REPLACE INTO t1 VALUES (1,'a'),(2,'b');
|
||||||
|
REPLACE INTO t1 VALUES (1,'c'),(2,'d') RETURNING *;
|
||||||
|
id1 val1
|
||||||
|
1 c
|
||||||
|
2 d
|
||||||
|
REPLACE INTO t1 VALUES (1,'e'),(2,'f') RETURNING id1+id1 AS total,
|
||||||
|
id1&&id1, id1|id1,UPPER(val1),f(id1);
|
||||||
|
total id1&&id1 id1|id1 UPPER(val1) f(id1)
|
||||||
|
2 1 1 E 2
|
||||||
|
4 1 2 F 4
|
||||||
|
REPLACE INTO t1 VALUES (1,'o'),(2,'p') RETURNING (SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 WHERE id2=1);
|
||||||
|
(SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 WHERE id2=1)
|
||||||
|
a
|
||||||
|
a
|
||||||
|
REPLACE INTO t1 VALUES (1,'q'),(2,'r') RETURNING (SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 GROUP BY id2 HAVING id2=id2+1);
|
||||||
|
(SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 GROUP BY id2 HAVING id2=id2+1)
|
||||||
|
NULL
|
||||||
|
NULL
|
||||||
|
PREPARE stmt FROM "REPLACE INTO t1 VALUES (1,'s'),(2,'t') RETURNING id1,
|
||||||
|
(SELECT id2 FROM t2 WHERE val2='b')";
|
||||||
|
EXECUTE stmt;
|
||||||
|
id1 (SELECT id2 FROM t2 WHERE val2='b')
|
||||||
|
1 2
|
||||||
|
2 2
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
id1 val1
|
||||||
|
1 s
|
||||||
|
2 t
|
||||||
|
TRUNCATE TABLE t1;
|
||||||
|
#
|
||||||
|
# REPLACE...SET...RETURNING
|
||||||
|
#
|
||||||
|
REPLACE INTO t1 SET id1=1, val1 = 'a';
|
||||||
|
REPLACE INTO t1 SET id1=2, val1 = 'b' RETURNING *;
|
||||||
|
id1 val1
|
||||||
|
2 b
|
||||||
|
REPLACE INTO t1 SET id1=3, val1 = 'c' RETURNING id1+id1 AS total,
|
||||||
|
id1&&id1, id1|id1,UPPER(val1),f(id1);
|
||||||
|
total id1&&id1 id1|id1 UPPER(val1) f(id1)
|
||||||
|
6 1 3 C 6
|
||||||
|
REPLACE INTO t1 SET id1=1, val1 = 'i' RETURNING (SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 WHERE id2=1);
|
||||||
|
(SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 WHERE id2=1)
|
||||||
|
a
|
||||||
|
REPLACE INTO t1 SET id1=2, val1='j' RETURNING (SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 GROUP BY id2 HAVING id2=id2+1);
|
||||||
|
(SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 GROUP BY id2 HAVING id2=id2+1)
|
||||||
|
NULL
|
||||||
|
PREPARE stmt FROM "REPLACE INTO t1 SET id1=3, val1='k' RETURNING id1,
|
||||||
|
(SELECT id2 FROM t2 WHERE val2='b')";
|
||||||
|
EXECUTE stmt;
|
||||||
|
id1 (SELECT id2 FROM t2 WHERE val2='b')
|
||||||
|
3 2
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
id1 val1
|
||||||
|
1 i
|
||||||
|
2 j
|
||||||
|
3 k
|
||||||
|
#
|
||||||
|
# REPLACE...SELECT...RETURNING
|
||||||
|
#
|
||||||
|
TRUNCATE TABLE t2;
|
||||||
|
REPLACE INTO t2(id2,val2) SELECT * FROM t1;
|
||||||
|
REPLACE INTO t2 SELECT * FROM t1 WHERE id1=1 RETURNING *;
|
||||||
|
id2 val2
|
||||||
|
1 i
|
||||||
|
REPLACE INTO t2 SELECT * FROM t1 WHERE id1=2 RETURNING id2+id2 AS total,
|
||||||
|
id2&&id2, id2|id2,UPPER(val2),f(id2);
|
||||||
|
total id2&&id2 id2|id2 UPPER(val2) f(id2)
|
||||||
|
4 1 2 J 4
|
||||||
|
REPLACE INTO t2 SELECT * FROM t1 WHERE id1=3 RETURNING (SELECT
|
||||||
|
GROUP_CONCAT(val1) FROM t1 WHERE id1=1);
|
||||||
|
(SELECT
|
||||||
|
GROUP_CONCAT(val1) FROM t1 WHERE id1=1)
|
||||||
|
i
|
||||||
|
REPLACE INTO t2 SELECT * FROM t1 WHERE id1=1 RETURNING (SELECT
|
||||||
|
GROUP_CONCAT(val1) FROM t1 GROUP BY id1 HAVING id1=id1+1);
|
||||||
|
(SELECT
|
||||||
|
GROUP_CONCAT(val1) FROM t1 GROUP BY id1 HAVING id1=id1+1)
|
||||||
|
NULL
|
||||||
|
PREPARE stmt FROM "REPLACE INTO t2 SELECT * FROM t1 WHERE id1=2 RETURNING
|
||||||
|
id2,(SELECT id1 FROM t1 WHERE val1='b')";
|
||||||
|
EXECUTE stmt;
|
||||||
|
id2 (SELECT id1 FROM t1 WHERE val1='b')
|
||||||
|
2 NULL
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
REPLACE INTO t2 SELECT * FROM t1 WHERE id1=3 RETURNING (SELECT id1+id2
|
||||||
|
FROM t1 WHERE id1=1);
|
||||||
|
(SELECT id1+id2
|
||||||
|
FROM t1 WHERE id1=1)
|
||||||
|
4
|
||||||
|
REPLACE INTO t2 SELECT * FROM t1 WHERE id1=1 RETURNING (SELECT id1+id2
|
||||||
|
FROM t2 WHERE id2=0);
|
||||||
|
(SELECT id1+id2
|
||||||
|
FROM t2 WHERE id2=0)
|
||||||
|
NULL
|
||||||
|
SELECT * FROM t2;
|
||||||
|
id2 val2
|
||||||
|
1 i
|
||||||
|
2 j
|
||||||
|
3 k
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP TABLE t2;
|
||||||
|
DROP FUNCTION f;
|
93
mysql-test/main/replace_returning.test
Normal file
93
mysql-test/main/replace_returning.test
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
--echo # Test for REPLACE...RETURNING
|
||||||
|
|
||||||
|
CREATE TABLE t1(id1 INT PRIMARY KEY, val1 VARCHAR(1));
|
||||||
|
CREATE TABLE t2(id2 INT PRIMARY KEY, val2 VARCHAR(1));
|
||||||
|
INSERT INTO t2 VALUES (1,'a'),(2,'b'),(3,'c');
|
||||||
|
|
||||||
|
DELIMITER |;
|
||||||
|
|
||||||
|
CREATE FUNCTION f(arg INT) RETURNS INT
|
||||||
|
BEGIN
|
||||||
|
RETURN (SELECT arg+arg);
|
||||||
|
END|
|
||||||
|
|
||||||
|
DELIMITER ;|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Simple replace statement...RETURNING
|
||||||
|
--echo #
|
||||||
|
REPLACE INTO t1 (id1, val1) VALUES (1, 'a');
|
||||||
|
REPLACE INTO t1 (id1, val1) VALUES (1, 'b') RETURNING *;
|
||||||
|
REPLACE INTO t1 (id1, val1) VALUES (1, 'c') RETURNING id1+id1 AS total,
|
||||||
|
id1&&id1, id1|id1,UPPER(val1),f(id1);
|
||||||
|
REPLACE INTO t1(id1,val1) VALUES (1,'d') RETURNING (SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 WHERE id2=1);
|
||||||
|
REPLACE INTO t1(id1,val1) VALUES(1,'e') RETURNING (SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 GROUP BY id2 HAVING id2=id2+1);
|
||||||
|
PREPARE stmt FROM "REPLACE INTO t1 (id1,val1) VALUES (1,'f') RETURNING
|
||||||
|
id1,(SELECT id2 FROM t2 WHERE val2='b')";
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
TRUNCATE TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Multiple values in one replace statement...RETURNING
|
||||||
|
--echo #
|
||||||
|
REPLACE INTO t1 VALUES (1,'a'),(2,'b');
|
||||||
|
REPLACE INTO t1 VALUES (1,'c'),(2,'d') RETURNING *;
|
||||||
|
REPLACE INTO t1 VALUES (1,'e'),(2,'f') RETURNING id1+id1 AS total,
|
||||||
|
id1&&id1, id1|id1,UPPER(val1),f(id1);
|
||||||
|
REPLACE INTO t1 VALUES (1,'o'),(2,'p') RETURNING (SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 WHERE id2=1);
|
||||||
|
REPLACE INTO t1 VALUES (1,'q'),(2,'r') RETURNING (SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 GROUP BY id2 HAVING id2=id2+1);
|
||||||
|
PREPARE stmt FROM "REPLACE INTO t1 VALUES (1,'s'),(2,'t') RETURNING id1,
|
||||||
|
(SELECT id2 FROM t2 WHERE val2='b')";
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
TRUNCATE TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # REPLACE...SET...RETURNING
|
||||||
|
--echo #
|
||||||
|
REPLACE INTO t1 SET id1=1, val1 = 'a';
|
||||||
|
REPLACE INTO t1 SET id1=2, val1 = 'b' RETURNING *;
|
||||||
|
REPLACE INTO t1 SET id1=3, val1 = 'c' RETURNING id1+id1 AS total,
|
||||||
|
id1&&id1, id1|id1,UPPER(val1),f(id1);
|
||||||
|
REPLACE INTO t1 SET id1=1, val1 = 'i' RETURNING (SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 WHERE id2=1);
|
||||||
|
REPLACE INTO t1 SET id1=2, val1='j' RETURNING (SELECT GROUP_CONCAT(val2)
|
||||||
|
FROM t2 GROUP BY id2 HAVING id2=id2+1);
|
||||||
|
PREPARE stmt FROM "REPLACE INTO t1 SET id1=3, val1='k' RETURNING id1,
|
||||||
|
(SELECT id2 FROM t2 WHERE val2='b')";
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # REPLACE...SELECT...RETURNING
|
||||||
|
--echo #
|
||||||
|
TRUNCATE TABLE t2;
|
||||||
|
REPLACE INTO t2(id2,val2) SELECT * FROM t1;
|
||||||
|
REPLACE INTO t2 SELECT * FROM t1 WHERE id1=1 RETURNING *;
|
||||||
|
REPLACE INTO t2 SELECT * FROM t1 WHERE id1=2 RETURNING id2+id2 AS total,
|
||||||
|
id2&&id2, id2|id2,UPPER(val2),f(id2);
|
||||||
|
REPLACE INTO t2 SELECT * FROM t1 WHERE id1=3 RETURNING (SELECT
|
||||||
|
GROUP_CONCAT(val1) FROM t1 WHERE id1=1);
|
||||||
|
REPLACE INTO t2 SELECT * FROM t1 WHERE id1=1 RETURNING (SELECT
|
||||||
|
GROUP_CONCAT(val1) FROM t1 GROUP BY id1 HAVING id1=id1+1);
|
||||||
|
PREPARE stmt FROM "REPLACE INTO t2 SELECT * FROM t1 WHERE id1=2 RETURNING
|
||||||
|
id2,(SELECT id1 FROM t1 WHERE val1='b')";
|
||||||
|
EXECUTE stmt;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
REPLACE INTO t2 SELECT * FROM t1 WHERE id1=3 RETURNING (SELECT id1+id2
|
||||||
|
FROM t1 WHERE id1=1);
|
||||||
|
REPLACE INTO t2 SELECT * FROM t1 WHERE id1=1 RETURNING (SELECT id1+id2
|
||||||
|
FROM t2 WHERE id2=0);
|
||||||
|
SELECT * FROM t2;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP TABLE t2;
|
||||||
|
DROP FUNCTION f;
|
61
mysql-test/main/replace_returning_datatypes.result
Normal file
61
mysql-test/main/replace_returning_datatypes.result
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
CREATE TABLE t1(num_int1 INT(2) PRIMARY KEY,
|
||||||
|
num_bit1 BIT(8),
|
||||||
|
num_float1 FLOAT(5,2),
|
||||||
|
num_double1 DOUBLE(5,2),
|
||||||
|
char_enum1 ENUM('A','B','C','D'),
|
||||||
|
char_set1 SET('a','b','c','d','e'),
|
||||||
|
str_varchar1 VARCHAR(2),
|
||||||
|
d1 DATE,
|
||||||
|
dt1 DATETIME,
|
||||||
|
ts1 TIMESTAMP,
|
||||||
|
y1 YEAR,
|
||||||
|
b1 BOOL);
|
||||||
|
CREATE TABLE t2(num_int2 INT(2) PRIMARY KEY,
|
||||||
|
num_bit2 BIT(8),
|
||||||
|
num_float2 FLOAT(5,2),
|
||||||
|
num_double2 DOUBLE(5,2),
|
||||||
|
char_enum2 ENUM('A','B','C','D'),
|
||||||
|
char_set2 SET('a','b','c','d','e'),
|
||||||
|
str_varchar2 VARCHAR(2),
|
||||||
|
d2 DATE,
|
||||||
|
dt2 DATETIME,
|
||||||
|
ts2 TIMESTAMP,
|
||||||
|
y2 YEAR,
|
||||||
|
b2 BOOL);
|
||||||
|
#
|
||||||
|
# SIMLPE REPLACE STATEMENT
|
||||||
|
#
|
||||||
|
REPLACE INTO t1(num_int1,num_bit1,num_float1,num_double1,char_enum1,char_set1,
|
||||||
|
str_varchar1, d1,dt1,ts1,y1,b1) VALUES(1,b'1000011', 123.45, 123.55,
|
||||||
|
'A','b,e', 'V','120314',"2012-04-19 13:08:22", '2001-07-22 12:12:12',
|
||||||
|
2012,0) RETURNING *;
|
||||||
|
num_int1 num_bit1 num_float1 num_double1 char_enum1 char_set1 str_varchar1 d1 dt1 ts1 y1 b1
|
||||||
|
1 C 123.45 123.55 A b,e V 2012-03-14 2012-04-19 13:08:22 2001-07-22 12:12:12 2012 0
|
||||||
|
#
|
||||||
|
# MULTIPLE ROWS IN SINGLE STATEMENT
|
||||||
|
#
|
||||||
|
REPLACE INTO t1 VALUES(1,b'1000011', 123.45, 123.55, 'A','b,e', 'V',
|
||||||
|
'120314',"2012-04-19 13:08:22", '2001-07-22 12:12:12',2012,0),(3,b'1000011',
|
||||||
|
123.45, 123.55, 'A','b,e', 'V','120314',"2012-04-19 13:08:22",
|
||||||
|
'2001-07-22 12:12:12',2012,1) RETURNING *;
|
||||||
|
num_int1 num_bit1 num_float1 num_double1 char_enum1 char_set1 str_varchar1 d1 dt1 ts1 y1 b1
|
||||||
|
1 C 123.45 123.55 A b,e V 2012-03-14 2012-04-19 13:08:22 2001-07-22 12:12:12 2012 0
|
||||||
|
3 C 123.45 123.55 A b,e V 2012-03-14 2012-04-19 13:08:22 2001-07-22 12:12:12 2012 1
|
||||||
|
#
|
||||||
|
# REPLACE...SET...RETURNING
|
||||||
|
#
|
||||||
|
REPLACE INTO t1 SET num_int1=1,num_bit1=b'1000011',num_float1=124.67,
|
||||||
|
num_double1=231.12,char_enum1='B',char_set1='a,d,e',
|
||||||
|
str_varchar1='AB',d1='120314',dt1="2012-04-19 13:08:22",
|
||||||
|
ts1='2001-07-22 12:12:1',y1=2014,b1=1 RETURNING *;
|
||||||
|
num_int1 num_bit1 num_float1 num_double1 char_enum1 char_set1 str_varchar1 d1 dt1 ts1 y1 b1
|
||||||
|
1 C 124.67 231.12 B a,d,e AB 2012-03-14 2012-04-19 13:08:22 2001-07-22 12:12:01 2014 1
|
||||||
|
#
|
||||||
|
# REPLACE...SELECT...RETURNING
|
||||||
|
#
|
||||||
|
REPLACE INTO t2 SELECT * FROM t1 RETURNING *;
|
||||||
|
num_int2 num_bit2 num_float2 num_double2 char_enum2 char_set2 str_varchar2 d2 dt2 ts2 y2 b2
|
||||||
|
1 C 124.67 231.12 B a,d,e AB 2012-03-14 2012-04-19 13:08:22 2001-07-22 12:12:01 2014 1
|
||||||
|
3 C 123.45 123.55 A b,e V 2012-03-14 2012-04-19 13:08:22 2001-07-22 12:12:12 2012 1
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP TABLE t2;
|
66
mysql-test/main/replace_returning_datatypes.test
Normal file
66
mysql-test/main/replace_returning_datatypes.test
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#Test for checking all dataypes are returned
|
||||||
|
|
||||||
|
CREATE TABLE t1(num_int1 INT(2) PRIMARY KEY,
|
||||||
|
num_bit1 BIT(8),
|
||||||
|
num_float1 FLOAT(5,2),
|
||||||
|
num_double1 DOUBLE(5,2),
|
||||||
|
char_enum1 ENUM('A','B','C','D'),
|
||||||
|
char_set1 SET('a','b','c','d','e'),
|
||||||
|
str_varchar1 VARCHAR(2),
|
||||||
|
d1 DATE,
|
||||||
|
dt1 DATETIME,
|
||||||
|
ts1 TIMESTAMP,
|
||||||
|
y1 YEAR,
|
||||||
|
b1 BOOL);
|
||||||
|
|
||||||
|
CREATE TABLE t2(num_int2 INT(2) PRIMARY KEY,
|
||||||
|
num_bit2 BIT(8),
|
||||||
|
num_float2 FLOAT(5,2),
|
||||||
|
num_double2 DOUBLE(5,2),
|
||||||
|
char_enum2 ENUM('A','B','C','D'),
|
||||||
|
char_set2 SET('a','b','c','d','e'),
|
||||||
|
str_varchar2 VARCHAR(2),
|
||||||
|
d2 DATE,
|
||||||
|
dt2 DATETIME,
|
||||||
|
ts2 TIMESTAMP,
|
||||||
|
y2 YEAR,
|
||||||
|
b2 BOOL);
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # SIMLPE REPLACE STATEMENT
|
||||||
|
--echo #
|
||||||
|
REPLACE INTO t1(num_int1,num_bit1,num_float1,num_double1,char_enum1,char_set1,
|
||||||
|
str_varchar1, d1,dt1,ts1,y1,b1) VALUES(1,b'1000011', 123.45, 123.55,
|
||||||
|
'A','b,e', 'V','120314',"2012-04-19 13:08:22", '2001-07-22 12:12:12',
|
||||||
|
2012,0) RETURNING *;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MULTIPLE ROWS IN SINGLE STATEMENT
|
||||||
|
--echo #
|
||||||
|
REPLACE INTO t1 VALUES(1,b'1000011', 123.45, 123.55, 'A','b,e', 'V',
|
||||||
|
'120314',"2012-04-19 13:08:22", '2001-07-22 12:12:12',2012,0),(3,b'1000011',
|
||||||
|
123.45, 123.55, 'A','b,e', 'V','120314',"2012-04-19 13:08:22",
|
||||||
|
'2001-07-22 12:12:12',2012,1) RETURNING *;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # REPLACE...SET...RETURNING
|
||||||
|
--echo #
|
||||||
|
REPLACE INTO t1 SET num_int1=1,num_bit1=b'1000011',num_float1=124.67,
|
||||||
|
num_double1=231.12,char_enum1='B',char_set1='a,d,e',
|
||||||
|
str_varchar1='AB',d1='120314',dt1="2012-04-19 13:08:22",
|
||||||
|
ts1='2001-07-22 12:12:1',y1=2014,b1=1 RETURNING *;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # REPLACE...SELECT...RETURNING
|
||||||
|
--echo #
|
||||||
|
REPLACE INTO t2 SELECT * FROM t1 RETURNING *;
|
||||||
|
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP TABLE t2;
|
69
mysql-test/main/replace_returning_err.result
Normal file
69
mysql-test/main/replace_returning_err.result
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
CREATE TABLE t1(id1 INT PRIMARY KEY, val1 VARCHAR(1));
|
||||||
|
CREATE TABLE t2(id2 INT PRIMARY KEY, val2 VARCHAR(1));
|
||||||
|
INSERT INTO t1 VALUES(1, 'a'), (2, 'b'), (3, 'c');
|
||||||
|
#
|
||||||
|
# SIMLPE REPLACE STATEMENT
|
||||||
|
#
|
||||||
|
REPLACE INTO t2(id2, val2) VALUES(1, 'a') RETURNING id1;
|
||||||
|
ERROR 42S22: Unknown column 'id1' in 'field list'
|
||||||
|
REPLACE INTO t2(id2, val2) values(2, 'b') RETURNING SUM(id2);
|
||||||
|
ERROR HY000: Invalid use of group function
|
||||||
|
REPLACE INTO t2(id2, val2) VALUES(3, 'c') RETURNING(SELECT id1 FROM t1);
|
||||||
|
ERROR 21000: Subquery returns more than 1 row
|
||||||
|
REPLACE INTO t2(id2, val2) VALUES(4, 'd') RETURNING(SELECT* FROM t1);
|
||||||
|
ERROR 21000: Operand should contain 1 column(s)
|
||||||
|
REPLACE INTO t2(id2, val2) VALUES(4, 'd') RETURNING(SELECT* FROM t2);
|
||||||
|
ERROR 21000: Operand should contain 1 column(s)
|
||||||
|
REPLACE INTO t2(id2, val2) VALUES(5, 'f') RETURNING(SELECT id2 FROM t2);
|
||||||
|
ERROR HY000: Table 't2' is specified twice, both as a target for 'INSERT' and as a separate source for data
|
||||||
|
#
|
||||||
|
# Multiple rows in single replace statement
|
||||||
|
#
|
||||||
|
REPLACE INTO t2 VALUES(1, 'a'), (2, 'b') RETURNING id1;
|
||||||
|
ERROR 42S22: Unknown column 'id1' in 'field list'
|
||||||
|
REPLACE INTO t2 VALUES(3, 'c'), (4, 'd') RETURNING MAX(id2);
|
||||||
|
ERROR HY000: Invalid use of group function
|
||||||
|
REPLACE INTO t2 VALUES(5, 'c'), (6, 'f') RETURNING(SELECT id1 FROM t1);
|
||||||
|
ERROR 21000: Subquery returns more than 1 row
|
||||||
|
REPLACE INTO t2 VALUES(7, 'g'), (8, 'h') RETURNING(SELECT* FROM t1);
|
||||||
|
ERROR 21000: Operand should contain 1 column(s)
|
||||||
|
REPLACE INTO t2 VALUES(9, 'g'), (10, 'h') RETURNING(SELECT* FROM t2);
|
||||||
|
ERROR 21000: Operand should contain 1 column(s)
|
||||||
|
REPLACE INTO t2 VALUES(13, 'f'), (14, 'g') RETURNING(SELECT id2 FROM t2);
|
||||||
|
ERROR HY000: Table 't2' is specified twice, both as a target for 'INSERT' and as a separate source for data
|
||||||
|
#
|
||||||
|
# REPLACE ... SET
|
||||||
|
#
|
||||||
|
REPLACE INTO t2 SET id2 = 1, val2 = 'a' RETURNING id1;
|
||||||
|
ERROR 42S22: Unknown column 'id1' in 'field list'
|
||||||
|
REPLACE INTO t2 SET id2 = 2, val2 = 'b' RETURNING COUNT(id2);
|
||||||
|
ERROR HY000: Invalid use of group function
|
||||||
|
REPLACE INTO t2 SET id2 = 3, val2 = 'c' RETURNING(SELECT id1 FROM t1);
|
||||||
|
ERROR 21000: Subquery returns more than 1 row
|
||||||
|
REPLACE INTO t2 SET id2 = 4, val2 = 'd' RETURNING(SELECT * FROM t1);
|
||||||
|
ERROR 21000: Operand should contain 1 column(s)
|
||||||
|
REPLACE INTO t2 SET id2 = 4, val2 = 'd' RETURNING(SELECT * FROM t2);
|
||||||
|
ERROR 21000: Operand should contain 1 column(s)
|
||||||
|
REPLACE INTO t2 SET id2 = 5, val2 = 'f' RETURNING(SELECT id2 FROM t2);
|
||||||
|
ERROR HY000: Table 't2' is specified twice, both as a target for 'INSERT' and as a separate source for data
|
||||||
|
#
|
||||||
|
# REPLACE...SELECT
|
||||||
|
#
|
||||||
|
REPLACE INTO t2(id2, val2) SELECT* FROM t1 WHERE id1 = 1 RETURNING id1;
|
||||||
|
ERROR 42S22: Unknown column 'id1' in 'field list'
|
||||||
|
REPLACE INTO t2(id2, val2) SELECT* FROM t1 WHERE id1 = 2 RETURNING MAX(id2);
|
||||||
|
ERROR HY000: Invalid use of group function
|
||||||
|
REPLACE INTO t2(id2, val2) SELECT* FROM t1 WHERE id1 = 2 RETURNING(SELECT id1
|
||||||
|
FROM t1);
|
||||||
|
ERROR 21000: Subquery returns more than 1 row
|
||||||
|
REPLACE INTO t2(id2, val2) SELECT* FROM t1 WHERE id1 = 2 RETURNING(SELECT *
|
||||||
|
FROM t1);
|
||||||
|
ERROR 21000: Operand should contain 1 column(s)
|
||||||
|
REPLACE INTO t2(id2, val2) SELECT* FROM t1 WHERE id1 = 2 RETURNING(SELECT *
|
||||||
|
FROM t2);
|
||||||
|
ERROR 21000: Operand should contain 1 column(s)
|
||||||
|
REPLACE INTO t2(id2, val2) SELECT* FROM t1 WHERE id1 = 2 RETURNING(SELECT id2
|
||||||
|
FROM t2);
|
||||||
|
ERROR 21000: Subquery returns more than 1 row
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP TABLE t2;
|
86
mysql-test/main/replace_returning_err.test
Normal file
86
mysql-test/main/replace_returning_err.test
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#
|
||||||
|
# Test for checking error message for REPLACE...RETURNING
|
||||||
|
#
|
||||||
|
|
||||||
|
#REPLACE INTO <table> ... RETURNING <not existing col>
|
||||||
|
#REPLACE INTO <table> ... RETURNING <expr with aggr function>
|
||||||
|
#REPLACE INTO ... RETURNING subquery with more than 1 row
|
||||||
|
#REPLACE INTO ... RETURNING operand should contain 1 colunm(s)
|
||||||
|
#REPLACE INTO ... RETURNING operand should contain 1 colunm(s)
|
||||||
|
#REPLACE INTO ... SELECT...RETURNING < SELECT <colname> FROM <REPLACE TABLE>
|
||||||
|
|
||||||
|
CREATE TABLE t1(id1 INT PRIMARY KEY, val1 VARCHAR(1));
|
||||||
|
CREATE TABLE t2(id2 INT PRIMARY KEY, val2 VARCHAR(1));
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES(1, 'a'), (2, 'b'), (3, 'c');
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # SIMLPE REPLACE STATEMENT
|
||||||
|
--echo #
|
||||||
|
--error ER_BAD_FIELD_ERROR
|
||||||
|
REPLACE INTO t2(id2, val2) VALUES(1, 'a') RETURNING id1;
|
||||||
|
--error ER_INVALID_GROUP_FUNC_USE
|
||||||
|
REPLACE INTO t2(id2, val2) values(2, 'b') RETURNING SUM(id2);
|
||||||
|
--error ER_SUBQUERY_NO_1_ROW
|
||||||
|
REPLACE INTO t2(id2, val2) VALUES(3, 'c') RETURNING(SELECT id1 FROM t1);
|
||||||
|
--error ER_OPERAND_COLUMNS
|
||||||
|
REPLACE INTO t2(id2, val2) VALUES(4, 'd') RETURNING(SELECT* FROM t1);
|
||||||
|
--error ER_OPERAND_COLUMNS
|
||||||
|
REPLACE INTO t2(id2, val2) VALUES(4, 'd') RETURNING(SELECT* FROM t2);
|
||||||
|
--error ER_UPDATE_TABLE_USED
|
||||||
|
REPLACE INTO t2(id2, val2) VALUES(5, 'f') RETURNING(SELECT id2 FROM t2);
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Multiple rows in single replace statement
|
||||||
|
--echo #
|
||||||
|
--error ER_BAD_FIELD_ERROR
|
||||||
|
REPLACE INTO t2 VALUES(1, 'a'), (2, 'b') RETURNING id1;
|
||||||
|
--error ER_INVALID_GROUP_FUNC_USE
|
||||||
|
REPLACE INTO t2 VALUES(3, 'c'), (4, 'd') RETURNING MAX(id2);
|
||||||
|
--error ER_SUBQUERY_NO_1_ROW
|
||||||
|
REPLACE INTO t2 VALUES(5, 'c'), (6, 'f') RETURNING(SELECT id1 FROM t1);
|
||||||
|
--error ER_OPERAND_COLUMNS
|
||||||
|
REPLACE INTO t2 VALUES(7, 'g'), (8, 'h') RETURNING(SELECT* FROM t1);
|
||||||
|
--error ER_OPERAND_COLUMNS
|
||||||
|
REPLACE INTO t2 VALUES(9, 'g'), (10, 'h') RETURNING(SELECT* FROM t2);
|
||||||
|
--error ER_UPDATE_TABLE_USED
|
||||||
|
REPLACE INTO t2 VALUES(13, 'f'), (14, 'g') RETURNING(SELECT id2 FROM t2);
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # REPLACE ... SET
|
||||||
|
--echo #
|
||||||
|
--error ER_BAD_FIELD_ERROR
|
||||||
|
REPLACE INTO t2 SET id2 = 1, val2 = 'a' RETURNING id1;
|
||||||
|
--error ER_INVALID_GROUP_FUNC_USE
|
||||||
|
REPLACE INTO t2 SET id2 = 2, val2 = 'b' RETURNING COUNT(id2);
|
||||||
|
--error ER_SUBQUERY_NO_1_ROW
|
||||||
|
REPLACE INTO t2 SET id2 = 3, val2 = 'c' RETURNING(SELECT id1 FROM t1);
|
||||||
|
--error ER_OPERAND_COLUMNS
|
||||||
|
REPLACE INTO t2 SET id2 = 4, val2 = 'd' RETURNING(SELECT * FROM t1);
|
||||||
|
--error ER_OPERAND_COLUMNS
|
||||||
|
REPLACE INTO t2 SET id2 = 4, val2 = 'd' RETURNING(SELECT * FROM t2);
|
||||||
|
--error ER_UPDATE_TABLE_USED
|
||||||
|
REPLACE INTO t2 SET id2 = 5, val2 = 'f' RETURNING(SELECT id2 FROM t2);
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # REPLACE...SELECT
|
||||||
|
--echo #
|
||||||
|
--error ER_BAD_FIELD_ERROR
|
||||||
|
REPLACE INTO t2(id2, val2) SELECT* FROM t1 WHERE id1 = 1 RETURNING id1;
|
||||||
|
--error ER_INVALID_GROUP_FUNC_USE
|
||||||
|
REPLACE INTO t2(id2, val2) SELECT* FROM t1 WHERE id1 = 2 RETURNING MAX(id2);
|
||||||
|
--error ER_SUBQUERY_NO_1_ROW
|
||||||
|
REPLACE INTO t2(id2, val2) SELECT* FROM t1 WHERE id1 = 2 RETURNING(SELECT id1
|
||||||
|
FROM t1);
|
||||||
|
--error ER_OPERAND_COLUMNS
|
||||||
|
REPLACE INTO t2(id2, val2) SELECT* FROM t1 WHERE id1 = 2 RETURNING(SELECT *
|
||||||
|
FROM t1);
|
||||||
|
--error ER_OPERAND_COLUMNS
|
||||||
|
REPLACE INTO t2(id2, val2) SELECT* FROM t1 WHERE id1 = 2 RETURNING(SELECT *
|
||||||
|
FROM t2);
|
||||||
|
--error ER_SUBQUERY_NO_1_ROW
|
||||||
|
REPLACE INTO t2(id2, val2) SELECT* FROM t1 WHERE id1 = 2 RETURNING(SELECT id2
|
||||||
|
FROM t2);
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP TABLE t2;
|
@ -7431,6 +7431,7 @@ SHOW_VAR status_vars[]= {
|
|||||||
{"Feature_dynamic_columns", (char*) offsetof(STATUS_VAR, feature_dynamic_columns), SHOW_LONG_STATUS},
|
{"Feature_dynamic_columns", (char*) offsetof(STATUS_VAR, feature_dynamic_columns), SHOW_LONG_STATUS},
|
||||||
{"Feature_fulltext", (char*) offsetof(STATUS_VAR, feature_fulltext), SHOW_LONG_STATUS},
|
{"Feature_fulltext", (char*) offsetof(STATUS_VAR, feature_fulltext), SHOW_LONG_STATUS},
|
||||||
{"Feature_gis", (char*) offsetof(STATUS_VAR, feature_gis), SHOW_LONG_STATUS},
|
{"Feature_gis", (char*) offsetof(STATUS_VAR, feature_gis), SHOW_LONG_STATUS},
|
||||||
|
{"Feature_insert_returning", (char*)offsetof(STATUS_VAR, feature_insert_returning), SHOW_LONG_STATUS},
|
||||||
{"Feature_invisible_columns", (char*) offsetof(STATUS_VAR, feature_invisible_columns), SHOW_LONG_STATUS},
|
{"Feature_invisible_columns", (char*) offsetof(STATUS_VAR, feature_invisible_columns), SHOW_LONG_STATUS},
|
||||||
{"Feature_json", (char*) offsetof(STATUS_VAR, feature_json), SHOW_LONG_STATUS},
|
{"Feature_json", (char*) offsetof(STATUS_VAR, feature_json), SHOW_LONG_STATUS},
|
||||||
{"Feature_locale", (char*) offsetof(STATUS_VAR, feature_locale), SHOW_LONG_STATUS},
|
{"Feature_locale", (char*) offsetof(STATUS_VAR, feature_locale), SHOW_LONG_STATUS},
|
||||||
|
@ -7631,6 +7631,26 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Perform checks like all given fields exists, if exists fill struct with
|
||||||
|
current data and expand all '*' in given fields for LEX::returning.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
thd Thread handler
|
||||||
|
table_list Global/local table list
|
||||||
|
*/
|
||||||
|
|
||||||
|
int setup_returning_fields(THD* thd, TABLE_LIST* table_list)
|
||||||
|
{
|
||||||
|
if (!thd->lex->has_returning())
|
||||||
|
return 0;
|
||||||
|
return setup_wild(thd, table_list, thd->lex->returning()->item_list, NULL,
|
||||||
|
thd->lex->returning())
|
||||||
|
|| setup_fields(thd, Ref_ptr_array(), thd->lex->returning()->item_list,
|
||||||
|
MARK_COLUMNS_READ, NULL, NULL, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
make list of leaves of join table tree
|
make list of leaves of join table tree
|
||||||
|
|
||||||
|
@ -176,6 +176,7 @@ void make_leaves_list(THD *thd, List<TABLE_LIST> &list, TABLE_LIST *tables,
|
|||||||
bool full_table_list, TABLE_LIST *boundary);
|
bool full_table_list, TABLE_LIST *boundary);
|
||||||
int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
|
int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
|
||||||
List<Item> *sum_func_list, SELECT_LEX *sl);
|
List<Item> *sum_func_list, SELECT_LEX *sl);
|
||||||
|
int setup_returning_fields(THD* thd, TABLE_LIST* table_list);
|
||||||
bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array,
|
bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array,
|
||||||
List<Item> &item, enum_column_usage column_usage,
|
List<Item> &item, enum_column_usage column_usage,
|
||||||
List<Item> *sum_func_list, List<Item> *pre_fix,
|
List<Item> *sum_func_list, List<Item> *pre_fix,
|
||||||
|
@ -878,6 +878,7 @@ typedef struct system_status_var
|
|||||||
ulong feature_system_versioning; /* +1 opening a table WITH SYSTEM VERSIONING */
|
ulong feature_system_versioning; /* +1 opening a table WITH SYSTEM VERSIONING */
|
||||||
ulong feature_application_time_periods;
|
ulong feature_application_time_periods;
|
||||||
/* +1 opening a table with application-time period */
|
/* +1 opening a table with application-time period */
|
||||||
|
ulong feature_insert_returning; /* +1 when INSERT...RETURNING is used */
|
||||||
ulong feature_timezone; /* +1 when XPATH is used */
|
ulong feature_timezone; /* +1 when XPATH is used */
|
||||||
ulong feature_trigger; /* +1 opening a table with triggers */
|
ulong feature_trigger; /* +1 opening a table with triggers */
|
||||||
ulong feature_xml; /* +1 when XPATH is used */
|
ulong feature_xml; /* +1 when XPATH is used */
|
||||||
@ -5517,16 +5518,17 @@ public:
|
|||||||
|
|
||||||
class select_insert :public select_result_interceptor {
|
class select_insert :public select_result_interceptor {
|
||||||
public:
|
public:
|
||||||
|
select_result *sel_result;
|
||||||
TABLE_LIST *table_list;
|
TABLE_LIST *table_list;
|
||||||
TABLE *table;
|
TABLE *table;
|
||||||
List<Item> *fields;
|
List<Item> *fields;
|
||||||
ulonglong autoinc_value_of_last_inserted_row; // autogenerated or not
|
ulonglong autoinc_value_of_last_inserted_row; // autogenerated or not
|
||||||
COPY_INFO info;
|
COPY_INFO info;
|
||||||
bool insert_into_view;
|
bool insert_into_view;
|
||||||
select_insert(THD *thd_arg, TABLE_LIST *table_list_par,
|
select_insert(THD *thd_arg, TABLE_LIST *table_list_par, TABLE *table_par,
|
||||||
TABLE *table_par, List<Item> *fields_par,
|
List<Item> *fields_par, List<Item> *update_fields,
|
||||||
List<Item> *update_fields, List<Item> *update_values,
|
List<Item> *update_values, enum_duplicates duplic,
|
||||||
enum_duplicates duplic, bool ignore);
|
bool ignore, select_result *sel_ret_list);
|
||||||
~select_insert();
|
~select_insert();
|
||||||
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
||||||
virtual int prepare2(JOIN *join);
|
virtual int prepare2(JOIN *join);
|
||||||
@ -5562,7 +5564,7 @@ public:
|
|||||||
List<Item> &select_fields,enum_duplicates duplic, bool ignore,
|
List<Item> &select_fields,enum_duplicates duplic, bool ignore,
|
||||||
TABLE_LIST *select_tables_arg):
|
TABLE_LIST *select_tables_arg):
|
||||||
select_insert(thd_arg, table_arg, NULL, &select_fields, 0, 0, duplic,
|
select_insert(thd_arg, table_arg, NULL, &select_fields, 0, 0, duplic,
|
||||||
ignore),
|
ignore, NULL),
|
||||||
create_table(table_arg),
|
create_table(table_arg),
|
||||||
create_info(create_info_par),
|
create_info(create_info_par),
|
||||||
select_tables(select_tables_arg),
|
select_tables(select_tables_arg),
|
||||||
|
@ -319,10 +319,10 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||||||
ORDER *order= (ORDER *) ((order_list && order_list->elements) ?
|
ORDER *order= (ORDER *) ((order_list && order_list->elements) ?
|
||||||
order_list->first : NULL);
|
order_list->first : NULL);
|
||||||
SELECT_LEX *select_lex= thd->lex->first_select_lex();
|
SELECT_LEX *select_lex= thd->lex->first_select_lex();
|
||||||
|
SELECT_LEX *returning= thd->lex->has_returning() ? thd->lex->returning() : 0;
|
||||||
killed_state killed_status= NOT_KILLED;
|
killed_state killed_status= NOT_KILLED;
|
||||||
THD::enum_binlog_query_type query_type= THD::ROW_QUERY_TYPE;
|
THD::enum_binlog_query_type query_type= THD::ROW_QUERY_TYPE;
|
||||||
bool binlog_is_row;
|
bool binlog_is_row;
|
||||||
bool with_select= !select_lex->item_list.is_empty();
|
|
||||||
Explain_delete *explain;
|
Explain_delete *explain;
|
||||||
Delete_plan query_plan(thd->mem_root);
|
Delete_plan query_plan(thd->mem_root);
|
||||||
Unique * deltempfile= NULL;
|
Unique * deltempfile= NULL;
|
||||||
@ -385,16 +385,14 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||||||
query_plan.select_lex= thd->lex->first_select_lex();
|
query_plan.select_lex= thd->lex->first_select_lex();
|
||||||
query_plan.table= table;
|
query_plan.table= table;
|
||||||
|
|
||||||
if (mysql_prepare_delete(thd, table_list, select_lex->with_wild,
|
if (mysql_prepare_delete(thd, table_list, &conds, &delete_while_scanning))
|
||||||
select_lex->item_list, &conds,
|
|
||||||
&delete_while_scanning))
|
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
if (delete_history)
|
if (delete_history)
|
||||||
table->vers_write= false;
|
table->vers_write= false;
|
||||||
|
|
||||||
if (with_select)
|
if (returning)
|
||||||
(void) result->prepare(select_lex->item_list, NULL);
|
(void) result->prepare(returning->item_list, NULL);
|
||||||
|
|
||||||
if (thd->lex->current_select->first_cond_optimization)
|
if (thd->lex->current_select->first_cond_optimization)
|
||||||
{
|
{
|
||||||
@ -459,9 +457,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||||||
|
|
||||||
has_triggers= table->triggers && table->triggers->has_delete_triggers();
|
has_triggers= table->triggers && table->triggers->has_delete_triggers();
|
||||||
|
|
||||||
if (!with_select && !using_limit && const_cond_result &&
|
if (!returning && !using_limit && const_cond_result &&
|
||||||
(!thd->is_current_stmt_binlog_format_row() &&
|
(!thd->is_current_stmt_binlog_format_row() && !has_triggers)
|
||||||
!has_triggers)
|
|
||||||
&& !table->versioned(VERS_TIMESTAMP) && !table_list->has_period())
|
&& !table->versioned(VERS_TIMESTAMP) && !table_list->has_period())
|
||||||
{
|
{
|
||||||
/* Update the table->file->stats.records number */
|
/* Update the table->file->stats.records number */
|
||||||
@ -632,7 +629,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if ((table->file->ha_table_flags() & HA_CAN_DIRECT_UPDATE_AND_DELETE) &&
|
if ((table->file->ha_table_flags() & HA_CAN_DIRECT_UPDATE_AND_DELETE) &&
|
||||||
!has_triggers && !binlog_is_row && !with_select &&
|
!has_triggers && !binlog_is_row && !returning &&
|
||||||
!table_list->has_period())
|
!table_list->has_period())
|
||||||
{
|
{
|
||||||
table->mark_columns_needed_for_delete();
|
table->mark_columns_needed_for_delete();
|
||||||
@ -682,7 +679,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||||||
DELETE ... RETURNING we can't, because the RETURNING part may have
|
DELETE ... RETURNING we can't, because the RETURNING part may have
|
||||||
a subquery in it)
|
a subquery in it)
|
||||||
*/
|
*/
|
||||||
if (!with_select)
|
if (!returning)
|
||||||
free_underlaid_joins(thd, select_lex);
|
free_underlaid_joins(thd, select_lex);
|
||||||
select= 0;
|
select= 0;
|
||||||
}
|
}
|
||||||
@ -717,11 +714,10 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||||||
!table->prepare_triggers_for_delete_stmt_or_event())
|
!table->prepare_triggers_for_delete_stmt_or_event())
|
||||||
will_batch= !table->file->start_bulk_delete();
|
will_batch= !table->file->start_bulk_delete();
|
||||||
|
|
||||||
if (with_select)
|
if (returning)
|
||||||
{
|
{
|
||||||
if (unlikely(result->send_result_set_metadata(select_lex->item_list,
|
if (result->send_result_set_metadata(returning->item_list,
|
||||||
Protocol::SEND_NUM_ROWS |
|
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
|
||||||
Protocol::SEND_EOF)))
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -804,7 +800,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// no LIMIT / OFFSET
|
// no LIMIT / OFFSET
|
||||||
if (with_select && result->send_data(select_lex->item_list) < 0)
|
if (returning && result->send_data(returning->item_list) < 0)
|
||||||
{
|
{
|
||||||
error=1;
|
error=1;
|
||||||
break;
|
break;
|
||||||
@ -948,7 +944,7 @@ cleanup:
|
|||||||
if (thd->lex->analyze_stmt)
|
if (thd->lex->analyze_stmt)
|
||||||
goto send_nothing_and_leave;
|
goto send_nothing_and_leave;
|
||||||
|
|
||||||
if (with_select)
|
if (returning)
|
||||||
result->send_eof();
|
result->send_eof();
|
||||||
else
|
else
|
||||||
my_ok(thd, deleted);
|
my_ok(thd, deleted);
|
||||||
@ -998,16 +994,13 @@ got_error:
|
|||||||
mysql_prepare_delete()
|
mysql_prepare_delete()
|
||||||
thd - thread handler
|
thd - thread handler
|
||||||
table_list - global/local table list
|
table_list - global/local table list
|
||||||
wild_num - number of wildcards used in optional SELECT clause
|
|
||||||
field_list - list of items in optional SELECT clause
|
|
||||||
conds - conditions
|
conds - conditions
|
||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
FALSE OK
|
FALSE OK
|
||||||
TRUE error
|
TRUE error
|
||||||
*/
|
*/
|
||||||
int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list,
|
int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds,
|
||||||
uint wild_num, List<Item> &field_list, Item **conds,
|
|
||||||
bool *delete_while_scanning)
|
bool *delete_while_scanning)
|
||||||
{
|
{
|
||||||
Item *fake_conds= 0;
|
Item *fake_conds= 0;
|
||||||
@ -1017,11 +1010,8 @@ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list,
|
|||||||
|
|
||||||
*delete_while_scanning= true;
|
*delete_while_scanning= true;
|
||||||
thd->lex->allow_sum_func.clear_all();
|
thd->lex->allow_sum_func.clear_all();
|
||||||
if (setup_tables_and_check_access(thd,
|
if (setup_tables_and_check_access(thd, &select_lex->context,
|
||||||
&thd->lex->first_select_lex()->context,
|
&select_lex->top_join_list, table_list,
|
||||||
&thd->lex->first_select_lex()->
|
|
||||||
top_join_list,
|
|
||||||
table_list,
|
|
||||||
select_lex->leaf_tables, FALSE,
|
select_lex->leaf_tables, FALSE,
|
||||||
DELETE_ACL, SELECT_ACL, TRUE))
|
DELETE_ACL, SELECT_ACL, TRUE))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
@ -1049,9 +1039,7 @@ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list,
|
|||||||
DBUG_RETURN(true);
|
DBUG_RETURN(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((wild_num && setup_wild(thd, table_list, field_list, NULL, select_lex)) ||
|
if (setup_returning_fields(thd, table_list) ||
|
||||||
setup_fields(thd, Ref_ptr_array(),
|
|
||||||
field_list, MARK_COLUMNS_READ, NULL, NULL, 0) ||
|
|
||||||
setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
|
setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
|
||||||
setup_ftfuncs(select_lex))
|
setup_ftfuncs(select_lex))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
@ -26,8 +26,7 @@ class select_result;
|
|||||||
typedef class Item COND;
|
typedef class Item COND;
|
||||||
template <typename T> class SQL_I_List;
|
template <typename T> class SQL_I_List;
|
||||||
|
|
||||||
int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list,
|
int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds,
|
||||||
uint wild_num, List<Item> &field_list, Item **conds,
|
|
||||||
bool *delete_while_scanning);
|
bool *delete_while_scanning);
|
||||||
bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
||||||
SQL_I_List<ORDER> *order, ha_rows rows,
|
SQL_I_List<ORDER> *order, ha_rows rows,
|
||||||
|
@ -677,18 +677,19 @@ Field **TABLE::field_to_fill()
|
|||||||
/**
|
/**
|
||||||
INSERT statement implementation
|
INSERT statement implementation
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
mysql_insert()
|
||||||
|
result NULL if the insert is not outputing results
|
||||||
|
via 'RETURNING' clause.
|
||||||
|
|
||||||
@note Like implementations of other DDL/DML in MySQL, this function
|
@note Like implementations of other DDL/DML in MySQL, this function
|
||||||
relies on the caller to close the thread tables. This is done in the
|
relies on the caller to close the thread tables. This is done in the
|
||||||
end of dispatch_command().
|
end of dispatch_command().
|
||||||
*/
|
*/
|
||||||
|
bool mysql_insert(THD *thd, TABLE_LIST *table_list,
|
||||||
bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
List<Item> &fields, List<List_item> &values_list,
|
||||||
List<Item> &fields,
|
List<Item> &update_fields, List<Item> &update_values,
|
||||||
List<List_item> &values_list,
|
enum_duplicates duplic, bool ignore, select_result *result)
|
||||||
List<Item> &update_fields,
|
|
||||||
List<Item> &update_values,
|
|
||||||
enum_duplicates duplic,
|
|
||||||
bool ignore)
|
|
||||||
{
|
{
|
||||||
bool retval= true;
|
bool retval= true;
|
||||||
int error, res;
|
int error, res;
|
||||||
@ -707,6 +708,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||||||
List_item *values;
|
List_item *values;
|
||||||
Name_resolution_context *context;
|
Name_resolution_context *context;
|
||||||
Name_resolution_context_state ctx_state;
|
Name_resolution_context_state ctx_state;
|
||||||
|
SELECT_LEX *returning= thd->lex->has_returning() ? thd->lex->returning() : 0;
|
||||||
|
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
char *query= thd->query();
|
char *query= thd->query();
|
||||||
/*
|
/*
|
||||||
@ -765,6 +768,9 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||||||
&unused_conds, FALSE))
|
&unused_conds, FALSE))
|
||||||
goto abort;
|
goto abort;
|
||||||
|
|
||||||
|
/* Prepares LEX::returing_list if it is not empty */
|
||||||
|
if (returning)
|
||||||
|
result->prepare(returning->item_list, NULL);
|
||||||
/* mysql_prepare_insert sets table_list->table if it was not set */
|
/* mysql_prepare_insert sets table_list->table if it was not set */
|
||||||
table= table_list->table;
|
table= table_list->table;
|
||||||
|
|
||||||
@ -934,6 +940,16 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||||||
goto values_loop_end;
|
goto values_loop_end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
If statement returns result set, we need to send the result set metadata
|
||||||
|
to the client so that it knows that it has to expect an EOF or ERROR.
|
||||||
|
At this point we have all the required information to send the result set
|
||||||
|
metadata.
|
||||||
|
*/
|
||||||
|
if (returning &&
|
||||||
|
result->send_result_set_metadata(returning->item_list,
|
||||||
|
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
|
||||||
|
goto values_loop_end;
|
||||||
|
|
||||||
THD_STAGE_INFO(thd, stage_update);
|
THD_STAGE_INFO(thd, stage_update);
|
||||||
do
|
do
|
||||||
@ -1063,6 +1079,18 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||||||
error=write_record(thd, table ,&info);
|
error=write_record(thd, table ,&info);
|
||||||
if (unlikely(error))
|
if (unlikely(error))
|
||||||
break;
|
break;
|
||||||
|
/*
|
||||||
|
We send the row after writing it to the table so that the
|
||||||
|
correct values are sent to the client. Otherwise it won't show
|
||||||
|
autoinc values (generated inside the handler::ha_write()) and
|
||||||
|
values updated in ON DUPLICATE KEY UPDATE (handled inside
|
||||||
|
write_record()).
|
||||||
|
*/
|
||||||
|
if (returning && result->send_data(returning->item_list) < 0)
|
||||||
|
{
|
||||||
|
error= 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
thd->get_stmt_da()->inc_current_row_for_warning();
|
thd->get_stmt_da()->inc_current_row_for_warning();
|
||||||
}
|
}
|
||||||
its.rewind();
|
its.rewind();
|
||||||
@ -1218,13 +1246,23 @@ values_loop_end:
|
|||||||
goto abort;
|
goto abort;
|
||||||
if (thd->lex->analyze_stmt)
|
if (thd->lex->analyze_stmt)
|
||||||
{
|
{
|
||||||
retval= thd->lex->explain->send_explain(thd);
|
retval= 0;
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((iteration * values_list.elements) == 1 && (!(thd->variables.option_bits & OPTION_WARNINGS) ||
|
if ((iteration * values_list.elements) == 1 && (!(thd->variables.option_bits & OPTION_WARNINGS) ||
|
||||||
!thd->cuted_fields))
|
!thd->cuted_fields))
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
Client expects an EOF/OK packet if result set metadata was sent. If
|
||||||
|
LEX::has_returning and the statement returns result set
|
||||||
|
we send EOF which is the indicator of the end of the row stream.
|
||||||
|
Oherwise we send an OK packet i.e when the statement returns only the
|
||||||
|
status information
|
||||||
|
*/
|
||||||
|
if (returning)
|
||||||
|
result->send_eof();
|
||||||
|
else
|
||||||
my_ok(thd, info.copied + info.deleted +
|
my_ok(thd, info.copied + info.deleted +
|
||||||
((thd->client_capabilities & CLIENT_FOUND_ROWS) ?
|
((thd->client_capabilities & CLIENT_FOUND_ROWS) ?
|
||||||
info.touched : info.updated), id);
|
info.touched : info.updated), id);
|
||||||
@ -1244,6 +1282,9 @@ values_loop_end:
|
|||||||
sprintf(buff, ER_THD(thd, ER_INSERT_INFO), (ulong) info.records,
|
sprintf(buff, ER_THD(thd, ER_INSERT_INFO), (ulong) info.records,
|
||||||
(ulong) (info.deleted + updated),
|
(ulong) (info.deleted + updated),
|
||||||
(long) thd->get_stmt_da()->current_statement_warn_count());
|
(long) thd->get_stmt_da()->current_statement_warn_count());
|
||||||
|
if (returning)
|
||||||
|
result->send_eof();
|
||||||
|
else
|
||||||
::my_ok(thd, info.copied + info.deleted + updated, id, buff);
|
::my_ok(thd, info.copied + info.deleted + updated, id, buff);
|
||||||
}
|
}
|
||||||
thd->abort_on_warning= 0;
|
thd->abort_on_warning= 0;
|
||||||
@ -1528,10 +1569,11 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
|
|||||||
table_list->next_local= 0;
|
table_list->next_local= 0;
|
||||||
context->resolve_in_table_list_only(table_list);
|
context->resolve_in_table_list_only(table_list);
|
||||||
|
|
||||||
res= (setup_fields(thd, Ref_ptr_array(),
|
res= setup_returning_fields(thd, table_list) ||
|
||||||
|
setup_fields(thd, Ref_ptr_array(),
|
||||||
*values, MARK_COLUMNS_READ, 0, NULL, 0) ||
|
*values, MARK_COLUMNS_READ, 0, NULL, 0) ||
|
||||||
check_insert_fields(thd, context->table_list, fields, *values,
|
check_insert_fields(thd, context->table_list, fields, *values,
|
||||||
!insert_into_view, 0, &map));
|
!insert_into_view, 0, &map);
|
||||||
|
|
||||||
if (!res)
|
if (!res)
|
||||||
res= setup_fields(thd, Ref_ptr_array(),
|
res= setup_fields(thd, Ref_ptr_array(),
|
||||||
@ -3527,7 +3569,7 @@ bool Delayed_insert::handle_inserts(void)
|
|||||||
TRUE Error
|
TRUE Error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool mysql_insert_select_prepare(THD *thd)
|
bool mysql_insert_select_prepare(THD *thd, select_result *sel_res)
|
||||||
{
|
{
|
||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
SELECT_LEX *select_lex= lex->first_select_lex();
|
SELECT_LEX *select_lex= lex->first_select_lex();
|
||||||
@ -3544,6 +3586,13 @@ bool mysql_insert_select_prepare(THD *thd)
|
|||||||
&select_lex->where, TRUE))
|
&select_lex->where, TRUE))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
If sel_res is not empty, it means we have items in returing_list.
|
||||||
|
So we prepare the list now
|
||||||
|
*/
|
||||||
|
if (sel_res)
|
||||||
|
sel_res->prepare(lex->returning()->item_list, NULL);
|
||||||
|
|
||||||
DBUG_ASSERT(select_lex->leaf_tables.elements != 0);
|
DBUG_ASSERT(select_lex->leaf_tables.elements != 0);
|
||||||
List_iterator<TABLE_LIST> ti(select_lex->leaf_tables);
|
List_iterator<TABLE_LIST> ti(select_lex->leaf_tables);
|
||||||
TABLE_LIST *table;
|
TABLE_LIST *table;
|
||||||
@ -3586,8 +3635,10 @@ select_insert::select_insert(THD *thd_arg, TABLE_LIST *table_list_par,
|
|||||||
List<Item> *update_fields,
|
List<Item> *update_fields,
|
||||||
List<Item> *update_values,
|
List<Item> *update_values,
|
||||||
enum_duplicates duplic,
|
enum_duplicates duplic,
|
||||||
bool ignore_check_option_errors):
|
bool ignore_check_option_errors,
|
||||||
|
select_result *result):
|
||||||
select_result_interceptor(thd_arg),
|
select_result_interceptor(thd_arg),
|
||||||
|
sel_result(result),
|
||||||
table_list(table_list_par), table(table_par), fields(fields_par),
|
table_list(table_list_par), table(table_par), fields(fields_par),
|
||||||
autoinc_value_of_last_inserted_row(0),
|
autoinc_value_of_last_inserted_row(0),
|
||||||
insert_into_view(table_list_par && table_list_par->view != 0)
|
insert_into_view(table_list_par && table_list_par->view != 0)
|
||||||
@ -3606,7 +3657,7 @@ int
|
|||||||
select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
||||||
{
|
{
|
||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
int res;
|
int res= 0;
|
||||||
table_map map= 0;
|
table_map map= 0;
|
||||||
SELECT_LEX *lex_current_select_save= lex->current_select;
|
SELECT_LEX *lex_current_select_save= lex->current_select;
|
||||||
DBUG_ENTER("select_insert::prepare");
|
DBUG_ENTER("select_insert::prepare");
|
||||||
@ -3620,10 +3671,10 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
|||||||
*/
|
*/
|
||||||
lex->current_select= lex->first_select_lex();
|
lex->current_select= lex->first_select_lex();
|
||||||
|
|
||||||
res= (setup_fields(thd, Ref_ptr_array(),
|
res= setup_returning_fields(thd, table_list) ||
|
||||||
values, MARK_COLUMNS_READ, 0, NULL, 0) ||
|
setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_READ, 0, 0, 0) ||
|
||||||
check_insert_fields(thd, table_list, *fields, values,
|
check_insert_fields(thd, table_list, *fields, values,
|
||||||
!insert_into_view, 1, &map));
|
!insert_into_view, 1, &map);
|
||||||
|
|
||||||
if (!res && fields->elements)
|
if (!res && fields->elements)
|
||||||
{
|
{
|
||||||
@ -3790,12 +3841,19 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
|||||||
int select_insert::prepare2(JOIN *)
|
int select_insert::prepare2(JOIN *)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("select_insert::prepare2");
|
DBUG_ENTER("select_insert::prepare2");
|
||||||
if (thd->lex->current_select->options & OPTION_BUFFER_RESULT &&
|
|
||||||
thd->locked_tables_mode <= LTM_LOCK_TABLES &&
|
|
||||||
!thd->lex->describe)
|
|
||||||
table->file->ha_start_bulk_insert((ha_rows) 0);
|
|
||||||
if (table->validate_default_values_of_unset_fields(thd))
|
if (table->validate_default_values_of_unset_fields(thd))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
if (thd->lex->describe)
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
if (thd->lex->current_select->options & OPTION_BUFFER_RESULT &&
|
||||||
|
thd->locked_tables_mode <= LTM_LOCK_TABLES)
|
||||||
|
table->file->ha_start_bulk_insert((ha_rows) 0);
|
||||||
|
|
||||||
|
/* Same as the other variants of INSERT */
|
||||||
|
if (sel_result &&
|
||||||
|
sel_result->send_result_set_metadata(thd->lex->returning()->item_list,
|
||||||
|
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
|
||||||
|
DBUG_RETURN(1);
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3809,6 +3867,7 @@ void select_insert::cleanup()
|
|||||||
select_insert::~select_insert()
|
select_insert::~select_insert()
|
||||||
{
|
{
|
||||||
DBUG_ENTER("~select_insert");
|
DBUG_ENTER("~select_insert");
|
||||||
|
sel_result= NULL;
|
||||||
if (table && table->is_created())
|
if (table && table->is_created())
|
||||||
{
|
{
|
||||||
table->next_number_field=0;
|
table->next_number_field=0;
|
||||||
@ -3850,6 +3909,15 @@ int select_insert::send_data(List<Item> &values)
|
|||||||
}
|
}
|
||||||
|
|
||||||
error= write_record(thd, table, &info);
|
error= write_record(thd, table, &info);
|
||||||
|
/*
|
||||||
|
Sending the result set to the cliet after writing record. The reason is
|
||||||
|
same as other variants of insert.
|
||||||
|
*/
|
||||||
|
if (sel_result && sel_result->send_data(thd->lex->returning()->item_list) < 0)
|
||||||
|
{
|
||||||
|
error= 1;
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
table->vers_write= table->versioned();
|
table->vers_write= table->versioned();
|
||||||
table->auto_increment_field_not_null= FALSE;
|
table->auto_increment_field_not_null= FALSE;
|
||||||
|
|
||||||
@ -4004,6 +4072,13 @@ bool select_insert::send_ok_packet() {
|
|||||||
thd->first_successful_insert_id_in_prev_stmt :
|
thd->first_successful_insert_id_in_prev_stmt :
|
||||||
(info.copied ? autoinc_value_of_last_inserted_row : 0));
|
(info.copied ? autoinc_value_of_last_inserted_row : 0));
|
||||||
|
|
||||||
|
/*
|
||||||
|
Client expects an EOF/OK packet If LEX::has_returning and if result set
|
||||||
|
meta was sent. See explanation for other variants of INSERT.
|
||||||
|
*/
|
||||||
|
if (sel_result)
|
||||||
|
sel_result->send_eof();
|
||||||
|
else
|
||||||
::my_ok(thd, row_count, id, message);
|
::my_ok(thd, row_count, id, message);
|
||||||
|
|
||||||
DBUG_RETURN(false);
|
DBUG_RETURN(false);
|
||||||
|
@ -31,7 +31,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
|
|||||||
bool mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields,
|
bool mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields,
|
||||||
List<List_item> &values, List<Item> &update_fields,
|
List<List_item> &values, List<Item> &update_fields,
|
||||||
List<Item> &update_values, enum_duplicates flag,
|
List<Item> &update_values, enum_duplicates flag,
|
||||||
bool ignore);
|
bool ignore, select_result* result);
|
||||||
void upgrade_lock_type_for_insert(THD *thd, thr_lock_type *lock_type,
|
void upgrade_lock_type_for_insert(THD *thd, thr_lock_type *lock_type,
|
||||||
enum_duplicates duplic,
|
enum_duplicates duplic,
|
||||||
bool is_multi_insert);
|
bool is_multi_insert);
|
||||||
|
@ -998,14 +998,16 @@ public:
|
|||||||
bool explainable()
|
bool explainable()
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Save plans for child subqueries, when
|
EXPLAIN/ANALYZE unit, when:
|
||||||
(1) they are not parts of eliminated WHERE/ON clauses.
|
(1) if it's a subquery - it's not part of eliminated WHERE/ON clause.
|
||||||
(2) they are not merged derived tables
|
(2) if it's a CTE - it's not hanging (needed for execution)
|
||||||
(3) they are not hanging CTEs (they are needed for execution)
|
(3) if it's a derived - it's not merged
|
||||||
|
if it's not 1/2/3 - it's some weird internal thing, ignore it
|
||||||
*/
|
*/
|
||||||
return !(item && item->eliminated) &&
|
return item ? !item->eliminated : // (1)
|
||||||
!(derived && !derived->is_materialized_derived()) &&
|
with_element ? derived && derived->derived_result : // (2)
|
||||||
!(with_element && (!derived || !derived->derived_result));
|
derived ? derived->is_materialized_derived() : // (3)
|
||||||
|
false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset_distinct();
|
void reset_distinct();
|
||||||
@ -4531,6 +4533,11 @@ public:
|
|||||||
void stmt_purge_to(const LEX_CSTRING &to);
|
void stmt_purge_to(const LEX_CSTRING &to);
|
||||||
bool stmt_purge_before(Item *item);
|
bool stmt_purge_before(Item *item);
|
||||||
|
|
||||||
|
SELECT_LEX *returning()
|
||||||
|
{ return &builtin_select; }
|
||||||
|
bool has_returning()
|
||||||
|
{ return !builtin_select.item_list.is_empty(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool stmt_create_routine_start(const DDL_options_st &options)
|
bool stmt_create_routine_start(const DDL_options_st &options)
|
||||||
{
|
{
|
||||||
|
@ -4451,6 +4451,7 @@ mysql_execute_command(THD *thd)
|
|||||||
case SQLCOM_INSERT:
|
case SQLCOM_INSERT:
|
||||||
{
|
{
|
||||||
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE);
|
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE);
|
||||||
|
select_result *sel_result= NULL;
|
||||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||||
|
|
||||||
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE);
|
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE);
|
||||||
@ -4471,9 +4472,41 @@ mysql_execute_command(THD *thd)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
MYSQL_INSERT_START(thd->query());
|
MYSQL_INSERT_START(thd->query());
|
||||||
|
Protocol* save_protocol=NULL;
|
||||||
|
|
||||||
|
if (lex->has_returning())
|
||||||
|
{
|
||||||
|
status_var_increment(thd->status_var.feature_insert_returning);
|
||||||
|
|
||||||
|
/* This is INSERT ... RETURNING. It will return output to the client */
|
||||||
|
if (thd->lex->analyze_stmt)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Actually, it is ANALYZE .. INSERT .. RETURNING. We need to produce
|
||||||
|
output and then discard it.
|
||||||
|
*/
|
||||||
|
sel_result= new (thd->mem_root) select_send_analyze(thd);
|
||||||
|
save_protocol= thd->protocol;
|
||||||
|
thd->protocol= new Protocol_discard(thd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!(sel_result= new (thd->mem_root) select_send(thd)))
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values,
|
res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values,
|
||||||
lex->update_list, lex->value_list,
|
lex->update_list, lex->value_list,
|
||||||
lex->duplicates, lex->ignore);
|
lex->duplicates, lex->ignore, sel_result);
|
||||||
|
if (save_protocol)
|
||||||
|
{
|
||||||
|
delete thd->protocol;
|
||||||
|
thd->protocol= save_protocol;
|
||||||
|
}
|
||||||
|
if (!res && thd->lex->analyze_stmt)
|
||||||
|
res= thd->lex->explain->send_explain(thd);
|
||||||
|
delete sel_result;
|
||||||
MYSQL_INSERT_DONE(res, (ulong) thd->get_row_count_func());
|
MYSQL_INSERT_DONE(res, (ulong) thd->get_row_count_func());
|
||||||
/*
|
/*
|
||||||
If we have inserted into a VIEW, and the base table has
|
If we have inserted into a VIEW, and the base table has
|
||||||
@ -4505,6 +4538,7 @@ mysql_execute_command(THD *thd)
|
|||||||
{
|
{
|
||||||
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE);
|
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE);
|
||||||
select_insert *sel_result;
|
select_insert *sel_result;
|
||||||
|
select_result *result= NULL;
|
||||||
bool explain= MY_TEST(lex->describe);
|
bool explain= MY_TEST(lex->describe);
|
||||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||||
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
|
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE);
|
||||||
@ -4553,6 +4587,31 @@ mysql_execute_command(THD *thd)
|
|||||||
Only the INSERT table should be merged. Other will be handled by
|
Only the INSERT table should be merged. Other will be handled by
|
||||||
select.
|
select.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
Protocol* save_protocol=NULL;
|
||||||
|
|
||||||
|
if (lex->has_returning())
|
||||||
|
{
|
||||||
|
status_var_increment(thd->status_var.feature_insert_returning);
|
||||||
|
|
||||||
|
/* This is INSERT ... RETURNING. It will return output to the client */
|
||||||
|
if (thd->lex->analyze_stmt)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Actually, it is ANALYZE .. INSERT .. RETURNING. We need to produce
|
||||||
|
output and then discard it.
|
||||||
|
*/
|
||||||
|
result= new (thd->mem_root) select_send_analyze(thd);
|
||||||
|
save_protocol= thd->protocol;
|
||||||
|
thd->protocol= new Protocol_discard(thd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!(result= new (thd->mem_root) select_send(thd)))
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Skip first table, which is the table we are inserting in */
|
/* Skip first table, which is the table we are inserting in */
|
||||||
TABLE_LIST *second_table= first_table->next_local;
|
TABLE_LIST *second_table= first_table->next_local;
|
||||||
/*
|
/*
|
||||||
@ -4565,15 +4624,17 @@ mysql_execute_command(THD *thd)
|
|||||||
select_lex->table_list.first= second_table;
|
select_lex->table_list.first= second_table;
|
||||||
select_lex->context.table_list=
|
select_lex->context.table_list=
|
||||||
select_lex->context.first_name_resolution_table= second_table;
|
select_lex->context.first_name_resolution_table= second_table;
|
||||||
res= mysql_insert_select_prepare(thd);
|
res= mysql_insert_select_prepare(thd, result);
|
||||||
if (!res && (sel_result= new (thd->mem_root) select_insert(thd,
|
if (!res &&
|
||||||
first_table,
|
(sel_result= new (thd->mem_root)
|
||||||
|
select_insert(thd, first_table,
|
||||||
first_table->table,
|
first_table->table,
|
||||||
&lex->field_list,
|
&lex->field_list,
|
||||||
&lex->update_list,
|
&lex->update_list,
|
||||||
&lex->value_list,
|
&lex->value_list,
|
||||||
lex->duplicates,
|
lex->duplicates,
|
||||||
lex->ignore)))
|
lex->ignore,
|
||||||
|
result)))
|
||||||
{
|
{
|
||||||
if (lex->analyze_stmt)
|
if (lex->analyze_stmt)
|
||||||
((select_result_interceptor*)sel_result)->disable_my_ok_calls();
|
((select_result_interceptor*)sel_result)->disable_my_ok_calls();
|
||||||
@ -4609,7 +4670,12 @@ mysql_execute_command(THD *thd)
|
|||||||
}
|
}
|
||||||
delete sel_result;
|
delete sel_result;
|
||||||
}
|
}
|
||||||
|
delete result;
|
||||||
|
if (save_protocol)
|
||||||
|
{
|
||||||
|
delete thd->protocol;
|
||||||
|
thd->protocol= save_protocol;
|
||||||
|
}
|
||||||
if (!res && (explain || lex->analyze_stmt))
|
if (!res && (explain || lex->analyze_stmt))
|
||||||
res= thd->lex->explain->send_explain(thd);
|
res= thd->lex->explain->send_explain(thd);
|
||||||
|
|
||||||
@ -4644,7 +4710,7 @@ mysql_execute_command(THD *thd)
|
|||||||
MYSQL_DELETE_START(thd->query());
|
MYSQL_DELETE_START(thd->query());
|
||||||
Protocol *save_protocol= NULL;
|
Protocol *save_protocol= NULL;
|
||||||
|
|
||||||
if (!select_lex->item_list.is_empty())
|
if (lex->has_returning())
|
||||||
{
|
{
|
||||||
/* This is DELETE ... RETURNING. It will return output to the client */
|
/* This is DELETE ... RETURNING. It will return output to the client */
|
||||||
if (thd->lex->analyze_stmt)
|
if (thd->lex->analyze_stmt)
|
||||||
|
@ -41,7 +41,7 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables);
|
|||||||
bool multi_delete_precheck(THD *thd, TABLE_LIST *tables);
|
bool multi_delete_precheck(THD *thd, TABLE_LIST *tables);
|
||||||
int mysql_multi_update_prepare(THD *thd);
|
int mysql_multi_update_prepare(THD *thd);
|
||||||
int mysql_multi_delete_prepare(THD *thd);
|
int mysql_multi_delete_prepare(THD *thd);
|
||||||
bool mysql_insert_select_prepare(THD *thd);
|
bool mysql_insert_select_prepare(THD *thd,select_result *sel_res);
|
||||||
bool update_precheck(THD *thd, TABLE_LIST *tables);
|
bool update_precheck(THD *thd, TABLE_LIST *tables);
|
||||||
bool delete_precheck(THD *thd, TABLE_LIST *tables);
|
bool delete_precheck(THD *thd, TABLE_LIST *tables);
|
||||||
bool insert_precheck(THD *thd, TABLE_LIST *tables);
|
bool insert_precheck(THD *thd, TABLE_LIST *tables);
|
||||||
|
@ -1482,8 +1482,6 @@ static bool mysql_test_delete(Prepared_statement *stmt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DBUG_RETURN(mysql_prepare_delete(thd, table_list,
|
DBUG_RETURN(mysql_prepare_delete(thd, table_list,
|
||||||
lex->first_select_lex()->with_wild,
|
|
||||||
lex->first_select_lex()->item_list,
|
|
||||||
&lex->first_select_lex()->where,
|
&lex->first_select_lex()->where,
|
||||||
&delete_while_scanning));
|
&delete_while_scanning));
|
||||||
error:
|
error:
|
||||||
@ -2157,7 +2155,7 @@ static int mysql_insert_select_prepare_tester(THD *thd)
|
|||||||
thd->lex->first_select_lex()->context.first_name_resolution_table=
|
thd->lex->first_select_lex()->context.first_name_resolution_table=
|
||||||
second_table;
|
second_table;
|
||||||
|
|
||||||
return mysql_insert_select_prepare(thd);
|
return mysql_insert_select_prepare(thd, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2080,7 +2080,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
|
|||||||
opt_persistent_stat_clause persistent_stat_spec
|
opt_persistent_stat_clause persistent_stat_spec
|
||||||
persistent_column_stat_spec persistent_index_stat_spec
|
persistent_column_stat_spec persistent_index_stat_spec
|
||||||
table_column_list table_index_list table_index_name
|
table_column_list table_index_list table_index_name
|
||||||
check start checksum
|
check start checksum opt_returning
|
||||||
field_list field_list_item kill key_def constraint_def
|
field_list field_list_item kill key_def constraint_def
|
||||||
keycache_list keycache_list_or_parts assign_to_keycache
|
keycache_list keycache_list_or_parts assign_to_keycache
|
||||||
assign_to_keycache_parts
|
assign_to_keycache_parts
|
||||||
@ -13477,7 +13477,8 @@ insert:
|
|||||||
{
|
{
|
||||||
Select->set_lock_for_tables($4, true);
|
Select->set_lock_for_tables($4, true);
|
||||||
}
|
}
|
||||||
insert_field_spec opt_insert_update stmt_end {}
|
insert_field_spec opt_insert_update opt_returning
|
||||||
|
stmt_end {}
|
||||||
;
|
;
|
||||||
|
|
||||||
replace:
|
replace:
|
||||||
@ -13490,7 +13491,8 @@ replace:
|
|||||||
{
|
{
|
||||||
Select->set_lock_for_tables($4, true);
|
Select->set_lock_for_tables($4, true);
|
||||||
}
|
}
|
||||||
insert_field_spec stmt_end {}
|
insert_field_spec opt_returning
|
||||||
|
stmt_end {}
|
||||||
;
|
;
|
||||||
|
|
||||||
insert_start: {
|
insert_start: {
|
||||||
@ -13890,7 +13892,7 @@ single_multi:
|
|||||||
opt_where_clause
|
opt_where_clause
|
||||||
opt_order_clause
|
opt_order_clause
|
||||||
delete_limit_clause
|
delete_limit_clause
|
||||||
opt_select_expressions
|
opt_returning
|
||||||
{
|
{
|
||||||
if ($3)
|
if ($3)
|
||||||
Select->order_list= *($3);
|
Select->order_list= *($3);
|
||||||
@ -13920,9 +13922,28 @@ single_multi:
|
|||||||
} stmt_end {}
|
} stmt_end {}
|
||||||
;
|
;
|
||||||
|
|
||||||
opt_select_expressions:
|
opt_returning:
|
||||||
/* empty */
|
/* empty */
|
||||||
| RETURNING_SYM select_item_list
|
{
|
||||||
|
DBUG_ASSERT(!Lex->has_returning());
|
||||||
|
}
|
||||||
|
| RETURNING_SYM
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(!Lex->has_returning());
|
||||||
|
if (($<num>$= (Select != Lex->returning())))
|
||||||
|
{
|
||||||
|
SELECT_LEX *sl= Lex->returning();
|
||||||
|
sl->set_master_unit(0);
|
||||||
|
Select->add_slave(Lex->create_unit(sl));
|
||||||
|
sl->include_global((st_select_lex_node**)&Lex->all_selects_list);
|
||||||
|
Lex->push_select(sl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
select_item_list
|
||||||
|
{
|
||||||
|
if ($<num>2)
|
||||||
|
Lex->pop_select();
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
table_wild_list:
|
table_wild_list:
|
||||||
|
@ -1555,7 +1555,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
|
|||||||
opt_persistent_stat_clause persistent_stat_spec
|
opt_persistent_stat_clause persistent_stat_spec
|
||||||
persistent_column_stat_spec persistent_index_stat_spec
|
persistent_column_stat_spec persistent_index_stat_spec
|
||||||
table_column_list table_index_list table_index_name
|
table_column_list table_index_list table_index_name
|
||||||
check start checksum
|
check start checksum opt_returning
|
||||||
field_list field_list_item kill key_def constraint_def
|
field_list field_list_item kill key_def constraint_def
|
||||||
keycache_list keycache_list_or_parts assign_to_keycache
|
keycache_list keycache_list_or_parts assign_to_keycache
|
||||||
assign_to_keycache_parts
|
assign_to_keycache_parts
|
||||||
@ -13594,7 +13594,8 @@ insert:
|
|||||||
{
|
{
|
||||||
Select->set_lock_for_tables($4, true);
|
Select->set_lock_for_tables($4, true);
|
||||||
}
|
}
|
||||||
insert_field_spec opt_insert_update stmt_end {}
|
insert_field_spec opt_insert_update opt_returning
|
||||||
|
stmt_end {}
|
||||||
;
|
;
|
||||||
|
|
||||||
replace:
|
replace:
|
||||||
@ -13607,7 +13608,8 @@ replace:
|
|||||||
{
|
{
|
||||||
Select->set_lock_for_tables($4, true);
|
Select->set_lock_for_tables($4, true);
|
||||||
}
|
}
|
||||||
insert_field_spec stmt_end {}
|
insert_field_spec opt_returning
|
||||||
|
stmt_end {}
|
||||||
;
|
;
|
||||||
|
|
||||||
insert_start: {
|
insert_start: {
|
||||||
@ -14007,7 +14009,7 @@ single_multi:
|
|||||||
opt_where_clause
|
opt_where_clause
|
||||||
opt_order_clause
|
opt_order_clause
|
||||||
delete_limit_clause
|
delete_limit_clause
|
||||||
opt_select_expressions
|
opt_returning
|
||||||
{
|
{
|
||||||
if ($3)
|
if ($3)
|
||||||
Select->order_list= *($3);
|
Select->order_list= *($3);
|
||||||
@ -14037,9 +14039,28 @@ single_multi:
|
|||||||
} stmt_end {}
|
} stmt_end {}
|
||||||
;
|
;
|
||||||
|
|
||||||
opt_select_expressions:
|
opt_returning:
|
||||||
/* empty */
|
/* empty */
|
||||||
| RETURNING_SYM select_item_list
|
{
|
||||||
|
DBUG_ASSERT(!Lex->has_returning());
|
||||||
|
}
|
||||||
|
| RETURNING_SYM
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(!Lex->has_returning());
|
||||||
|
if (($<num>$= (Select != Lex->returning())))
|
||||||
|
{
|
||||||
|
SELECT_LEX *sl= Lex->returning();
|
||||||
|
sl->set_master_unit(0);
|
||||||
|
Select->add_slave(Lex->create_unit(sl));
|
||||||
|
sl->include_global((st_select_lex_node**)&Lex->all_selects_list);
|
||||||
|
Lex->push_select(sl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
select_item_list
|
||||||
|
{
|
||||||
|
if ($<num>2)
|
||||||
|
Lex->pop_select();
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
table_wild_list:
|
table_wild_list:
|
||||||
|
Reference in New Issue
Block a user