cockroachdb / cockroachdb/cockroach
sql/plpgsql: support dynamic EXECUTE in UDFs and DO blocks
- Dominant language
- Go
- Stars
- 32.5k
- Forks
- 4.1k
- PR merge metrics
- PR metrics pending
Description
**Is your feature request related to a problem? Please describe.**
CockroachDB's dynamic `EXECUTE` support was previously restricted to
stored procedures only, rejecting it in user-defined functions and DO
blocks. PostgreSQL's `exec_stmt_dynexecute` makes no such distinction —
`EXECUTE` behaves identically in functions and procedures.
**Describe the solution you'd like**
- Lift the procedure-only restriction so `EXECUTE` (DML and `SELECT`, no
DDL/DCL) works in UDFs and DO blocks; trigger functions remain blocked
with a clear error.
- DO blocks build with the procedure options set, but must reject dynamic
DDL the same way functions do, since they already reject static DDL
like functions. Dynamic DDL in functions and DO blocks continues to be
rejected by the existing statement-type check, with the same error as
static DDL in a function body.
- The CREATE-time `SECURITY DEFINER` convenience check (#172404) applies
to functions as well as procedures, since a function can be flipped to
`SECURITY DEFINER` by `ALTER FUNCTION` after creation — the mandatory
runtime `UnderSecurityDefiner` check already catches that case
regardless.
- No changes to the execution machinery are needed; existing safeguards
compose without modification:
- A routine containing `EXECUTE` is conservatively classified as
mutating (empty body with a `BodyBuilder`), so a function invoking
dynamic SQL is never distributed or run on a leaf transaction.
- The CREATE-time volatility check rejects `EXECUTE` in `IMMUTABLE` and
`STABLE` functions, since the dynamic-statement continuation is
inherently volatile.
- A function that falls off the end of its body after an `EXECUTE`
raises the missing-`RETURN` error at runtime rather than `CREATE`
time, because the rest-of-body build is deferred.
**Describe alternatives you've considered**
N/A — this removes an artificial procedure-only restriction; PostgreSQL's
`EXECUTE` behaves identically in both contexts, so keeping functions
blocked would create an unnecessary parity gap.
**Additional context**
Part of the dynamic-SQL EXECUTE effort tracked in #169581. Builds on basic
`EXECUTE` support (#172401) and the `SECURITY DEFINER` restriction
(#172404). Trigger functions remain unsupported. Dynamic DDL/DCL remains
restricted to stored procedures (#172433).
Epic CRDB-48117
Jira issue: CRDB-65675
Contributor guide
Research direction
Start with the existing procedure-only restriction around dynamic EXECUTE and compare handling of UDFs, DO blocks, and trigger functions with PostgreSQL's exec_stmt_dynexecute. Verify that DML and SELECT work in functions and DO blocks, while dynamic DDL/DCL and trigger-function execution remain rejected with the specified errors. Confirm the existing volatility, security-definer, distribution, and missing-RETURN safeguards still apply.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, sql
- Domain
- databases
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100