Fix string-bodied CREATE FUNCTION swallowing the next statement#97
Merged
MasterOdin merged 1 commit intoJun 10, 2026
Conversation
CREATE FUNCTION/PROCEDURE/TRIGGER are kept open across semicolons so that token-level semicolons inside a BEGIN...END body don't terminate them early. But when the body is supplied as a quoted or dollar-quoted string (e.g. PostgreSQL `AS 'select 1'` / `AS $$ ... $$`), or when a PostgreSQL trigger merely references a function, no block ever opens, so `canEnd` was never set and the statement greedily consumed whatever followed it. This only surfaced when such a statement was not the last one, since end-of-input otherwise terminated it. Fixes: - Set `canEnd` once a string/dollar-quoted body has been consumed at the top level following the `AS` keyword (CREATE FUNCTION/PROCEDURE). - Make `statementsWithEnds` dialect-aware: exclude CREATE_TRIGGER for PostgreSQL/Snowflake, where triggers have no inline body. The block-based `canEnd` logic is left intact so T-SQL bodies (e.g. mssql triggers with `IF ... RETURN;` before a BEGIN...END) still protect their token-level semicolons.
MasterOdin
approved these changes
Jun 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The library fails to split the following into two statements:
It is parsed as a single
CREATE_FUNCTIONthat greedily consumes the trailingSELECT 1;.The bug is broader than the single reported case — it affects any
CREATE FUNCTION/PROCEDUREwhose body is a quoted or dollar-quoted string (PostgreSQL/Snowflake/standard SQL), and PostgreSQLCREATE TRIGGER(which only references a function). These only worked before when they happened to be the last statement, since end-of-input terminated them.Root cause
CREATE_FUNCTION/CREATE_PROCEDURE/CREATE_TRIGGERare instatementsWithEnds, so a semicolon only terminates them oncestatement.canEndis set — andcanEndis only set when aBEGIN...ENDblock closes. When the body is a single string/dollar-quoted token (no block) or the trigger has no body,canEndwas never set, so the statement swallowed everything after it.Fix
canEndonce a string/dollar-quoted body has been consumed at the top level following theASkeyword (CREATE FUNCTION/PROCEDURE).statementsWithEndsdialect-aware: excludeCREATE_TRIGGERfor PostgreSQL/Snowflake, where triggers have no inline body.The block-based
canEndlogic is left intact, so T-SQL bodies (e.g. mssql triggers withIF ... RETURN;before aBEGIN...END) still protect their token-level semicolons.Tests
Added a
multiple-statementdescribe block covering:plpgsqlwith internalBEGIN...END)BEGIN...ENDfunction bodiesAll existing tests continue to pass.