cockroachdb / cockroachdb/cockroach

sql: disallow PL/pgSQL txn control statements in a simple protocol query batch

Open
#149,103 1 comment 0 reactions 0 assignees View on GitHub
A-sql-pgwire A-sql-plpgsql A-sql-routine C-bug E-quick-win T-sql-queries
Dominant language
Go
Stars
32.5k
Forks
4.1k
PR merge metrics
PR metrics pending

Description

When two or more queries are executed together via the simple protocol (like `SELECT 1; SELECT 2;`), they are executed as part of the same implicit transaction. Postgres does not allow PL/pgSQL transaction control statements within this context, similar to the way it disallows them in explicit transactions:
```
cockroach % psql postgres -c 'select transaction_timestamp(); call p();'
NOTICE: foo 2025-06-27 01:01:32.05846-06
transaction_timestamp
------------------------------
2025-06-27 01:01:32.05846-06
(1 row)

ERROR: invalid transaction termination
CONTEXT: PL/pgSQL function p() line 1 at COMMIT
```
psql doesn't use the simple protocol by default, so the default interactive mode doesn't throw an error:
```
postgres=# select transaction_timestamp(); call p(); select transaction_timestamp();
transaction_timestamp
-------------------------------
2025-06-27 00:11:47.945857-06
(1 row)

NOTICE: foo 2025-06-27 00:11:47.94828-06
NOTICE: bar 2025-06-27 00:11:47.948528-06
NOTICE: baz 2025-06-27 00:11:47.94857-06
CALL
transaction_timestamp
-------------------------------
2025-06-27 00:11:47.948729-06
(1 row)
```
On the other hand, our CLI does use the simple protocol, but _doesn't_ disallow transaction control statements in a multi-statement implicit transaction:
```
root@localhost:26257/defaultdb> select transaction_timestamp(); call p(); select transaction_timestamp();
transaction_timestamp
---------------------------------
2025-06-27 06:20:03.666635+00
(1 row)
CALL
transaction_timestamp
---------------------------------
2025-06-27 06:20:03.676169+00
(1 row)

Note: timings for multiple statements on a single line are not supported. See https://go.crdb.dev/issue-v/48180/v25.3.

NOTICE: foo 2025-06-27 06:20:03.666635+00
NOTICE: bar 2025-06-27 06:20:03.675952+00
NOTICE: baz 2025-06-27 06:20:03.676169+00
```
Note how the first notice (printed by the stored proc) has the same timestamp as the first `transaction_timestamp()` call, and similar for the last notice and second `transaction_timestamp()` call. Rather than allowing this, we should return an error like Postgres.

Jira issue: CRDB-51984

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.