Skip to content

fix(bigquery): limit result set size to prevent browser memory crashes - #38588

Merged
rusackas merged 9 commits into
masterfrom
adopt-pr-36387-bq-memory-limit
May 23, 2026
Merged

fix(bigquery): limit result set size to prevent browser memory crashes#38588
rusackas merged 9 commits into
masterfrom
adopt-pr-36387-bq-memory-limit

Conversation

@rusackas

@rusackas rusackas commented Mar 11, 2026

Copy link
Copy Markdown
Member

User description

SUMMARY

Adopts and improves the fix from #36387 (originally by @ethan-l-geotab). Fixes #36385.

BigQuery queries returning huge result sets (950+ MB) crash Chrome by loading everything into browser memory at once. This PR implements memory-aware progressive fetching in BigQueryEngineSpec.fetch_data:

  1. Progressive fetch: Samples an initial batch (1000 rows) to estimate row size, then extrapolates how many total rows fit within the BQ_FETCH_MAX_MB config limit (default 200 MB)
  2. Warning propagation: When results are truncated, a warning is passed through Flask g to the query context processor, which adds it to the response payload
  3. Frontend toast: The chart action handler displays a warning toast to the user when results were truncated
  4. Graceful fallback: On any error in the progressive fetch, falls back to the parent BaseEngineSpec.fetch_data implementation

Key differences from the original PR (#36387):

  • Removed the BQ_MEMORY_LIMIT_FETCH feature flag -- the fix is always-on
  • The BQ_FETCH_MAX_MB config constant (default 200 MB) is the only operator-level knob
  • Added comprehensive unit tests for the new BigQuery fetch logic and warning propagation
  • Applied to the renamed chartAction.ts (was .js in the original PR)

Files changed:

  • superset/db_engine_specs/bigquery.py -- Memory-aware progressive fetch implementation
  • superset/common/query_context_processor.py -- Warning propagation via Flask g
  • superset/config.py -- BQ_FETCH_MAX_MB = 200 config constant
  • superset-frontend/src/components/Chart/chartAction.ts -- Warning toast display
  • superset-frontend/packages/superset-ui-core/src/query/types/QueryResponse.ts -- warning field on ChartDataResponseResult
  • tests/unit_tests/db_engine_specs/test_bigquery.py -- 5 new test cases
  • tests/unit_tests/common/test_query_context_processor.py -- 2 new test cases

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

Before: Chrome crashes or becomes unresponsive when BigQuery returns 950+ MB of data.

After: Results are truncated to fit within the configured memory budget, and a warning toast informs the user.

TESTING INSTRUCTIONS

  1. Configure a BigQuery datasource in Superset
  2. Run a query that returns a very large result set (millions of rows)
  3. Verify that results are truncated and a warning toast appears
  4. Set BQ_FETCH_MAX_MB to a smaller value (e.g., 10) in superset_config.py to test truncation with smaller datasets
  5. Verify that queries returning small result sets work normally without any warning
  6. Run the new unit tests: pytest tests/unit_tests/db_engine_specs/test_bigquery.py -k test_fetch_data -v

ADDITIONAL INFORMATION

Co-authored-by: ethan-l-geotab ethanliong@geotab.com


CodeAnt-AI Description

Limit BigQuery fetch size to avoid browser memory crashes and show truncation warning

What Changed

  • BigQuery query results are fetched progressively and capped by a memory budget so very large result sets no longer load entirely into the browser (default budget: 200 MB)
  • When results are truncated due to the memory cap, the backend includes a user-facing warning in the query payload and the frontend shows a warning toast explaining the truncation
  • Added a BQ_FETCH_MAX_MB configuration (default 200) to control the fetch budget and added a warning field to query responses

Impact

✅ Fewer browser crashes when querying BigQuery
✅ Clearer warnings when chart data is truncated
✅ Predictable memory usage during large BigQuery queries

💡 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.

Implement memory-aware progressive fetching in BigQuery's fetch_data
method. Large result sets (950+ MB) previously crashed Chrome by loading
everything into memory at once. The fix samples an initial batch to
estimate row size, then fetches only as many rows as fit within the
BQ_FETCH_MAX_MB config limit (default 200 MB). A warning toast is shown
to users when results are truncated.

This is always-on with no feature flag -- operators control the budget
via the BQ_FETCH_MAX_MB config constant.

Originally by @ethan-l-geotab in #36387.

Co-authored-by: ethan-l-geotab <ethanliong@geotab.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@dosubot dosubot Bot added the data:connect:googlebigquery Related to BigQuery label Mar 11, 2026

@bito-code-review bito-code-review Bot 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.

Code Review Agent Run #e5147f

Actionable Suggestions - 3
  • superset/db_engine_specs/bigquery.py - 2
  • superset-frontend/packages/superset-ui-core/src/query/types/QueryResponse.ts - 1
    • Backend schema missing warning field · Line 80-80
Review Details
  • Files reviewed - 7 · Commit Range: 1773531..1773531
    • superset-frontend/packages/superset-ui-core/src/query/types/QueryResponse.ts
    • superset-frontend/src/components/Chart/chartAction.ts
    • superset/common/query_context_processor.py
    • superset/config.py
    • superset/db_engine_specs/bigquery.py
    • tests/unit_tests/common/test_query_context_processor.py
    • tests/unit_tests/db_engine_specs/test_bigquery.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ 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

Comment thread superset/db_engine_specs/bigquery.py Outdated
Comment thread superset/db_engine_specs/bigquery.py
@codeant-ai-for-open-source codeant-ai-for-open-source Bot added the size:L This PR changes 100-499 lines, ignoring generated files label Mar 17, 2026
Comment thread superset-frontend/src/components/Chart/chartAction.ts
Comment thread superset/common/query_context_processor.py

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

Implements a memory-aware progressive fetch in the BigQuery engine spec to prevent large result sets from overwhelming browser memory, and propagates a truncation warning through the backend response so the frontend can notify the user.

Changes:

  • Add progressive, memory-budgeted fetching in BigQueryEngineSpec.fetch_data (default cap via new BQ_FETCH_MAX_MB config).
  • Propagate a truncation warning into chart data responses and show it as a frontend warning toast.
  • Add unit tests for BigQuery fetch behavior and warning propagation.

Reviewed changes

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

Show a summary per file
File Description
superset/db_engine_specs/bigquery.py Adds progressive fetch logic and sets truncation flags for warning propagation.
superset/common/query_context_processor.py Adds a warning field to the per-query payload when truncation is detected.
superset/config.py Introduces BQ_FETCH_MAX_MB default configuration value (200 MB).
superset-frontend/src/components/Chart/chartAction.ts Displays a warning toast when a query response includes warning.
superset-frontend/packages/superset-ui-core/src/query/types/QueryResponse.ts Extends query response typing to include optional warning.
tests/unit_tests/db_engine_specs/test_bigquery.py Adds unit tests for the new BigQuery fetch/truncation behavior and fallback.
tests/unit_tests/common/test_query_context_processor.py Adds unit tests ensuring warning is included/omitted appropriately.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread superset/db_engine_specs/bigquery.py Outdated
Comment thread superset/db_engine_specs/bigquery.py Outdated
Comment thread superset/db_engine_specs/bigquery.py Outdated
Comment thread superset/common/query_context_processor.py
Comment thread superset/common/query_context_processor.py
Comment thread superset-frontend/src/components/Chart/chartAction.ts
Comment thread superset/db_engine_specs/bigquery.py
- Use has_app_context()/has_request_context() guards so fetch_data
  is safe to call outside a Flask request (fixes RuntimeError on g
  writes and current_app access in non-request paths)
- Replace sys.getsizeof(str(batch)) with per-row getsizeof sum for
  more accurate memory estimation without the str() allocation
- Fix false-positive truncation: fetch remaining+1 rows and check
  len > remaining to confirm more data exists beyond the cap
- Reset g.bq_memory_limited/g.bq_memory_limited_row_count after
  reading in get_df_payload to prevent flag leaking across multiple
  queries in the same request
- Wrap warning string in _() for i18n
- Add warning field to ChartDataResponseResult Marshmallow schema
- Pass noDuplicate: true to addWarningToast to suppress duplicate
  toasts when a multi-query chart has multiple truncated responses

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@netlify

netlify Bot commented Apr 7, 2026

Copy link
Copy Markdown

Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit 3601013
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/69e91e24e9d940000811c30d
😎 Deploy Preview https://deploy-preview-38588--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.

Comment thread superset/db_engine_specs/bigquery.py Outdated
@codecov

codecov Bot commented Apr 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 46.37681% with 37 lines in your changes missing coverage. Please review.
✅ Project coverage is 64.17%. Comparing base (c945ef6) to head (03521a4).
⚠️ Report is 12 commits behind head on master.

Files with missing lines Patch % Lines
superset/db_engine_specs/bigquery.py 33.33% 31 Missing and 1 partial ⚠️
superset/common/query_context_processor.py 16.66% 4 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #38588      +/-   ##
==========================================
- Coverage   64.19%   64.17%   -0.02%     
==========================================
  Files        2592     2592              
  Lines      139080   139161      +81     
  Branches    32299    32316      +17     
==========================================
+ Hits        89281    89313      +32     
- Misses      48267    48313      +46     
- Partials     1532     1535       +3     
Flag Coverage Δ
hive 39.24% <10.60%> (-0.04%) ⬇️
javascript 67.29% <100.00%> (+<0.01%) ⬆️
mysql 58.76% <43.93%> (-0.03%) ⬇️
postgres 58.84% <43.93%> (-0.03%) ⬇️
presto 40.92% <21.21%> (-0.04%) ⬇️
python 60.40% <43.93%> (-0.03%) ⬇️
sqlite 58.48% <43.93%> (-0.03%) ⬇️
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.

Cache persistence: persist bq_memory_limited flag in QueryCacheManager
so truncation warnings survive cache hits. The flag is now saved into
the cache value dict in set_query_result (reading from g and resetting
it there), and restored from cache in get(). get_df_payload now reads
cache.bq_memory_limited instead of g, removing the need for g entirely
in query_context_processor.py.

Frontend test: add two tests to chartActions.test.ts verifying that
addWarningToast is dispatched (with noDuplicate: true) when a query
response carries a warning field, and not dispatched when it doesn't.

Updated existing test_query_context_processor tests to set the flag on
mock_cache directly rather than patching g.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@bito-code-review

bito-code-review Bot commented Apr 7, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #97d812

Actionable Suggestions - 0
Review Details
  • Files reviewed - 7 · Commit Range: 1773531..bbbd149
    • superset-frontend/src/components/Chart/chartAction.ts
    • superset/charts/schemas.py
    • superset/common/query_context_processor.py
    • superset/db_engine_specs/bigquery.py
    • superset-frontend/src/components/Chart/chartActions.test.ts
    • superset/common/utils/query_cache_manager.py
    • tests/unit_tests/common/test_query_context_processor.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ 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

sys.getsizeof(row) on a tuple only measures the container, not the
referenced cell values. Switch to summing container + element sizes
(one level deep) for a more accurate memory budget estimate. Most
BigQuery cell values are primitives (str, int, float, date), so one
level captures the dominant allocation without deep recursion overhead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@bito-code-review

bito-code-review Bot commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #8a5284

Actionable Suggestions - 0
Review Details
  • Files reviewed - 1 · Commit Range: bbbd149..889f23e
    • superset/db_engine_specs/bigquery.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

The new bq_memory_limited warning path in get_df_payload iterates all
cache mocks in existing tests. Those pre-existing tests don't set
bq_memory_limited on their MagicMock/MockCache instances, causing
TypeErrors on f-string format or AttributeErrors. Set the field to
False/0 in the three impacted tests so they exercise the no-warning
code path.
@bito-code-review

bito-code-review Bot commented Apr 19, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #6a86fb

Actionable Suggestions - 0
Review Details
  • Files reviewed - 1 · Commit Range: 889f23e..05a9b47
    • tests/unit_tests/common/test_query_context_processor.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

@aminghadersohi aminghadersohi 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.

LGTM — well-crafted fix for a real production pain point. The progressive-fetch approach with an upfront sample is sound, and the author has already addressed all bot-review concerns (false-positive truncation detection, g-flag leakage, cache persistence, LocalProxy safety, i18n wrapping, frontend test coverage).

One MEDIUM style nit worth fixing before merge:

  • superset/db_engine_specs/bigquery.py:317current_app.config.get("BQ_FETCH_MAX_MB", 200) should be current_app.config["BQ_FETCH_MAX_MB"] since the key has a default in config.py. The Superset convention is config["KEY"].get() with a fallback hides missing-config bugs and duplicates the default unnecessarily.

Non-blocking NITs:

  • bigquery.py:322 — magic number 1000 for the initial sample batch size could be a named constant (_BQ_INITIAL_SAMPLE_ROWS) for clarity/testability.
  • bigquery.py:379 — the broad except Exception (already pylint-disabled) would benefit from a comment naming the expected failure modes (BQ DB-API errors, network timeouts, unexpected Row subtypes).
  • test_query_context_processor.py:1615, 1675 — the two new test functions are missing -> None return type annotations.

Particularly well done: the +1 fetch trick to confirm truncation without false positives, the g-flag cache persistence pattern, and the noDuplicate: true toast dedup.

- bigquery.py: switch `config.get("BQ_FETCH_MAX_MB", 200)` to bracket
  access in-context. The default lives in config.py; bracket access
  surfaces a missing key as a loud KeyError rather than silently
  masking it with a duplicated fallback. The 200 still applies in the
  no-app-context branch.
- bigquery.py: extract `1000` initial sample size to module-level
  `_BQ_INITIAL_SAMPLE_ROWS` constant with a docstring.
- bigquery.py: add a comment to the broad `except Exception` naming
  the expected failure modes (DB-API errors, network/auth timeouts,
  `sys.getsizeof` on unknown cell types, future `Row` subclasses).
- test_query_context_processor.py: add `-> None` return annotations
  to the two new `test_get_df_payload_bq_memory_limited_*` functions.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@rusackas

Copy link
Copy Markdown
Member Author

Thanks for the careful review @aminghadersohi! Applied all four in 03521a4:

  • MEDIUM: bigquery.py:317 switched to current_app.config["BQ_FETCH_MAX_MB"]. Added a comment noting the 200 fallback is only used when running outside an app context.
  • NIT: extracted 1000 to _BQ_INITIAL_SAMPLE_ROWS module-level constant with docstring.
  • NIT: added a comment to the broad except Exception naming expected failure modes (DB-API errors, network/auth timeouts, sys.getsizeof on unknown cell types, future Row subclasses).
  • NIT: added -> None return annotations to both test_get_df_payload_bq_memory_limited_* test functions.

Pre-commit (ruff/mypy/pylint) all pass locally. Should be green and ready to merge once CI re-runs.

@rusackas
rusackas merged commit e573870 into master May 23, 2026
72 checks passed
@rusackas
rusackas deleted the adopt-pr-36387-bq-memory-limit branch May 23, 2026 04:07
@bito-code-review

Copy link
Copy Markdown
Contributor

Bito Automatic Review Skipped – PR Already Merged

Bito scheduled an automatic review for this pull request, but the review was skipped because this PR was merged before the review could be run.
No action is needed if you didn't intend to review it. To get a review, you can type /review in a comment and save it

kasiazjc pushed a commit that referenced this pull request May 26, 2026
#38588)

Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: ethan-l-geotab <ethanliong@geotab.com>
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 packages preset-io size/L size:L This PR changes 100-499 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Large chart data doesn't return a helpful error message

4 participants