Skip to content

IBX-11939: [Doctrine Migrations] Added Doctrine Migrations-based schema and data install path (inlined SQL) - #787

Open
Steveb-p wants to merge 8 commits into
base/ibx-11939-4.6-merged-5.0from
feature/fix-schema-rename-migration-5.0-postgres
Open

IBX-11939: [Doctrine Migrations] Added Doctrine Migrations-based schema and data install path (inlined SQL)#787
Steveb-p wants to merge 8 commits into
base/ibx-11939-4.6-merged-5.0from
feature/fix-schema-rename-migration-5.0-postgres

Conversation

@Steveb-p

@Steveb-p Steveb-p commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Warning

This PR's base branch (base/ibx-11939-4.6-merged-5.0) is not the real 5.0 branch — it's 5.0 with the 4.6 feature branch (#785) merged in. This PR intentionally shows only the changes introduced on top of "4.6, once merged forward" — review #785 first. Once #785 merges for real and is merged forward into 5.0, this PR's base will be updated to point at the real 5.0 branch.

Warning

This is the 5.0 follow-up to #785 (4.6). Review that PR first — this carries the same migration forward onto this branch.

🎫 Issue IBX-11939

Related PRs:

Package 4.6 5.0 6.0
ibexa/activity-log #166 #167 #168
ibexa/cart #172 #173 🔄 #174
ibexa/collaboration #115 #116
ibexa/connector-ai #198 #199
ibexa/connector-payum ⚠️ #39 #40 #41
ibexa/core #785 🩹 #787this PR 🔄 🩹 #788 🩹
ibexa/corporate-account #369 #370 🔄 #371
ibexa/discounts #341 🩹 #342 🩹
ibexa/discounts-codes #50 #51
ibexa/doctrine-migrations #1 #2 #3
ibexa/doctrine-schema #41 #42 #43
ibexa/fieldtype-page #208 🩹 #209 🔄 🩹 #210 🩹
ibexa/form-builder #240 🩹 #241 🔄 🩹 #242 🩹
ibexa/measurement #133 #134 🔄 #135
ibexa/messenger #22 #23
ibexa/migrations #438 #439 #440
ibexa/order-management #188 #189 🔄 #190
ibexa/payment #204 #205 🔄 #206
ibexa/product-catalog #1543 #1544 🔄 #1545
ibexa/product-catalog-date-time-attribute #53 #54
ibexa/product-catalog-symbol-attribute #17 #18
ibexa/scheduler #168 #169 🔄 #170
ibexa/segmentation #186 #187 🔄 #188
ibexa/share #190 #191
ibexa/shipping #154 #155 🔄 #156
ibexa/site-context #121
ibexa/site-factory #172 #173 🔄 🩹 #174 🩹
ibexa/taxonomy ⚠️ #431 #432 #433
ibexa/translations-management #174 #175
ibexa/user #128 #129 🔄 #130
ibexa/workflow #191 🩹 #192 🔄 🩹 #193 🩹

🔄 = this branch adds an upgrade migration (renames/FK-retargets existing schema), not just a fresh baseline.
🩹 = this branch also received a backported delta migration, converted from a legacy ibexa/installer upgrade/db/*.sql script (4.6.0 or later) that the original baseline-only migration didn't cover. See IBX-11939 upgrade-scripts backport report or that package's own PR description for details.
⚠️ = fixes a different, related problem (missing SchemaBuilderEvent support for a plain Doctrine ORM entity/table) — not a Doctrine Migrations baseline/upgrade migration like the rest of this table. See that package's own PR description for details.

Description:

Fixes a gap in #785's Doctrine Migrations installer path. On the 5.0 and 6.0 branches, InstallSchemaMigration/ImportDataMigration had been independently rewritten to create the already-renamed (ibexa_*) schema from scratch — instead of replaying the real 4.6→5.0 rename. This meant a project already running 4.6 (with legacy ez* table names) had no actual migration path to 5.0/6.0 via this mechanism, only a fresh-install script.

This PR:

  • Is a follow-up PR to IBX-11939: [Doctrine Migrations] Added Doctrine Migrations-based schema and data install path (inlined SQL) #785, applying the same fix pattern on this branch. All three platform branches — MySQL, PostgreSQL, and SQLite — are implemented in RenameSchemaTo5_0Migration (and carried through in the restored InstallSchemaMigration/ImportDataMigration baseline); verified against all three, not just one engine.
  • Restores InstallSchemaMigration/ImportDataMigration to the 4.6-shaped baseline (still tagged 4.6.0, legacy ez* table names — unchanged from the 4.6 branch).
  • Adds RenameSchemaTo5_0Migration (tagged 5.0.0) with the real rename diff, sourced from ibexa/installer's own shipped upgrade SQL (upgrade/db/{mysql,postgresql}/ibexa-4.6.latest-to-5.0.0.sql), filtered to core-owned tables, plus a hand-derived SQLite equivalent (SQLite has no RENAME INDEX, so those become DROP INDEX+CREATE INDEX; FK constraint-name-only renames are skipped as cosmetic, since SQLite auto-updates FK/column references across the schema on RENAME TABLE/RENAME COLUMN).
  • Includes 3 genuine data-value renames found alongside the schema rename in the installer's script (ez_lockibexa_lock object-state identifier; ezstringibexa_string field-type identifier, in two tables).

IbexaMigrationComparator orders migrations by getTargetVersion() then getCreationDate(), so TaggedMigrationsRunner replays these correctly both for a fresh 6.0 install (both migrations run) and for an existing 4.6→6.0 upgrade (only the 5.0.0 rename runs; already-applied migrations are skipped via the standard Doctrine Migrations metadata table).

Verification caught two real gaps in the installer's own shipped SQL, both fixed here:

  • A stray FK-backing index (ezcontentclass_attribute_ml_lang_fk) needed renaming, not just the FK constraint itself.
  • An index-name mismatch: the installer script renames to ibexa_content_type_field_definition_ct_id, but the live schema.yaml actually expects ..._ctid (no underscore) — used the live schema as ground truth.

For QA:

Ran both migrations end-to-end against a real SQLite connection and diffed the resulting table/index names against a fresh bin/console ibexa:doctrine:schema:dump-sql src/bundle/Core/Resources/config/storage/legacy/schema.yaml --force-platform=sqlite — they match exactly.

To verify manually: set ibexa.installer.schema_builder_event.enabled: false, run ibexa:install, and confirm the resulting schema matches an install with the flag left at its default true.

Documentation:

N/A — internal installer implementation detail.

@Steveb-p Steveb-p changed the title IBX-11939: [Doctrine Migrations] Fixed schema rename migration to replay 4.6→5.0 history IBX-11939: [Doctrine Migrations] Added Doctrine Migrations-based schema and data install path (inlined SQL) Jul 21, 2026
@Steveb-p
Steveb-p force-pushed the feature/fix-schema-rename-migration-5.0-postgres branch 2 times, most recently from 2e5073b to be5d0a0 Compare July 24, 2026 11:37
@Steveb-p
Steveb-p changed the base branch from 5.0 to base/ibx-11939-4.6-merged-5.0 July 24, 2026 11:37
@Steveb-p
Steveb-p marked this pull request as ready for review July 24, 2026 12:14
….6 base

Squashes the net effect of the 16 commits previously on this branch
(since the old base/ibx-11939-4.6-merged-5.0 merge point) into one commit.
Most of those commits were parallel duplicates of work already landed on
the 4.6 feature branch and merged forward via the rebuilt base branch;
only the genuinely 5.0-specific delta is carried here:

- RenameSchemaTo5_0Migration + supporting SQL: renames the legacy ez*
  schema to the ibexa_* naming scheme introduced in 5.0.
- FixLegacyIdentifiersMigration + supporting SQL: fixes legacy
  identifiers as part of that rename.
- InstallSchemaMigration: idempotency guard checks the post-rename
  "ibexa_content" table name instead of "ezcontentobject".
- services.yml: registers both new migrations as tagged services.
- composer.json: points ibexa/doctrine-migrations at its 5.0 branch.
Steveb-p added a commit that referenced this pull request Jul 28, 2026
…for PR #787)

# Conflicts:
#	composer.json
#	phpstan-baseline.neon
#	src/bundle/RepositoryInstaller/Command/InstallPlatformCommand.php
#	src/bundle/RepositoryInstaller/DependencyInjection/Compiler/InstallerTagPass.php
#	src/bundle/RepositoryInstaller/Installer/CoreInstaller.php
#	tests/bundle/RepositoryInstaller/DependencyInjection/Compiler/InstallerTagPassTest.php
#	tests/bundle/RepositoryInstaller/DependencyInjection/IbexaInstallerExtensionTest.php
#	tests/bundle/RepositoryInstaller/IbexaRepositoryInstallerBundleTest.php
@Steveb-p
Steveb-p force-pushed the base/ibx-11939-4.6-merged-5.0 branch from 4e1d96a to 42fc503 Compare July 28, 2026 14:51
@Steveb-p
Steveb-p force-pushed the feature/fix-schema-rename-migration-5.0-postgres branch from 648a27c to 402fbc2 Compare July 28, 2026 16:28
Steveb-p added 6 commits July 29, 2026 00:27
Converts installer's upgrade/db/ibexa-4.5.1-to-4.5.2.sql and
upgrade/db/ibexa-4.6.20-to-4.6.21.sql into guarded Doctrine migrations
targeting the pre-rename (4.6.0) table names, for installs whose schema
already predates these indexes. Needed on this branch too, independently
of the 4.6 branch: RenameSchemaTo5_0Migration's RENAME INDEX statements
assume these indexes already exist under their old names.
$schema->getTable() throws TableDoesNotExist rather than returning null,
so a guard that calls it directly (without checking hasTable() first)
crashes -- rather than skipping -- on any install that never had the
table under this name at all. Caught via live testing against a real
database. Guard now checks hasTable() first. Same content as the 4.6
branch.
…into baseline

Same rationale as ibexa/product-catalog: doctrine migrations only exist
starting at 4.6, so InstallSchemaMigration's baseline already includes
these indexes (originally shipped via installer's
upgrade/db/ibexa-4.5.0-to-4.5.1.sql). A standalone migration for pre-4.6
content can never have real work to do on a genuine 4.6+ install.
The feat/doctrine-migrations-5.0 branch it previously required has
been merged into and deleted from the primary 5.0 branch upstream,
so the old constraint no longer resolves.
$migration->up(new Schema()) gave every migration's hasTable()/
getTable() guard checks an always-empty schema to inspect, regardless
of what earlier migrations in the same run (or a prior run) actually
created against the real database -- guards written the correct way
(checking hasTable() before trusting a table exists) would incorrectly
conclude the table is missing and either skip work that still needs
doing, or crash outright on getTable() for a table that does exist.
Introspect the live database instead, the same way the standalone
'doctrine:migrations:migrate' command already does via
DBALSchemaDiffProvider::createFromSchema().
InstallSchemaMigration, AddUrlAliasMlLinkIndexMigration, RenameSchemaTo5_0Migration,
ImportDataMigration, and FixLegacyIdentifiersMigration only depend on the persistence
connection -- they don't need anything from IbexaRepositoryInstallerBundle
(CoreInstaller, BuildSchemaSubscriber), which is scoped to installer-time concerns
and additionally requires DoctrineSchemaBundle to boot at all. Declaring them in
IbexaCoreBundle instead matches how every other package in this effort declares
its own InstallSchemaMigration in its own bundle, and lets any consumer discover
core's schema migrations via ibexa:doctrine:migrations:migrate without needing the
installer bundle registered -- useful for integration test kernels that don't
otherwise need CoreInstaller.
… SQL

install-schema-sqlite.sql and import-data-sqlite.sql were generated from
the MySQL source without adapting to SQLite's stricter SQL semantics:

- import-data-sqlite.sql used MySQL-style backslash escapes (\" and \n)
  inside string literals. SQLite (unlike MySQL) does not interpret
  backslash as an escape character at all, so these were stored as
  literal two-byte sequences, corrupting PHP-serialized content-type
  names/descriptions (unserialize() failures) and embedded XML field
  data (DOMDocument parse failures, e.g. the admin user's own ezimage
  field).

- install-schema-sqlite.sql collapsed the composite primary keys on
  ezcontentclass, ezcontentclass_attribute and ezcontentobject_attribute
  (id, version) down to a single-column `id INTEGER PRIMARY KEY
  AUTOINCREMENT`, dropping the `version` component entirely -- unlike
  the mysql/postgresql variants, which both correctly declare
  `PRIMARY KEY(id, version)`. This made SQLite reject the second row
  (e.g. publishing a content-type draft, which legitimately reuses the
  same id with a different version/status) as a duplicate primary key.

Both only affect the SQLite platform; MySQL and PostgreSQL were
already correct.
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
3.5% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant