Skip to content

fix(bigquery): use backslash escaping for apostrophes in filter values - #38925

Closed
vijaygovindaraja wants to merge 3 commits into
apache:masterfrom
vijaygovindaraja:fix/bigquery-apostrophe-escaping
Closed

vijaygovindaraja wants to merge 3 commits into
apache:masterfrom
vijaygovindaraja:fix/bigquery-apostrophe-escaping

Conversation

@vijaygovindaraja

@vijaygovindaraja vijaygovindaraja commented Mar 27, 2026 •

Copy link
Copy Markdown

User description

SUMMARY

Fixes BigQuery syntax errors when filter values contain apostrophes (e.g., "Armando's").

BigQuery does not support double-apostrophe escaping ('Armando''s'), which is the default behavior of SQLAlchemy's literal processor. This causes a 400 Syntax error: concatenated string literals must be separated by whitespace or comments error.

BEFORE

-- Generated SQL (broken)
WHERE `restaurant_name` IN ('Armando''s')
-- BigQuery error: Syntax error: concatenated string literals must be separated by whitespace

AFTER

-- Generated SQL (correct)
WHERE `restaurant_name` IN ('Armando\'s')
-- BigQuery executes successfully

CHANGES

superset/db_engine_specs/bigquery.py:

  • Add BigQueryStringType — a TypeDecorator that overrides literal_processor to use backslash escaping instead of double-apostrophe escaping
  • Add _monkeypatch_bigquery_dialect() — patches BigQueryDialect.colspecs to use the custom string type
  • Follows the same proven pattern as the Databricks dialect fix (DatabricksStringType + monkeypatch_dialect())

tests/unit_tests/jinja_context_test.py:

  • Add test_where_in_bigquery_apostrophe — verifies BigQuery dialect uses backslash escaping for filter values containing apostrophes

TESTING INSTRUCTIONS

  1. Connect a BigQuery data source
  2. Create a filter on a text column
  3. Select a value containing an apostrophe (e.g., "Armando's", "O'Brien")
  4. Verify the chart/dashboard loads without a 400 syntax error

ADDITIONAL INFORMATION


CodeAnt-AI Description

Fix BigQuery filters with apostrophes

What Changed

  • BigQuery filter values now keep apostrophes in a format BigQuery accepts, so names like Armando's no longer trigger a query syntax error
  • Added coverage to confirm BigQuery does not fall back to the broken double-apostrophe escaping for quoted filter values

Impact

✅ Fewer BigQuery filter errors
✅ More reliable dashboards with apostrophe-containing values
✅ Clearer filter behavior for quoted names

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

BigQuery does not support double-apostrophe escaping for single quotes
in string literals. When a filter value contains an apostrophe (e.g.,
"Armando's"), SQLAlchemy's default literal processor generates
'Armando''s' which causes a BigQuery syntax error: "concatenated
string literals must be separated by whitespace or comments".

Add a BigQueryStringType that overrides the literal_processor to use
backslash escaping ('Armando\'s') instead. Apply it via monkeypatching
the BigQueryDialect.colspecs, following the same pattern used for the
Databricks dialect fix.

Fixes apache#35857

Signed-off-by: V Govindarajan <vijay.govindarajan91@gmail.com>
@bito-code-review

bito-code-review Bot commented Mar 27, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #0c4e27

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: e2b3188..e2b3188
    • superset/db_engine_specs/bigquery.py
    • tests/unit_tests/jinja_context_test.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@dosubot dosubot Bot added the data:connect:googlebigquery Related to BigQuery label Mar 27, 2026
@codeant-ai-for-open-source codeant-ai-for-open-source Bot added the size:M This PR changes 30-99 lines, ignoring generated files label Mar 27, 2026
Comment thread tests/unit_tests/jinja_context_test.py Outdated
assert "''" not in result, (
f"BigQuery should use backslash escaping, got double-apostrophe: {result}"
)
assert "\\'" in result or "Armando" in result

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: The final assertion in this test is too weak: by allowing "Armando" as an alternative condition, the test will still pass if the generated SQL contains an unescaped apostrophe like Armando's (which is invalid BigQuery SQL), so the test does not actually enforce the stated requirement that BigQuery use backslash escaping for apostrophes. [logic error]

Severity Level: Major ⚠️
- ❌ BigQuery filters with apostrophes can regress without test failing.
- ⚠️ Dashboards using where_in on BigQuery may break silently.
- ⚠️ Regression risk for issue #35857 remains insufficiently covered.
Suggested change
assert "\\'" in result or "Armando" in result
assert "\\'" in result, (
f"BigQuery should escape apostrophes with backslash: {result}"
)
Steps of Reproduction ✅
1. Inspect `test_where_in_bigquery_apostrophe` in `tests/unit_tests/jinja_context_test.py`
lines 510–527, where `result = WhereInMacro(BigQueryDialect())(["Armando's"])` and the
assertions `assert "''" not in result` and `assert "\\'" in result or "Armando" in result`
are evaluated.

2. Note from `superset/jinja_context.py:190–233` that `WhereInMacro.__call__` builds a
parenthesized IN list using the SQLAlchemy dialect's literal rendering, and from
`superset/db_engine_specs/bigquery.py:125–147` that the intended behavior is to escape
apostrophes with backslash for BigQuery.

3. Consider an invalid-but-plausible BigQuery literal output such as `result =
"('Armando's')"` (no double-apostrophe, no backslash escaping), which would cause a
BigQuery syntax error in real queries, but still satisfies the current test conditions: it
contains no `"''"` substring and does contain `"Armando"`.

4. Evaluate the current test logic with this `result` value: the first assertion (`"''"
not in result`) passes because there are no doubled quotes, and the second assertion
(`"\\'" in result or "Armando" in result`) passes because `"Armando"` is present, so
`pytest` would report the test as passing even though the BigQuery requirement
(backslash-escaped apostrophes) is violated.
Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** tests/unit_tests/jinja_context_test.py
**Line:** 526:526
**Comment:**
	*Logic Error: The final assertion in this test is too weak: by allowing `"Armando"` as an alternative condition, the test will still pass if the generated SQL contains an unescaped apostrophe like `Armando's` (which is invalid BigQuery SQL), so the test does not actually enforce the stated requirement that BigQuery use backslash escaping for apostrophes.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
👍 | 👎

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — fixed in 2e48b86. Removed the weak fallback and now strictly asserts backslash escaping is present.

Remove the weak `or "Armando" in result` fallback that would allow
the test to pass even without proper backslash escaping.

Signed-off-by: V Govindarajan <vijay.govindarajan91@gmail.com>
@bito-code-review

bito-code-review Bot commented Mar 28, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #8a05e4

Actionable Suggestions - 0
Review Details
  • Files reviewed - 1 · Commit Range: e2b3188..2e48b86
    • tests/unit_tests/jinja_context_test.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses BigQuery query failures caused by SQLAlchemy’s default string literal escaping ('') when filter values contain apostrophes, by switching BigQuery string literal escaping to backslash style (\') and adding a regression test.

Changes:

  • Added a BigQuery-specific TypeDecorator (BigQueryStringType) to render string literals with backslash-escaped apostrophes.
  • Monkeypatched sqlalchemy_bigquery.BigQueryDialect.colspecs so compiled literals use the custom string type.
  • Added a unit test asserting where_in output for BigQuery does not contain doubled apostrophes and does contain backslash escaping.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
superset/db_engine_specs/bigquery.py Introduces the custom string literal processor and applies a BigQuery dialect monkeypatch at import time.
tests/unit_tests/jinja_context_test.py Adds coverage for BigQuery where_in output when values contain apostrophes.

See: https://github.com/apache/superset/issues/35857
"""
try:
from sqlalchemy_bigquery import BigQueryDialect

Copilot AI Mar 31, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is non-deterministic: the BigQuery dialect monkeypatch is applied when superset/db_engine_specs/bigquery.py is imported, but this test only imports sqlalchemy_bigquery.BigQueryDialect. If the BigQuery engine spec module hasn’t been imported earlier in the test run, WhereInMacro(BigQueryDialect()) will still use the unpatched colspecs and this assertion will fail. Import the Superset BigQuery engine spec (or call the patch helper) in the test before instantiating BigQueryDialect so the test doesn’t depend on global import order.

Suggested change
from sqlalchemy_bigquery import BigQueryDialect
from sqlalchemy_bigquery import BigQueryDialect
# Import the Superset BigQuery engine spec so its dialect monkeypatch is applied
from superset.db_engine_specs import bigquery as _bigquery_engine_spec # noqa: F401

Copilot uses AI. Check for mistakes.
Comment thread superset/db_engine_specs/bigquery.py Outdated
Comment on lines +23 to +25
from datetime import datetime
from re import Pattern
from collections.abc import Callable

Copilot AI Mar 31, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import ordering: from collections.abc import Callable is inserted after from datetime import datetime/from re import Pattern, which is likely to fail the repo’s import-sorting lint (ruff/isort). Reorder the stdlib from ... import ... lines so they’re sorted consistently.

Suggested change
from datetime import datetime
from re import Pattern
from collections.abc import Callable
from collections.abc import Callable
from datetime import datetime
from re import Pattern

Copilot uses AI. Check for mistakes.
@codecov

codecov Bot commented Mar 31, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 61.11111% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 64.58%. Comparing base (dbc25dc) to head (2e48b86).
⚠️ Report is 34 commits behind head on master.

Files with missing lines Patch % Lines
superset/db_engine_specs/bigquery.py 61.11% 7 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #38925      +/-   ##
==========================================
- Coverage   64.58%   64.58%   -0.01%     
==========================================
  Files        2536     2536              
  Lines      130811   130829      +18     
  Branches    30346    30346              
==========================================
+ Hits        84486    84497      +11     
- Misses      44856    44863       +7     
  Partials     1469     1469              
Flag Coverage Δ
hive 40.36% <61.11%> (+<0.01%) ⬆️
mysql 61.29% <61.11%> (-0.01%) ⬇️
postgres 61.37% <61.11%> (-0.01%) ⬇️
presto 40.37% <61.11%> (+<0.01%) ⬆️
python 62.97% <61.11%> (-0.01%) ⬇️
sqlite 60.99% <61.11%> (+<0.01%) ⬆️
unit 100.00% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@netlify

netlify Bot commented Apr 12, 2026

Copy link
Copy Markdown

✅ Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit 228a226
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/69dae5703e52ec00089c85fc
😎 Deploy Preview https://deploy-preview-38925--superset-docs-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@bito-code-review

bito-code-review Bot commented Apr 12, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #294b3d

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: 2e48b86..228a226
    • superset/db_engine_specs/bigquery.py
    • tests/unit_tests/jinja_context_test.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@vijaygovindaraja

Copy link
Copy Markdown
Author

anyone available to review this? fixes apostrophe escaping in BigQuery filter values.

@rusackas

Copy link
Copy Markdown
Member

Thanks @vijaygovindaraja. Would love to see this close #35857. My one hesitation is the import-time monkeypatch of BigQueryDialect.colspecs rather than scoping it to the engine spec. @betodealmeida does a global colspecs override feel right here, given we do something similar for Databricks?

@rusackas

Copy link
Copy Markdown
Member

Looks like this is a duplicate of #38835, which targets the same issue with the same approach but is further along with green CI. FWIW, #40455 is a third PR on this same issue.

@rusackas

Copy link
Copy Markdown
Member

Thanks for this @vijaygovindaraja, and nice that you landed on the same backslash-escaping approach. We just merged #38835 for this (same fix for #35857), which had been through a couple of review rounds, so I'm going to close this as a duplicate. Genuinely appreciate the fix though... sorry it overlapped. Please keep 'em coming :)

@rusackas rusackas closed this Jun 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

data:connect:googlebigquery Related to BigQuery size/M size:M This PR changes 30-99 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BigQuery errors when filters on text columns have apostrophes in them

3 participants