cockroachdb / cockroachdb/cockroach

sql: inlining of UDFs only works for IMMUTABLE or STABLE functions

Open
#101,257 0 comments 0 reactions 0 assignees View on GitHub
A-sql-routine C-bug O-qa T-sql-queries
Dominant language
Go
Stars
32.5k
Forks
4.1k
PR merge metrics
PR metrics pending

Description

**Describe the problem**

UDFs can only be inlined if the function is declared to be IMMUTABLE or STABLE. This is true even if there is only a single statement in the UDF and it is only called from a single place in a query. This seems too restrictive, since I imagine that many people will write UDFs that omit the IMMUTABLE or STABLE designation. Note that Postgres seems to inline functions if they have a single statement that can be constant-folded, regardless of the volatility.

**To Reproduce**

On `cockroach demo` on master or v23.1 alpha, run:
```
CREATE TABLE tab (x int, y int);
INSERT INTO tab VALUES (1, 1), (2, 2);
CREATE FUNCTION foo() RETURNS bool AS $$
SELECT (x + y) = 2 FROM tab WHERE x = 1;
$$ LANGUAGE SQL;
```
This function does not get inlined even if it's only called in a single place. For example:
```
EXPLAIN (VERBOSE) SELECT foo();
```
Returns:
```
demo@127.0.0.1:26257/demoapp/movr> EXPLAIN (VERBOSE) SELECT foo();
info
---------------------------
distribution: local
vectorized: true

• values
columns: (foo)
size: 1 column, 1 row
row 0, expr 0: foo()
(7 rows)
```
This one doesn't either:
```
CREATE FUNCTION foo2() RETURNS bool AS $$
SELECT true;
$$ LANGUAGE SQL;
EXPLAIN (VERBOSE) SELECT foo2();
```
It does get inlined if I specify that the function is IMMUTABLE or STABLE, though:
```
CREATE FUNCTION foo3() RETURNS bool AS $$
SELECT true;
$$ LANGUAGE SQL STABLE;
EXPLAIN (VERBOSE) SELECT foo3();
```
Produces:
```
info
-----------------------------------
distribution: local
vectorized: true

• root
│ columns: (foo3)

├── • values
│ columns: (foo3)
│ size: 1 column, 1 row
│ row 0, expr 0: @S1

└── • subquery
│ id: @S1
│ original sql:
│ exec mode: one row

└── • values
columns: (bool)
size: 1 column, 1 row
row 0, expr 0: true
(20 rows)
```

**Expected behavior**
I could be wrong, but it seems like we are being too conservative with inlining. It seems like we should be able to inline in all the cases above.

Jira issue: CRDB-26883

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the SQL UDF examples with `cockroach demo`, then compare the `EXPLAIN (VERBOSE)` output for functions with and without IMMUTABLE or STABLE. Trace the SQL UDF inlining behavior and verify that eligible single-statement functions are inlined without an explicit volatility designation, while preserving correct semantics.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, sql
Domain
databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.