`run_sql` with `no_transaction: true` mis-splits dollar-quoted ($$) PL/pgSQL blocks
Version Information
Server Version: v2.48.5 CLI Version (for CLI related issue): n/a
Environment
OSS
What is the current behaviour?
When run_sql is called with no_transaction: true, the server splits the SQL into individual statements via splitSQLStatements. That splitter mis-handles bare $$ dollar-quoting: it represents the empty tag internally as the single character "$", and its closing-delimiter check is a prefix match against that tag. As a result, any lone $ inside the body (e.g. a $ regex end-anchor in a string literal like '^foo$') is mistaken for the closing $$. The parser then falls out of dollar-quote mode and treats the next ; as a statement separator, slicing a single DO $$ … $$; / CREATE FUNCTION … $$; block into invalid fragments. Postgres then rejects the fragment with a syntax error.
This only happens with no_transaction: true; the default path sends the whole body in one call and is unaffected. Named dollar-quote tags ($tag$ … $tag$) are also unaffected.
The relevant code is at https://github.com/hasura/graphql-engine/blob/v2.48.5/server/src-lib/Hasura/Backends/Postgres/DDL/RunSQL.hs#L302-L335
What is the expected behaviour?
No syntax error when running SQL that contains $$ in no_transaction mode.
How to reproduce the issue?
- Call
run_sqlwithDO $$ BEGIN IF 'x' ~ '^x$' THEN NULL; END IF; END $$;andno_transaction: true - Notice that it fails with Postgres syntax error
- Run the same SQL, but without
no_transaction: true. - Notice that it succeeds
Screenshots or Screencast
Please provide any traces or logs that could help here.
Any possible solutions/workarounds you're aware of?
Use named dollar-quote tags ($foo$) instead of $$. Or don't use no_transaction.
Keywords
Source: hasura/graphql-engine