statement ok
CREATE TABLE t (a INT PRIMARY KEY, b INT DEFAULT 0);

statement error pgcode 42P13 pq: return type mismatch in function declared to return record\nDETAIL: Function's final statement must be SELECT or INSERT/UPDATE/DELETE RETURNING.
CREATE FUNCTION f_err() RETURNS RECORD AS
$$
  INSERT INTO t VALUES (1,2);
$$ LANGUAGE SQL;

statement ok
CREATE FUNCTION f_void() RETURNS VOID AS
$$
  INSERT INTO t VALUES (0,1);
$$ LANGUAGE SQL;

query T
SELECT f_void();
----
NULL

# Note: This does not error in postgres until the function is executed.
statement error pgcode 23502 missing "a" primary key column
CREATE FUNCTION f_err(b INT) RETURNS RECORD AS
$$
  INSERT INTO t (b) VALUES (b);
  SELECT * FROM t WHERE t.a=a AND t.b=b;
$$ LANGUAGE SQL;

statement error pgcode 22023 pq: volatile statement not allowed in stable function
CREATE FUNCTION f_err(i INT, j INT) RETURNS RECORD STABLE AS
$$
  INSERT INTO t VALUES (i,j) RETURNING *;
$$ LANGUAGE SQL;

statement error pgcode 22023 pq: volatile statement not allowed in immutable function
CREATE FUNCTION f_err(i INT, j INT) RETURNS RECORD IMMUTABLE AS
$$
  INSERT INTO t VALUES (i,j) RETURNING *;
$$ LANGUAGE SQL;

statement ok
CREATE FUNCTION f_insert(i INT, j INT) RETURNS RECORD AS
$$
  INSERT INTO t VALUES (i, j);
  SELECT * FROM t WHERE t.a=i AND t.b=j;
$$ LANGUAGE SQL;

query T
SELECT f_insert(1,2);
----
(1,2)

query T
SELECT f_insert(3,4);
----
(3,4)

statement error pgcode 23505 duplicate key
SELECT f_insert(3,4);

query II rowsort
SELECT * FROM t;
----
0 1
1 2
3 4

statement ok
CREATE FUNCTION f_insert_select(i INT, j INT) RETURNS SETOF RECORD AS
$$
  INSERT INTO t VALUES (i, j);
  SELECT * FROM t WHERE a > 3;
$$ LANGUAGE SQL;

# UDF invocations see inserts from previous UDF invocations in the same query.
query II rowsort
SELECT * FROM f_insert_select(5,6) AS t1(a INT, b INT) UNION ALL SELECT * FROM f_insert_select(7,8) AS t2(a INT, b INT)
----
5 6
5 6
7 8

statement ok
CREATE FUNCTION f_returning(a INT, b INT) RETURNS RECORD AS
$$
  INSERT INTO t VALUES (a, b) RETURNING a, b as foo, t.a, test.t.b;
$$ LANGUAGE SQL;

query T colnames
select f_returning(15,16);
----
f_returning
(15,16,15,16)

statement ok
CREATE FUNCTION f_returning_star(a INT, b INT) RETURNS RECORD AS
$$
  INSERT INTO t VALUES (a, b) RETURNING *;
$$ LANGUAGE SQL;

query T colnames
SELECT f_returning_star(17,18);
----
f_returning_star
(17,18)

query II colnames
SELECT * FROM f_returning_star(19,20) AS foo(a INT, b INT);
----
a b
19 20

statement ok
CREATE FUNCTION f_default(a INT) RETURNS RECORD AS
$$
  INSERT INTO t VALUES (a, DEFAULT) RETURNING *;
$$ LANGUAGE SQL;

query T
SELECT f_default(21);
----
(21,0)

subtest multi_insert

statement ok
CREATE TABLE t_multi (a INT PRIMARY KEY, b INT DEFAULT 0);

statement ok
CREATE FUNCTION f_2values(i INT, j INT, m INT, n INT) RETURNS SETOF RECORD AS
$$
  INSERT INTO t_multi VALUES (i, j), (m, n);
  SELECT * FROM t_multi WHERE t_multi.a=i OR t_multi.a=m;
$$ LANGUAGE SQL;

query T rowsort
SELECT f_2values(7,8,9,10);
----
(7,8)
(9,10)

statement error pgcode 23505 pq: duplicate key value violates unique constraint "t_multi_pkey"
SELECT f_2values(42,42,42,42);

statement ok
CREATE FUNCTION f_2inserts(i INT, j INT, m INT, n INT) RETURNS SETOF RECORD AS
$$
  INSERT INTO t_multi VALUES (i, j);
  INSERT INTO t_multi VALUES (m, n);
  SELECT * FROM t_multi WHERE t_multi.a=i OR t_multi.a=m;
$$ LANGUAGE SQL;

query T rowsort
SELECT f_2inserts(11,12,13,14);
----
(11,12)
(13,14)

statement error pgcode 23505 pq: duplicate key value violates unique constraint "t_multi_pkey"
SELECT f_2inserts(42,42,42,42);

# None of the duplicate key inserts should have succeeded.
query I
SELECT count(*) FROM t_multi WHERE a = 42;
----
0

subtest end

subtest schema_changes

statement ok
CREATE TABLE t_alter (a INT);

statement ok
CREATE FUNCTION f_int(i INT) RETURNS INT AS
$$
  INSERT INTO t_alter VALUES (i) RETURNING *;
$$ LANGUAGE SQL;

query I
SELECT f_int(0);
----
0

statement ok
CREATE FUNCTION f_record(i INT) RETURNS RECORD AS
$$
  INSERT INTO t_alter VALUES (i) RETURNING *;
$$ LANGUAGE SQL;

query T
SELECT f_record(1)
----
(1)

statement ok
ALTER TABLE t_alter ADD COLUMN b INT DEFAULT 0;

query T
SELECT f_record(2)
----
(2)

statement ok
ALTER TABLE t_alter ADD COLUMN c INT;

query T
SELECT f_record(3)
----
(3)

query I
SELECT f_int(4);
----
4

query III rowsort
SELECT * FROM t_alter;
----
0 0 NULL
1 0 NULL
2 0 NULL
3 0 NULL
4 0 NULL

statement ok
CREATE FUNCTION f_drop(i INT, j INT, k INT) RETURNS RECORD AS
$$
  INSERT INTO t_alter VALUES (i, j, k) RETURNING *;
$$ LANGUAGE SQL;

query T
SELECT f_drop(5,100,101);
----
(5,100,101)

statement error pgcode 2BP01 cannot drop column \"c\" because function \"f_drop\" depends on it
ALTER TABLE t_alter DROP COLUMN c;

query T
SELECT f_record(6);
----
(6)

subtest end

subtest constraints

statement ok
CREATE TABLE t_checkb(
  a INT PRIMARY KEY,
  b INT,
  CHECK (b > 1)
)

statement ok
CREATE FUNCTION f_checkb() RETURNS RECORD AS
$$
  INSERT INTO t_checkb VALUES (1, 0) ON CONFLICT(a) DO UPDATE SET b=0 RETURNING *;
$$ LANGUAGE SQL;

statement error pgcode 23514 pq: failed to satisfy CHECK constraint \(b > 1:::INT8\)
SELECT f_checkb();

subtest end
