You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
sql: disallow pausable portal for transaction control statement
Statement that is a transaction control statement is no longer allowed
with pausable portals. Specifically, the following won't be allowed:
```
CALL
PAUSE JOB
PAUSE SCHEDULE
PAUSE JOBS
PAUSE JOBS
COMMIT PREPARED
DEALLOCATE
DISCARD
EXECUTE
ROLLBACK PREPARED
SET TRANSACTION
UNLISTEN
```
Ideally, we should only disallow the CALL statements for procedures that
contains mutations. However, the `CanMutate` is not fully propagated
from the function body yet. (Issue #147568) For now, we just disallow
any TCL statements with pausable portal.
Release note (sql change): Previously, using pausable portal with
procedure call caused panic, depending on the function body. Now
statements that are transaction control statement, such as procedure
call(e.g. `CALL myfunc()`) are not allowed with pausable portal.
# PG allows procedure with pausable portal, but CRDB does not.
1483
+
until noncrdb_only
1484
+
ReadyForQuery
1485
+
----
1486
+
{"Type":"ParseComplete"}
1487
+
{"Type":"BindComplete"}
1488
+
{"Type":"CommandComplete","CommandTag":"CALL"}
1489
+
{"Type":"ReadyForQuery","TxStatus":"I"}
1490
+
1491
+
until crdb_only keepErrMessage
1492
+
ErrorResponse
1493
+
ReadyForQuery
1494
+
----
1495
+
{"Type":"ParseComplete"}
1496
+
{"Type":"BindComplete"}
1497
+
{"Type":"ErrorResponse","Code":"0A000","Message":"unimplemented: the statement for a pausable portal must be a read-only SELECT query with no sub-queries or post-queries","Hint":"You have attempted to use a feature that is not yet implemented.\nSee: https://go.crdb.dev/issue-v/98911/dev"}
1498
+
{"Type":"ReadyForQuery","TxStatus":"I"}
1499
+
1500
+
# If calling this procedure without `"MaxRows": 100` (i.e. make it a non-pausable portal),
Query {"String": "CREATE TABLE IF NOT EXISTS sensors (id TEXT NOT NULL, ts TIMESTAMPTZ NOT NULL, val FLOAT8 NULL, CONSTRAINT s_pk PRIMARY KEY (id, ts));"}
1536
+
Query {"String": "TRUNCATE sensors;"}
1537
+
Query {"String": "INSERT INTO sensors values ('a', now(), 0.1);"}
1538
+
Query {"String": "CREATE TABLE IF NOT EXISTS sensors_summary (id TEXT NOT NULL, val FLOAT8 NULL, CONSTRAINT ss_pk PRIMARY KEY (id));"}
1539
+
Query {"String": "TRUNCATE sensors_summary;"}
1540
+
Query {"String": "CREATE TYPE IF NOT EXISTS k AS (x TEXT, y FLOAT8);"}
Query {"String": "CREATE OR REPLACE PROCEDURE fab5() LANGUAGE plpgsql AS $$ DECLARE id_array k[]; BEGIN SELECT array_agg(row(id, avg_val)::k) INTO id_array FROM (SELECT id, avg(val) AS avg_val FROM sensors WHERE now() - INTERVAL '3 days' < ts GROUP BY id) AS sub; INSERT INTO sensors_summary (id, val) SELECT (arr).x, (arr).y FROM unnest(id_array) AS arr; RAISE NOTICE 'Inserted % rows', array_length(id_array, 1); END; $$;"}
1566
+
----
1567
+
1568
+
send crdb_only
1569
+
Query {"String": "CREATE OR REPLACE PROCEDURE fab5() LANGUAGE PLpgSQL AS $$ DECLARE i k := ('', 0.0 ); id_array k[]; BEGIN begin commit; SELECT array_agg((id, avg_val)) FROM (SELECT id, avg(val) as avg_val FROM sensors where now() - INTERVAL '3 days' < ts group by id) INTO id_array; end; commit; INSERT INTO sensors_summary (id, val) select (arr).x, (arr).y from (select unnest(id_array) as arr); RAISE NOTICE 'Inserted % rows', array_length(id_array, 1); END $$;"}
# PG allows procedure with pausable portal, but CRDB does not.
1587
+
until noncrdb_only ignore=RowDescription ignore=NoticeResponse
1588
+
ReadyForQuery
1589
+
----
1590
+
{"Type":"ParseComplete"}
1591
+
{"Type":"BindComplete"}
1592
+
{"Type":"BindComplete"}
1593
+
{"Type":"CommandComplete","CommandTag":"CALL"}
1594
+
{"Type":"ReadyForQuery","TxStatus":"I"}
1595
+
1596
+
until crdb_only keepErrMessage
1597
+
ErrorResponse
1598
+
ReadyForQuery
1599
+
----
1600
+
{"Type":"ParseComplete"}
1601
+
{"Type":"BindComplete"}
1602
+
{"Type":"BindComplete"}
1603
+
{"Type":"ErrorResponse","Code":"0A000","Message":"unimplemented: the statement for a pausable portal must be a read-only SELECT query with no sub-queries or post-queries","Hint":"You have attempted to use a feature that is not yet implemented.\nSee: https://go.crdb.dev/issue-v/98911/dev"}
1604
+
{"Type":"ReadyForQuery","TxStatus":"I"}
1605
+
1606
+
# Both PG and CRDB allows procedure with non-pausable portal.
0 commit comments