diff --git a/pkg/sql/logictest/testdata/logic_test/delete b/pkg/sql/logictest/testdata/logic_test/delete index 60ce035416c1..fe98b59e5f92 100644 --- a/pkg/sql/logictest/testdata/logic_test/delete +++ b/pkg/sql/logictest/testdata/logic_test/delete @@ -153,13 +153,13 @@ statement ok INSERT INTO unindexed VALUES (1, 9), (8, 2), (3, 7), (6, 4) query II -DELETE FROM unindexed WHERE k > 1 AND v < 7 ORDER BY v DESC RETURNING v,k +DELETE FROM unindexed WHERE k > 1 AND v < 7 ORDER BY v DESC LIMIT 2 RETURNING v,k ---- 4 6 2 8 query II -DELETE FROM unindexed ORDER BY v RETURNING k,v +DELETE FROM unindexed ORDER BY v LIMIT 2 RETURNING k,v ---- 3 7 1 9 diff --git a/pkg/sql/logictest/testdata/logic_test/interleaved b/pkg/sql/logictest/testdata/logic_test/interleaved index 4a5d73bd41b4..6037776c8149 100644 --- a/pkg/sql/logictest/testdata/logic_test/interleaved +++ b/pkg/sql/logictest/testdata/logic_test/interleaved @@ -382,431 +382,3 @@ query I SELECT count(*) FROM users JOIN documents ON users.id=documents.user_id WHERE documents.id=0 ---- 1 - -subtest InterleavedDeleteFastPath -statement ok -CREATE TABLE a ( - a_id INT PRIMARY KEY -); - -statement ok -CREATE TABLE b( - b_id INT, - a_id INT, - FOREIGN KEY (a_id) REFERENCES a(a_id) ON UPDATE CASCADE ON DELETE CASCADE, - PRIMARY KEY(a_id, b_id) -) INTERLEAVE IN PARENT a(a_id) - -statement ok -CREATE TABLE c( - c_id INT, - a_id INT, - b_id INT, - FOREIGN KEY (a_id, b_id) REFERENCES b(a_id, b_id) ON UPDATE CASCADE ON DELETE CASCADE, - PRIMARY KEY(a_id, b_id, c_id) -) INTERLEAVE IN PARENT b(a_id, b_id) - -statement ok -INSERT INTO a SELECT generate_series(1,10); -INSERT INTO b(a_id, b_id) SELECT generate_series(1,10), 1 - -statement ok -DELETE FROM a WHERE a_id <= 2 - -query I -SELECT count(*) from a ----- -8 - -query I -SELECT count(*) from b ----- -8 - -query I colnames -SELECT * from a order by a_id ----- -a_id -3 -4 -5 -6 -7 -8 -9 -10 - -query II colnames -SELECT * from b order by a_id, b_id ----- -b_id a_id -1 3 -1 4 -1 5 -1 6 -1 7 -1 8 -1 9 -1 10 - -statement ok -INSERT INTO b(a_id, b_id) select a.a_id, 2 from a; -INSERT INTO c(a_id, b_id, c_id) select a.a_id, b.b_id, 1 from a, b where a.a_id = b.a_id - -query III colnames -SELECT * from c order by a_id, b_id, c_id ----- -c_id a_id b_id -1 3 1 -1 3 2 -1 4 1 -1 4 2 -1 5 1 -1 5 2 -1 6 1 -1 6 2 -1 7 1 -1 7 2 -1 8 1 -1 8 2 -1 9 1 -1 9 2 -1 10 1 -1 10 2 - -statement ok -SET TRACING = on,kv,results; DELETE FROM a where a_id <= 7 and a_id >= 5; SET tracing = off - -query T -SELECT message FROM [SHOW KV TRACE FOR SESSION] ----- -Scan /Table/79/1/{5-7/#} -querying next range at /Table/79/1/5 -r19: sending batch 1 Scan to (n1,s1):1 -DelRange /Table/79/1/5 - /Table/79/1/7/NULL -querying next range at /Table/79/1/5 -r19: sending batch 1 DelRng, 1 BeginTxn, 1 EndTxn to (n1,s1):1 -fast path completed -rows affected: 3 - -query II colnames -select * from b order by a_id, b_id ----- -b_id a_id -1 3 -2 3 -1 4 -2 4 -1 8 -2 8 -1 9 -2 9 -1 10 -2 10 - -query III colnames -select * from c order by a_id, b_id, c_id ----- -c_id a_id b_id -1 3 1 -1 3 2 -1 4 1 -1 4 2 -1 8 1 -1 8 2 -1 9 1 -1 9 2 -1 10 1 -1 10 2 - -statement ok -SET TRACING = on,kv,results; DELETE FROM a; SET tracing = off - -query T -select message FROM [SHOW KV TRACE FOR SESSION] ----- -Scan /Table/79/{1-2} -querying next range at /Table/79/1 -r19: sending batch 1 Scan to (n1,s1):1 -DelRange /Table/79/1 - /Table/79/3 -querying next range at /Table/79/1 -r19: sending batch 1 DelRng, 1 BeginTxn, 1 EndTxn to (n1,s1):1 -fast path completed -rows affected: 5 - -query II colnames -select * from b order by a_id, b_id ----- -b_id a_id - -query III colnames -select * from c order by a_id, b_id, c_id ----- -c_id a_id b_id - -statement ok -INSERT INTO a SELECT generate_series(1,10); -INSERT INTO b(a_id, b_id) SELECT generate_series(1,10), 1 - -statement ok -SET TRACING = on,kv,results; - -query I -delete from a returning * ----- -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 - -statement ok -SET TRACING=off; - -query T -select message FROM [SHOW KV TRACE FOR SESSION]; ----- -Scan /Table/79/{1-2} -querying next range at /Table/79/1 -r19: sending batch 1 Scan to (n1,s1):1 -fetched: /a/primary/1 -> NULL -Del /Table/79/1/1/0 -cascading delete into table: 80 using index: 1 -CascadeScan /Table/79/1/1/#/80/{1-2} -querying next range at /Table/79/1/1/#/80/1 -r19: sending batch 1 Scan to (n1,s1):1 -CascadeScan /Table/79/1/1/#/80/1/1{-/#} -querying next range at /Table/79/1/1/#/80/1/1 -r19: sending batch 1 Scan to (n1,s1):1 -Del /Table/79/1/1/#/80/1/1/0 -querying next range at /Table/79/1/1/#/80/1/1/0 -r19: sending batch 1 Del, 1 BeginTxn to (n1,s1):1 -cascading delete into table: 81 using index: 1 -CascadeScan /Table/79/1/1/#/80/1/1/#/81/{1-2} -querying next range at /Table/79/1/1/#/80/1/1/#/81/1 -r19: sending batch 1 Scan to (n1,s1):1 -FKScan /Table/79/1/1/#/80/1/1/#/81/{1-2} -querying next range at /Table/79/1/1/#/80/1/1/#/81/1 -r19: sending batch 1 Scan to (n1,s1):1 -FKScan /Table/79/1/1/#/80/{1-2} -querying next range at /Table/79/1/1/#/80/1 -r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 -fetched: /a/primary/2 -> NULL -Del /Table/79/1/2/0 -cascading delete into table: 80 using index: 1 -CascadeScan /Table/79/1/2/#/80/{1-2} -querying next range at /Table/79/1/2/#/80/1 -r19: sending batch 1 Scan to (n1,s1):1 -CascadeScan /Table/79/1/2/#/80/1/1{-/#} -querying next range at /Table/79/1/2/#/80/1/1 -r19: sending batch 1 Scan to (n1,s1):1 -Del /Table/79/1/2/#/80/1/1/0 -querying next range at /Table/79/1/2/#/80/1/1/0 -r19: sending batch 1 Del to (n1,s1):1 -cascading delete into table: 81 using index: 1 -CascadeScan /Table/79/1/2/#/80/1/1/#/81/{1-2} -querying next range at /Table/79/1/2/#/80/1/1/#/81/1 -r19: sending batch 1 Scan to (n1,s1):1 -FKScan /Table/79/1/2/#/80/1/1/#/81/{1-2} -querying next range at /Table/79/1/2/#/80/1/1/#/81/1 -r19: sending batch 1 Scan to (n1,s1):1 -FKScan /Table/79/1/2/#/80/{1-2} -querying next range at /Table/79/1/2/#/80/1 -r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 -fetched: /a/primary/3 -> NULL -Del /Table/79/1/3/0 -cascading delete into table: 80 using index: 1 -CascadeScan /Table/79/1/3/#/80/{1-2} -querying next range at /Table/79/1/3/#/80/1 -r19: sending batch 1 Scan to (n1,s1):1 -CascadeScan /Table/79/1/3/#/80/1/1{-/#} -querying next range at /Table/79/1/3/#/80/1/1 -r19: sending batch 1 Scan to (n1,s1):1 -Del /Table/79/1/3/#/80/1/1/0 -querying next range at /Table/79/1/3/#/80/1/1/0 -r19: sending batch 1 Del to (n1,s1):1 -cascading delete into table: 81 using index: 1 -CascadeScan /Table/79/1/3/#/80/1/1/#/81/{1-2} -querying next range at /Table/79/1/3/#/80/1/1/#/81/1 -r19: sending batch 1 Scan to (n1,s1):1 -FKScan /Table/79/1/3/#/80/1/1/#/81/{1-2} -querying next range at /Table/79/1/3/#/80/1/1/#/81/1 -r19: sending batch 1 Scan to (n1,s1):1 -FKScan /Table/79/1/3/#/80/{1-2} -querying next range at /Table/79/1/3/#/80/1 -r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 -fetched: /a/primary/4 -> NULL -Del /Table/79/1/4/0 -cascading delete into table: 80 using index: 1 -CascadeScan /Table/79/1/4/#/80/{1-2} -querying next range at /Table/79/1/4/#/80/1 -r19: sending batch 1 Scan to (n1,s1):1 -CascadeScan /Table/79/1/4/#/80/1/1{-/#} -querying next range at /Table/79/1/4/#/80/1/1 -r19: sending batch 1 Scan to (n1,s1):1 -Del /Table/79/1/4/#/80/1/1/0 -querying next range at /Table/79/1/4/#/80/1/1/0 -r19: sending batch 1 Del to (n1,s1):1 -cascading delete into table: 81 using index: 1 -CascadeScan /Table/79/1/4/#/80/1/1/#/81/{1-2} -querying next range at /Table/79/1/4/#/80/1/1/#/81/1 -r19: sending batch 1 Scan to (n1,s1):1 -FKScan /Table/79/1/4/#/80/1/1/#/81/{1-2} -querying next range at /Table/79/1/4/#/80/1/1/#/81/1 -r19: sending batch 1 Scan to (n1,s1):1 -FKScan /Table/79/1/4/#/80/{1-2} -querying next range at /Table/79/1/4/#/80/1 -r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 -fetched: /a/primary/5 -> NULL -Del /Table/79/1/5/0 -cascading delete into table: 80 using index: 1 -CascadeScan /Table/79/1/5/#/80/{1-2} -querying next range at /Table/79/1/5/#/80/1 -r19: sending batch 1 Scan to (n1,s1):1 -CascadeScan /Table/79/1/5/#/80/1/1{-/#} -querying next range at /Table/79/1/5/#/80/1/1 -r19: sending batch 1 Scan to (n1,s1):1 -Del /Table/79/1/5/#/80/1/1/0 -querying next range at /Table/79/1/5/#/80/1/1/0 -r19: sending batch 1 Del to (n1,s1):1 -cascading delete into table: 81 using index: 1 -CascadeScan /Table/79/1/5/#/80/1/1/#/81/{1-2} -querying next range at /Table/79/1/5/#/80/1/1/#/81/1 -r19: sending batch 1 Scan to (n1,s1):1 -FKScan /Table/79/1/5/#/80/1/1/#/81/{1-2} -querying next range at /Table/79/1/5/#/80/1/1/#/81/1 -r19: sending batch 1 Scan to (n1,s1):1 -FKScan /Table/79/1/5/#/80/{1-2} -querying next range at /Table/79/1/5/#/80/1 -r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 -fetched: /a/primary/6 -> NULL -Del /Table/79/1/6/0 -cascading delete into table: 80 using index: 1 -CascadeScan /Table/79/1/6/#/80/{1-2} -querying next range at /Table/79/1/6/#/80/1 -r19: sending batch 1 Scan to (n1,s1):1 -CascadeScan /Table/79/1/6/#/80/1/1{-/#} -querying next range at /Table/79/1/6/#/80/1/1 -r19: sending batch 1 Scan to (n1,s1):1 -Del /Table/79/1/6/#/80/1/1/0 -querying next range at /Table/79/1/6/#/80/1/1/0 -r19: sending batch 1 Del to (n1,s1):1 -cascading delete into table: 81 using index: 1 -CascadeScan /Table/79/1/6/#/80/1/1/#/81/{1-2} -querying next range at /Table/79/1/6/#/80/1/1/#/81/1 -r19: sending batch 1 Scan to (n1,s1):1 -FKScan /Table/79/1/6/#/80/1/1/#/81/{1-2} -querying next range at /Table/79/1/6/#/80/1/1/#/81/1 -r19: sending batch 1 Scan to (n1,s1):1 -FKScan /Table/79/1/6/#/80/{1-2} -querying next range at /Table/79/1/6/#/80/1 -r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 -fetched: /a/primary/7 -> NULL -Del /Table/79/1/7/0 -cascading delete into table: 80 using index: 1 -CascadeScan /Table/79/1/7/#/80/{1-2} -querying next range at /Table/79/1/7/#/80/1 -r19: sending batch 1 Scan to (n1,s1):1 -CascadeScan /Table/79/1/7/#/80/1/1{-/#} -querying next range at /Table/79/1/7/#/80/1/1 -r19: sending batch 1 Scan to (n1,s1):1 -Del /Table/79/1/7/#/80/1/1/0 -querying next range at /Table/79/1/7/#/80/1/1/0 -r19: sending batch 1 Del to (n1,s1):1 -cascading delete into table: 81 using index: 1 -CascadeScan /Table/79/1/7/#/80/1/1/#/81/{1-2} -querying next range at /Table/79/1/7/#/80/1/1/#/81/1 -r19: sending batch 1 Scan to (n1,s1):1 -FKScan /Table/79/1/7/#/80/1/1/#/81/{1-2} -querying next range at /Table/79/1/7/#/80/1/1/#/81/1 -r19: sending batch 1 Scan to (n1,s1):1 -FKScan /Table/79/1/7/#/80/{1-2} -querying next range at /Table/79/1/7/#/80/1 -r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 -fetched: /a/primary/8 -> NULL -Del /Table/79/1/8/0 -cascading delete into table: 80 using index: 1 -CascadeScan /Table/79/1/8/#/80/{1-2} -querying next range at /Table/79/1/8/#/80/1 -r19: sending batch 1 Scan to (n1,s1):1 -CascadeScan /Table/79/1/8/#/80/1/1{-/#} -querying next range at /Table/79/1/8/#/80/1/1 -r19: sending batch 1 Scan to (n1,s1):1 -Del /Table/79/1/8/#/80/1/1/0 -querying next range at /Table/79/1/8/#/80/1/1/0 -r19: sending batch 1 Del to (n1,s1):1 -cascading delete into table: 81 using index: 1 -CascadeScan /Table/79/1/8/#/80/1/1/#/81/{1-2} -querying next range at /Table/79/1/8/#/80/1/1/#/81/1 -r19: sending batch 1 Scan to (n1,s1):1 -FKScan /Table/79/1/8/#/80/1/1/#/81/{1-2} -querying next range at /Table/79/1/8/#/80/1/1/#/81/1 -r19: sending batch 1 Scan to (n1,s1):1 -FKScan /Table/79/1/8/#/80/{1-2} -querying next range at /Table/79/1/8/#/80/1 -r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 -fetched: /a/primary/9 -> NULL -Del /Table/79/1/9/0 -cascading delete into table: 80 using index: 1 -CascadeScan /Table/79/1/9/#/80/{1-2} -querying next range at /Table/79/1/9/#/80/1 -r19: sending batch 1 Scan to (n1,s1):1 -CascadeScan /Table/79/1/9/#/80/1/1{-/#} -querying next range at /Table/79/1/9/#/80/1/1 -r19: sending batch 1 Scan to (n1,s1):1 -Del /Table/79/1/9/#/80/1/1/0 -querying next range at /Table/79/1/9/#/80/1/1/0 -r19: sending batch 1 Del to (n1,s1):1 -cascading delete into table: 81 using index: 1 -CascadeScan /Table/79/1/9/#/80/1/1/#/81/{1-2} -querying next range at /Table/79/1/9/#/80/1/1/#/81/1 -r19: sending batch 1 Scan to (n1,s1):1 -FKScan /Table/79/1/9/#/80/1/1/#/81/{1-2} -querying next range at /Table/79/1/9/#/80/1/1/#/81/1 -r19: sending batch 1 Scan to (n1,s1):1 -FKScan /Table/79/1/9/#/80/{1-2} -querying next range at /Table/79/1/9/#/80/1 -r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 -fetched: /a/primary/10 -> NULL -Del /Table/79/1/10/0 -cascading delete into table: 80 using index: 1 -CascadeScan /Table/79/1/10/#/80/{1-2} -querying next range at /Table/79/1/10/#/80/1 -r19: sending batch 1 Scan to (n1,s1):1 -CascadeScan /Table/79/1/10/#/80/1/1{-/#} -querying next range at /Table/79/1/10/#/80/1/1 -r19: sending batch 1 Scan to (n1,s1):1 -Del /Table/79/1/10/#/80/1/1/0 -querying next range at /Table/79/1/10/#/80/1/1/0 -r19: sending batch 1 Del to (n1,s1):1 -cascading delete into table: 81 using index: 1 -CascadeScan /Table/79/1/10/#/80/1/1/#/81/{1-2} -querying next range at /Table/79/1/10/#/80/1/1/#/81/1 -r19: sending batch 1 Scan to (n1,s1):1 -FKScan /Table/79/1/10/#/80/1/1/#/81/{1-2} -querying next range at /Table/79/1/10/#/80/1/1/#/81/1 -r19: sending batch 1 Scan to (n1,s1):1 -FKScan /Table/79/1/10/#/80/{1-2} -querying next range at /Table/79/1/10/#/80/1 -r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 -querying next range at /Table/79/1/1/0 -r19: sending batch 10 Del, 1 EndTxn to (n1,s1):1 -output row: [1] -output row: [2] -output row: [3] -output row: [4] -output row: [5] -output row: [6] -output row: [7] -output row: [8] -output row: [9] -output row: [10] -rows affected: 10 - -statement ok -DROP TABLE c; DROP TABLE b; DROP TABLE a diff --git a/pkg/sql/logictest/testdata/logic_test/optimizer b/pkg/sql/logictest/testdata/logic_test/optimizer index b15c6a23b603..a1924d4ca226 100644 --- a/pkg/sql/logictest/testdata/logic_test/optimizer +++ b/pkg/sql/logictest/testdata/logic_test/optimizer @@ -126,8 +126,14 @@ SET experimental_optimizer_mutations = false statement error pq: no data source matches prefix: t UPDATE t SET v=(SELECT v+1 FROM t AS t2 WHERE t2.k=t.k) +statement error pq: no data source matches prefix: t +DELETE FROM t WHERE EXISTS(SELECT * FROM t AS t2 WHERE t2.k=t.k) + statement ok SET experimental_optimizer_mutations = true statement ok UPDATE t SET v=(SELECT v+1 FROM t AS t2 WHERE t2.k=t.k) + +statement ok +DELETE FROM t WHERE EXISTS(SELECT * FROM t AS t2 WHERE t2.k=t.k) diff --git a/pkg/sql/logictest/testdata/planner_test/interleaved b/pkg/sql/logictest/testdata/planner_test/interleaved index ca35262138ee..9eee4b6ed7f4 100644 --- a/pkg/sql/logictest/testdata/planner_test/interleaved +++ b/pkg/sql/logictest/testdata/planner_test/interleaved @@ -139,3 +139,435 @@ fetched: /p1_0/primary/3/'3'/d -> 3 output row: [3 '3' '3.01' 3] fetched: /p1_0/primary/5/'5' -> NULL output row: [5 '5' NULL NULL] + +# ------------------------------------------------------------------------------ +# Test interleaved delete fast path. +# ------------------------------------------------------------------------------ +subtest InterleavedDeleteFastPath + +statement ok +CREATE TABLE a ( + a_id INT PRIMARY KEY +); + +statement ok +CREATE TABLE b( + b_id INT, + a_id INT, + FOREIGN KEY (a_id) REFERENCES a(a_id) ON UPDATE CASCADE ON DELETE CASCADE, + PRIMARY KEY(a_id, b_id) +) INTERLEAVE IN PARENT a(a_id) + +statement ok +CREATE TABLE c( + c_id INT, + a_id INT, + b_id INT, + FOREIGN KEY (a_id, b_id) REFERENCES b(a_id, b_id) ON UPDATE CASCADE ON DELETE CASCADE, + PRIMARY KEY(a_id, b_id, c_id) +) INTERLEAVE IN PARENT b(a_id, b_id) + +statement ok +INSERT INTO a SELECT generate_series(1,10); +INSERT INTO b(a_id, b_id) SELECT generate_series(1,10), 1 + +statement ok +DELETE FROM a WHERE a_id <= 2 + +query I +SELECT count(*) from a +---- +8 + +query I +SELECT count(*) from b +---- +8 + +query I colnames +SELECT * from a order by a_id +---- +a_id +3 +4 +5 +6 +7 +8 +9 +10 + +query II colnames +SELECT * from b order by a_id, b_id +---- +b_id a_id +1 3 +1 4 +1 5 +1 6 +1 7 +1 8 +1 9 +1 10 + +statement ok +INSERT INTO b(a_id, b_id) select a.a_id, 2 from a; +INSERT INTO c(a_id, b_id, c_id) select a.a_id, b.b_id, 1 from a, b where a.a_id = b.a_id + +query III colnames +SELECT * from c order by a_id, b_id, c_id +---- +c_id a_id b_id +1 3 1 +1 3 2 +1 4 1 +1 4 2 +1 5 1 +1 5 2 +1 6 1 +1 6 2 +1 7 1 +1 7 2 +1 8 1 +1 8 2 +1 9 1 +1 9 2 +1 10 1 +1 10 2 + +statement ok +SET TRACING = on,kv,results; DELETE FROM a where a_id <= 7 and a_id >= 5; SET tracing = off + +query T +SELECT message FROM [SHOW KV TRACE FOR SESSION] +---- +Scan /Table/61/1/{5-7/#} +querying next range at /Table/61/1/5 +r19: sending batch 1 Scan to (n1,s1):1 +DelRange /Table/61/1/5 - /Table/61/1/7/NULL +querying next range at /Table/61/1/5 +r19: sending batch 1 DelRng, 1 BeginTxn, 1 EndTxn to (n1,s1):1 +fast path completed +rows affected: 3 + +query II colnames +select * from b order by a_id, b_id +---- +b_id a_id +1 3 +2 3 +1 4 +2 4 +1 8 +2 8 +1 9 +2 9 +1 10 +2 10 + +query III colnames +select * from c order by a_id, b_id, c_id +---- +c_id a_id b_id +1 3 1 +1 3 2 +1 4 1 +1 4 2 +1 8 1 +1 8 2 +1 9 1 +1 9 2 +1 10 1 +1 10 2 + +statement ok +SET TRACING = on,kv,results; DELETE FROM a; SET tracing = off + +query T +select message FROM [SHOW KV TRACE FOR SESSION] +---- +Scan /Table/61/{1-2} +querying next range at /Table/61/1 +r19: sending batch 1 Scan to (n1,s1):1 +DelRange /Table/61/1 - /Table/61/3 +querying next range at /Table/61/1 +r19: sending batch 1 DelRng, 1 BeginTxn, 1 EndTxn to (n1,s1):1 +fast path completed +rows affected: 5 + +query II colnames +select * from b order by a_id, b_id +---- +b_id a_id + +query III colnames +select * from c order by a_id, b_id, c_id +---- +c_id a_id b_id + +statement ok +INSERT INTO a SELECT generate_series(1,10); +INSERT INTO b(a_id, b_id) SELECT generate_series(1,10), 1 + +statement ok +SET TRACING = on,kv,results; + +query I +delete from a returning * +---- +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 + +statement ok +SET TRACING=off; + +query T +select message FROM [SHOW KV TRACE FOR SESSION]; +---- +Scan /Table/61/{1-2} +querying next range at /Table/61/1 +r19: sending batch 1 Scan to (n1,s1):1 +fetched: /a/primary/1 -> NULL +Del /Table/61/1/1/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/1/#/62/{1-2} +querying next range at /Table/61/1/1/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/1/#/62/1/1{-/#} +querying next range at /Table/61/1/1/#/62/1/1 +r19: sending batch 1 Scan to (n1,s1):1 +Del /Table/61/1/1/#/62/1/1/0 +querying next range at /Table/61/1/1/#/62/1/1/0 +r19: sending batch 1 Del, 1 BeginTxn to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/1/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/1/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/1/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/1/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/1/#/62/{1-2} +querying next range at /Table/61/1/1/#/62/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +fetched: /a/primary/2 -> NULL +Del /Table/61/1/2/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/2/#/62/{1-2} +querying next range at /Table/61/1/2/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/2/#/62/1/1{-/#} +querying next range at /Table/61/1/2/#/62/1/1 +r19: sending batch 1 Scan to (n1,s1):1 +Del /Table/61/1/2/#/62/1/1/0 +querying next range at /Table/61/1/2/#/62/1/1/0 +r19: sending batch 1 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/2/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/2/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/2/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/2/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/2/#/62/{1-2} +querying next range at /Table/61/1/2/#/62/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +fetched: /a/primary/3 -> NULL +Del /Table/61/1/3/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/3/#/62/{1-2} +querying next range at /Table/61/1/3/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/3/#/62/1/1{-/#} +querying next range at /Table/61/1/3/#/62/1/1 +r19: sending batch 1 Scan to (n1,s1):1 +Del /Table/61/1/3/#/62/1/1/0 +querying next range at /Table/61/1/3/#/62/1/1/0 +r19: sending batch 1 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/3/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/3/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/3/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/3/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/3/#/62/{1-2} +querying next range at /Table/61/1/3/#/62/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +fetched: /a/primary/4 -> NULL +Del /Table/61/1/4/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/4/#/62/{1-2} +querying next range at /Table/61/1/4/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/4/#/62/1/1{-/#} +querying next range at /Table/61/1/4/#/62/1/1 +r19: sending batch 1 Scan to (n1,s1):1 +Del /Table/61/1/4/#/62/1/1/0 +querying next range at /Table/61/1/4/#/62/1/1/0 +r19: sending batch 1 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/4/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/4/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/4/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/4/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/4/#/62/{1-2} +querying next range at /Table/61/1/4/#/62/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +fetched: /a/primary/5 -> NULL +Del /Table/61/1/5/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/5/#/62/{1-2} +querying next range at /Table/61/1/5/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/5/#/62/1/1{-/#} +querying next range at /Table/61/1/5/#/62/1/1 +r19: sending batch 1 Scan to (n1,s1):1 +Del /Table/61/1/5/#/62/1/1/0 +querying next range at /Table/61/1/5/#/62/1/1/0 +r19: sending batch 1 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/5/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/5/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/5/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/5/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/5/#/62/{1-2} +querying next range at /Table/61/1/5/#/62/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +fetched: /a/primary/6 -> NULL +Del /Table/61/1/6/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/6/#/62/{1-2} +querying next range at /Table/61/1/6/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/6/#/62/1/1{-/#} +querying next range at /Table/61/1/6/#/62/1/1 +r19: sending batch 1 Scan to (n1,s1):1 +Del /Table/61/1/6/#/62/1/1/0 +querying next range at /Table/61/1/6/#/62/1/1/0 +r19: sending batch 1 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/6/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/6/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/6/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/6/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/6/#/62/{1-2} +querying next range at /Table/61/1/6/#/62/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +fetched: /a/primary/7 -> NULL +Del /Table/61/1/7/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/7/#/62/{1-2} +querying next range at /Table/61/1/7/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/7/#/62/1/1{-/#} +querying next range at /Table/61/1/7/#/62/1/1 +r19: sending batch 1 Scan to (n1,s1):1 +Del /Table/61/1/7/#/62/1/1/0 +querying next range at /Table/61/1/7/#/62/1/1/0 +r19: sending batch 1 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/7/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/7/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/7/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/7/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/7/#/62/{1-2} +querying next range at /Table/61/1/7/#/62/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +fetched: /a/primary/8 -> NULL +Del /Table/61/1/8/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/8/#/62/{1-2} +querying next range at /Table/61/1/8/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/8/#/62/1/1{-/#} +querying next range at /Table/61/1/8/#/62/1/1 +r19: sending batch 1 Scan to (n1,s1):1 +Del /Table/61/1/8/#/62/1/1/0 +querying next range at /Table/61/1/8/#/62/1/1/0 +r19: sending batch 1 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/8/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/8/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/8/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/8/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/8/#/62/{1-2} +querying next range at /Table/61/1/8/#/62/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +fetched: /a/primary/9 -> NULL +Del /Table/61/1/9/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/9/#/62/{1-2} +querying next range at /Table/61/1/9/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/9/#/62/1/1{-/#} +querying next range at /Table/61/1/9/#/62/1/1 +r19: sending batch 1 Scan to (n1,s1):1 +Del /Table/61/1/9/#/62/1/1/0 +querying next range at /Table/61/1/9/#/62/1/1/0 +r19: sending batch 1 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/9/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/9/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/9/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/9/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/9/#/62/{1-2} +querying next range at /Table/61/1/9/#/62/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +fetched: /a/primary/10 -> NULL +Del /Table/61/1/10/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/10/#/62/{1-2} +querying next range at /Table/61/1/10/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/10/#/62/1/1{-/#} +querying next range at /Table/61/1/10/#/62/1/1 +r19: sending batch 1 Scan to (n1,s1):1 +Del /Table/61/1/10/#/62/1/1/0 +querying next range at /Table/61/1/10/#/62/1/1/0 +r19: sending batch 1 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/10/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/10/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/10/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/10/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/10/#/62/{1-2} +querying next range at /Table/61/1/10/#/62/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +querying next range at /Table/61/1/1/0 +r19: sending batch 10 Del, 1 EndTxn to (n1,s1):1 +output row: [1] +output row: [2] +output row: [3] +output row: [4] +output row: [5] +output row: [6] +output row: [7] +output row: [8] +output row: [9] +output row: [10] +rows affected: 10 + +statement ok +DROP TABLE c; DROP TABLE b; DROP TABLE a diff --git a/pkg/sql/opt/bench/stub_factory.go b/pkg/sql/opt/bench/stub_factory.go index 3f7533aca113..9687ab8e5d91 100644 --- a/pkg/sql/opt/bench/stub_factory.go +++ b/pkg/sql/opt/bench/stub_factory.go @@ -222,3 +222,9 @@ func (f *stubFactory) ConstructUpsert( ) (exec.Node, error) { return struct{}{}, nil } + +func (f *stubFactory) ConstructDelete( + input exec.Node, table cat.Table, fetchCols exec.ColumnOrdinalSet, rowsNeeded bool, +) (exec.Node, error) { + return struct{}{}, nil +} diff --git a/pkg/sql/opt/exec/execbuilder/relational_builder.go b/pkg/sql/opt/exec/execbuilder/relational_builder.go index 53f2f0bd6140..4b4ef1f1993a 100644 --- a/pkg/sql/opt/exec/execbuilder/relational_builder.go +++ b/pkg/sql/opt/exec/execbuilder/relational_builder.go @@ -214,6 +214,9 @@ func (b *Builder) buildRelational(e memo.RelExpr) (execPlan, error) { case *memo.UpsertExpr: ep, err = b.buildUpsert(t) + case *memo.DeleteExpr: + ep, err = b.buildDelete(t) + case *memo.CreateTableExpr: ep, err = b.buildCreateTable(t) @@ -1247,6 +1250,39 @@ func (b *Builder) buildUpsert(ups *memo.UpsertExpr) (execPlan, error) { return ep, nil } +func (b *Builder) buildDelete(del *memo.DeleteExpr) (execPlan, error) { + // Build the input query and ensure that the fetch columns are projected. + input, err := b.buildRelational(del.Input) + if err != nil { + return execPlan{}, err + } + + // Ensure that order of input columns matches order of target table columns. + // + // TODO(andyk): Using ensureColumns here can result in an extra Render. + // Upgrade execution engine to not require this. + input, err = b.ensureColumns(input, del.FetchCols, nil, del.ProvidedPhysical().Ordering) + if err != nil { + return execPlan{}, err + } + + // Construct the Delete node. + md := b.mem.Metadata() + tab := md.Table(del.Table) + fetchColOrds := ordinalSetFromColList(del.FetchCols) + node, err := b.factory.ConstructDelete(input.root, tab, fetchColOrds, del.NeedResults) + if err != nil { + return execPlan{}, err + } + + // Construct the output column map. + ep := execPlan{root: node} + if del.NeedResults { + ep.outputCols = mutationOutputColMap(del) + } + return ep, nil +} + func (b *Builder) buildCreateTable(ct *memo.CreateTableExpr) (execPlan, error) { var root exec.Node if ct.Syntax.As() { diff --git a/pkg/sql/opt/exec/execbuilder/testdata/delete b/pkg/sql/opt/exec/execbuilder/testdata/delete index eece6149145f..286803945fe0 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/delete +++ b/pkg/sql/opt/exec/execbuilder/testdata/delete @@ -57,25 +57,24 @@ SELECT message FROM [SHOW KV TRACE FOR SESSION] query TTT colnames EXPLAIN DELETE FROM unindexed ---- -tree field description -count · · - └── delete · · - │ from unindexed - │ strategy fast deleter - └── render · · - └── scan · · -· table unindexed@primary -· spans ALL +tree field description +count · · + └── delete · · + │ from unindexed + │ strategy fast deleter + └── scan · · +· table unindexed@primary +· spans ALL query TTT -EXPLAIN DELETE FROM unindexed WHERE v = 7 ORDER BY v +EXPLAIN DELETE FROM unindexed WHERE v = 7 ORDER BY v LIMIT 10 ---- count · · └── delete · · │ from unindexed │ strategy deleter - └── nosort · · - │ order +v + └── limit · · + │ count 10 └── scan · · · table unindexed@primary · spans ALL @@ -85,62 +84,58 @@ count · · query TTT EXPLAIN DELETE FROM unindexed WHERE v = 5 LIMIT 10 ---- -count · · - └── delete · · - │ from unindexed - │ strategy deleter - └── limit · · - │ count 10 - └── render · · - └── scan · · -· table unindexed@primary -· spans ALL -· filter v = 5 +count · · + └── delete · · + │ from unindexed + │ strategy deleter + └── limit · · + │ count 10 + └── scan · · +· table unindexed@primary +· spans ALL +· filter v = 5 +# TODO(andyk): Prune columns so that index-join is not necessary. query TTT EXPLAIN DELETE FROM indexed WHERE value = 5 LIMIT 10 ---- -count · · - └── delete · · - │ from indexed - │ strategy deleter - └── limit · · - │ count 10 - └── render · · - └── scan · · -· table indexed@indexed_value_idx -· spans /5-/6 -· limit 10 +count · · + └── delete · · + │ from indexed + │ strategy deleter + └── index-join · · + ├── scan · · + │ table indexed@indexed_value_idx + │ spans /5-/6 + │ limit 10 + └── scan · · +· table indexed@primary query TTT EXPLAIN DELETE FROM indexed LIMIT 10 ---- -count · · - └── delete · · - │ from indexed - │ strategy deleter - └── limit · · - │ count 10 - └── render · · - └── scan · · -· table indexed@primary -· spans ALL -· limit 10 - +count · · + └── delete · · + │ from indexed + │ strategy deleter + └── scan · · +· table indexed@primary +· spans ALL +· limit 10 + +# TODO(andyk): Prune columns so that index-join is not necessary. query TTT EXPLAIN DELETE FROM indexed WHERE value = 5 LIMIT 10 RETURNING id ---- -render · · - └── run · · - └── delete · · - │ from indexed - │ strategy deleter - └── limit · · - │ count 10 - └── index-join · · - ├── scan · · - │ table indexed@indexed_value_idx - │ spans /5-/6 - │ limit 10 - └── scan · · -· table indexed@primary +render · · + └── run · · + └── delete · · + │ from indexed + │ strategy deleter + └── index-join · · + ├── scan · · + │ table indexed@indexed_value_idx + │ spans /5-/6 + │ limit 10 + └── scan · · +· table indexed@primary diff --git a/pkg/sql/opt/exec/execbuilder/testdata/explain b/pkg/sql/opt/exec/execbuilder/testdata/explain index 4dfd857203e9..2502578afbb2 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/explain +++ b/pkg/sql/opt/exec/execbuilder/testdata/explain @@ -512,16 +512,14 @@ render · · query TTTTT EXPLAIN (TYPES) DELETE FROM t WHERE v > 1 ---- -count · · () · - └── delete · · () · - │ from t · · - │ strategy deleter · · - └── render · · (k int) k!=NULL; key(k) - │ render 0 (k)[int] · · - └── scan · · (k int, v int) k!=NULL; v!=NULL; key(k) -· table t@primary · · -· spans ALL · · -· filter ((v)[int] > (1)[int])[bool] · · +count · · () · + └── delete · · () · + │ from t · · + │ strategy deleter · · + └── scan · · (k int, v int) · +· table t@primary · · +· spans ALL · · +· filter ((v)[int] > (1)[int])[bool] · · query TTTTT EXPLAIN (TYPES) UPDATE t SET v = k + 1 WHERE v > 123 diff --git a/pkg/sql/opt/exec/execbuilder/testdata/interleaved b/pkg/sql/opt/exec/execbuilder/testdata/interleaved index daa8c4005ae7..9387929db699 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/interleaved +++ b/pkg/sql/opt/exec/execbuilder/testdata/interleaved @@ -139,3 +139,725 @@ fetched: /p1_0/primary/3/'3'/d -> 3 output row: [3 '3' '3.01' 3] fetched: /p1_0/primary/5/'5' -> NULL output row: [5 '5' NULL NULL] + +# ------------------------------------------------------------------------------ +# Test interleaved delete fast path. +# TODO(andyk): Not yet implemented for cost-based optimizer. +# ------------------------------------------------------------------------------ +subtest InterleavedDeleteFastPath + +statement ok +CREATE TABLE a ( + a_id INT PRIMARY KEY +); + +statement ok +CREATE TABLE b( + b_id INT, + a_id INT, + FOREIGN KEY (a_id) REFERENCES a(a_id) ON UPDATE CASCADE ON DELETE CASCADE, + PRIMARY KEY(a_id, b_id) +) INTERLEAVE IN PARENT a(a_id) + +statement ok +CREATE TABLE c( + c_id INT, + a_id INT, + b_id INT, + FOREIGN KEY (a_id, b_id) REFERENCES b(a_id, b_id) ON UPDATE CASCADE ON DELETE CASCADE, + PRIMARY KEY(a_id, b_id, c_id) +) INTERLEAVE IN PARENT b(a_id, b_id) + +statement ok +INSERT INTO a SELECT generate_series(1,10); +INSERT INTO b(a_id, b_id) SELECT generate_series(1,10), 1 + +statement ok +DELETE FROM a WHERE a_id <= 2 + +query I +SELECT count(*) from a +---- +8 + +query I +SELECT count(*) from b +---- +8 + +query I colnames +SELECT * from a order by a_id +---- +a_id +3 +4 +5 +6 +7 +8 +9 +10 + +query II colnames +SELECT * from b order by a_id, b_id +---- +b_id a_id +1 3 +1 4 +1 5 +1 6 +1 7 +1 8 +1 9 +1 10 + +statement ok +INSERT INTO b(a_id, b_id) select a.a_id, 2 from a; +INSERT INTO c(a_id, b_id, c_id) select a.a_id, b.b_id, 1 from a, b where a.a_id = b.a_id + +query III colnames +SELECT * from c order by a_id, b_id, c_id +---- +c_id a_id b_id +1 3 1 +1 3 2 +1 4 1 +1 4 2 +1 5 1 +1 5 2 +1 6 1 +1 6 2 +1 7 1 +1 7 2 +1 8 1 +1 8 2 +1 9 1 +1 9 2 +1 10 1 +1 10 2 + +statement ok +SET TRACING = on,kv,results; DELETE FROM a where a_id <= 7 and a_id >= 5; SET tracing = off + +# TODO(andyk): Need to implement fast-path delete. +query T +SELECT message FROM [SHOW KV TRACE FOR SESSION] +---- +Scan /Table/61/1/{5-7/#} +querying next range at /Table/61/1/5 +r19: sending batch 1 Scan to (n1,s1):1 +fetched: /a/primary/5 -> NULL +Del /Table/61/1/5/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/5/#/62/{1-2} +querying next range at /Table/61/1/5/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/5/#/62/1/1{-/#} +CascadeScan /Table/61/1/5/#/62/1/2{-/#} +querying next range at /Table/61/1/5/#/62/1/1 +r19: sending batch 2 Scan to (n1,s1):1 +Del /Table/61/1/5/#/62/1/1/0 +Del /Table/61/1/5/#/62/1/2/0 +querying next range at /Table/61/1/5/#/62/1/1/0 +r19: sending batch 2 Del, 1 BeginTxn to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/5/#/62/1/1/#/63/{1-2} +CascadeScan /Table/61/1/5/#/62/1/2/#/63/{1-2} +querying next range at /Table/61/1/5/#/62/1/1/#/63/1 +r19: sending batch 2 Scan to (n1,s1):1 +CascadeScan /Table/61/1/5/#/62/1/1/#/63/1/1{-/#} +CascadeScan /Table/61/1/5/#/62/1/2/#/63/1/1{-/#} +querying next range at /Table/61/1/5/#/62/1/1/#/63/1/1 +r19: sending batch 2 Scan to (n1,s1):1 +Del /Table/61/1/5/#/62/1/1/#/63/1/1/0 +Del /Table/61/1/5/#/62/1/2/#/63/1/1/0 +querying next range at /Table/61/1/5/#/62/1/1/#/63/1/1/0 +r19: sending batch 2 Del to (n1,s1):1 +FKScan /Table/61/1/5/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/5/#/62/1/1/#/63/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +FKScan /Table/61/1/5/#/62/1/2/#/63/{1-2} +querying next range at /Table/61/1/5/#/62/1/2/#/63/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +FKScan /Table/61/1/5/#/62/{1-2} +querying next range at /Table/61/1/5/#/62/1 +r19: sending batch 1 Scan, 2 QueryIntent to (n1,s1):1 +fetched: /a/primary/6 -> NULL +Del /Table/61/1/6/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/6/#/62/{1-2} +querying next range at /Table/61/1/6/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/6/#/62/1/1{-/#} +CascadeScan /Table/61/1/6/#/62/1/2{-/#} +querying next range at /Table/61/1/6/#/62/1/1 +r19: sending batch 2 Scan to (n1,s1):1 +Del /Table/61/1/6/#/62/1/1/0 +Del /Table/61/1/6/#/62/1/2/0 +querying next range at /Table/61/1/6/#/62/1/1/0 +r19: sending batch 2 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/6/#/62/1/1/#/63/{1-2} +CascadeScan /Table/61/1/6/#/62/1/2/#/63/{1-2} +querying next range at /Table/61/1/6/#/62/1/1/#/63/1 +r19: sending batch 2 Scan to (n1,s1):1 +CascadeScan /Table/61/1/6/#/62/1/1/#/63/1/1{-/#} +CascadeScan /Table/61/1/6/#/62/1/2/#/63/1/1{-/#} +querying next range at /Table/61/1/6/#/62/1/1/#/63/1/1 +r19: sending batch 2 Scan to (n1,s1):1 +Del /Table/61/1/6/#/62/1/1/#/63/1/1/0 +Del /Table/61/1/6/#/62/1/2/#/63/1/1/0 +querying next range at /Table/61/1/6/#/62/1/1/#/63/1/1/0 +r19: sending batch 2 Del to (n1,s1):1 +FKScan /Table/61/1/6/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/6/#/62/1/1/#/63/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +FKScan /Table/61/1/6/#/62/1/2/#/63/{1-2} +querying next range at /Table/61/1/6/#/62/1/2/#/63/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +FKScan /Table/61/1/6/#/62/{1-2} +querying next range at /Table/61/1/6/#/62/1 +r19: sending batch 1 Scan, 2 QueryIntent to (n1,s1):1 +fetched: /a/primary/7 -> NULL +Del /Table/61/1/7/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/7/#/62/{1-2} +querying next range at /Table/61/1/7/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/7/#/62/1/1{-/#} +CascadeScan /Table/61/1/7/#/62/1/2{-/#} +querying next range at /Table/61/1/7/#/62/1/1 +r19: sending batch 2 Scan to (n1,s1):1 +Del /Table/61/1/7/#/62/1/1/0 +Del /Table/61/1/7/#/62/1/2/0 +querying next range at /Table/61/1/7/#/62/1/1/0 +r19: sending batch 2 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/7/#/62/1/1/#/63/{1-2} +CascadeScan /Table/61/1/7/#/62/1/2/#/63/{1-2} +querying next range at /Table/61/1/7/#/62/1/1/#/63/1 +r19: sending batch 2 Scan to (n1,s1):1 +CascadeScan /Table/61/1/7/#/62/1/1/#/63/1/1{-/#} +CascadeScan /Table/61/1/7/#/62/1/2/#/63/1/1{-/#} +querying next range at /Table/61/1/7/#/62/1/1/#/63/1/1 +r19: sending batch 2 Scan to (n1,s1):1 +Del /Table/61/1/7/#/62/1/1/#/63/1/1/0 +Del /Table/61/1/7/#/62/1/2/#/63/1/1/0 +querying next range at /Table/61/1/7/#/62/1/1/#/63/1/1/0 +r19: sending batch 2 Del to (n1,s1):1 +FKScan /Table/61/1/7/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/7/#/62/1/1/#/63/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +FKScan /Table/61/1/7/#/62/1/2/#/63/{1-2} +querying next range at /Table/61/1/7/#/62/1/2/#/63/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +FKScan /Table/61/1/7/#/62/{1-2} +querying next range at /Table/61/1/7/#/62/1 +r19: sending batch 1 Scan, 2 QueryIntent to (n1,s1):1 +querying next range at /Table/61/1/5/0 +r19: sending batch 3 Del, 1 EndTxn to (n1,s1):1 +fast path completed +rows affected: 3 + +query II colnames +select * from b order by a_id, b_id +---- +b_id a_id +1 3 +2 3 +1 4 +2 4 +1 8 +2 8 +1 9 +2 9 +1 10 +2 10 + +query III colnames +select * from c order by a_id, b_id, c_id +---- +c_id a_id b_id +1 3 1 +1 3 2 +1 4 1 +1 4 2 +1 8 1 +1 8 2 +1 9 1 +1 9 2 +1 10 1 +1 10 2 + +statement ok +SET TRACING = on,kv,results; DELETE FROM a; SET tracing = off + +query T +select message FROM [SHOW KV TRACE FOR SESSION] +---- +Scan /Table/61/{1-2} +querying next range at /Table/61/1 +r19: sending batch 1 Scan to (n1,s1):1 +fetched: /a/primary/3 -> NULL +Del /Table/61/1/3/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/3/#/62/{1-2} +querying next range at /Table/61/1/3/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/3/#/62/1/1{-/#} +CascadeScan /Table/61/1/3/#/62/1/2{-/#} +querying next range at /Table/61/1/3/#/62/1/1 +r19: sending batch 2 Scan to (n1,s1):1 +Del /Table/61/1/3/#/62/1/1/0 +Del /Table/61/1/3/#/62/1/2/0 +querying next range at /Table/61/1/3/#/62/1/1/0 +r19: sending batch 2 Del, 1 BeginTxn to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/3/#/62/1/1/#/63/{1-2} +CascadeScan /Table/61/1/3/#/62/1/2/#/63/{1-2} +querying next range at /Table/61/1/3/#/62/1/1/#/63/1 +r19: sending batch 2 Scan to (n1,s1):1 +CascadeScan /Table/61/1/3/#/62/1/1/#/63/1/1{-/#} +CascadeScan /Table/61/1/3/#/62/1/2/#/63/1/1{-/#} +querying next range at /Table/61/1/3/#/62/1/1/#/63/1/1 +r19: sending batch 2 Scan to (n1,s1):1 +Del /Table/61/1/3/#/62/1/1/#/63/1/1/0 +Del /Table/61/1/3/#/62/1/2/#/63/1/1/0 +querying next range at /Table/61/1/3/#/62/1/1/#/63/1/1/0 +r19: sending batch 2 Del to (n1,s1):1 +FKScan /Table/61/1/3/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/3/#/62/1/1/#/63/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +FKScan /Table/61/1/3/#/62/1/2/#/63/{1-2} +querying next range at /Table/61/1/3/#/62/1/2/#/63/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +FKScan /Table/61/1/3/#/62/{1-2} +querying next range at /Table/61/1/3/#/62/1 +r19: sending batch 1 Scan, 2 QueryIntent to (n1,s1):1 +fetched: /a/primary/4 -> NULL +Del /Table/61/1/4/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/4/#/62/{1-2} +querying next range at /Table/61/1/4/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/4/#/62/1/1{-/#} +CascadeScan /Table/61/1/4/#/62/1/2{-/#} +querying next range at /Table/61/1/4/#/62/1/1 +r19: sending batch 2 Scan to (n1,s1):1 +Del /Table/61/1/4/#/62/1/1/0 +Del /Table/61/1/4/#/62/1/2/0 +querying next range at /Table/61/1/4/#/62/1/1/0 +r19: sending batch 2 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/4/#/62/1/1/#/63/{1-2} +CascadeScan /Table/61/1/4/#/62/1/2/#/63/{1-2} +querying next range at /Table/61/1/4/#/62/1/1/#/63/1 +r19: sending batch 2 Scan to (n1,s1):1 +CascadeScan /Table/61/1/4/#/62/1/1/#/63/1/1{-/#} +CascadeScan /Table/61/1/4/#/62/1/2/#/63/1/1{-/#} +querying next range at /Table/61/1/4/#/62/1/1/#/63/1/1 +r19: sending batch 2 Scan to (n1,s1):1 +Del /Table/61/1/4/#/62/1/1/#/63/1/1/0 +Del /Table/61/1/4/#/62/1/2/#/63/1/1/0 +querying next range at /Table/61/1/4/#/62/1/1/#/63/1/1/0 +r19: sending batch 2 Del to (n1,s1):1 +FKScan /Table/61/1/4/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/4/#/62/1/1/#/63/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +FKScan /Table/61/1/4/#/62/1/2/#/63/{1-2} +querying next range at /Table/61/1/4/#/62/1/2/#/63/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +FKScan /Table/61/1/4/#/62/{1-2} +querying next range at /Table/61/1/4/#/62/1 +r19: sending batch 1 Scan, 2 QueryIntent to (n1,s1):1 +fetched: /a/primary/8 -> NULL +Del /Table/61/1/8/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/8/#/62/{1-2} +querying next range at /Table/61/1/8/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/8/#/62/1/1{-/#} +CascadeScan /Table/61/1/8/#/62/1/2{-/#} +querying next range at /Table/61/1/8/#/62/1/1 +r19: sending batch 2 Scan to (n1,s1):1 +Del /Table/61/1/8/#/62/1/1/0 +Del /Table/61/1/8/#/62/1/2/0 +querying next range at /Table/61/1/8/#/62/1/1/0 +r19: sending batch 2 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/8/#/62/1/1/#/63/{1-2} +CascadeScan /Table/61/1/8/#/62/1/2/#/63/{1-2} +querying next range at /Table/61/1/8/#/62/1/1/#/63/1 +r19: sending batch 2 Scan to (n1,s1):1 +CascadeScan /Table/61/1/8/#/62/1/1/#/63/1/1{-/#} +CascadeScan /Table/61/1/8/#/62/1/2/#/63/1/1{-/#} +querying next range at /Table/61/1/8/#/62/1/1/#/63/1/1 +r19: sending batch 2 Scan to (n1,s1):1 +Del /Table/61/1/8/#/62/1/1/#/63/1/1/0 +Del /Table/61/1/8/#/62/1/2/#/63/1/1/0 +querying next range at /Table/61/1/8/#/62/1/1/#/63/1/1/0 +r19: sending batch 2 Del to (n1,s1):1 +FKScan /Table/61/1/8/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/8/#/62/1/1/#/63/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +FKScan /Table/61/1/8/#/62/1/2/#/63/{1-2} +querying next range at /Table/61/1/8/#/62/1/2/#/63/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +FKScan /Table/61/1/8/#/62/{1-2} +querying next range at /Table/61/1/8/#/62/1 +r19: sending batch 1 Scan, 2 QueryIntent to (n1,s1):1 +fetched: /a/primary/9 -> NULL +Del /Table/61/1/9/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/9/#/62/{1-2} +querying next range at /Table/61/1/9/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/9/#/62/1/1{-/#} +CascadeScan /Table/61/1/9/#/62/1/2{-/#} +querying next range at /Table/61/1/9/#/62/1/1 +r19: sending batch 2 Scan to (n1,s1):1 +Del /Table/61/1/9/#/62/1/1/0 +Del /Table/61/1/9/#/62/1/2/0 +querying next range at /Table/61/1/9/#/62/1/1/0 +r19: sending batch 2 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/9/#/62/1/1/#/63/{1-2} +CascadeScan /Table/61/1/9/#/62/1/2/#/63/{1-2} +querying next range at /Table/61/1/9/#/62/1/1/#/63/1 +r19: sending batch 2 Scan to (n1,s1):1 +CascadeScan /Table/61/1/9/#/62/1/1/#/63/1/1{-/#} +CascadeScan /Table/61/1/9/#/62/1/2/#/63/1/1{-/#} +querying next range at /Table/61/1/9/#/62/1/1/#/63/1/1 +r19: sending batch 2 Scan to (n1,s1):1 +Del /Table/61/1/9/#/62/1/1/#/63/1/1/0 +Del /Table/61/1/9/#/62/1/2/#/63/1/1/0 +querying next range at /Table/61/1/9/#/62/1/1/#/63/1/1/0 +r19: sending batch 2 Del to (n1,s1):1 +FKScan /Table/61/1/9/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/9/#/62/1/1/#/63/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +FKScan /Table/61/1/9/#/62/1/2/#/63/{1-2} +querying next range at /Table/61/1/9/#/62/1/2/#/63/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +FKScan /Table/61/1/9/#/62/{1-2} +querying next range at /Table/61/1/9/#/62/1 +r19: sending batch 1 Scan, 2 QueryIntent to (n1,s1):1 +fetched: /a/primary/10 -> NULL +Del /Table/61/1/10/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/10/#/62/{1-2} +querying next range at /Table/61/1/10/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/10/#/62/1/1{-/#} +CascadeScan /Table/61/1/10/#/62/1/2{-/#} +querying next range at /Table/61/1/10/#/62/1/1 +r19: sending batch 2 Scan to (n1,s1):1 +Del /Table/61/1/10/#/62/1/1/0 +Del /Table/61/1/10/#/62/1/2/0 +querying next range at /Table/61/1/10/#/62/1/1/0 +r19: sending batch 2 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/10/#/62/1/1/#/63/{1-2} +CascadeScan /Table/61/1/10/#/62/1/2/#/63/{1-2} +querying next range at /Table/61/1/10/#/62/1/1/#/63/1 +r19: sending batch 2 Scan to (n1,s1):1 +CascadeScan /Table/61/1/10/#/62/1/1/#/63/1/1{-/#} +CascadeScan /Table/61/1/10/#/62/1/2/#/63/1/1{-/#} +querying next range at /Table/61/1/10/#/62/1/1/#/63/1/1 +r19: sending batch 2 Scan to (n1,s1):1 +Del /Table/61/1/10/#/62/1/1/#/63/1/1/0 +Del /Table/61/1/10/#/62/1/2/#/63/1/1/0 +querying next range at /Table/61/1/10/#/62/1/1/#/63/1/1/0 +r19: sending batch 2 Del to (n1,s1):1 +FKScan /Table/61/1/10/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/10/#/62/1/1/#/63/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +FKScan /Table/61/1/10/#/62/1/2/#/63/{1-2} +querying next range at /Table/61/1/10/#/62/1/2/#/63/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +FKScan /Table/61/1/10/#/62/{1-2} +querying next range at /Table/61/1/10/#/62/1 +r19: sending batch 1 Scan, 2 QueryIntent to (n1,s1):1 +querying next range at /Table/61/1/3/0 +r19: sending batch 5 Del, 1 EndTxn to (n1,s1):1 +fast path completed +rows affected: 5 + +query II colnames +select * from b order by a_id, b_id +---- +b_id a_id + +query III colnames +select * from c order by a_id, b_id, c_id +---- +c_id a_id b_id + +statement ok +INSERT INTO a SELECT generate_series(1,10); +INSERT INTO b(a_id, b_id) SELECT generate_series(1,10), 1 + +statement ok +SET TRACING = on,kv,results; + +query I +delete from a returning * +---- +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 + +statement ok +SET TRACING=off; + +query T +select message FROM [SHOW KV TRACE FOR SESSION]; +---- +Scan /Table/61/{1-2} +querying next range at /Table/61/1 +r19: sending batch 1 Scan to (n1,s1):1 +fetched: /a/primary/1 -> NULL +Del /Table/61/1/1/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/1/#/62/{1-2} +querying next range at /Table/61/1/1/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/1/#/62/1/1{-/#} +querying next range at /Table/61/1/1/#/62/1/1 +r19: sending batch 1 Scan to (n1,s1):1 +Del /Table/61/1/1/#/62/1/1/0 +querying next range at /Table/61/1/1/#/62/1/1/0 +r19: sending batch 1 Del, 1 BeginTxn to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/1/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/1/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/1/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/1/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/1/#/62/{1-2} +querying next range at /Table/61/1/1/#/62/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +fetched: /a/primary/2 -> NULL +Del /Table/61/1/2/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/2/#/62/{1-2} +querying next range at /Table/61/1/2/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/2/#/62/1/1{-/#} +querying next range at /Table/61/1/2/#/62/1/1 +r19: sending batch 1 Scan to (n1,s1):1 +Del /Table/61/1/2/#/62/1/1/0 +querying next range at /Table/61/1/2/#/62/1/1/0 +r19: sending batch 1 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/2/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/2/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/2/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/2/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/2/#/62/{1-2} +querying next range at /Table/61/1/2/#/62/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +fetched: /a/primary/3 -> NULL +Del /Table/61/1/3/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/3/#/62/{1-2} +querying next range at /Table/61/1/3/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/3/#/62/1/1{-/#} +querying next range at /Table/61/1/3/#/62/1/1 +r19: sending batch 1 Scan to (n1,s1):1 +Del /Table/61/1/3/#/62/1/1/0 +querying next range at /Table/61/1/3/#/62/1/1/0 +r19: sending batch 1 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/3/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/3/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/3/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/3/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/3/#/62/{1-2} +querying next range at /Table/61/1/3/#/62/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +fetched: /a/primary/4 -> NULL +Del /Table/61/1/4/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/4/#/62/{1-2} +querying next range at /Table/61/1/4/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/4/#/62/1/1{-/#} +querying next range at /Table/61/1/4/#/62/1/1 +r19: sending batch 1 Scan to (n1,s1):1 +Del /Table/61/1/4/#/62/1/1/0 +querying next range at /Table/61/1/4/#/62/1/1/0 +r19: sending batch 1 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/4/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/4/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/4/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/4/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/4/#/62/{1-2} +querying next range at /Table/61/1/4/#/62/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +fetched: /a/primary/5 -> NULL +Del /Table/61/1/5/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/5/#/62/{1-2} +querying next range at /Table/61/1/5/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/5/#/62/1/1{-/#} +querying next range at /Table/61/1/5/#/62/1/1 +r19: sending batch 1 Scan to (n1,s1):1 +Del /Table/61/1/5/#/62/1/1/0 +querying next range at /Table/61/1/5/#/62/1/1/0 +r19: sending batch 1 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/5/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/5/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/5/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/5/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/5/#/62/{1-2} +querying next range at /Table/61/1/5/#/62/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +fetched: /a/primary/6 -> NULL +Del /Table/61/1/6/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/6/#/62/{1-2} +querying next range at /Table/61/1/6/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/6/#/62/1/1{-/#} +querying next range at /Table/61/1/6/#/62/1/1 +r19: sending batch 1 Scan to (n1,s1):1 +Del /Table/61/1/6/#/62/1/1/0 +querying next range at /Table/61/1/6/#/62/1/1/0 +r19: sending batch 1 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/6/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/6/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/6/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/6/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/6/#/62/{1-2} +querying next range at /Table/61/1/6/#/62/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +fetched: /a/primary/7 -> NULL +Del /Table/61/1/7/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/7/#/62/{1-2} +querying next range at /Table/61/1/7/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/7/#/62/1/1{-/#} +querying next range at /Table/61/1/7/#/62/1/1 +r19: sending batch 1 Scan to (n1,s1):1 +Del /Table/61/1/7/#/62/1/1/0 +querying next range at /Table/61/1/7/#/62/1/1/0 +r19: sending batch 1 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/7/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/7/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/7/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/7/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/7/#/62/{1-2} +querying next range at /Table/61/1/7/#/62/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +fetched: /a/primary/8 -> NULL +Del /Table/61/1/8/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/8/#/62/{1-2} +querying next range at /Table/61/1/8/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/8/#/62/1/1{-/#} +querying next range at /Table/61/1/8/#/62/1/1 +r19: sending batch 1 Scan to (n1,s1):1 +Del /Table/61/1/8/#/62/1/1/0 +querying next range at /Table/61/1/8/#/62/1/1/0 +r19: sending batch 1 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/8/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/8/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/8/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/8/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/8/#/62/{1-2} +querying next range at /Table/61/1/8/#/62/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +fetched: /a/primary/9 -> NULL +Del /Table/61/1/9/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/9/#/62/{1-2} +querying next range at /Table/61/1/9/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/9/#/62/1/1{-/#} +querying next range at /Table/61/1/9/#/62/1/1 +r19: sending batch 1 Scan to (n1,s1):1 +Del /Table/61/1/9/#/62/1/1/0 +querying next range at /Table/61/1/9/#/62/1/1/0 +r19: sending batch 1 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/9/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/9/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/9/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/9/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/9/#/62/{1-2} +querying next range at /Table/61/1/9/#/62/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +fetched: /a/primary/10 -> NULL +Del /Table/61/1/10/0 +cascading delete into table: 62 using index: 1 +CascadeScan /Table/61/1/10/#/62/{1-2} +querying next range at /Table/61/1/10/#/62/1 +r19: sending batch 1 Scan to (n1,s1):1 +CascadeScan /Table/61/1/10/#/62/1/1{-/#} +querying next range at /Table/61/1/10/#/62/1/1 +r19: sending batch 1 Scan to (n1,s1):1 +Del /Table/61/1/10/#/62/1/1/0 +querying next range at /Table/61/1/10/#/62/1/1/0 +r19: sending batch 1 Del to (n1,s1):1 +cascading delete into table: 63 using index: 1 +CascadeScan /Table/61/1/10/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/10/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/10/#/62/1/1/#/63/{1-2} +querying next range at /Table/61/1/10/#/62/1/1/#/63/1 +r19: sending batch 1 Scan to (n1,s1):1 +FKScan /Table/61/1/10/#/62/{1-2} +querying next range at /Table/61/1/10/#/62/1 +r19: sending batch 1 Scan, 1 QueryIntent to (n1,s1):1 +querying next range at /Table/61/1/1/0 +r19: sending batch 10 Del to (n1,s1):1 +output row: [1] +output row: [2] +output row: [3] +output row: [4] +output row: [5] +output row: [6] +output row: [7] +output row: [8] +output row: [9] +output row: [10] +rows affected: 10 +querying next range at /Table/61/1/1/0 +r19: sending batch 1 EndTxn, 10 QueryIntent to (n1,s1):1 + +statement ok +DROP TABLE c; DROP TABLE b; DROP TABLE a diff --git a/pkg/sql/opt/exec/execbuilder/testdata/orderby b/pkg/sql/opt/exec/execbuilder/testdata/orderby index b6a823b2b5c1..8135e09c90a1 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/orderby +++ b/pkg/sql/opt/exec/execbuilder/testdata/orderby @@ -497,15 +497,15 @@ render · · (b) · query TTTTT EXPLAIN (VERBOSE) DELETE FROM t WHERE a = 3 RETURNING b ---- -render · · (b) key() - │ render 0 test.public.t.b · · - └── run · · (a, b, c) a=CONST; key() - └── delete · · (a, b, c) a=CONST; key() - │ from t · · - │ strategy deleter · · - └── scan · · (a, b, c) a=CONST; key() -· table t@primary · · -· spans /3-/3/# · · +render · · (b) · + │ render 0 b · · + └── run · · (a, b, c) · + └── delete · · (a, b, c) · + │ from t · · + │ strategy deleter · · + └── scan · · (a, b, c) · +· table t@primary · · +· spans /3-/3/# · · query TTTTT EXPLAIN (VERBOSE) UPDATE t SET c = TRUE RETURNING b diff --git a/pkg/sql/opt/exec/execbuilder/testdata/select_index b/pkg/sql/opt/exec/execbuilder/testdata/select_index index e12c4498758d..e3149fcab1a5 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/select_index +++ b/pkg/sql/opt/exec/execbuilder/testdata/select_index @@ -1431,14 +1431,13 @@ count · · query TTT EXPLAIN DELETE FROM t4 WHERE a = 10 and b = 20 ---- -count · · - └── delete · · - │ from t4 - │ strategy fast deleter - └── render · · - └── scan · · -· table t4@primary -· spans /10/20-/10/20/# +count · · + └── delete · · + │ from t4 + │ strategy fast deleter + └── scan · · +· table t4@primary +· spans /10/20-/10/20/# # Optimization should not be applied for non point lookups. query TTT diff --git a/pkg/sql/opt/exec/factory.go b/pkg/sql/opt/exec/factory.go index 0ae4f91bae7d..8366e6acc9e2 100644 --- a/pkg/sql/opt/exec/factory.go +++ b/pkg/sql/opt/exec/factory.go @@ -297,6 +297,18 @@ type Factory interface { rowsNeeded bool, ) (Node, error) + // ConstructDelete creates a node that implements a DELETE statement. The + // input contains columns that were fetched from the target table, and that + // will be deleted. + // + // The fetchCols set contains the ordinal positions of the fetch columns in + // the target table. The input must contain those columns in the same order + // as they appear in the table schema. The rowsNeeded parameter is true if a + // RETURNING clause needs the deleted row(s) as output. + ConstructDelete( + input Node, table cat.Table, fetchCols ColumnOrdinalSet, rowsNeeded bool, + ) (Node, error) + // ConstructCreateTable returns a node that implements a CREATE TABLE // statement. ConstructCreateTable(input Node, schema cat.Schema, ct *tree.CreateTable) (Node, error) diff --git a/pkg/sql/opt_exec_factory.go b/pkg/sql/opt_exec_factory.go index 2f7db4c916c8..86f280e32b55 100644 --- a/pkg/sql/opt_exec_factory.go +++ b/pkg/sql/opt_exec_factory.go @@ -1142,6 +1142,75 @@ func (ef *execFactory) ConstructUpsert( return &rowCountNode{source: ups}, nil } +func (ef *execFactory) ConstructDelete( + input exec.Node, table cat.Table, fetchCols exec.ColumnOrdinalSet, rowsNeeded bool, +) (exec.Node, error) { + // Derive table and column descriptors. + tabDesc := table.(*optTable).desc + fetchColDescs := makeColDescList(table, fetchCols) + + // Determine the foreign key tables involved in the update. + fkTables, err := row.TablesNeededForFKs( + ef.planner.extendedEvalCtx.Context, + *tabDesc, + row.CheckDeletes, + ef.planner.LookupTableByID, + ef.planner.CheckPrivilege, + ef.planner.analyzeExpr, + ) + if err != nil { + return nil, err + } + + // Create the table deleter, which does the bulk of the work. In the HP, + // the deleter derives the columns that need to be fetched. By contrast, the + // CBO will have already determined the set of fetch columns, and passes + // those sets into the deleter (which will basically be a no-op). + rd, err := row.MakeDeleter( + ef.planner.txn, + tabDesc, + fkTables, + fetchColDescs, + row.CheckFKs, + ef.planner.EvalContext(), + &ef.planner.alloc, + ) + if err != nil { + return nil, err + } + + // Determine the relational type of the generated delete node. + // If rows are not needed, no columns are returned. + var returnCols sqlbase.ResultColumns + if rowsNeeded { + // Delete always returns all non-mutation columns, in the same order they + // are defined in the table. + returnCols = sqlbase.ResultColumnsFromColDescs(tabDesc.Columns) + } + + // Now make a delete node. We use a pool. + del := deleteNodePool.Get().(*deleteNode) + *del = deleteNode{ + source: input.(planNode), + columns: returnCols, + run: deleteRun{ + td: tableDeleter{rd: rd, alloc: &ef.planner.alloc}, + rowsNeeded: rowsNeeded, + }, + } + + // Serialize the data-modifying plan to ensure that no data is observed that + // hasn't been validated first. See the comments on BatchedNext() in + // plan_batch.go. + if rowsNeeded { + return &spoolNode{source: &serializeNode{source: del}}, nil + } + + // We could use serializeNode here, but using rowCountNode is an + // optimization that saves on calls to Next() by the caller. + return &rowCountNode{source: del}, nil +} + func (ef *execFactory) ConstructCreateTable( input exec.Node, schema cat.Schema, ct *tree.CreateTable, ) (exec.Node, error) { diff --git a/pkg/sql/plan_opt.go b/pkg/sql/plan_opt.go index 154848bce756..1645f776c0e0 100644 --- a/pkg/sql/plan_opt.go +++ b/pkg/sql/plan_opt.go @@ -117,7 +117,7 @@ func checkOptSupportForTopStatement(AST tree.Statement) error { switch AST.(type) { case *tree.ParenSelect, *tree.Select, *tree.SelectClause, *tree.UnionClause, *tree.ValuesClause, *tree.Explain, - *tree.Insert, *tree.Update, *tree.CreateTable: + *tree.Insert, *tree.Update, *tree.Delete, *tree.CreateTable: return nil default: