Repository navigation
feat(mysql): adapt to derived DDL with typed table and column options - #56
Merged
Merged
Conversation
…formatting - Drop the private supports_inline_index/format_inline_index declarations from MySQLTableSupport; the capability now comes from the core TableSupport protocol (default False, MySQL overrides True) - Converge inline index rendering onto the core format_index_definition override (returns (sql, params)); remove the parallel method - Point CI at the core feature branch that carries the protocol
…rations MySQLPartitionDefinition / MySQLSubpartitionDefinition now derive from the generic PartitionDefinition / SubpartitionDefinition base declarations, keeping MySQL-specific boundary validation (requires exactly one boundary).
The generic SubpartitionDefinition base now validates the name in __post_init__, so MySQLSubpartitionDefinition rejects an empty name at construction time rather than in the formatter.
Introduce the MySQL-specific column definition derived from the generic ColumnDefinition, carrying typed CHARACTER SET / COLUMN_FORMAT / STORAGE / INVISIBLE attributes (no dialect_options bag). MySQLColumnOptions declares them and directs the deriver to build a MySQLColumnDefinition. MySQL format_column_definition now accepts both the generic and MySQL column definition and renders the MySQL-only attributes. Export the new classes and cover them with tests.
Introduce MySQLCreateTableOptions (deriving the generic CreateTableOptions) carrying the MySQL-only ENGINE / CHARSET / table COLLATE options with no dialect_options bag. The MySQL CREATE TABLE formatter reads these typed fields and the generic comment field, dropping the bag fallbacks.
The MySQL formatter now reads typed table_options.comment instead of the dialect_options bag; update the comment and engine/charset/collate tests accordingly.
Move the ADD COLUMN ... AFTER option off the dialect_options bag onto a typed MySQLAddColumn subclass read by the MysqlColumnMixin formatter.
The MySQL INSERT IGNORE / REPLACE variants move off the dialect_options bag onto a typed MySQLInsertExpression read by the dialect.
…ressions Remove the unused/reserved dialect_options parameter, attribute, pass-through arguments and docs from MySQL statement expressions (admin/utility, table maintenance, routine, rename table, table value statements, load XML). The data-type family (expression/types.py) keeps its own dialect_options.
Core DataType no longer carries a dialect_options bag; backend type subclasses stop forwarding it. Update the type-protocol tests.
…_option The view formatter rendered WITH CHECK OPTION unconditionally, leaving the capability bit inert.
…+ validation Add MySQLCharsetCollationSupport protocol and MySQLCharsetCollationMixin implementing a version-filtered whitelist (MySQLCharset, MySQLStorageEngine, MySQLCollation) plus validate_* helpers. MySQLCreateTableOptions now validates engine/charset/collate at construction instead of storing arbitrary strings. Fold the expression-level COLLATE handling into the mixin and drop the overlapping mixins/collation.py.
Fold the MySQLCollation enum and version gates into MySQLCharsetCollationMixin; remove the standalone collation.py module and the free validator functions. Collation/charset/engine validation is now exclusively a dialect protocol-implementation concern.
Add auto_increment (positive int) and row_format (MySQLRowFormat) typed fields to MySQLCreateTableOptions with validation, rendered by the MySQL create-table formatter.
The database DDL mixin existed but was not included in MySQLDialect, so CreateDatabaseExpression failed with a missing-formatting-method error.
Remove identity/identity_start/identity_increment/identity_clause from XxxColumnDefinition and XxxColumnOptions to match core's column-attribute migration; XxxColumnDefinition now forwards attributes.
Render the dialect-free column attributes channel in each backend's format_column_definition (it was silently dropped), and give backends whose identity syntax differs from the SQL-standard form a format_identity_clause override (MySQL/MariaDB AUTO_INCREMENT, SQL Server IDENTITY(seed, inc)). Oracle gates column COLLATE to 12.2+; MariaDB drops the duplicate dialect formatter so the attribute-aware mixin is authoritative.
Core added the ColumnAttributeSupport protocol and renamed the deriver plan entry to creation_plan(); update protocol conformance and derived-DDL tests.
Inline table/column comments are now TableCommentClause / ColumnCommentClause nodes; render them through format_table_comment_clause / format_column_comment_clause. Tests updated to build the clause nodes.
Model base already defaults to "id"; fixtures should exercise the unspecified-PK default path.
Verify MySQL DDLSource declarations, backend types, column options, and dialect rendering.
Expression classes moved under backend.expression/ and several were renamed during the derived-DDL refactor, leaving relative-import depths and forward references in TYPE_CHECKING blocks pointing at modules and classes that no longer exist. Type checkers and any runtime evaluation of those blocks fail to resolve them. Verified statically: every TYPE_CHECKING import in the touched files now resolves to an existing module and an existing top-level symbol, and no string annotation references a name absent from the workspace.
The suite applies markers that were never declared in [tool.pytest.ini_options] markers. pytest only warns for an unknown marker, so the warning scrolls past unnoticed and a dropped or misspelt registration is silent. Registers the ones in use, with descriptions that say what they do: collection grouping, not ordering. `feature` labels feature-area tests and `benchmark_relation` marks relation benchmarks; neither affects scheduling, so neither substitutes for the xdist_group marker that actually serialises a suite. usefixtures needs no entry and is not added: pytest provides it, so it was a false positive in the isolation audit rather than a missing registration.
… 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 4980455, 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.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## release/v1.0.0.dev20 #56 +/- ##
========================================================
+ Coverage 70.34% 70.41% +0.06%
========================================================
Files 106 110 +4
Lines 9733 10028 +295
Branches 1393 1432 +39
========================================================
+ Hits 6847 7061 +214
- Misses 2435 2500 +65
- Partials 451 467 +16
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
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
Adapts the MySQL backend to the derived-DDL model in rhosocial/python-activerecord#121,
which derives DDL from model declarations instead of carrying a dialect-specific option
bag on every expression.
The central change is replacing
dialect_optionswith typed, declared options. A dialect nowdeclares what it supports and the generic formatters consume that declaration:
MySQLColumnDefinitionand typed column options, including backend-specific identitysyntax.
MySQLCreateTableOptionswith typedAUTO_INCREMENTandROW_FORMAT, read from thegeneric declaration path.
collation whitelist moved into the dialect mixin.
declarations and subpartition names validated at construction.
MySQLInsertExpressioncarrying typedIGNORE/REPLACE, andMySQLAddColumnwith atyped
afterfield.Capability bits are wired through so unsupported forms fail loudly rather than emitting SQL
the server rejects:
supports_view_check_optiongatesCREATE VIEW ... WITH CHECK OPTION,supports_column_commentand the typed comment clauses replace the legacy identity fields,and
TABLESPACE/INHERITSare no longer silently dropped.Two contracts are added on top: a type-domain negative contract, and coverage for
DDLSourcecollection, table inheritance, tablespace and inline-index rendering from derivedDDL.
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 changes are expected for typical end-user applications. Table
options are now declared through typed options rather than a free-form bag, so DDL is
generated from the same declarations the ORM exposes.
Impact on Backend Developers (Custom Implementations):
Relevant to anyone extending or forking this backend rather than consuming it:
dialect_optionsbag is removed from data-type value objects, DDL/adminexpressions, and partition definitions. Anything reading or writing it must move to a
declared option or a capability bit.
MySQLDatabaseMixinis wired into the dialect, andMySQLTableSupportdeclaresformat_index_definitionwhile inline-index capability is inherited from core, so theformatting entry point is unified rather than per-backend.
nodes.
repaired so type checkers resolve them.
Related Repositories/Packages
This is the MySQL half of the derived-DDL work. The core half is
rhosocial/python-activerecord#121 (merged into
release/v1.0.0.dev30) and the sharedcontract 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. Both
dependencies were previously pinned to
feature/activerecord-derived-ddl, a branch thatonly exists to carry the derived-DDL work; leaving the old ref in place would have made the
first run after that branch is deleted fail to resolve.
The remaining eight backends carry the same adaptation and the same workflow repoint, and
should be merged in the same sequence before the feature branches are deleted:
4e9d1f4a5f9a9fff98cf00870faf03c6d8c0c573289e7e2824d2e9f0Testing
Local full-suite execution was skipped at the user's instruction. Verification relied on
remote CI, which ran on this exact tip
cbd1470and covers the version matrix againstMySQL 5.6, 5.7, 8.0, 8.4, 9.0, 9.1, 9.2, 9.3, 9.4, 9.5, 9.6 and 9.7, on Python 3.8
through 3.15 including free-threaded builds, plus a benchmarks job. All sixteen jobs pass.
That run also covers the workflow change in this PR: it is the first execution against
release/v1.0.0.dev30andrelease/v1.0.0.dev17rather than the feature branches, so thenew dependency refs are verified to resolve.
Checklist
changelog.d/(to be added after this PR isopened, named by the actual PR number)
Additional Notes
Three commits in this branch are not part of the DDL adaptation and are called out so a
reviewer is not surprised:
ci: install core and testsuite from release branches— the workflow repoint describedabove, a prerequisite for merging.
fix(scripts): stop the pre-commit hook from blocking commits on older revisions— arepository-hygiene fix, kept identical across all ten repositories so they do not drift.
fix(backend): repair unresolvable TYPE_CHECKING importsandchore(test): register the pytest markers the suite already uses— mechanical repairs required for type checkingand lint to run at all after the namespace split.