Skip to content

fix(i18n): make module-level error constants lazy gettext - #44180

Merged
aminghadersohi merged 8 commits into
apache:masterfrom
mikebridge:sc-120397-lazy-module-constant
Sep 18, 2026
Merged

aminghadersohi merged 8 commits into
apache:masterfrom
mikebridge:sc-120397-lazy-module-constant

Conversation

@mikebridge

@mikebridge mikebridge commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

SUMMARY

DATASOURCE_MISSING_ERR (views/core.py) and PARAMETER_MISSING_ERR (sqllab/query_render.py) were built with the eager gettext alias at module scope, so each was resolved exactly once at import time — no request, no locale context — and then served in the default locale to every user forever. This is the mirror image of the bug fixed in #44090 (lazy gettext inside request handlers), and together they define the convention:

  • eager __() for strings built inside request handlers;
  • lazy _() for module-scope constants, coerced with str() at the point of use inside the request.

The point-of-use str() also makes this PR independent of #44090's LazyString coercion in json_error_response — correct in either merge order.

Also removed: USER_MISSING_ERR and views/core.py's duplicate PARAMETER_MISSING_ERR, which had no consumers anywhere (dead constants).

Review round (Codex, python lens): the package tripwire was rewritten from a text scan to an AST scanner — the substring approach had a false-positive class ("gettext as __" also matches lazy_gettext as __) and blind spots (annotated assignments, bare gettext(...), other aliases, class-body constants, docstring text). The AST scanner resolves each module's actual Babel import bindings and inspects Assign/AnnAssign at import-time scopes only. It immediately caught a fourth real offender the old scan could not see: CertificateException's class-level default message (exceptions.py binds _ to eager gettext). The default is now translated at construction — explicit messages, causes, and error types preserved — and parse_ssl_cert drops its redundant untranslated literal so the translated default is reachable. No consumer reads the class attribute or the exception's message (the DB schema validator emits its own).

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

N/A — i18n behavior. Before: a French user got "The data source seems to have been deleted". After: "La source de données semble avoir été effacée".

TESTING INSTRUCTIONS

pytest tests/unit_tests/views/test_i18n_constants.py (27 tests) —

  • the constants are pinned as LazyString (fails pre-fix);
  • a translation-lookup pin stubs flask-babel's get_domain with a sentinel catalog and asserts every str() of the constant consults the live lookup — runs on every backend, no compiled catalog needed;
  • a two-locale pin compiles a real catalog into a temp dir and renders the same constant under two request contexts with different locales through real Babel selection (an eager constant would render identically in both);
  • the inverse-convention tripwire scans the whole package with the AST scanner (fails pre-fix on all four eager constants incl. CertificateException; pairs with fix(views): error-response bodies must carry their message #44090's lazy-in-request scan), and 20 classifier self-test cases pin the scanner's corners (lazy aliases not flagged, function bodies skipped, annotated assignments and class bodies caught, docstrings inert, class-local rebinding scoped);
  • CertificateException construction is pinned: default message translated exactly once, explicit message bypasses translation, cause and error type preserved.

Reverting the production change flips the LazyString pins and the tripwire.

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags:
  • Changes UI
  • Includes DB Migration (follow approval process in SIP-59)
    • Migration is atomic, supports rollback & is backwards-compatible
    • Confirm DB migration upgrade and downgrade tested
    • Runtime estimates and downtime expectations provided
  • Introduces new feature or API
  • Removes existing feature or API

🤖 Generated with Claude Code

https://claude.ai/code/session_01JRLEJS4mUqKBoPjSjviKUW

DATASOURCE_MISSING_ERR (views/core.py) and PARAMETER_MISSING_ERR
(sqllab/query_render.py) were built with the eager gettext alias at
module scope, so they were resolved exactly once at import time — no
request, no locale context — and served in the default locale to every
user forever. The mirror image of sc-120052's bug, defining the paired
convention: eager __() for strings built inside request handlers, lazy
_() for module-scope constants, coerced with str() at the point of use
(which also keeps this independent of apache#44090's LazyString coercion —
correct in either merge order).

USER_MISSING_ERR and views/core.py's duplicate PARAMETER_MISSING_ERR had
no consumers at all and are removed. Tests pin the constants as
LazyString, render DATASOURCE_MISSING_ERR under fr/en per-request locale
(skipped where the fr catalog is not compiled), and add the
inverse-convention tripwire: no module-level NAME = __(...) may exist in
any module binding __ to eager gettext.

sc-120397

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JRLEJS4mUqKBoPjSjviKUW
@github-actions github-actions Bot added the api Related to the REST API label Sep 11, 2026
Committer-round optional fold: the per-locale render pin was skipif'd on
a compiled fr catalog that CI never builds, so CI never ran it. Stub
flask-babel's get_domain with a sentinel catalog instead: every str() of
the constant must consult the live lookup (an eager constant would have
been frozen to a plain str before the stub existed), which runs
everywhere and stops hard-coding the fr catalog's exact French.

sc-120397

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JRLEJS4mUqKBoPjSjviKUW
@mikebridge
mikebridge marked this pull request as ready for review September 11, 2026 22:46
@codecov

codecov Bot commented Sep 11, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.88889% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 80.39%. Comparing base (4c77b0b) to head (bab9116).
⚠️ Report is 9 commits behind head on master.

Files with missing lines Patch % Lines
superset/views/core.py 66.66% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #44180      +/-   ##
==========================================
- Coverage   80.40%   80.39%   -0.01%     
==========================================
  Files        2932     2932              
  Lines      174525   174526       +1     
  Branches    40548    40548              
==========================================
- Hits       140319   140317       -2     
- Misses      31537    31540       +3     
  Partials     2669     2669              
Flag Coverage Δ
hive 37.15% <66.66%> (-0.01%) ⬇️
mysql 56.60% <88.88%> (-0.01%) ⬇️
postgres 56.62% <88.88%> (-0.01%) ⬇️
presto 39.22% <66.66%> (-0.01%) ⬇️
python 84.75% <88.88%> (-0.01%) ⬇️
sqlite 56.31% <66.66%> (-0.01%) ⬇️
unit 76.36% <77.77%> (+<0.01%) ⬆️

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

☔ View full report in Codecov by Harness.
📢 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.

…xception default at construction

Review round on the tripwire (Codex astra, python lens) — the substring
scan had a false-positive class (`"gettext as __" in source` also
matches lazy_gettext) and blind spots (annotated assignments, bare
gettext(), other aliases, class-body constants, docstring text).
Replaced with an AST scanner: resolves each module's actual Babel
import bindings (from-imports incl. aliases, and module-attribute calls
like fb.gettext), then inspects Assign and AnnAssign at import-time
scopes (module body, class bodies, module-level if/try/with) while
skipping function bodies. 20 classifier self-test cases pin every
probed corner.

The stronger scanner immediately caught a fourth real offender:
CertificateException's class-level default message, eager-translated at
import (exceptions.py binds `_` to eager gettext — the alias the old
scan could not see). The default now translates at construction;
explicit messages, causes, and error types are preserved (tested), and
the parse_ssl_cert raise site drops its redundant untranslated literal
so the translated default is actually reachable. No consumer reads the
class attribute or the exception's message (the schema validator emits
its own).

Also: LazyString annotations at both constant definition sites, and a
two-locale test proving per-request locale SELECTION through real Babel
machinery (compiled catalog + locale selector), not just deferred
lookup.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JRLEJS4mUqKBoPjSjviKUW
Comment thread superset/exceptions.py
@bito-code-review

Copy link
Copy Markdown
Contributor

The flagged issue is correct. Constructing CertificateException() at the module level or outside a request context triggers gettext to attempt translation immediately, which fails because the Flask application context is not yet available, resulting in a RuntimeError.

