Repository navigation
fix(adapters): escape cursor bounds and UDF packages as dialect string literals - #1346
Merged
Merged
Conversation
…g literals Cursor bounds in delete+insert filters, eligible-max probes and bound literals, and BigQuery Python UDF package names, were interpolated into quotes without escaping. They now go through each adapter's own string quoting. Databricks string literals process backslash escapes and concatenate adjacent literals, so its quoting now backslash-escapes backslashes and quotes instead of doubling the quote.
kvlonge
enabled auto-merge (squash)
November 7, 2026 12:04
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.
Why
Several adapters interpolated cursor bounds into quotes unescaped (delete+insert filters, eligible-max probes, bound literals, cursor filters), and BigQuery did the same for Python UDF packages. A quote in a value breaks the statement and in principle lets data shape the SQL.
Databricks also quoted every string wrongly: its literals process backslash escapes and concatenate adjacent literals, so
'O''Brien'yieldsOBrien, and a trailing backslash escaped the closing quote.Changes
BaseAdapter._quote_sql_stringis a method, which adapters already override with their dialect's quoting. The base, DuckDB-backed, Postgres, Snowflake, SQL Server, BigQuery and Databricks cursor renderings use it instead of'{value}'. SQLite and ClickHouse already did.\and'for typed STRING scalars (no longer the ANSI doubling renderer), typed objects, loader literals, view-definition lookups and cursor bounds. Identifiers are unchanged: doubled backticks are valid Spark SQL.Timestamps and integers render as before. A Databricks model whose compiled SQL embeds a typed string with
'or\gets a new definition hash once, now holding the intended value.DuckShop: not applicable. Its cursors are timestamps or integers, which cannot carry a quote, and it never emits Databricks or BigQuery SQL.
Verification
',\and a newline through bound literals, eligible-max date probes and delete+insert filters. It fails on the previous code for DuckDB, MotherDuck, Postgres, SQL Server, Snowflake, Databricks and BigQuery and passes now; ClickHouse, the control, passes on both.make check-ci, public-repository scan.