Bug
The Supabase CLI statement splitter fails to parse multi-statement migration files when a function name contains the substring atomic (case-insensitive). It appears to misinterpret it as the SQL-standard BEGIN ATOMIC ... END; syntax, breaking $$ dollar-quoting detection.
Minimal reproduction
This 8-line migration fails on supabase db reset and supabase db push:
CREATE OR REPLACE FUNCTION fn_atomic()
RETURNS void LANGUAGE plpgsql AS $$
BEGIN
NULL;
END;
$$;
SELECT 1;
ERROR: cannot insert multiple commands into a prepared statement (SQLSTATE 42601)
Change one character in the name and it passes:
CREATE OR REPLACE FUNCTION fn_atomix()
RETURNS void LANGUAGE plpgsql AS $$
BEGIN
NULL;
END;
$$;
SELECT 1;
Verified behavior
atomic anywhere in the identifier triggers the bug: fn_atomic, atomic_fn, my_atomic_thing, xatomicx
- Case-insensitive:
ATOMIC, Atomic, atomiC all trigger it
- Single-statement migrations (no
SELECT 1 / REVOKE / GRANT after $$;) work fine regardless of name
- The SQL is valid PostgreSQL — running the same file via
psql works perfectly
- Tested on CLI v2.75.0 and v2.84.2 on macOS (Darwin 24.6.0) — both affected
Expected behavior
The statement splitter should not treat atomic inside an identifier (e.g. fn_atomic) as the BEGIN ATOMIC keyword. BEGIN ATOMIC is only valid as a function body delimiter in SQL-standard syntax, not inside $$ dollar-quoted blocks or as part of an identifier.
Workaround
Split multi-statement migrations so each file contains a single statement, or avoid the substring atomic in function names.
Bug
The Supabase CLI statement splitter fails to parse multi-statement migration files when a function name contains the substring
atomic(case-insensitive). It appears to misinterpret it as the SQL-standardBEGIN ATOMIC ... END;syntax, breaking$$dollar-quoting detection.Minimal reproduction
This 8-line migration fails on
supabase db resetandsupabase db push:Change one character in the name and it passes:
Verified behavior
atomicanywhere in the identifier triggers the bug:fn_atomic,atomic_fn,my_atomic_thing,xatomicxATOMIC,Atomic,atomiCall trigger itSELECT 1/REVOKE/GRANTafter$$;) work fine regardless of namepsqlworks perfectlyExpected behavior
The statement splitter should not treat
atomicinside an identifier (e.g.fn_atomic) as theBEGIN ATOMICkeyword.BEGIN ATOMICis only valid as a function body delimiter in SQL-standard syntax, not inside$$dollar-quoted blocks or as part of an identifier.Workaround
Split multi-statement migrations so each file contains a single statement, or avoid the substring
atomicin function names.