statement ok
CREATE TABLE kv (
  k INT PRIMARY KEY,
  v INT,
  UNIQUE INDEX foo (v),
  INDEX bar (k, v)
)

statement count 4
INSERT INTO kv VALUES (1, 2), (3, 4), (5, 6), (7, 8)

statement ok
CREATE VIEW kview AS SELECT k,v FROM kv

statement error pgcode 42809 pq: "test.public.kview" is not a table
CREATE FUNCTION f_view() RETURNS RECORD AS
$$
  DELETE FROM kview;
$$ LANGUAGE SQL;

statement ok
CREATE FUNCTION f_kv_predicate() RETURNS SETOF RECORD AS
$$
  DELETE FROM kv WHERE k=3 OR v=6 RETURNING k, v;
$$ LANGUAGE SQL;

query T rowsort
SELECT f_kv_predicate()
----
(3,4)
(5,6)

query II rowsort
SELECT * FROM kv
----
1 2
7 8

# Delete non-existent values.
query T rowsort
SELECT f_kv_predicate()
----

statement ok
CREATE FUNCTION f_kv_all() RETURNS SETOF RECORD AS
$$
  DELETE FROM kv RETURNING *;
$$ LANGUAGE SQL;

query II rowsort
SELECT * FROM f_kv_all() AS foo(a INT, b INT)
----
1 2
7 8

query II
SELECT * FROM kv
----

statement ok
CREATE FUNCTION f_kv2(i INT, j INT) RETURNS SETOF RECORD AS
$$
  DELETE FROM kv WHERE k = i RETURNING k, v;
  DELETE FROM kv WHERE v = j RETURNING k, v;
$$ LANGUAGE SQL;

statement ok
INSERT INTO kv VALUES (1, 2), (3, 4), (5, 6), (7, 8)

statement ok
SELECT f_kv2(1, 9)

query II rowsort
SELECT * FROM kv
----
3  4
5  6
7  8

statement ok
SELECT f_kv2(i, j) FROM (VALUES (3, 0), (0, 8)) v(i, j)

query II
SELECT * FROM kv
----
5  6

statement ok
CREATE FUNCTION f_no_op(i INT, j INT) RETURNS SETOF RECORD AS
$$
  INSERT INTO kv VALUES (i, j);
  DELETE FROM kv WHERE k=i AND v=j RETURNING k, v;
$$ LANGUAGE SQL;

statement ok
SELECT f_no_op(9, 10)

query II
SELECT * FROM kv
----
5  6

statement ok
CREATE TABLE unindexed (
  k INT PRIMARY KEY,
  v INT
)

statement count 4
INSERT INTO unindexed VALUES (1, 2), (3, 4), (5, 6), (7, 8)

statement ok
CREATE FUNCTION f_unindexed_predicate() RETURNS SETOF RECORD AS
$$
  DELETE FROM unindexed WHERE k=3 OR v=6 RETURNING k, v;
$$ LANGUAGE SQL;

query T rowsort
SELECT f_unindexed_predicate()
----
(3,4)
(5,6)

query II rowsort
SELECT * FROM unindexed
----
1 2
7 8

# Delete non-existent values.
query T rowsort
SELECT f_unindexed_predicate()
----

statement ok
CREATE FUNCTION f_unindexed_all() RETURNS SETOF RECORD AS
$$
  DELETE FROM unindexed RETURNING *;
$$ LANGUAGE SQL;

query II rowsort
SELECT * FROM f_unindexed_all() AS foo(a INT, b INT);
----
1 2
7 8

query II
SELECT * FROM unindexed;
----

statement ok
INSERT INTO unindexed VALUES (1, 9), (8, 2), (3, 7), (6, 4)

statement ok
CREATE FUNCTION f_orderby1() RETURNS SETOF RECORD AS
$$
  DELETE FROM unindexed WHERE k > 1 AND v < 7 ORDER BY v DESC LIMIT 2 RETURNING v,k;
$$ LANGUAGE SQL;

query II nosort
SELECT * FROM f_orderby1() AS foo(a INT, b INT);
----
4  6
2  8

statement ok
CREATE FUNCTION f_orderby2() RETURNS SETOF RECORD AS
$$
  DELETE FROM unindexed ORDER BY v LIMIT 2 RETURNING k,v;
$$ LANGUAGE SQL;

query II nosort
SELECT * FROM f_orderby2() AS foo(a INT, b INT);
----
3  7
1  9

statement count 4
INSERT INTO unindexed VALUES (1, 2), (3, 4), (5, 6), (7, 8)

statement ok
CREATE FUNCTION f_limit(i INT) RETURNS SETOF RECORD AS
$$
  DELETE FROM unindexed LIMIT i RETURNING v
$$ LANGUAGE SQL;

query I
SELECT count(*) FROM f_limit(2) AS foo(v INT);
----
2

query I
SELECT count(*) FROM f_limit(1) AS foo(v INT);
----
1

query I
SELECT count(*) FROM f_limit(5) AS foo(v INT);
----
1


subtest delete_using

statement ok
CREATE TABLE u_a (
    a INT NOT NULL PRIMARY KEY,
    b STRING,
    c INT
)

statement ok
CREATE TABLE u_b (
  a INT NOT NULL PRIMARY KEY,
  b STRING
)

statement ok
CREATE TABLE u_c (
  a INT NOT NULL PRIMARY KEY,
  b STRING,
  c INT
)

statement ok
CREATE TABLE u_d (
  a INT,
  b INT
)

statement ok
INSERT INTO u_a VALUES (1, 'a', 10), (2, 'b', 20), (3, 'c', 30), (4, 'd', 40)

statement ok
INSERT INTO u_b VALUES (10, 'a'), (20, 'b'), (30, 'c'), (40, 'd')

statement ok
INSERT INTO u_c VALUES (1, 'a', 10), (2, 'b', 50), (3, 'c', 50), (4, 'd', 40)

# Test a join with a filter.
statement ok
CREATE FUNCTION f_using_filter(s STRING) RETURNS SETOF RECORD AS
$$
  DELETE FROM u_a USING u_b WHERE c = u_b.a AND u_b.b = s RETURNING u_a.a, u_a.b, u_a.c, u_b.*
$$ LANGUAGE SQL;

query T
SELECT f_using_filter('d');
----
(4,d,40,40,d)

query ITI rowsort
SELECT * FROM u_a;
----
1  a  10
2  b  20
3  c  30

# Test a self join.
statement ok
INSERT INTO u_a VALUES (5, 'd', 5), (6, 'e', 6)

statement ok
CREATE FUNCTION f_using_self_join() RETURNS SETOF RECORD AS
$$
  DELETE FROM u_a USING u_a u_a2 WHERE u_a.a = u_a2.c RETURNING *
$$ LANGUAGE SQL;

query T rowsort
SELECT f_using_self_join();
----
(5,d,5,5,d,5)
(6,e,6,6,e,6)

query ITI rowsort
SELECT * FROM u_a;
----
1  a  10
2  b  20
3  c  30

# Test when USING uses multiple tables.

statement ok
INSERT INTO u_c VALUES (30, 'a', 1)

statement ok
CREATE FUNCTION f_using_multi() RETURNS SETOF RECORD AS
$$
DELETE FROM u_a USING u_b, u_c WHERE u_a.c = u_b.a AND u_a.c = u_c.a RETURNING *
$$ LANGUAGE SQL;

query T rowsort
SELECT f_using_multi();
----
(3,c,30,30,c,30,a,1)

query ITI rowsort
SELECT * FROM u_a;
----
1  a  10
2  b  20

subtest end
