cockroachdb / cockroachdb/cockroach

plpgsql: internal error when using SELECT INTO with TG_* variables in trigger functions

Open
#162,289 1 comment 0 reactions 1 assignee Claimed by @DrewKimball View on GitHub
A-sql-trigger C-bug T-sql-queries
Dominant language
Go
Stars
32.5k
Forks
4.1k
PR merge metrics
PR metrics pending

Description

**Describe the problem**

Using `SELECT INTO ` inside a PL/pgSQL trigger function causes an internal error:

```
internal error: top-level relational expression cannot have outer columns: (38)
```

This affects all trigger-specific variables (`TG_NAME`, `TG_OP`, `TG_WHEN`, `TG_TABLE_NAME`, `TG_TABLE_SCHEMA`, `TG_NARGS`, `TG_RELID`).

**Workaround:** Direct assignment works correctly (`v := TG_NAME`).

**To Reproduce**

```sql
CREATE TABLE xy (x INT, y INT);

CREATE FUNCTION test_select_into() RETURNS TRIGGER LANGUAGE PLpgSQL AS $$
DECLARE
v TEXT;
BEGIN
SELECT TG_NAME INTO v; -- This fails
RAISE NOTICE 'TG_NAME: %', v;
RETURN NEW;
END
$$;

CREATE TRIGGER tr_test BEFORE INSERT ON xy FOR EACH ROW EXECUTE FUNCTION test_select_into();

INSERT INTO xy VALUES (1, 1); -- Internal error
```

**Expected behavior**

The `SELECT INTO` statement should work the same as PostgreSQL, which correctly assigns the trigger variable value to the local variable.

**Working workaround**

Direct assignment works correctly:

```sql
CREATE FUNCTION test_direct_assign() RETURNS TRIGGER LANGUAGE PLpgSQL AS $$
DECLARE
v TEXT;
BEGIN
v := TG_NAME; -- This works
RAISE NOTICE 'TG_NAME: %', v;
RETURN NEW;
END
$$;
```

**PostgreSQL behavior**

PostgreSQL 16 handles `SELECT TG_NAME INTO v` correctly:

```
NOTICE: TG_NAME: tr_test, TG_OP: INSERT, TG_WHEN: BEFORE, ...
```

**Environment:**

- CockroachDB version: master (commit ~0fbbeaf8982)
- Server OS: macOS (darwin_arm64)

**Stack trace**

```
ERROR: internal error: top-level relational expression cannot have outer columns: (38)
SQLSTATE: XX000
DETAIL: stack trace:
pkg/sql/opt/xform/optimizer.go:277: Optimize()
pkg/sql/opt/exec/execbuilder/scalar.go:1288: func2()
pkg/sql/routine.go:329: startInternal()
pkg/sql/routine.go:279: Start()
pkg/sql/routine.go:179: EvalRoutineExpr()
pkg/sql/sem/eval/expr.go:648: EvalRoutineExpr()
bazel-out/darwin_arm64-fastbuild/bin/pkg/sql/sem/tree/eval_expr_generated.go:361: Eval()
pkg/sql/sem/eval/expr.go:22: Expr()
pkg/sql/execinfra/execexpr/expr.go:310: eval()
pkg/sql/execinfra/execexpr/expr.go:163: EvalExpr()
pkg/sql/execinfra/processorsbase.go:294: ProcessRow()
pkg/sql/execinfra/processorsbase.go:744: ProcessRowHelper()
pkg/sql/rowexec/noop.go:96: Next()
pkg/sql/colexec/columnarizer.go:244: Next()
pkg/sql/colflow/stats.go:122: next()
pkg/sql/colexecerror/error.go:162: CatchVectorizedRuntimeError()
pkg/sql/colflow/stats.go:130: Next()
bazel-out/darwin_arm64-fastbuild/bin/pkg/sql/colexec/is_null_ops.eg.go:220: Next()
pkg/sql/colflow/stats.go:122: next()
pkg/sql/colexecerror/error.go:162: CatchVectorizedRuntimeError()
pkg/sql/colflow/stats.go:130: Next()
pkg/sql/colexecop/operator.go:472: Next()
pkg/sql/colexec/materializer.go:248: next()
pkg/sql/colexec/materializer.go:276: nextAdapter()
pkg/sql/colexecerror/error.go:162: CatchVectorizedRuntimeError()
pkg/sql/colexec/materializer.go:282: Next()
pkg/sql/rowexec/stats.go:64: Next()
pkg/sql/rowexec/noop.go:83: Next()
pkg/sql/colexec/columnarizer.go:244: Next()
pkg/sql/colflow/stats.go:122: next()
pkg/sql/colexecerror/error.go:162: CatchVectorizedRuntimeError()
pkg/sql/colflow/stats.go:130: Next()
```

Jira issue: CRDB-59360

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.