To resolve this, you should use lazy_gettext (often aliased as _) instead of gettext (aliased as __) for module-level constants. This defers translation until the string is actually accessed within a request context. In superset/exceptions.py, you can update the CertificateException to accept a lazy string or handle the translation lazily within the __init__ method.

Would you like me to fetch all other comments on this PR to validate them and implement fixes for the rest?

superset/exceptions.py

from flask_babel import lazy_gettext as _

class CertificateException(SupersetException):
    def __init__(self, message: str = "", ...):
        super().__init__(
            message=message or _("Invalid certificate"),
            ...
        )

@bito-code-review

Copy link
Copy Markdown
Contributor

Bito Automatic Review Failed - Technical Failure

Bito encountered technical difficulties while generating code feedback . To retry, type /review in a comment and save. If the issue persists, contact support@bito.ai and provide the following details:

Agent Run ID: c774bac3-53f6-4bd8-a571-a22a1be869be

@mikebridge mikebridge closed this Sep 12, 2026
@mikebridge mikebridge reopened this Sep 12, 2026

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

Adversarial review of the lazy-i18n-constants change. This is a clean, well-tested i18n fix — the removed constants have no consumers, the AST classifier flags exactly the offender lines, the eager __ imports stay used (no F401), and the two behavioral tests (get_domain stub + real two-locale render) genuinely pin per-request translation. No correctness bugs. Two lower-severity notes below — one on the repo-wide tripwire test's robustness, one a constructive alternative for the CertificateException change. (Automated review; posted by a human reviewer.)

Comment thread tests/unit_tests/views/test_i18n_constants.py
Comment thread superset/exceptions.py
…state the construction-time rationale

Review round (fitzee): the package tripwire gains an explicit (empty)
allowlist as the opt-out for a future legitimately-eager module, skips
unparseable files instead of failing an unrelated i18n test, and its
docstring concedes the linter-rule home (a custom pylint checker is the
right follow-up; the walk is ~1s meanwhile). CertificateException's
__init__ now states why it diverges from the sibling class-attr
pattern: construction-time translation resolves to plain str inside the
raising request, so no LazyString can leak into to_dict()/JSON bodies.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JRLEJS4mUqKBoPjSjviKUW
@netlify

netlify Bot commented Sep 14, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit 5a43e6e
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/6aab5af9283e200008f12aaa
😎 Deploy Preview https://deploy-preview-44180--superset-docs-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

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

@mikebridge mikebridge closed this Sep 14, 2026
@mikebridge mikebridge reopened this Sep 14, 2026
@bito-code-review

bito-code-review Bot commented Sep 14, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #8f54c9

Actionable Suggestions - 0
Review Details
  • Files reviewed - 5 · Commit Range: 4a7518e..c1f602e
    • superset/exceptions.py
    • superset/sqllab/query_render.py
    • superset/utils/core.py
    • superset/views/core.py
    • tests/unit_tests/views/test_i18n_constants.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

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

  • /review - Manually triggers an incremental AI Review.

  • /review full - 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 self-requested a review September 15, 2026 07:50

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

Two inlines: the str() coercion the PR is built around is load-bearing but unasserted (dropping it empties the response body), and the new __init__ docstring's "sibling pattern" premise doesn't hold.

Comment thread superset/views/core.py
# Check if datasource exists
if not datasource:
return json_error_response(DATASOURCE_MISSING_ERR)
return json_error_response(str(DATASOURCE_MISSING_ERR))

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.

json_error_response dispatches on isinstance(error_details, str) with no else, and LazyString is not a str subclass. Drop this str() and the body becomes {} — message silently gone — yet all 27 new tests still pass. No fence: the fix is a test, not a line here.

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.

Retracting the consequence half of this: your merge pulled in #44090, which added an elif isinstance(error_details, LazyString) branch, so dropping this str() now yields a byte-identical body (measured). Redundant rather than load-bearing — nothing to change.

Comment thread superset/exceptions.py Outdated
Comment on lines +217 to +218
Deliberately diverges from the sibling pattern of a class-level
``message`` default: translating at construction resolves to a

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.

Parsed all 49 classes in this file: CertificateException was the only subclass carrying a class-level message default (SupersetException.message = "" is the base, not a sibling). No sibling pattern to diverge from — this converges on what the other 47 already do.

Suggested change
Deliberately diverges from the sibling pattern of a class-level
``message`` default: translating at construction resolves to a
Drops the class-level ``message`` default that made this the only
such subclass: translating at construction resolves to a

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in a2e72b4: the CertificateException docstring describes this subclass’s construction-time translation without claiming a sibling class-level pattern. No behavior change. The i18n suite passed (27 tests), pre-commit passed on all branch-changed files, and an independent Claude review approved the final snapshot. The retracted LazyString concern and accepted lint-rule follow-up remain unchanged.

@bito-code-review

bito-code-review Bot commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #298e05

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

Bito Usage Guide

Commands

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

  • /review - Manually triggers an incremental AI Review.

  • /review full - 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

@mikebridge

Copy link
Copy Markdown
Contributor Author

CI refresh: merged Apache master containing the already-merged migration repair #44364 into this branch, published at 5a43e6e. No duplicate migration was added. The fresh PR merge ref includes repair commit 4c77b0b; its migration directory matches that repaired baseline.

Local verification: 28 focused tests passed (including the single-migration-head regression), all applicable pre-commit hooks passed against the complete branch-changed file list, and the final source snapshot received independent Python review.

Fresh CI has been triggered; this is not an all-green claim. Live database integration remains a remote-CI gate. The older migration failures tested pre-repair merge snapshots and are not evidence about this new head.

@mikebridge

Copy link
Copy Markdown
Contributor Author

Readiness follow-through at 5a43e6e: fresh checks have completed with no failing or pending checks (64 success, 10 skipped, 2 neutral). PostgreSQL tested 858333e, which includes merged migration repair #44364, and passed 2,790 tests.

The CertificateException docstring correction is published as described in the inline reply. The LazyString consequence was explicitly retracted by the reviewer; the deferred lint-rule follow-up remains separate. Author work is complete, with reviewer confirmation still outstanding on the docstring thread. No new approval or automatic thread resolution is implied.

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

Docstring correction verified accurate against master (CertificateException did carry a class-level message). Three mutants on the lazy constants all fail as intended. One detection-scope gap in the tripwire, inline.

bindings = bindings.copy()
_record_gettext_import(node, bindings)
if isinstance(node, (ast.Assign, ast.AnnAssign)):
if isinstance(node.value, ast.Call) and _is_eager_gettext_call(

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.

Only a direct node.value Call is checked, so an eager call nested in a kwarg/dict/list is invisible: 80 import-time sites across 24 files pass today — e.g. db_engine_specs/base.py:3046, metadata={"description": __("Username")}. No fence; widening needs an allowlist call.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in bab9116. The tripwire now visits nested assignment expressions, including keyword metadata, dict/list values and eager comprehensions. It excludes deferred lambda/generator bodies while checking lambda defaults and generator outer iterables.

The wider scan finds 137 individual calls across 24 files. These are recorded as explicit existing debt by file + normalized call expression + occurrence budget, rather than exempting whole files or converting unrelated metadata to lazy strings. Controls reject a new message and extra occurrences of an allowed call.

Four new classifier cases failed before the fix; the final focused suite passes all 36 tests, and scoped pre-commit checks pass for all five branch-changed files. No production behavior changes in this follow-up. The scanner remains a bounded syntax guard, not an interprocedural evaluator. Fresh CI on this SHA is still pending.

@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 #cb3a2a

Actionable Suggestions - 1
  • tests/unit_tests/views/test_i18n_constants.py - 1
Additional Suggestions - 1
  • tests/unit_tests/views/test_i18n_constants.py - 1
    • Stale allowlist entries undetected · Line 249-538
      Every allowlist entry is consumed by real eager calls today (verified by re-running the classifier over `superset/`), but nothing fails when an entry goes stale: `_unexpected_eager_calls` only counts calls upward, never budgets downward. Once a message is fixed upstream, its entry becomes dead weight that silently re-exempts a future regression of the same call. Consider asserting all budgets are consumed.
Review Details
  • Files reviewed - 1 · Commit Range: a2e72b4..bab9116
    • tests/unit_tests/views/test_i18n_constants.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

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

  • /review - Manually triggers an incremental AI Review.

  • /review full - 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 on lines +130 to +134
if isinstance(node, ast.Call) and _is_eager_gettext_call(node.func, bindings):
yield node
child: ast.AST
for child in ast.iter_child_nodes(node):
yield from _iter_eager_gettext_calls(child, bindings)

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.

Duplicate yield for nested calls

In _iter_eager_gettext_calls, after yielding a matched ast.Call at line 130-131, control falls through to the ast.iter_child_nodes loop at line 133, which re-visits the call's arguments. For a nested eager call like tr(tr("x")) the inner call is yielded twice, so _unexpected_eager_calls's Counter budget (line 543-549) consumes two allowlist slots for one real occurrence and can false-fail the fence. Return after yielding a matched call.

Code Review Run #cb3a2a


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

@aminghadersohi
aminghadersohi merged commit f1dc566 into apache:master Sep 18, 2026
83 checks passed
villebro pushed a commit that referenced this pull request Sep 20, 2026
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Mike Bridge <michael.bridge@ext.preset.io>
(cherry picked from commit f1dc566)
mapledan added a commit to mapledan/superset that referenced this pull request Sep 22, 2026
…ation

`schema` as a constructor parameter on `BaseTemplateProcessor` took a name
away from users. A dataset's `template_params` are passed as keyword
arguments -- `models.helpers`: `template_kwargs.update(self.template_params_dict)`
-- so `{"schema": "sales"}` with `SELECT * FROM {{ schema }}.orders` stopped
rendering and left the reference in place. Verified against master, which
renders it.

Estimation instead builds an unpersisted `Query`, the way the execution path
has one, and passes it: the processor reads the location from it as it always
has, so no keyword is claimed and nothing else moves. `catalog` travels the
same way, from the same source as the schema, because
`presto.latest_partition` has to read partition metadata from the catalog the
query runs in, not the connection's default.

That query also carries the rendered SQL to the authorization check, pinned as
`executed_sql` -- the handle `_validate_rendered_access` uses for the same
reason. `raise_for_access` builds an equivalent query from a raw `sql=`, so
this is parity of mechanism rather than a change in what is authorized, and
the regression test says so rather than claiming more.

`PARAMETER_MISSING_ERR` follows apache#44180 and is lazy, resolved to `str` at each
response, so the suggestion is not frozen in the locale that imported it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
mapledan added a commit to mapledan/superset that referenced this pull request Sep 22, 2026
…ation

`schema` as a constructor parameter on `BaseTemplateProcessor` took a name
away from users. A dataset's `template_params` are passed as keyword
arguments -- `models.helpers`: `template_kwargs.update(self.template_params_dict)`
-- so `{"schema": "sales"}` with `SELECT * FROM {{ schema }}.orders` stopped
rendering and left the reference in place. Verified against master, which
renders it.

Estimation instead builds an unpersisted `Query`, the way the execution path
has one, and passes it: the processor reads the location from it as it always
has, so no keyword is claimed and nothing else moves. `catalog` travels the
same way, from the same source as the schema, because
`presto.latest_partition` has to read partition metadata from the catalog the
query runs in, not the connection's default.

That query also carries the rendered SQL to the authorization check, pinned as
`executed_sql` -- the handle `_validate_rendered_access` uses for the same
reason. `raise_for_access` builds an equivalent query from a raw `sql=`, so
this is parity of mechanism rather than a change in what is authorized, and
the regression test says so rather than claiming more.

`PARAMETER_MISSING_ERR` follows apache#44180 and is lazy, resolved to `str` at each
response, so the suggestion is not frozen in the locale that imported it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api Related to the REST API size/XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants