Hi,

read_sql_construct() in pl_gram.y takes up to three terminator tokens.
Callers pass 0 for the ones they don't use, but 0 is also the token code
for end of input.  The loop compares against until2 and until3 before it
gets to its own "tok == 0" check, which is what produces the
    missing "%s" at end of SQL expression/statement
error.

So when a function body ends in the middle of a construct, EOF is taken as
a valid terminator and the helpful message is skipped.  The text read so
far is then handed to the core parser or the next grammar rule, which
reports something generic or misleading:

    do $$ begin if true $$;
    ERROR:  syntax error at end of input

    do $$ begin while true $$;
    ERROR:  syntax error at end of input

    do $$ begin case 1 $$;
    ERROR:  missing expression at end of input

    do $$ declare x int; begin x := 1 $$;
    ERROR:  syntax error at end of input

The attached patch only compares against until2/until3 when they are
non-zero (until is always non-zero for every caller).  With it:

    do $$ begin if true $$;
    ERROR:  missing "THEN" at end of SQL expression

    do $$ begin while true $$;
    ERROR:  missing "LOOP" at end of SQL expression

    do $$ begin case 1 $$;
    ERROR:  missing "WHEN" at end of SQL expression

    do $$ declare x int; begin x := 1 $$;
    ERROR:  missing ";" at end of SQL statement

The error position is the same as before (end of input).  I added the four
statements above to plpgsql.sql; no existing expected output changes.

Since this only changes error message text, which tests and external tools
may match on, I think master only is the safer choice (or v19 as it is not
yet released), but I'm happy to hear
other opinions.

Thanks,

-- 
*Jeevan Chalke*
*Senior Principal Engineer, Engineering Manager*
*Product Development*

enterprisedb.com <https://www.enterprisedb.com>

Attachment: v1-0001-Fix-PL-pgSQL-missing-X-at-end-of-SQL-expression-e.patch
Description: Binary data

Reply via email to