Summary
In Oracle mode, psql's EXEC[UTE] wraps the rest of the line as BEGIN <text>; END; (src/bin/psql/mainloop.c, the PSQLPLUS_CMD_EXECUTE case). It skips its own terminator only when the last byte of the text is a semicolon, but the scanner leaves the line's trailing whitespace on the text, so
typed with a space or a newline after the semicolon becomes BEGIN protest; ; END and fails with syntax error at or near ";". src/oracle_test/regress/expected/ora_plisql.out records that failure for two of its lines (exec protest; and EXEC test_proc1; ) as the expected output.
SQLPlus runs exec proc; and exec proc alike. Measured on Oracle XE 21c: exec protest; with trailing spaces, exec protest and EXEC protest; with a trailing tab all run the procedure; exec protest; -- note and exec protest -- note fail there too, because SQLPlus builds the same one-line block and the comment swallows the END.
Fix
Trim trailing whitespace from the statement text before deciding whether a terminator is still needed. ASCII whitespace only (" \t\n\r\f"): no client encoding uses those bytes inside a multibyte character, and isspace() follows the locale (Windows' C runtime treats 0xA0 as a space in a Latin-1 locale, and 0xA0 is a legal trail byte in SJIS and GBK). Twelve lines in mainloop.c; I have it on a branch from master and will open the pull request once the ora_plisql expected rows are re-recorded from a run on master (on master the two recorded lines then fail one step later, at the bare call protest; itself, so the exact rows have to come from a run there).
Summary
In Oracle mode, psql's
EXEC[UTE]wraps the rest of the line asBEGIN <text>; END;(src/bin/psql/mainloop.c, thePSQLPLUS_CMD_EXECUTEcase). It skips its own terminator only when the last byte of the text is a semicolon, but the scanner leaves the line's trailing whitespace on the text, sotyped with a space or a newline after the semicolon becomes
BEGIN protest; ; ENDand fails withsyntax error at or near ";".src/oracle_test/regress/expected/ora_plisql.outrecords that failure for two of its lines (exec protest;andEXEC test_proc1;) as the expected output.SQLPlus runs
exec proc;andexec procalike. Measured on Oracle XE 21c:exec protest;with trailing spaces,exec protestandEXEC protest;with a trailing tab all run the procedure;exec protest; -- noteandexec protest -- notefail there too, because SQLPlus builds the same one-line block and the comment swallows the END.Fix
Trim trailing whitespace from the statement text before deciding whether a terminator is still needed. ASCII whitespace only (
" \t\n\r\f"): no client encoding uses those bytes inside a multibyte character, andisspace()follows the locale (Windows' C runtime treats 0xA0 as a space in a Latin-1 locale, and 0xA0 is a legal trail byte in SJIS and GBK). Twelve lines inmainloop.c; I have it on a branch frommasterand will open the pull request once theora_plisqlexpected rows are re-recorded from a run onmaster(onmasterthe two recorded lines then fail one step later, at the bare callprotest;itself, so the exact rows have to come from a run there).