Skip to content

Phase 2: Auto-enable identity primary keys in Migration[8.2]+ (depends on Rails per-adapter-migration-compatibility) [DRAFT]#2596

Open
yahonda wants to merge 1 commit into
rsim:masterfrom
yahonda:migration-8-2-default-identity
Open

Phase 2: Auto-enable identity primary keys in Migration[8.2]+ (depends on Rails per-adapter-migration-compatibility) [DRAFT]#2596
yahonda wants to merge 1 commit into
rsim:masterfrom
yahonda:migration-8-2-default-identity

Conversation

@yahonda
Copy link
Copy Markdown
Collaborator

@yahonda yahonda commented Apr 25, 2026

Summary

Phase 2 of splitting #2579: build on Phase 1's explicit identity:
option (now merged) and flip the default for create_table to
identity: true on Oracle 12.1+, scoped to migrations declared at
Migration[8.2] or later. Migration[8.1] and earlier, Schema.define,
and direct connection.create_table keep the existing sequence + trigger
behavior, so applications see no change unless they explicitly adopt
Migration[8.2].

This PR is a draft because it depends on the unmerged Rails extension
point
AbstractAdapter#migration_compatibility_module_for(migration_class)
plus the Migration::Compatibility::Versioned convention from
yahonda/rails per-adapter-migration-compatibility.
Once that lands on rails/rails#main:

  1. Switch Gemfile back to rails/rails#main
  2. Mark this PR ready for review

Behavior matrix

Caller identity: arg Oracle server Result
Migration[8.2]+ omitted ≥ 12.1 Identity (V8_2 default)
Migration[8.2]+ omitted < 12.1 Sequence (V8_2 auto-inject gated by supports_identity_columns?)
Migration[8.2]+ omitted, with sequence_name: / sequence_start_value: any Sequence (V8_2 treats sequence options as opt-out)
Migration[8.2]+ true ≥ 12.1 Identity (explicit)
Migration[8.2]+ true < 12.1 ArgumentError (Phase 1)
Migration[8.2]+ false any Sequence (per-table opt-out)
Migration[8.1] or older omitted any Sequence (forced by V8_1 module)
Migration[8.1] or older true ≥ 12.1 Identity (explicit still honored)
Migration[8.1] or older true < 12.1 ArgumentError
Migration[8.1] or older false any Sequence
Schema.define / direct connection.create_table omitted any Sequence (no migration version context, default unchanged)
Schema.define / direct connection.create_table true ≥ 12.1 Identity (explicit)
Schema.define / direct connection.create_table false any Sequence

Implementation notes

  • OracleEnhanced::MigrationCompatibility registers two compat modules
    via Rails' Migration::Compatibility::Versioned:
    • V8_2 forces options[:identity] = true when the option is omitted,
      no sequence_name: / sequence_start_value: is given,
      id: :primary_key is in effect (default), the PK is not composite,
      and the server supports identity columns. This is the new flip,
      scoped to migrations at Migration[8.2]+.
    • V8_1 forces options[:identity] = false for migrations at
      Migration[8.1] or earlier. Because Rails' versioned dispatch
      includes both modules for older migrations and V8_1 sets the
      explicit option first, V8_2 sees options.key?(:identity) and
      leaves it alone — older migrations keep sequence-backed behavior.
  • OracleEnhancedSchemaStatements#create_table honors
    options[:identity] exactly as given and does no auto-injection
    of its own. Callers that bypass migration compat (Schema.define,
    direct connection.create_table) therefore keep the existing
    sequence-backed default unless they pass identity: true explicitly.
  • OracleEnhancedSchemaStatements#rename_table and #drop_table are
    now identity-aware: they no longer rename or drop <table>_seq for
    tables whose primary key is an Oracle identity column. Previously,
    an unrelated application-owned sequence sharing that name would be
    silently mutated or removed. full_drop already had this protection
    via its ISEQ$$_ filter; this brings the table-level DDL paths in
    line.
  • OracleEnhancedSchemaDumper emits identity: true / identity: false
    explicitly for every primary-key table when the connected server
    supports identity columns, so db/schema.rb roundtrips remain
    unambiguous regardless of which loader runs them.
  • OracleEnhancedDatabaseStatements#empty_insert_statement_value is
    already in master from Implement empty_insert_statement_value for identity primary keys #2609 — this PR depends on that change so
    identity tables can satisfy Model.create! with no attributes.

