Repository navigation
feat(bigquery): add native materialized view support and type domain contract - #1
Merged
Merged
Conversation
BigQuery has native materialized views, but supports_materialized_view() inherited
the core default of False, so there was no support at all — raw SQL was the only
option.
Implemented against the GoogleSQL DDL reference (each clause checked against the
official documentation):
CREATE [OR REPLACE] MATERIALIZED VIEW [IF NOT EXISTS] mv_name
[PARTITION BY expr] [CLUSTER BY cols] [OPTIONS(...)] AS query
ALTER MATERIALIZED VIEW [IF EXISTS] mv_name SET OPTIONS(...)
DROP MATERIALIZED VIEW [IF EXISTS] mv_name
CREATE MATERIALIZED VIEW replica [OPTIONS(...)] AS REPLICA OF source
Design notes:
- BigQuery has no REFRESH MATERIALIZED VIEW statement; refresh is scheduled
through OPTIONS(enable_refresh=…, refresh_interval_minutes=…), so
supports_refresh_materialized_view() stays False and schedule changes go
through BigQueryAlterMaterializedViewSetOptionsExpression.
- Clauses BigQuery lacks are refused rather than silently dropped: column
aliases (a BQ MV takes its column names from the query), TABLESPACE, storage
parameters, WITH [NO] DATA and DROP ... CASCADE. Passing them via the generic
expressions raises UnsupportedFeatureError.
- Option names are enumerated as BigQueryMaterializedViewOption (10 documented
options with value_type and documented defaults) and validated against that
enum rather than by pattern matching — the same trade-off as PostgreSQL's
PostgresStorageParameter.
- OR REPLACE and IF NOT EXISTS are mutually exclusive (explicit in BQ's grammar),
so they are rejected up front instead of producing SQL the server refuses.
- Replica creation validates replication_interval_seconds within the documented
[60, 3600] range.
Tests: 42 new cases covering clause order, clause rejection, the option
catalogue, boundary values, protocol conformance, and the backend-side
assertion of the MRO invariant "the formatter is owned by the BigQuery mixin".
…iour test_materialized_view_not_supported in test_bigquery_ddl_improvements asserted supports_materialized_view() is False (surfaced by CI run 36214625382). BigQuery now supports native materialized views, so it asserts True and additionally pins supports_refresh_materialized_view() to False — BigQuery has no REFRESH MATERIALIZED VIEW statement, refresh is scheduled through OPTIONS.
… revisions The installed hook exec'd scripts/preflight.sh unconditionally. That hook is a local, untracked artifact, so it survives a checkout of any commit that predates the script, and on such a commit exec failed with a bare "No such file or directory" — blocking the commit with nothing to act on. In this repository scripts/preflight.sh first appears at 71de328, so every earlier commit is affected. The failure is also silent in a dangerous way: it swallowed a `git commit --amend`, so a commit-message rewrite reported as applied when it had not been, and had to be redone. The hook now checks the script is executable and exits 0 otherwise, so a revision without the pre-flight simply skips it. Normal operation is unchanged. Also honours core.hooksPath. git ignores .git/hooks entirely once that is set, so the hook was being written to a location that would never run while this script still reported success. No repository sets it today, so that part is latent.
Both dependencies were pinned to feature/activerecord-derived-ddl, a branch that exists only to carry the derived-DDL work. Now that the core change has landed in release/v1.0.0.dev30 and the matching testsuite change in release/v1.0.0.dev17, pinning to the feature branch means CI keeps resolving a branch that will be deleted once the backend PRs merge. This is a prerequisite for merging: leaving the old ref in place means the first run after that branch disappears fails to resolve, not the code.
vistart
added a commit
that referenced
this pull request
Oct 11, 2026
Two defects, both silent. The configured template path pointed at a file that was never committed, so owncrier build failed outright instead of emitting a changelog -- verified on a clean checkout, not just locally. Filled in with the template the other backends use. Separately, PR #1 left a 1.internal.md behind, but internal is not one of the four types this repo configures. towncrier skips a fragment whose type it has no directory for, so that entry -- installing core and testsuite from release branches, and the pre-commit hook fix -- would have vanished from the next release notes. Moved to 1.changed.md, a type this repo does configure, and deleted the original. Verified after both changes: owncrier build --draft exits 0 and renders every fragment from all four pull requests under its section.
vistart
added a commit
that referenced
this pull request
Oct 11, 2026
… new string nodes (#4) * feat: the typed-columns column-type suggestion table * feat: align the column-type table with the rebuilt core protocol * fix(bigquery): follow the core rename of DateTimeColumn to TimestampColumn * test: follow the rebuilt DDL-source accessor semantics (column_type / column_data_type) * test: build predicates explicitly, now that the bare Column offers no operators * deps: pin pydantic 2.12.2 / pydantic-core 2.41.4 on Python 3.13 (incl. 3.13t) * feat: render the new pad/repeat/trim nodes (BigQuery spells lpad/rpad/repeat natively, trim via TRIM/LTRIM/RTRIM) * test: enumerate every core node class so a missing formatter cannot stay silent * ci: add the Python 3.15 leg (GIL only — no cp315t wheel for the driver) google-cloud-bigquery 3.46.1 is a universal wheel and declares a Python :: 3.15 classifier, but publishes no cp315t wheel, so a free-threaded 3.15t leg has nothing to run and is deliberately not declared. CI: append '3.15' to the plain python-version matrix list, on the same required footing as the other legs (no continue-on-error, no if: gate). pyproject: insert the Programming Language :: Python :: 3.15 classifier in sorted position (the list starts at 3.10; no lower versions invented). README: state the supported Python range explicitly (3.10 through 3.15 inclusive; requires-python is a floor, not a cap) and note the dynamic pyversions badge reads the classifiers from PyPI, so it picks 3.15 up on publish. * ci: install the core from its release branch now that typed-columns has merged While these branches were in development, CI installed the core from `@feature/typed-columns`, because the release branch did not carry the rebuilt column layer yet. That branch has now merged into `release/v1.0.0.dev30` (PR #126), so the feature reference is both stale and about to disappear with branch deletion. Point the core dependency at `release/v1.0.0.dev30` instead — the same branch these backends are merging into, which is what the release-side CI already used. The testsuite reference is deliberately left alone: that branch (`test/typed-column-contracts`) has not merged into its release yet, and pointing at a release that lacks the new contracts would break every backend at once. It moves when the testsuite merges. ClickHouse expresses the dependency as a `ref:` on `actions/checkout` rather than as a pip requirement; that one is switched the same way. * chore: add changelog fragment for PR #4 * fix(changelog): add the missing template and stop dropping a fragment Two defects, both silent. The configured template path pointed at a file that was never committed, so owncrier build failed outright instead of emitting a changelog -- verified on a clean checkout, not just locally. Filled in with the template the other backends use. Separately, PR #1 left a 1.internal.md behind, but internal is not one of the four types this repo configures. towncrier skips a fragment whose type it has no directory for, so that entry -- installing core and testsuite from release branches, and the pre-commit hook fix -- would have vanished from the next release notes. Moved to 1.changed.md, a type this repo does configure, and deleted the original. Verified after both changes: owncrier build --draft exits 0 and renders every fragment from all four pull requests under its section.
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.
Description
Brings the BigQuery backend onto the derived-DDL model in
rhosocial/python-activerecord#121. This is the smallest of the backend changes — 9 commits
across 19 files — and it is mostly additive.
support for DDL it could not emit, so the existing case that asserted the old probe
behaviour is realigned rather than deleted.
DDLSourcecollection, table inheritanceand tablespace are covered.
Type of change
feat: A new featuredocs: Documentation only changes (if related to the new feature)test: Adding missing tests or correcting existing tests (for the new feature)chore: Changes to the build process or auxiliary tools and libraries (if related to the new feature)Breaking Change
No commit carries a
!marker. The public model and query APIs are unchanged.Impact on End-Users:
No backward-incompatible API changes. Materialized views now render instead of being
reported as supported and then dropped.
Impact on Backend Developers (Custom Implementations):
old value will fail.
Related Repositories/Packages
The core half is rhosocial/python-activerecord#121 (merged into
release/v1.0.0.dev30) andthe shared contract half is rhosocial/python-activerecord-testsuite#21 (merged into
release/v1.0.0.dev17).This PR also repoints this repository's workflow at those release branches, a prerequisite for
merging: the dependencies were pinned to
feature/activerecord-derived-ddl, a branch thatonly exists to carry this work.
Merged or in flight: mysql #56, postgres #58, mariadb #5, sqlserver #4, oracle. Still to
merge: clickhouse, firebird, snowflake.
Testing
Local full-suite execution was skipped at the user's instruction. Verification relied on
remote CI on this exact tip
4d2e9f0, which is also the first execution against the releasebranches rather than the feature branch, so the new dependency refs are verified to resolve.
Checklist
changelog.d/(to be added after this PR isopened, named by the actual PR number)
Additional Notes
There is no pre-written
1.added.mdin this repository'schangelog.d/; existing fragmentsare numbered 2 and 3 from an earlier release, so PR #1 does not collide with anything.
Unlike the other eight backends, this repository has no prior pull request, so this is its
first PR against the derived-DDL model and its first CI run against the release branches.