fix(editor): make statement splitting dollar-quote aware for PostgreSQL (#1559)#1560
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5a1b2445a1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| SQLStatementScanner.allStatements( | ||
| in: sql, | ||
| dialect: SqlDialect.from(databaseTypeId: databaseType.rawValue) | ||
| ).count > 1 |
There was a problem hiding this comment.
Classify PostgreSQL DO blocks before unblocking them
For PostgreSQL, this now makes DO $$ BEGIN DROP TABLE t; END $$; count as a single statement, but classifyTier still only checks top-level prefixes and returns .safe for DO. The AI/MCP execute_query paths rely on this multi-statement guard plus the tier check before running with pre-cleared capabilities, so a destructive operation hidden inside a dollar-quoted DO block can bypass the dedicated confirmation tool and safe-mode write/destructive classification. Please either classify DO blocks conservatively for PostgreSQL or keep a separate non-UI guard for these executable blocks.
Useful? React with 👍 / 👎.
Signed-off-by: Ngô Quốc Đạt <datlechin@gmail.com>
Summary
Fixes #1559. Running a PostgreSQL script with a
DO $$ ... $$;block or a dollar-quoted function body failed withERROR: unterminated dollar-quoted string at or near "$$".Root cause
The editor's statement splitter,
SQLStatementScanner, splits a buffer on semicolons while skipping over strings and comments, but it had no concept of PostgreSQL dollar-quoting. A semicolon insideDO $$ BEGIN ...; ... END $$;was treated as a statement terminator, so a broken fragment reached the server.A second splitter,
SQLFileParser(used only for SQL file import), already handled dollar-quoting correctly and was gated by dialect. The editor path never got that logic.QueryClassifier.isMultiStatementdelegates to the editor splitter, so the MCP, AI, and safe-mode gates miscounted these scripts too.What changed
SqlDollarQuoteholds the dollar-quote lexing (opener detection, close matching, identifier rules) as one shared, pureNSStringhelper.SQLFileParsernow delegates to it. Behavior is unchanged; its existing tests still pass.SQLStatementScannertakes adialectand treats a dollar-quoted region as opaque when the dialect is PostgreSQL family. A token-start guard keeps$1positional parameters anda$$identifiers from being read as openers. Other dialects are unaffected.QueryClassifier.isMultiStatement, so the AI/MCP/safe-mode gates stop miscounting aDOblock as multi-statement.Tests
SQLStatementScannercases:DO $$ ... $$;, tagged$func$, nested different tags,$1not an opener,a$$identifier not an opener, dialect gating, and cursor inside a dollar body.SQLFileParser,QueryClassifier, and scanner tests pass.swiftlint --strictclean.Not in scope
The two splitters still differ on nested block comments and
E'...'escapes, and autocomplete is not dialect-aware. These are separate from this issue and left for a follow-up.