sqldelight / sqldelight/sql-psi

Trigger pseudo-tables NEW/OLD not resolved when uppercase (case-sensitive matching)

Open
#771 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Kotlin
Stars
104
Forks
35
Avg merge
1h 11m
Merged PRs (30d)
14

Description

Summary

The trigger pseudo-tables NEW / OLD are only resolved when written in lowercase (new / old). When written in uppercase (NEW / OLD) — which is valid SQLite, since these references are case-insensitive — sql-psi fails resolution with No table found with name NEW (or OLD).

This is a compile-time-only problem: the SQL runs fine in SQLite either way, so triggers authored in uppercase work at runtime but cannot be expressed in a .sq schema file. Mixed/uppercase is extremely common in hand-written SQL, so this bites anyone migrating existing trigger DDL into SQLDelight.

Minimal reproduction

CREATE TABLE foo (id INTEGER PRIMARY KEY, val TEXT);
CREATE TABLE log (foo_id INTEGER, val TEXT);

-- ✅ Compiles
CREATE TRIGGER lower_ok
AFTER UPDATE ON foo
BEGIN
    INSERT INTO log (foo_id, val) VALUES (new.id, new.val);
END;

-- ❌ Fails: "No table found with name NEW"
CREATE TRIGGER upper_fails
AFTER UPDATE ON foo
BEGIN
    INSERT INTO log (foo_id, val) VALUES (NEW.id, NEW.val);
END;

The two triggers are identical apart from the case of new vs NEW. The lowercase one generates fine; the uppercase one fails at code generation:

... :9:48 No table found with name NEW
... :9:56 No table found with name NEW

The same applies to old / OLD in AFTER UPDATE / AFTER DELETE triggers, and in every body position (VALUES lists, INSERT ... SELECT row sources, UPDATE ... SET/WHERE, WHEN clauses, and subqueries).

Expected behaviour

Both triggers should compile. Per the SQLite grammar these NEW/OLD references are case-insensitive, like other identifiers/keywords, so resolution of the synthetic trigger tables should be case-insensitive.

Actual behaviour

Only the lowercase form resolves. Uppercase NEW/OLD is treated as an unknown table reference.

Environment

  • SQLDelight 2.3.2, dialect app.cash.sqldelight:sqlite-3-25-dialect
  • Reproduced via the SQLDelight Gradle generate…Interface task.

Notes

Likely the synthetic trigger-table names are matched case-sensitively where they're injected into the statement scope (cf. #96 "Pass the trigger-tables to select statements"). A case-insensitive comparison (matching how SQLite itself treats these references) should resolve it.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the issue with the Gradle generate…Interface task using the sqlite-3-25-dialect, then trace where synthetic trigger-table names are injected into the statement scope. Compare resolution of new/old with NEW/OLD across the trigger body. Done means both forms compile and the existing lowercase behavior remains intact.

Written by the indexing model from the issue text.

Assessment

Tech stack
kotlin, sql, sqlite
Domain
databases, tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
65/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.