Tests

  • New migration_compatibility_spec.rb cases exercise the V8_2 / V8_1
    layering, the sequence-option opt-out, and the Schema.define /
    direct-call path that preserves sequence-backed PKs by default.
  • New identity_primary_key_spec.rb cases cover identity-aware
    rename_table and drop_table against an unrelated app-owned
    <table>_seq, plus the identity counterparts to the existing
    sequence-prerequisite tests (pk_and_sequence_for, NEXTVAL-free
    insert, full_drop filter, long-name rename).

Test plan

  • bundle exec rubocop — clean
  • Full spec suite on Oracle 23ai (FREEPDB1) — 573 examples, 0 failures, 7 pending
  • CI on full matrix (3.3 / 3.4 / 4.0 / jruby)
  • Switch Gemfile back to rails/rails#main once per-adapter-migration-compatibility lands

Related

🤖 Generated with Claude Code

@yahonda yahonda force-pushed the migration-8-2-default-identity branch 3 times, most recently from eb3fd69 to a94a652 Compare April 25, 2026 05:14
@yahonda yahonda force-pushed the migration-8-2-default-identity branch from a94a652 to bdbf838 Compare April 25, 2026 22:38
@yahonda yahonda marked this pull request as ready for review April 25, 2026 23:11
@yahonda yahonda force-pushed the migration-8-2-default-identity branch 4 times, most recently from 529545a to 4d7a6c9 Compare April 27, 2026 14:33
@yahonda yahonda force-pushed the migration-8-2-default-identity branch from 4d7a6c9 to 7741715 Compare May 4, 2026 22:50
@yahonda yahonda force-pushed the migration-8-2-default-identity branch from 7741715 to 2b74926 Compare May 10, 2026 09:29
Phase 2 of rsim#2579: build on the explicit `identity:` option from Phase 1
and switch the default for migrations declared at
`ActiveRecord::Migration[8.2]` or later. Older migration versions,
`Schema.define`, and direct `connection.create_table` keep the existing
sequence + trigger behavior, so existing applications see no change
unless they explicitly adopt `Migration[8.2]`.

Wired through the new per-adapter extension point
`AbstractAdapter#migration_compatibility_module_for(migration_class)`
from yahonda/rails `per-adapter-migration-compatibility` (not yet on
rails master). The Gemfile temporarily points at that branch; once the
Rails commit lands on `rails/rails#main` the Gemfile reference can be
reverted.

Architecture: two compat modules layered via Rails' versioned dispatch.
`V8_2` forces `identity: true` for the current default; `V8_1` forces
`identity: false` to preserve legacy behavior on older migrations. The
adapter's underlying `create_table` honors `options[:identity]` exactly
as given and does no auto-injection, so callers outside the migration
compat chain (`Schema.define`, direct `connection.create_table`) keep
sequence-backed PKs by default. `db/schema.rb` roundtrips remain safe
because the schema dumper now emits `identity: true` / `identity: false`
explicitly for every primary-key table.

`V8_2` also treats explicit Oracle sequence options as opt-out: when
`sequence_name:` or `sequence_start_value:` is given, the requested
sequence is created and the PK stays sequence-backed.

`V8_2` pre-checks `connection.supports_identity_columns?` so
`Migration[8.2]+` on Oracle <12.1 silently falls back to the legacy
sequence path instead of triggering the Phase 1 ArgumentError. Per-table
opt-out remains via `identity: false`; per-migration opt-out via
`Migration[8.1]` or earlier.

`rename_table` and `drop_table` are now identity-aware: they no longer
rename or drop `<table>_seq` for tables whose primary key is an Oracle
identity column. Previously, an unrelated application-owned sequence
sharing that name would be silently mutated or removed when the table
was renamed/dropped.
@yahonda yahonda force-pushed the migration-8-2-default-identity branch from 2b74926 to ba8c016 Compare May 19, 2026 14:41
@yahonda yahonda changed the title Phase 2: Auto-enable identity primary keys in Migration[8.2]+ (depends on Rails another-33269) [DRAFT] Phase 2: Auto-enable identity primary keys in Migration[8.2]+ (depends on Rails per-adapter-migration-compatibility) [DRAFT] May 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant