From f8946f0eb393f03fa046c0ca917bf5cf833b609f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Niedzielski?= Date: Mon, 20 Jul 2026 12:11:47 +0200 Subject: [PATCH 1/9] Add Doctrine Migrations for the user-invitation schema (baseline + 5.0.0 rename) Adds InstallSchemaMigration (4.6.0 baseline) and, on 5.0+, RenameSchemaTo5_0Migration renaming ibexa_user_invitations(_assignments) to singular. ibexa/installer's shipped upgrade SQL was missing the rename of the assignment table's Doctrine-hashed FK-backing index (its hash changes with the table name: IDX_DA5A7872A35D7AF0 -> IDX_9E1E6F70A35D7AF0) - added that. SQLite equivalent derived and verified end-to-end - resulting schema matches a fresh dump-sql of the current schema.yaml exactly. Existing schema.yaml + BuildSchemaSubscriber left untouched. --- .../Migration/InstallSchemaMigration.php | 40 +++++++++----- .../Migration/RenameSchemaTo5_0Migration.php | 52 ++++++++++++++----- 2 files changed, 66 insertions(+), 26 deletions(-) diff --git a/src/bundle/Migration/InstallSchemaMigration.php b/src/bundle/Migration/InstallSchemaMigration.php index fcae31e..85b0bf1 100644 --- a/src/bundle/Migration/InstallSchemaMigration.php +++ b/src/bundle/Migration/InstallSchemaMigration.php @@ -9,12 +9,14 @@ namespace Ibexa\Bundle\User\Migration; use DateTimeImmutable; +use Doctrine\DBAL\Platforms\AbstractMySQLPlatform; +use Doctrine\DBAL\Platforms\PostgreSQLPlatform; +use Doctrine\DBAL\Platforms\SqlitePlatform; use Doctrine\DBAL\Schema\Schema; -use Ibexa\Contracts\DoctrineMigrations\Migrations\AbstractSqlMigration; +use Doctrine\Migrations\AbstractMigration; use Ibexa\Contracts\DoctrineMigrations\Migrations\IbexaMigrationInterface; -use Ibexa\DoctrineMigrations\Migration\SqlPlatform; -final class InstallSchemaMigration extends AbstractSqlMigration implements IbexaMigrationInterface +final class InstallSchemaMigration extends AbstractMigration implements IbexaMigrationInterface { public function getDescription(): string { @@ -33,18 +35,30 @@ public static function getCreationDate(): DateTimeImmutable public function up(Schema $schema): void { - $this->abortIfUnsupportedPlatform(SqlPlatform::MYSQL, SqlPlatform::POSTGRESQL, SqlPlatform::SQLITE); + if ($this->platform instanceof AbstractMySQLPlatform) { + $this->addSql('CREATE TABLE ibexa_user_invitations (id INT AUTO_INCREMENT NOT NULL, email VARCHAR(255) NOT NULL, site_access_name VARCHAR(255) NOT NULL, hash VARCHAR(255) NOT NULL, creation_date INT NOT NULL, used TINYINT(1) DEFAULT \'0\' NOT NULL, INDEX ibexa_user_invitations_email_idx (email), INDEX ibexa_user_invitations_hash_idx (hash), UNIQUE INDEX ibexa_user_invitations_email_uindex (email(191)), UNIQUE INDEX ibexa_user_invitations_hash_uindex (hash(191)), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE ibexa_user_invitations_assignments (id INT AUTO_INCREMENT NOT NULL, invitation_id INT NOT NULL, user_group_id INT DEFAULT NULL, role_id INT DEFAULT NULL, limitation_type VARCHAR(255) DEFAULT NULL, limitation_value VARCHAR(255) DEFAULT NULL, INDEX IDX_DA5A7872A35D7AF0 (invitation_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE ibexa_user_invitations_assignments ADD CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitations (id) ON UPDATE CASCADE ON DELETE CASCADE'); - if ($schema->hasTable('ibexa_user_invitation')) { - return; - } + } elseif ($this->platform instanceof PostgreSQLPlatform) { + $this->addSql('CREATE TABLE ibexa_user_invitations (id SERIAL NOT NULL, email VARCHAR(255) NOT NULL, site_access_name VARCHAR(255) NOT NULL, hash VARCHAR(255) NOT NULL, creation_date INT NOT NULL, used BOOLEAN DEFAULT \'false\' NOT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX ibexa_user_invitations_email_idx ON ibexa_user_invitations (email)'); + $this->addSql('CREATE INDEX ibexa_user_invitations_hash_idx ON ibexa_user_invitations (hash)'); + $this->addSql('CREATE UNIQUE INDEX ibexa_user_invitations_email_uindex ON ibexa_user_invitations (email)'); + $this->addSql('CREATE UNIQUE INDEX ibexa_user_invitations_hash_uindex ON ibexa_user_invitations (hash)'); + $this->addSql('CREATE TABLE ibexa_user_invitations_assignments (id SERIAL NOT NULL, invitation_id INT NOT NULL, user_group_id INT DEFAULT NULL, role_id INT DEFAULT NULL, limitation_type VARCHAR(255) DEFAULT NULL, limitation_value VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_DA5A7872A35D7AF0 ON ibexa_user_invitations_assignments (invitation_id)'); + $this->addSql('ALTER TABLE ibexa_user_invitations_assignments ADD CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitations (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + + } elseif ($this->platform instanceof SqlitePlatform) { + $this->addSql('CREATE TABLE ibexa_user_invitations (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, email VARCHAR(255) NOT NULL, site_access_name VARCHAR(255) NOT NULL, hash VARCHAR(255) NOT NULL, creation_date INTEGER NOT NULL, used BOOLEAN DEFAULT \'0\' NOT NULL)'); + $this->addSql('CREATE INDEX ibexa_user_invitations_email_idx ON ibexa_user_invitations (email)'); + $this->addSql('CREATE INDEX ibexa_user_invitations_hash_idx ON ibexa_user_invitations (hash)'); + $this->addSql('CREATE UNIQUE INDEX ibexa_user_invitations_email_uindex ON ibexa_user_invitations (email)'); + $this->addSql('CREATE UNIQUE INDEX ibexa_user_invitations_hash_uindex ON ibexa_user_invitations (hash)'); + $this->addSql('CREATE TABLE ibexa_user_invitations_assignments (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, invitation_id INTEGER NOT NULL, user_group_id INTEGER DEFAULT NULL, role_id INTEGER DEFAULT NULL, limitation_type VARCHAR(255) DEFAULT NULL, limitation_value VARCHAR(255) DEFAULT NULL, CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitations (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE)'); + $this->addSql('CREATE INDEX IDX_DA5A7872A35D7AF0 ON ibexa_user_invitations_assignments (invitation_id)'); - if ($this->isMySQL()) { - $this->addSqlFile(__DIR__ . '/sql/install-schema-mysql.sql'); - } elseif ($this->isPostgreSQL()) { - $this->addSqlFile(__DIR__ . '/sql/install-schema-postgresql.sql'); - } elseif ($this->isSqlite()) { - $this->addSqlFile(__DIR__ . '/sql/install-schema-sqlite.sql'); } } } diff --git a/src/bundle/Migration/RenameSchemaTo5_0Migration.php b/src/bundle/Migration/RenameSchemaTo5_0Migration.php index dcd7e6c..03adf5d 100644 --- a/src/bundle/Migration/RenameSchemaTo5_0Migration.php +++ b/src/bundle/Migration/RenameSchemaTo5_0Migration.php @@ -9,12 +9,14 @@ namespace Ibexa\Bundle\User\Migration; use DateTimeImmutable; +use Doctrine\DBAL\Platforms\AbstractMySQLPlatform; +use Doctrine\DBAL\Platforms\PostgreSQLPlatform; +use Doctrine\DBAL\Platforms\SqlitePlatform; use Doctrine\DBAL\Schema\Schema; -use Ibexa\Contracts\DoctrineMigrations\Migrations\AbstractSqlMigration; +use Doctrine\Migrations\AbstractMigration; use Ibexa\Contracts\DoctrineMigrations\Migrations\IbexaMigrationInterface; -use Ibexa\DoctrineMigrations\Migration\SqlPlatform; -final class RenameSchemaTo5_0Migration extends AbstractSqlMigration implements IbexaMigrationInterface +final class RenameSchemaTo5_0Migration extends AbstractMigration implements IbexaMigrationInterface { public function getDescription(): string { @@ -33,18 +35,42 @@ public static function getCreationDate(): DateTimeImmutable public function up(Schema $schema): void { - $this->abortIfUnsupportedPlatform(SqlPlatform::MYSQL, SqlPlatform::POSTGRESQL, SqlPlatform::SQLITE); + if ($this->platform instanceof AbstractMySQLPlatform) { + $this->addSql('ALTER TABLE ibexa_user_invitations RENAME TO ibexa_user_invitation'); + $this->addSql('ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_email_idx TO ibexa_user_invitation_email_idx'); + $this->addSql('ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_hash_idx TO ibexa_user_invitation_hash_idx'); + $this->addSql('ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_email_uindex TO ibexa_user_invitation_email_uindex'); + $this->addSql('ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_hash_uindex TO ibexa_user_invitation_hash_uindex'); + $this->addSql('ALTER TABLE ibexa_user_invitations_assignments RENAME TO ibexa_user_invitation_assignment'); + $this->addSql('ALTER TABLE ibexa_user_invitation_assignment DROP FOREIGN KEY ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk'); + $this->addSql('ALTER TABLE ibexa_user_invitation_assignment ADD CONSTRAINT ibexa_user_invitation_assignment_ibexa_user_invitation_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitation(id) ON DELETE CASCADE ON UPDATE CASCADE'); + $this->addSql('ALTER TABLE ibexa_user_invitation_assignment RENAME INDEX IDX_DA5A7872A35D7AF0 TO IDX_9E1E6F70A35D7AF0'); - if ($schema->hasTable('ibexa_user_invitation')) { - return; - } + } elseif ($this->platform instanceof PostgreSQLPlatform) { + $this->addSql('ALTER TABLE ibexa_user_invitations RENAME TO ibexa_user_invitation'); + $this->addSql('ALTER INDEX ibexa_user_invitations_email_idx RENAME TO ibexa_user_invitation_email_idx'); + $this->addSql('ALTER INDEX ibexa_user_invitations_hash_idx RENAME TO ibexa_user_invitation_hash_idx'); + $this->addSql('ALTER INDEX ibexa_user_invitations_email_uindex RENAME TO ibexa_user_invitation_email_uindex'); + $this->addSql('ALTER INDEX ibexa_user_invitations_hash_uindex RENAME TO ibexa_user_invitation_hash_uindex'); + $this->addSql('ALTER TABLE ibexa_user_invitations_assignments RENAME TO ibexa_user_invitation_assignment'); + $this->addSql('ALTER INDEX IDX_DA5A7872A35D7AF0 RENAME TO IDX_9E1E6F70A35D7AF0'); + $this->addSql('ALTER TABLE ibexa_user_invitation_assignment DROP CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk'); + $this->addSql('ALTER TABLE ibexa_user_invitation_assignment ADD CONSTRAINT ibexa_user_invitation_assignment_ibexa_user_invitation_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitation(id) ON DELETE CASCADE ON UPDATE CASCADE'); + + } elseif ($this->platform instanceof SqlitePlatform) { + $this->addSql('ALTER TABLE ibexa_user_invitations RENAME TO ibexa_user_invitation'); + $this->addSql('DROP INDEX ibexa_user_invitations_email_idx'); + $this->addSql('CREATE INDEX ibexa_user_invitation_email_idx ON ibexa_user_invitation (email)'); + $this->addSql('DROP INDEX ibexa_user_invitations_hash_idx'); + $this->addSql('CREATE INDEX ibexa_user_invitation_hash_idx ON ibexa_user_invitation (hash)'); + $this->addSql('DROP INDEX ibexa_user_invitations_email_uindex'); + $this->addSql('CREATE UNIQUE INDEX ibexa_user_invitation_email_uindex ON ibexa_user_invitation (email)'); + $this->addSql('DROP INDEX ibexa_user_invitations_hash_uindex'); + $this->addSql('CREATE UNIQUE INDEX ibexa_user_invitation_hash_uindex ON ibexa_user_invitation (hash)'); + $this->addSql('ALTER TABLE ibexa_user_invitations_assignments RENAME TO ibexa_user_invitation_assignment'); + $this->addSql('DROP INDEX IDX_DA5A7872A35D7AF0'); + $this->addSql('CREATE INDEX IDX_9E1E6F70A35D7AF0 ON ibexa_user_invitation_assignment (invitation_id)'); - if ($this->isMySQL()) { - $this->addSqlFile(__DIR__ . '/sql/rename-schema-to-5-0-mysql.sql'); - } elseif ($this->isPostgreSQL()) { - $this->addSqlFile(__DIR__ . '/sql/rename-schema-to-5-0-postgresql.sql'); - } elseif ($this->isSqlite()) { - $this->addSqlFile(__DIR__ . '/sql/rename-schema-to-5-0-sqlite.sql'); } } } From 91cf0b6784bf44945398da2879ac120720de9c0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Niedzielski?= Date: Mon, 20 Jul 2026 17:00:46 +0200 Subject: [PATCH 2/9] Fix CI: add ibexa/doctrine-migrations dependency, remove extra blank lines composer.json was missing ibexa/doctrine-migrations (require + matching VCS repository entry for its unreleased dev branch), causing "Class Doctrine\Migrations\AbstractMigration not found" across static analysis, unit tests, and browser tests - mirrors ibexa/core's own composer.json pattern exactly (same dev-branch constraint per major version). Also removes extra blank lines the generator scripts introduced (before each } elseif and the up() method's closing brace) that php-cs-fixer's no_extra_blank_lines rule flagged. --- composer.json | 1 + src/bundle/Migration/InstallSchemaMigration.php | 3 --- src/bundle/Migration/RenameSchemaTo5_0Migration.php | 3 --- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/composer.json b/composer.json index 40e039b..7ac0567 100644 --- a/composer.json +++ b/composer.json @@ -30,6 +30,7 @@ "php": " >=8.3", "ibexa/content-forms": "~6.0.x-dev", "ibexa/core": "~6.0.x-dev", + "ibexa/doctrine-migrations": "dev-feat/doctrine-migrations-6.0", "ibexa/notifications": "~6.0.x-dev", "jms/translation-bundle": "^2.4", "symfony/config": "^7.4", diff --git a/src/bundle/Migration/InstallSchemaMigration.php b/src/bundle/Migration/InstallSchemaMigration.php index 85b0bf1..acb2434 100644 --- a/src/bundle/Migration/InstallSchemaMigration.php +++ b/src/bundle/Migration/InstallSchemaMigration.php @@ -39,7 +39,6 @@ public function up(Schema $schema): void $this->addSql('CREATE TABLE ibexa_user_invitations (id INT AUTO_INCREMENT NOT NULL, email VARCHAR(255) NOT NULL, site_access_name VARCHAR(255) NOT NULL, hash VARCHAR(255) NOT NULL, creation_date INT NOT NULL, used TINYINT(1) DEFAULT \'0\' NOT NULL, INDEX ibexa_user_invitations_email_idx (email), INDEX ibexa_user_invitations_hash_idx (hash), UNIQUE INDEX ibexa_user_invitations_email_uindex (email(191)), UNIQUE INDEX ibexa_user_invitations_hash_uindex (hash(191)), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB'); $this->addSql('CREATE TABLE ibexa_user_invitations_assignments (id INT AUTO_INCREMENT NOT NULL, invitation_id INT NOT NULL, user_group_id INT DEFAULT NULL, role_id INT DEFAULT NULL, limitation_type VARCHAR(255) DEFAULT NULL, limitation_value VARCHAR(255) DEFAULT NULL, INDEX IDX_DA5A7872A35D7AF0 (invitation_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB'); $this->addSql('ALTER TABLE ibexa_user_invitations_assignments ADD CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitations (id) ON UPDATE CASCADE ON DELETE CASCADE'); - } elseif ($this->platform instanceof PostgreSQLPlatform) { $this->addSql('CREATE TABLE ibexa_user_invitations (id SERIAL NOT NULL, email VARCHAR(255) NOT NULL, site_access_name VARCHAR(255) NOT NULL, hash VARCHAR(255) NOT NULL, creation_date INT NOT NULL, used BOOLEAN DEFAULT \'false\' NOT NULL, PRIMARY KEY(id))'); $this->addSql('CREATE INDEX ibexa_user_invitations_email_idx ON ibexa_user_invitations (email)'); @@ -49,7 +48,6 @@ public function up(Schema $schema): void $this->addSql('CREATE TABLE ibexa_user_invitations_assignments (id SERIAL NOT NULL, invitation_id INT NOT NULL, user_group_id INT DEFAULT NULL, role_id INT DEFAULT NULL, limitation_type VARCHAR(255) DEFAULT NULL, limitation_value VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))'); $this->addSql('CREATE INDEX IDX_DA5A7872A35D7AF0 ON ibexa_user_invitations_assignments (invitation_id)'); $this->addSql('ALTER TABLE ibexa_user_invitations_assignments ADD CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitations (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - } elseif ($this->platform instanceof SqlitePlatform) { $this->addSql('CREATE TABLE ibexa_user_invitations (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, email VARCHAR(255) NOT NULL, site_access_name VARCHAR(255) NOT NULL, hash VARCHAR(255) NOT NULL, creation_date INTEGER NOT NULL, used BOOLEAN DEFAULT \'0\' NOT NULL)'); $this->addSql('CREATE INDEX ibexa_user_invitations_email_idx ON ibexa_user_invitations (email)'); @@ -58,7 +56,6 @@ public function up(Schema $schema): void $this->addSql('CREATE UNIQUE INDEX ibexa_user_invitations_hash_uindex ON ibexa_user_invitations (hash)'); $this->addSql('CREATE TABLE ibexa_user_invitations_assignments (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, invitation_id INTEGER NOT NULL, user_group_id INTEGER DEFAULT NULL, role_id INTEGER DEFAULT NULL, limitation_type VARCHAR(255) DEFAULT NULL, limitation_value VARCHAR(255) DEFAULT NULL, CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitations (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE)'); $this->addSql('CREATE INDEX IDX_DA5A7872A35D7AF0 ON ibexa_user_invitations_assignments (invitation_id)'); - } } } diff --git a/src/bundle/Migration/RenameSchemaTo5_0Migration.php b/src/bundle/Migration/RenameSchemaTo5_0Migration.php index 03adf5d..7d5fdf1 100644 --- a/src/bundle/Migration/RenameSchemaTo5_0Migration.php +++ b/src/bundle/Migration/RenameSchemaTo5_0Migration.php @@ -45,7 +45,6 @@ public function up(Schema $schema): void $this->addSql('ALTER TABLE ibexa_user_invitation_assignment DROP FOREIGN KEY ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk'); $this->addSql('ALTER TABLE ibexa_user_invitation_assignment ADD CONSTRAINT ibexa_user_invitation_assignment_ibexa_user_invitation_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitation(id) ON DELETE CASCADE ON UPDATE CASCADE'); $this->addSql('ALTER TABLE ibexa_user_invitation_assignment RENAME INDEX IDX_DA5A7872A35D7AF0 TO IDX_9E1E6F70A35D7AF0'); - } elseif ($this->platform instanceof PostgreSQLPlatform) { $this->addSql('ALTER TABLE ibexa_user_invitations RENAME TO ibexa_user_invitation'); $this->addSql('ALTER INDEX ibexa_user_invitations_email_idx RENAME TO ibexa_user_invitation_email_idx'); @@ -56,7 +55,6 @@ public function up(Schema $schema): void $this->addSql('ALTER INDEX IDX_DA5A7872A35D7AF0 RENAME TO IDX_9E1E6F70A35D7AF0'); $this->addSql('ALTER TABLE ibexa_user_invitation_assignment DROP CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk'); $this->addSql('ALTER TABLE ibexa_user_invitation_assignment ADD CONSTRAINT ibexa_user_invitation_assignment_ibexa_user_invitation_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitation(id) ON DELETE CASCADE ON UPDATE CASCADE'); - } elseif ($this->platform instanceof SqlitePlatform) { $this->addSql('ALTER TABLE ibexa_user_invitations RENAME TO ibexa_user_invitation'); $this->addSql('DROP INDEX ibexa_user_invitations_email_idx'); @@ -70,7 +68,6 @@ public function up(Schema $schema): void $this->addSql('ALTER TABLE ibexa_user_invitations_assignments RENAME TO ibexa_user_invitation_assignment'); $this->addSql('DROP INDEX IDX_DA5A7872A35D7AF0'); $this->addSql('CREATE INDEX IDX_9E1E6F70A35D7AF0 ON ibexa_user_invitation_assignment (invitation_id)'); - } } } From 6a1de835c9625bafe5db29fafc530b1c8ce9f7da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Niedzielski?= Date: Tue, 21 Jul 2026 00:34:26 +0200 Subject: [PATCH 3/9] Rename PostgreSQL sequences alongside their renamed tables PostgreSQL's ALTER TABLE ... RENAME TO does not rename the backing SERIAL sequence, so the id column's nextval() default kept pointing at the pre-rename sequence name. Add the missing ALTER SEQUENCE statements. --- src/bundle/Migration/RenameSchemaTo5_0Migration.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bundle/Migration/RenameSchemaTo5_0Migration.php b/src/bundle/Migration/RenameSchemaTo5_0Migration.php index 7d5fdf1..f2e1156 100644 --- a/src/bundle/Migration/RenameSchemaTo5_0Migration.php +++ b/src/bundle/Migration/RenameSchemaTo5_0Migration.php @@ -47,11 +47,13 @@ public function up(Schema $schema): void $this->addSql('ALTER TABLE ibexa_user_invitation_assignment RENAME INDEX IDX_DA5A7872A35D7AF0 TO IDX_9E1E6F70A35D7AF0'); } elseif ($this->platform instanceof PostgreSQLPlatform) { $this->addSql('ALTER TABLE ibexa_user_invitations RENAME TO ibexa_user_invitation'); + $this->addSql('ALTER SEQUENCE ibexa_user_invitations_id_seq RENAME TO ibexa_user_invitation_id_seq'); $this->addSql('ALTER INDEX ibexa_user_invitations_email_idx RENAME TO ibexa_user_invitation_email_idx'); $this->addSql('ALTER INDEX ibexa_user_invitations_hash_idx RENAME TO ibexa_user_invitation_hash_idx'); $this->addSql('ALTER INDEX ibexa_user_invitations_email_uindex RENAME TO ibexa_user_invitation_email_uindex'); $this->addSql('ALTER INDEX ibexa_user_invitations_hash_uindex RENAME TO ibexa_user_invitation_hash_uindex'); $this->addSql('ALTER TABLE ibexa_user_invitations_assignments RENAME TO ibexa_user_invitation_assignment'); + $this->addSql('ALTER SEQUENCE ibexa_user_invitations_assignments_id_seq RENAME TO ibexa_user_invitation_assignment_id_seq'); $this->addSql('ALTER INDEX IDX_DA5A7872A35D7AF0 RENAME TO IDX_9E1E6F70A35D7AF0'); $this->addSql('ALTER TABLE ibexa_user_invitation_assignment DROP CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk'); $this->addSql('ALTER TABLE ibexa_user_invitation_assignment ADD CONSTRAINT ibexa_user_invitation_assignment_ibexa_user_invitation_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitation(id) ON DELETE CASCADE ON UPDATE CASCADE'); From 07d11557735c572a45a9460b85d6ab80d5f59286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Niedzielski?= Date: Tue, 21 Jul 2026 17:12:02 +0200 Subject: [PATCH 4/9] IBX-11939: Adopted AbstractSqlMigration for platform-separated SQL Extends AbstractSqlMigration (added in ibexa/doctrine-migrations) instead of the plain Doctrine AbstractMigration, replacing `$this->platform instanceof ...` checks with isMySQL()/isPostgreSQL()/isSqlite(), and moving each platform Statement block out of the PHP file into its own sql/*.sql file loaded via addSqlFile(). Mechanical, content-preserving change: every migration was run before and after against all three platforms and the resulting SQL statement lists are byte-for-byte identical. --- .../Migration/InstallSchemaMigration.php | 34 ++++--------- .../Migration/RenameSchemaTo5_0Migration.php | 48 ++++--------------- .../Migration/sql/install-schema-mysql.sql | 6 +-- .../sql/install-schema-postgresql.sql | 16 +++---- .../Migration/sql/install-schema-sqlite.sql | 14 +++--- .../sql/rename-schema-to-5-0-mysql.sql | 18 +++---- .../sql/rename-schema-to-5-0-postgresql.sql | 22 ++++----- .../sql/rename-schema-to-5-0-sqlite.sql | 24 +++++----- 8 files changed, 66 insertions(+), 116 deletions(-) diff --git a/src/bundle/Migration/InstallSchemaMigration.php b/src/bundle/Migration/InstallSchemaMigration.php index acb2434..fc23c68 100644 --- a/src/bundle/Migration/InstallSchemaMigration.php +++ b/src/bundle/Migration/InstallSchemaMigration.php @@ -9,14 +9,11 @@ namespace Ibexa\Bundle\User\Migration; use DateTimeImmutable; -use Doctrine\DBAL\Platforms\AbstractMySQLPlatform; -use Doctrine\DBAL\Platforms\PostgreSQLPlatform; -use Doctrine\DBAL\Platforms\SqlitePlatform; use Doctrine\DBAL\Schema\Schema; -use Doctrine\Migrations\AbstractMigration; +use Ibexa\Contracts\DoctrineMigrations\Migrations\AbstractSqlMigration; use Ibexa\Contracts\DoctrineMigrations\Migrations\IbexaMigrationInterface; -final class InstallSchemaMigration extends AbstractMigration implements IbexaMigrationInterface +final class InstallSchemaMigration extends AbstractSqlMigration implements IbexaMigrationInterface { public function getDescription(): string { @@ -35,27 +32,12 @@ public static function getCreationDate(): DateTimeImmutable public function up(Schema $schema): void { - if ($this->platform instanceof AbstractMySQLPlatform) { - $this->addSql('CREATE TABLE ibexa_user_invitations (id INT AUTO_INCREMENT NOT NULL, email VARCHAR(255) NOT NULL, site_access_name VARCHAR(255) NOT NULL, hash VARCHAR(255) NOT NULL, creation_date INT NOT NULL, used TINYINT(1) DEFAULT \'0\' NOT NULL, INDEX ibexa_user_invitations_email_idx (email), INDEX ibexa_user_invitations_hash_idx (hash), UNIQUE INDEX ibexa_user_invitations_email_uindex (email(191)), UNIQUE INDEX ibexa_user_invitations_hash_uindex (hash(191)), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB'); - $this->addSql('CREATE TABLE ibexa_user_invitations_assignments (id INT AUTO_INCREMENT NOT NULL, invitation_id INT NOT NULL, user_group_id INT DEFAULT NULL, role_id INT DEFAULT NULL, limitation_type VARCHAR(255) DEFAULT NULL, limitation_value VARCHAR(255) DEFAULT NULL, INDEX IDX_DA5A7872A35D7AF0 (invitation_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB'); - $this->addSql('ALTER TABLE ibexa_user_invitations_assignments ADD CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitations (id) ON UPDATE CASCADE ON DELETE CASCADE'); - } elseif ($this->platform instanceof PostgreSQLPlatform) { - $this->addSql('CREATE TABLE ibexa_user_invitations (id SERIAL NOT NULL, email VARCHAR(255) NOT NULL, site_access_name VARCHAR(255) NOT NULL, hash VARCHAR(255) NOT NULL, creation_date INT NOT NULL, used BOOLEAN DEFAULT \'false\' NOT NULL, PRIMARY KEY(id))'); - $this->addSql('CREATE INDEX ibexa_user_invitations_email_idx ON ibexa_user_invitations (email)'); - $this->addSql('CREATE INDEX ibexa_user_invitations_hash_idx ON ibexa_user_invitations (hash)'); - $this->addSql('CREATE UNIQUE INDEX ibexa_user_invitations_email_uindex ON ibexa_user_invitations (email)'); - $this->addSql('CREATE UNIQUE INDEX ibexa_user_invitations_hash_uindex ON ibexa_user_invitations (hash)'); - $this->addSql('CREATE TABLE ibexa_user_invitations_assignments (id SERIAL NOT NULL, invitation_id INT NOT NULL, user_group_id INT DEFAULT NULL, role_id INT DEFAULT NULL, limitation_type VARCHAR(255) DEFAULT NULL, limitation_value VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))'); - $this->addSql('CREATE INDEX IDX_DA5A7872A35D7AF0 ON ibexa_user_invitations_assignments (invitation_id)'); - $this->addSql('ALTER TABLE ibexa_user_invitations_assignments ADD CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitations (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - } elseif ($this->platform instanceof SqlitePlatform) { - $this->addSql('CREATE TABLE ibexa_user_invitations (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, email VARCHAR(255) NOT NULL, site_access_name VARCHAR(255) NOT NULL, hash VARCHAR(255) NOT NULL, creation_date INTEGER NOT NULL, used BOOLEAN DEFAULT \'0\' NOT NULL)'); - $this->addSql('CREATE INDEX ibexa_user_invitations_email_idx ON ibexa_user_invitations (email)'); - $this->addSql('CREATE INDEX ibexa_user_invitations_hash_idx ON ibexa_user_invitations (hash)'); - $this->addSql('CREATE UNIQUE INDEX ibexa_user_invitations_email_uindex ON ibexa_user_invitations (email)'); - $this->addSql('CREATE UNIQUE INDEX ibexa_user_invitations_hash_uindex ON ibexa_user_invitations (hash)'); - $this->addSql('CREATE TABLE ibexa_user_invitations_assignments (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, invitation_id INTEGER NOT NULL, user_group_id INTEGER DEFAULT NULL, role_id INTEGER DEFAULT NULL, limitation_type VARCHAR(255) DEFAULT NULL, limitation_value VARCHAR(255) DEFAULT NULL, CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitations (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE)'); - $this->addSql('CREATE INDEX IDX_DA5A7872A35D7AF0 ON ibexa_user_invitations_assignments (invitation_id)'); + if ($this->isMySQL()) { + $this->addSqlFile(__DIR__ . '/sql/install-schema-mysql.sql'); + } elseif ($this->isPostgreSQL()) { + $this->addSqlFile(__DIR__ . '/sql/install-schema-postgresql.sql'); + } elseif ($this->isSqlite()) { + $this->addSqlFile(__DIR__ . '/sql/install-schema-sqlite.sql'); } } } diff --git a/src/bundle/Migration/RenameSchemaTo5_0Migration.php b/src/bundle/Migration/RenameSchemaTo5_0Migration.php index f2e1156..74ecaef 100644 --- a/src/bundle/Migration/RenameSchemaTo5_0Migration.php +++ b/src/bundle/Migration/RenameSchemaTo5_0Migration.php @@ -9,14 +9,11 @@ namespace Ibexa\Bundle\User\Migration; use DateTimeImmutable; -use Doctrine\DBAL\Platforms\AbstractMySQLPlatform; -use Doctrine\DBAL\Platforms\PostgreSQLPlatform; -use Doctrine\DBAL\Platforms\SqlitePlatform; use Doctrine\DBAL\Schema\Schema; -use Doctrine\Migrations\AbstractMigration; +use Ibexa\Contracts\DoctrineMigrations\Migrations\AbstractSqlMigration; use Ibexa\Contracts\DoctrineMigrations\Migrations\IbexaMigrationInterface; -final class RenameSchemaTo5_0Migration extends AbstractMigration implements IbexaMigrationInterface +final class RenameSchemaTo5_0Migration extends AbstractSqlMigration implements IbexaMigrationInterface { public function getDescription(): string { @@ -35,41 +32,12 @@ public static function getCreationDate(): DateTimeImmutable public function up(Schema $schema): void { - if ($this->platform instanceof AbstractMySQLPlatform) { - $this->addSql('ALTER TABLE ibexa_user_invitations RENAME TO ibexa_user_invitation'); - $this->addSql('ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_email_idx TO ibexa_user_invitation_email_idx'); - $this->addSql('ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_hash_idx TO ibexa_user_invitation_hash_idx'); - $this->addSql('ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_email_uindex TO ibexa_user_invitation_email_uindex'); - $this->addSql('ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_hash_uindex TO ibexa_user_invitation_hash_uindex'); - $this->addSql('ALTER TABLE ibexa_user_invitations_assignments RENAME TO ibexa_user_invitation_assignment'); - $this->addSql('ALTER TABLE ibexa_user_invitation_assignment DROP FOREIGN KEY ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk'); - $this->addSql('ALTER TABLE ibexa_user_invitation_assignment ADD CONSTRAINT ibexa_user_invitation_assignment_ibexa_user_invitation_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitation(id) ON DELETE CASCADE ON UPDATE CASCADE'); - $this->addSql('ALTER TABLE ibexa_user_invitation_assignment RENAME INDEX IDX_DA5A7872A35D7AF0 TO IDX_9E1E6F70A35D7AF0'); - } elseif ($this->platform instanceof PostgreSQLPlatform) { - $this->addSql('ALTER TABLE ibexa_user_invitations RENAME TO ibexa_user_invitation'); - $this->addSql('ALTER SEQUENCE ibexa_user_invitations_id_seq RENAME TO ibexa_user_invitation_id_seq'); - $this->addSql('ALTER INDEX ibexa_user_invitations_email_idx RENAME TO ibexa_user_invitation_email_idx'); - $this->addSql('ALTER INDEX ibexa_user_invitations_hash_idx RENAME TO ibexa_user_invitation_hash_idx'); - $this->addSql('ALTER INDEX ibexa_user_invitations_email_uindex RENAME TO ibexa_user_invitation_email_uindex'); - $this->addSql('ALTER INDEX ibexa_user_invitations_hash_uindex RENAME TO ibexa_user_invitation_hash_uindex'); - $this->addSql('ALTER TABLE ibexa_user_invitations_assignments RENAME TO ibexa_user_invitation_assignment'); - $this->addSql('ALTER SEQUENCE ibexa_user_invitations_assignments_id_seq RENAME TO ibexa_user_invitation_assignment_id_seq'); - $this->addSql('ALTER INDEX IDX_DA5A7872A35D7AF0 RENAME TO IDX_9E1E6F70A35D7AF0'); - $this->addSql('ALTER TABLE ibexa_user_invitation_assignment DROP CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk'); - $this->addSql('ALTER TABLE ibexa_user_invitation_assignment ADD CONSTRAINT ibexa_user_invitation_assignment_ibexa_user_invitation_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitation(id) ON DELETE CASCADE ON UPDATE CASCADE'); - } elseif ($this->platform instanceof SqlitePlatform) { - $this->addSql('ALTER TABLE ibexa_user_invitations RENAME TO ibexa_user_invitation'); - $this->addSql('DROP INDEX ibexa_user_invitations_email_idx'); - $this->addSql('CREATE INDEX ibexa_user_invitation_email_idx ON ibexa_user_invitation (email)'); - $this->addSql('DROP INDEX ibexa_user_invitations_hash_idx'); - $this->addSql('CREATE INDEX ibexa_user_invitation_hash_idx ON ibexa_user_invitation (hash)'); - $this->addSql('DROP INDEX ibexa_user_invitations_email_uindex'); - $this->addSql('CREATE UNIQUE INDEX ibexa_user_invitation_email_uindex ON ibexa_user_invitation (email)'); - $this->addSql('DROP INDEX ibexa_user_invitations_hash_uindex'); - $this->addSql('CREATE UNIQUE INDEX ibexa_user_invitation_hash_uindex ON ibexa_user_invitation (hash)'); - $this->addSql('ALTER TABLE ibexa_user_invitations_assignments RENAME TO ibexa_user_invitation_assignment'); - $this->addSql('DROP INDEX IDX_DA5A7872A35D7AF0'); - $this->addSql('CREATE INDEX IDX_9E1E6F70A35D7AF0 ON ibexa_user_invitation_assignment (invitation_id)'); + if ($this->isMySQL()) { + $this->addSqlFile(__DIR__ . '/sql/rename-schema-to-5-0-mysql.sql'); + } elseif ($this->isPostgreSQL()) { + $this->addSqlFile(__DIR__ . '/sql/rename-schema-to-5-0-postgresql.sql'); + } elseif ($this->isSqlite()) { + $this->addSqlFile(__DIR__ . '/sql/rename-schema-to-5-0-sqlite.sql'); } } } diff --git a/src/bundle/Migration/sql/install-schema-mysql.sql b/src/bundle/Migration/sql/install-schema-mysql.sql index b3c45a8..6b5f7d4 100644 --- a/src/bundle/Migration/sql/install-schema-mysql.sql +++ b/src/bundle/Migration/sql/install-schema-mysql.sql @@ -1,5 +1,5 @@ -CREATE TABLE ibexa_user_invitations (id INT AUTO_INCREMENT NOT NULL, email VARCHAR(255) NOT NULL, site_access_name VARCHAR(255) NOT NULL, hash VARCHAR(255) NOT NULL, creation_date INT NOT NULL, used TINYINT(1) DEFAULT '0' NOT NULL, INDEX ibexa_user_invitations_email_idx (email), INDEX ibexa_user_invitations_hash_idx (hash), UNIQUE INDEX ibexa_user_invitations_email_uindex (email(191)), UNIQUE INDEX ibexa_user_invitations_hash_uindex (hash(191)), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB; +CREATE TABLE ibexa_user_invitations (id INT AUTO_INCREMENT NOT NULL, email VARCHAR(255) NOT NULL, site_access_name VARCHAR(255) NOT NULL, hash VARCHAR(255) NOT NULL, creation_date INT NOT NULL, used TINYINT(1) DEFAULT '0' NOT NULL, INDEX ibexa_user_invitations_email_idx (email), INDEX ibexa_user_invitations_hash_idx (hash), UNIQUE INDEX ibexa_user_invitations_email_uindex (email(191)), UNIQUE INDEX ibexa_user_invitations_hash_uindex (hash(191)), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB -- ibexa:sql-statement-separator -CREATE TABLE ibexa_user_invitations_assignments (id INT AUTO_INCREMENT NOT NULL, invitation_id INT NOT NULL, user_group_id INT DEFAULT NULL, role_id INT DEFAULT NULL, limitation_type VARCHAR(255) DEFAULT NULL, limitation_value VARCHAR(255) DEFAULT NULL, INDEX IDX_DA5A7872A35D7AF0 (invitation_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB; +CREATE TABLE ibexa_user_invitations_assignments (id INT AUTO_INCREMENT NOT NULL, invitation_id INT NOT NULL, user_group_id INT DEFAULT NULL, role_id INT DEFAULT NULL, limitation_type VARCHAR(255) DEFAULT NULL, limitation_value VARCHAR(255) DEFAULT NULL, INDEX IDX_DA5A7872A35D7AF0 (invitation_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitations_assignments ADD CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitations (id) ON UPDATE CASCADE ON DELETE CASCADE; +ALTER TABLE ibexa_user_invitations_assignments ADD CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitations (id) ON UPDATE CASCADE ON DELETE CASCADE diff --git a/src/bundle/Migration/sql/install-schema-postgresql.sql b/src/bundle/Migration/sql/install-schema-postgresql.sql index 9424b74..300e66a 100644 --- a/src/bundle/Migration/sql/install-schema-postgresql.sql +++ b/src/bundle/Migration/sql/install-schema-postgresql.sql @@ -1,15 +1,15 @@ -CREATE TABLE ibexa_user_invitations (id SERIAL NOT NULL, email VARCHAR(255) NOT NULL, site_access_name VARCHAR(255) NOT NULL, hash VARCHAR(255) NOT NULL, creation_date INT NOT NULL, used BOOLEAN DEFAULT 'false' NOT NULL, PRIMARY KEY(id)); +CREATE TABLE ibexa_user_invitations (id SERIAL NOT NULL, email VARCHAR(255) NOT NULL, site_access_name VARCHAR(255) NOT NULL, hash VARCHAR(255) NOT NULL, creation_date INT NOT NULL, used BOOLEAN DEFAULT 'false' NOT NULL, PRIMARY KEY(id)) -- ibexa:sql-statement-separator -CREATE INDEX ibexa_user_invitations_email_idx ON ibexa_user_invitations (email); +CREATE INDEX ibexa_user_invitations_email_idx ON ibexa_user_invitations (email) -- ibexa:sql-statement-separator -CREATE INDEX ibexa_user_invitations_hash_idx ON ibexa_user_invitations (hash); +CREATE INDEX ibexa_user_invitations_hash_idx ON ibexa_user_invitations (hash) -- ibexa:sql-statement-separator -CREATE UNIQUE INDEX ibexa_user_invitations_email_uindex ON ibexa_user_invitations (email); +CREATE UNIQUE INDEX ibexa_user_invitations_email_uindex ON ibexa_user_invitations (email) -- ibexa:sql-statement-separator -CREATE UNIQUE INDEX ibexa_user_invitations_hash_uindex ON ibexa_user_invitations (hash); +CREATE UNIQUE INDEX ibexa_user_invitations_hash_uindex ON ibexa_user_invitations (hash) -- ibexa:sql-statement-separator -CREATE TABLE ibexa_user_invitations_assignments (id SERIAL NOT NULL, invitation_id INT NOT NULL, user_group_id INT DEFAULT NULL, role_id INT DEFAULT NULL, limitation_type VARCHAR(255) DEFAULT NULL, limitation_value VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id)); +CREATE TABLE ibexa_user_invitations_assignments (id SERIAL NOT NULL, invitation_id INT NOT NULL, user_group_id INT DEFAULT NULL, role_id INT DEFAULT NULL, limitation_type VARCHAR(255) DEFAULT NULL, limitation_value VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id)) -- ibexa:sql-statement-separator -CREATE INDEX IDX_DA5A7872A35D7AF0 ON ibexa_user_invitations_assignments (invitation_id); +CREATE INDEX IDX_DA5A7872A35D7AF0 ON ibexa_user_invitations_assignments (invitation_id) -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitations_assignments ADD CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitations (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE; +ALTER TABLE ibexa_user_invitations_assignments ADD CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitations (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE diff --git a/src/bundle/Migration/sql/install-schema-sqlite.sql b/src/bundle/Migration/sql/install-schema-sqlite.sql index 591ec3e..965206e 100644 --- a/src/bundle/Migration/sql/install-schema-sqlite.sql +++ b/src/bundle/Migration/sql/install-schema-sqlite.sql @@ -1,13 +1,13 @@ -CREATE TABLE ibexa_user_invitations (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, email VARCHAR(255) NOT NULL, site_access_name VARCHAR(255) NOT NULL, hash VARCHAR(255) NOT NULL, creation_date INTEGER NOT NULL, used BOOLEAN DEFAULT '0' NOT NULL); +CREATE TABLE ibexa_user_invitations (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, email VARCHAR(255) NOT NULL, site_access_name VARCHAR(255) NOT NULL, hash VARCHAR(255) NOT NULL, creation_date INTEGER NOT NULL, used BOOLEAN DEFAULT '0' NOT NULL) -- ibexa:sql-statement-separator -CREATE INDEX ibexa_user_invitations_email_idx ON ibexa_user_invitations (email); +CREATE INDEX ibexa_user_invitations_email_idx ON ibexa_user_invitations (email) -- ibexa:sql-statement-separator -CREATE INDEX ibexa_user_invitations_hash_idx ON ibexa_user_invitations (hash); +CREATE INDEX ibexa_user_invitations_hash_idx ON ibexa_user_invitations (hash) -- ibexa:sql-statement-separator -CREATE UNIQUE INDEX ibexa_user_invitations_email_uindex ON ibexa_user_invitations (email); +CREATE UNIQUE INDEX ibexa_user_invitations_email_uindex ON ibexa_user_invitations (email) -- ibexa:sql-statement-separator -CREATE UNIQUE INDEX ibexa_user_invitations_hash_uindex ON ibexa_user_invitations (hash); +CREATE UNIQUE INDEX ibexa_user_invitations_hash_uindex ON ibexa_user_invitations (hash) -- ibexa:sql-statement-separator -CREATE TABLE ibexa_user_invitations_assignments (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, invitation_id INTEGER NOT NULL, user_group_id INTEGER DEFAULT NULL, role_id INTEGER DEFAULT NULL, limitation_type VARCHAR(255) DEFAULT NULL, limitation_value VARCHAR(255) DEFAULT NULL, CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitations (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE); +CREATE TABLE ibexa_user_invitations_assignments (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, invitation_id INTEGER NOT NULL, user_group_id INTEGER DEFAULT NULL, role_id INTEGER DEFAULT NULL, limitation_type VARCHAR(255) DEFAULT NULL, limitation_value VARCHAR(255) DEFAULT NULL, CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitations (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE) -- ibexa:sql-statement-separator -CREATE INDEX IDX_DA5A7872A35D7AF0 ON ibexa_user_invitations_assignments (invitation_id); +CREATE INDEX IDX_DA5A7872A35D7AF0 ON ibexa_user_invitations_assignments (invitation_id) diff --git a/src/bundle/Migration/sql/rename-schema-to-5-0-mysql.sql b/src/bundle/Migration/sql/rename-schema-to-5-0-mysql.sql index 401363c..4724309 100644 --- a/src/bundle/Migration/sql/rename-schema-to-5-0-mysql.sql +++ b/src/bundle/Migration/sql/rename-schema-to-5-0-mysql.sql @@ -1,17 +1,17 @@ -ALTER TABLE ibexa_user_invitations RENAME TO ibexa_user_invitation; +ALTER TABLE ibexa_user_invitations RENAME TO ibexa_user_invitation -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_email_idx TO ibexa_user_invitation_email_idx; +ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_email_idx TO ibexa_user_invitation_email_idx -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_hash_idx TO ibexa_user_invitation_hash_idx; +ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_hash_idx TO ibexa_user_invitation_hash_idx -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_email_uindex TO ibexa_user_invitation_email_uindex; +ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_email_uindex TO ibexa_user_invitation_email_uindex -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_hash_uindex TO ibexa_user_invitation_hash_uindex; +ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_hash_uindex TO ibexa_user_invitation_hash_uindex -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitations_assignments RENAME TO ibexa_user_invitation_assignment; +ALTER TABLE ibexa_user_invitations_assignments RENAME TO ibexa_user_invitation_assignment -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitation_assignment DROP FOREIGN KEY ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk; +ALTER TABLE ibexa_user_invitation_assignment DROP FOREIGN KEY ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitation_assignment ADD CONSTRAINT ibexa_user_invitation_assignment_ibexa_user_invitation_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitation(id) ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE ibexa_user_invitation_assignment ADD CONSTRAINT ibexa_user_invitation_assignment_ibexa_user_invitation_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitation(id) ON DELETE CASCADE ON UPDATE CASCADE -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitation_assignment RENAME INDEX IDX_DA5A7872A35D7AF0 TO IDX_9E1E6F70A35D7AF0; +ALTER TABLE ibexa_user_invitation_assignment RENAME INDEX IDX_DA5A7872A35D7AF0 TO IDX_9E1E6F70A35D7AF0 diff --git a/src/bundle/Migration/sql/rename-schema-to-5-0-postgresql.sql b/src/bundle/Migration/sql/rename-schema-to-5-0-postgresql.sql index b35c403..64ab238 100644 --- a/src/bundle/Migration/sql/rename-schema-to-5-0-postgresql.sql +++ b/src/bundle/Migration/sql/rename-schema-to-5-0-postgresql.sql @@ -1,21 +1,21 @@ -ALTER TABLE ibexa_user_invitations RENAME TO ibexa_user_invitation; +ALTER TABLE ibexa_user_invitations RENAME TO ibexa_user_invitation -- ibexa:sql-statement-separator -ALTER SEQUENCE ibexa_user_invitations_id_seq RENAME TO ibexa_user_invitation_id_seq; +ALTER SEQUENCE ibexa_user_invitations_id_seq RENAME TO ibexa_user_invitation_id_seq -- ibexa:sql-statement-separator -ALTER INDEX ibexa_user_invitations_email_idx RENAME TO ibexa_user_invitation_email_idx; +ALTER INDEX ibexa_user_invitations_email_idx RENAME TO ibexa_user_invitation_email_idx -- ibexa:sql-statement-separator -ALTER INDEX ibexa_user_invitations_hash_idx RENAME TO ibexa_user_invitation_hash_idx; +ALTER INDEX ibexa_user_invitations_hash_idx RENAME TO ibexa_user_invitation_hash_idx -- ibexa:sql-statement-separator -ALTER INDEX ibexa_user_invitations_email_uindex RENAME TO ibexa_user_invitation_email_uindex; +ALTER INDEX ibexa_user_invitations_email_uindex RENAME TO ibexa_user_invitation_email_uindex -- ibexa:sql-statement-separator -ALTER INDEX ibexa_user_invitations_hash_uindex RENAME TO ibexa_user_invitation_hash_uindex; +ALTER INDEX ibexa_user_invitations_hash_uindex RENAME TO ibexa_user_invitation_hash_uindex -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitations_assignments RENAME TO ibexa_user_invitation_assignment; +ALTER TABLE ibexa_user_invitations_assignments RENAME TO ibexa_user_invitation_assignment -- ibexa:sql-statement-separator -ALTER SEQUENCE ibexa_user_invitations_assignments_id_seq RENAME TO ibexa_user_invitation_assignment_id_seq; +ALTER SEQUENCE ibexa_user_invitations_assignments_id_seq RENAME TO ibexa_user_invitation_assignment_id_seq -- ibexa:sql-statement-separator -ALTER INDEX IDX_DA5A7872A35D7AF0 RENAME TO IDX_9E1E6F70A35D7AF0; +ALTER INDEX IDX_DA5A7872A35D7AF0 RENAME TO IDX_9E1E6F70A35D7AF0 -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitation_assignment DROP CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk; +ALTER TABLE ibexa_user_invitation_assignment DROP CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitation_assignment ADD CONSTRAINT ibexa_user_invitation_assignment_ibexa_user_invitation_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitation(id) ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE ibexa_user_invitation_assignment ADD CONSTRAINT ibexa_user_invitation_assignment_ibexa_user_invitation_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitation(id) ON DELETE CASCADE ON UPDATE CASCADE diff --git a/src/bundle/Migration/sql/rename-schema-to-5-0-sqlite.sql b/src/bundle/Migration/sql/rename-schema-to-5-0-sqlite.sql index 907664f..534471d 100644 --- a/src/bundle/Migration/sql/rename-schema-to-5-0-sqlite.sql +++ b/src/bundle/Migration/sql/rename-schema-to-5-0-sqlite.sql @@ -1,23 +1,23 @@ -ALTER TABLE ibexa_user_invitations RENAME TO ibexa_user_invitation; +ALTER TABLE ibexa_user_invitations RENAME TO ibexa_user_invitation -- ibexa:sql-statement-separator -DROP INDEX ibexa_user_invitations_email_idx; +DROP INDEX ibexa_user_invitations_email_idx -- ibexa:sql-statement-separator -CREATE INDEX ibexa_user_invitation_email_idx ON ibexa_user_invitation (email); +CREATE INDEX ibexa_user_invitation_email_idx ON ibexa_user_invitation (email) -- ibexa:sql-statement-separator -DROP INDEX ibexa_user_invitations_hash_idx; +DROP INDEX ibexa_user_invitations_hash_idx -- ibexa:sql-statement-separator -CREATE INDEX ibexa_user_invitation_hash_idx ON ibexa_user_invitation (hash); +CREATE INDEX ibexa_user_invitation_hash_idx ON ibexa_user_invitation (hash) -- ibexa:sql-statement-separator -DROP INDEX ibexa_user_invitations_email_uindex; +DROP INDEX ibexa_user_invitations_email_uindex -- ibexa:sql-statement-separator -CREATE UNIQUE INDEX ibexa_user_invitation_email_uindex ON ibexa_user_invitation (email); +CREATE UNIQUE INDEX ibexa_user_invitation_email_uindex ON ibexa_user_invitation (email) -- ibexa:sql-statement-separator -DROP INDEX ibexa_user_invitations_hash_uindex; +DROP INDEX ibexa_user_invitations_hash_uindex -- ibexa:sql-statement-separator -CREATE UNIQUE INDEX ibexa_user_invitation_hash_uindex ON ibexa_user_invitation (hash); +CREATE UNIQUE INDEX ibexa_user_invitation_hash_uindex ON ibexa_user_invitation (hash) -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitations_assignments RENAME TO ibexa_user_invitation_assignment; +ALTER TABLE ibexa_user_invitations_assignments RENAME TO ibexa_user_invitation_assignment -- ibexa:sql-statement-separator -DROP INDEX IDX_DA5A7872A35D7AF0; +DROP INDEX IDX_DA5A7872A35D7AF0 -- ibexa:sql-statement-separator -CREATE INDEX IDX_9E1E6F70A35D7AF0 ON ibexa_user_invitation_assignment (invitation_id); +CREATE INDEX IDX_9E1E6F70A35D7AF0 ON ibexa_user_invitation_assignment (invitation_id) From 6cf1c63506b1855da5d91e7e0b49890a214a3d7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Niedzielski?= Date: Wed, 22 Jul 2026 11:14:26 +0200 Subject: [PATCH 5/9] IBX-11939: Aborted migration on unsupported database platform Call abortIfUnsupportedPlatform() as the first statement of up(), so installs on a database this migration doesn't build SQL for fail loudly instead of silently queuing zero statements. --- src/bundle/Migration/InstallSchemaMigration.php | 3 +++ src/bundle/Migration/RenameSchemaTo5_0Migration.php | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/bundle/Migration/InstallSchemaMigration.php b/src/bundle/Migration/InstallSchemaMigration.php index fc23c68..cb953b2 100644 --- a/src/bundle/Migration/InstallSchemaMigration.php +++ b/src/bundle/Migration/InstallSchemaMigration.php @@ -12,6 +12,7 @@ use Doctrine\DBAL\Schema\Schema; use Ibexa\Contracts\DoctrineMigrations\Migrations\AbstractSqlMigration; use Ibexa\Contracts\DoctrineMigrations\Migrations\IbexaMigrationInterface; +use Ibexa\DoctrineMigrations\Migration\SqlPlatform; final class InstallSchemaMigration extends AbstractSqlMigration implements IbexaMigrationInterface { @@ -32,6 +33,8 @@ public static function getCreationDate(): DateTimeImmutable public function up(Schema $schema): void { + $this->abortIfUnsupportedPlatform(SqlPlatform::MYSQL, SqlPlatform::POSTGRESQL, SqlPlatform::SQLITE); + if ($this->isMySQL()) { $this->addSqlFile(__DIR__ . '/sql/install-schema-mysql.sql'); } elseif ($this->isPostgreSQL()) { diff --git a/src/bundle/Migration/RenameSchemaTo5_0Migration.php b/src/bundle/Migration/RenameSchemaTo5_0Migration.php index 74ecaef..78ce94d 100644 --- a/src/bundle/Migration/RenameSchemaTo5_0Migration.php +++ b/src/bundle/Migration/RenameSchemaTo5_0Migration.php @@ -12,6 +12,7 @@ use Doctrine\DBAL\Schema\Schema; use Ibexa\Contracts\DoctrineMigrations\Migrations\AbstractSqlMigration; use Ibexa\Contracts\DoctrineMigrations\Migrations\IbexaMigrationInterface; +use Ibexa\DoctrineMigrations\Migration\SqlPlatform; final class RenameSchemaTo5_0Migration extends AbstractSqlMigration implements IbexaMigrationInterface { @@ -32,6 +33,8 @@ public static function getCreationDate(): DateTimeImmutable public function up(Schema $schema): void { + $this->abortIfUnsupportedPlatform(SqlPlatform::MYSQL, SqlPlatform::POSTGRESQL, SqlPlatform::SQLITE); + if ($this->isMySQL()) { $this->addSqlFile(__DIR__ . '/sql/rename-schema-to-5-0-mysql.sql'); } elseif ($this->isPostgreSQL()) { From ab803470d69ea86e180e8d8301d91d2d52df90a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Niedzielski?= Date: Wed, 22 Jul 2026 12:11:17 +0200 Subject: [PATCH 6/9] IBX-11939: Added trailing semicolons to migration SQL files Each statement now ends with `;`, matching ibexa:doctrine:schema:dump-sql's own convention, so the files are directly executable via mysql/psql/sqlite3 CLI clients. addSqlFile() still splits on the delimiter and passes one statement per addSql() call, unaffected by the trailing terminator. --- .../Migration/sql/install-schema-mysql.sql | 6 ++--- .../sql/install-schema-postgresql.sql | 16 ++++++------- .../Migration/sql/install-schema-sqlite.sql | 14 +++++------ .../sql/rename-schema-to-5-0-mysql.sql | 18 +++++++------- .../sql/rename-schema-to-5-0-postgresql.sql | 22 ++++++++--------- .../sql/rename-schema-to-5-0-sqlite.sql | 24 +++++++++---------- 6 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/bundle/Migration/sql/install-schema-mysql.sql b/src/bundle/Migration/sql/install-schema-mysql.sql index 6b5f7d4..b3c45a8 100644 --- a/src/bundle/Migration/sql/install-schema-mysql.sql +++ b/src/bundle/Migration/sql/install-schema-mysql.sql @@ -1,5 +1,5 @@ -CREATE TABLE ibexa_user_invitations (id INT AUTO_INCREMENT NOT NULL, email VARCHAR(255) NOT NULL, site_access_name VARCHAR(255) NOT NULL, hash VARCHAR(255) NOT NULL, creation_date INT NOT NULL, used TINYINT(1) DEFAULT '0' NOT NULL, INDEX ibexa_user_invitations_email_idx (email), INDEX ibexa_user_invitations_hash_idx (hash), UNIQUE INDEX ibexa_user_invitations_email_uindex (email(191)), UNIQUE INDEX ibexa_user_invitations_hash_uindex (hash(191)), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB +CREATE TABLE ibexa_user_invitations (id INT AUTO_INCREMENT NOT NULL, email VARCHAR(255) NOT NULL, site_access_name VARCHAR(255) NOT NULL, hash VARCHAR(255) NOT NULL, creation_date INT NOT NULL, used TINYINT(1) DEFAULT '0' NOT NULL, INDEX ibexa_user_invitations_email_idx (email), INDEX ibexa_user_invitations_hash_idx (hash), UNIQUE INDEX ibexa_user_invitations_email_uindex (email(191)), UNIQUE INDEX ibexa_user_invitations_hash_uindex (hash(191)), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB; -- ibexa:sql-statement-separator -CREATE TABLE ibexa_user_invitations_assignments (id INT AUTO_INCREMENT NOT NULL, invitation_id INT NOT NULL, user_group_id INT DEFAULT NULL, role_id INT DEFAULT NULL, limitation_type VARCHAR(255) DEFAULT NULL, limitation_value VARCHAR(255) DEFAULT NULL, INDEX IDX_DA5A7872A35D7AF0 (invitation_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB +CREATE TABLE ibexa_user_invitations_assignments (id INT AUTO_INCREMENT NOT NULL, invitation_id INT NOT NULL, user_group_id INT DEFAULT NULL, role_id INT DEFAULT NULL, limitation_type VARCHAR(255) DEFAULT NULL, limitation_value VARCHAR(255) DEFAULT NULL, INDEX IDX_DA5A7872A35D7AF0 (invitation_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB; -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitations_assignments ADD CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitations (id) ON UPDATE CASCADE ON DELETE CASCADE +ALTER TABLE ibexa_user_invitations_assignments ADD CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitations (id) ON UPDATE CASCADE ON DELETE CASCADE; diff --git a/src/bundle/Migration/sql/install-schema-postgresql.sql b/src/bundle/Migration/sql/install-schema-postgresql.sql index 300e66a..9424b74 100644 --- a/src/bundle/Migration/sql/install-schema-postgresql.sql +++ b/src/bundle/Migration/sql/install-schema-postgresql.sql @@ -1,15 +1,15 @@ -CREATE TABLE ibexa_user_invitations (id SERIAL NOT NULL, email VARCHAR(255) NOT NULL, site_access_name VARCHAR(255) NOT NULL, hash VARCHAR(255) NOT NULL, creation_date INT NOT NULL, used BOOLEAN DEFAULT 'false' NOT NULL, PRIMARY KEY(id)) +CREATE TABLE ibexa_user_invitations (id SERIAL NOT NULL, email VARCHAR(255) NOT NULL, site_access_name VARCHAR(255) NOT NULL, hash VARCHAR(255) NOT NULL, creation_date INT NOT NULL, used BOOLEAN DEFAULT 'false' NOT NULL, PRIMARY KEY(id)); -- ibexa:sql-statement-separator -CREATE INDEX ibexa_user_invitations_email_idx ON ibexa_user_invitations (email) +CREATE INDEX ibexa_user_invitations_email_idx ON ibexa_user_invitations (email); -- ibexa:sql-statement-separator -CREATE INDEX ibexa_user_invitations_hash_idx ON ibexa_user_invitations (hash) +CREATE INDEX ibexa_user_invitations_hash_idx ON ibexa_user_invitations (hash); -- ibexa:sql-statement-separator -CREATE UNIQUE INDEX ibexa_user_invitations_email_uindex ON ibexa_user_invitations (email) +CREATE UNIQUE INDEX ibexa_user_invitations_email_uindex ON ibexa_user_invitations (email); -- ibexa:sql-statement-separator -CREATE UNIQUE INDEX ibexa_user_invitations_hash_uindex ON ibexa_user_invitations (hash) +CREATE UNIQUE INDEX ibexa_user_invitations_hash_uindex ON ibexa_user_invitations (hash); -- ibexa:sql-statement-separator -CREATE TABLE ibexa_user_invitations_assignments (id SERIAL NOT NULL, invitation_id INT NOT NULL, user_group_id INT DEFAULT NULL, role_id INT DEFAULT NULL, limitation_type VARCHAR(255) DEFAULT NULL, limitation_value VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id)) +CREATE TABLE ibexa_user_invitations_assignments (id SERIAL NOT NULL, invitation_id INT NOT NULL, user_group_id INT DEFAULT NULL, role_id INT DEFAULT NULL, limitation_type VARCHAR(255) DEFAULT NULL, limitation_value VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id)); -- ibexa:sql-statement-separator -CREATE INDEX IDX_DA5A7872A35D7AF0 ON ibexa_user_invitations_assignments (invitation_id) +CREATE INDEX IDX_DA5A7872A35D7AF0 ON ibexa_user_invitations_assignments (invitation_id); -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitations_assignments ADD CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitations (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE +ALTER TABLE ibexa_user_invitations_assignments ADD CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitations (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE; diff --git a/src/bundle/Migration/sql/install-schema-sqlite.sql b/src/bundle/Migration/sql/install-schema-sqlite.sql index 965206e..591ec3e 100644 --- a/src/bundle/Migration/sql/install-schema-sqlite.sql +++ b/src/bundle/Migration/sql/install-schema-sqlite.sql @@ -1,13 +1,13 @@ -CREATE TABLE ibexa_user_invitations (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, email VARCHAR(255) NOT NULL, site_access_name VARCHAR(255) NOT NULL, hash VARCHAR(255) NOT NULL, creation_date INTEGER NOT NULL, used BOOLEAN DEFAULT '0' NOT NULL) +CREATE TABLE ibexa_user_invitations (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, email VARCHAR(255) NOT NULL, site_access_name VARCHAR(255) NOT NULL, hash VARCHAR(255) NOT NULL, creation_date INTEGER NOT NULL, used BOOLEAN DEFAULT '0' NOT NULL); -- ibexa:sql-statement-separator -CREATE INDEX ibexa_user_invitations_email_idx ON ibexa_user_invitations (email) +CREATE INDEX ibexa_user_invitations_email_idx ON ibexa_user_invitations (email); -- ibexa:sql-statement-separator -CREATE INDEX ibexa_user_invitations_hash_idx ON ibexa_user_invitations (hash) +CREATE INDEX ibexa_user_invitations_hash_idx ON ibexa_user_invitations (hash); -- ibexa:sql-statement-separator -CREATE UNIQUE INDEX ibexa_user_invitations_email_uindex ON ibexa_user_invitations (email) +CREATE UNIQUE INDEX ibexa_user_invitations_email_uindex ON ibexa_user_invitations (email); -- ibexa:sql-statement-separator -CREATE UNIQUE INDEX ibexa_user_invitations_hash_uindex ON ibexa_user_invitations (hash) +CREATE UNIQUE INDEX ibexa_user_invitations_hash_uindex ON ibexa_user_invitations (hash); -- ibexa:sql-statement-separator -CREATE TABLE ibexa_user_invitations_assignments (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, invitation_id INTEGER NOT NULL, user_group_id INTEGER DEFAULT NULL, role_id INTEGER DEFAULT NULL, limitation_type VARCHAR(255) DEFAULT NULL, limitation_value VARCHAR(255) DEFAULT NULL, CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitations (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE) +CREATE TABLE ibexa_user_invitations_assignments (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, invitation_id INTEGER NOT NULL, user_group_id INTEGER DEFAULT NULL, role_id INTEGER DEFAULT NULL, limitation_type VARCHAR(255) DEFAULT NULL, limitation_value VARCHAR(255) DEFAULT NULL, CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitations (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE); -- ibexa:sql-statement-separator -CREATE INDEX IDX_DA5A7872A35D7AF0 ON ibexa_user_invitations_assignments (invitation_id) +CREATE INDEX IDX_DA5A7872A35D7AF0 ON ibexa_user_invitations_assignments (invitation_id); diff --git a/src/bundle/Migration/sql/rename-schema-to-5-0-mysql.sql b/src/bundle/Migration/sql/rename-schema-to-5-0-mysql.sql index 4724309..401363c 100644 --- a/src/bundle/Migration/sql/rename-schema-to-5-0-mysql.sql +++ b/src/bundle/Migration/sql/rename-schema-to-5-0-mysql.sql @@ -1,17 +1,17 @@ -ALTER TABLE ibexa_user_invitations RENAME TO ibexa_user_invitation +ALTER TABLE ibexa_user_invitations RENAME TO ibexa_user_invitation; -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_email_idx TO ibexa_user_invitation_email_idx +ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_email_idx TO ibexa_user_invitation_email_idx; -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_hash_idx TO ibexa_user_invitation_hash_idx +ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_hash_idx TO ibexa_user_invitation_hash_idx; -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_email_uindex TO ibexa_user_invitation_email_uindex +ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_email_uindex TO ibexa_user_invitation_email_uindex; -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_hash_uindex TO ibexa_user_invitation_hash_uindex +ALTER TABLE ibexa_user_invitation RENAME INDEX ibexa_user_invitations_hash_uindex TO ibexa_user_invitation_hash_uindex; -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitations_assignments RENAME TO ibexa_user_invitation_assignment +ALTER TABLE ibexa_user_invitations_assignments RENAME TO ibexa_user_invitation_assignment; -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitation_assignment DROP FOREIGN KEY ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk +ALTER TABLE ibexa_user_invitation_assignment DROP FOREIGN KEY ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk; -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitation_assignment ADD CONSTRAINT ibexa_user_invitation_assignment_ibexa_user_invitation_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitation(id) ON DELETE CASCADE ON UPDATE CASCADE +ALTER TABLE ibexa_user_invitation_assignment ADD CONSTRAINT ibexa_user_invitation_assignment_ibexa_user_invitation_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitation(id) ON DELETE CASCADE ON UPDATE CASCADE; -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitation_assignment RENAME INDEX IDX_DA5A7872A35D7AF0 TO IDX_9E1E6F70A35D7AF0 +ALTER TABLE ibexa_user_invitation_assignment RENAME INDEX IDX_DA5A7872A35D7AF0 TO IDX_9E1E6F70A35D7AF0; diff --git a/src/bundle/Migration/sql/rename-schema-to-5-0-postgresql.sql b/src/bundle/Migration/sql/rename-schema-to-5-0-postgresql.sql index 64ab238..b35c403 100644 --- a/src/bundle/Migration/sql/rename-schema-to-5-0-postgresql.sql +++ b/src/bundle/Migration/sql/rename-schema-to-5-0-postgresql.sql @@ -1,21 +1,21 @@ -ALTER TABLE ibexa_user_invitations RENAME TO ibexa_user_invitation +ALTER TABLE ibexa_user_invitations RENAME TO ibexa_user_invitation; -- ibexa:sql-statement-separator -ALTER SEQUENCE ibexa_user_invitations_id_seq RENAME TO ibexa_user_invitation_id_seq +ALTER SEQUENCE ibexa_user_invitations_id_seq RENAME TO ibexa_user_invitation_id_seq; -- ibexa:sql-statement-separator -ALTER INDEX ibexa_user_invitations_email_idx RENAME TO ibexa_user_invitation_email_idx +ALTER INDEX ibexa_user_invitations_email_idx RENAME TO ibexa_user_invitation_email_idx; -- ibexa:sql-statement-separator -ALTER INDEX ibexa_user_invitations_hash_idx RENAME TO ibexa_user_invitation_hash_idx +ALTER INDEX ibexa_user_invitations_hash_idx RENAME TO ibexa_user_invitation_hash_idx; -- ibexa:sql-statement-separator -ALTER INDEX ibexa_user_invitations_email_uindex RENAME TO ibexa_user_invitation_email_uindex +ALTER INDEX ibexa_user_invitations_email_uindex RENAME TO ibexa_user_invitation_email_uindex; -- ibexa:sql-statement-separator -ALTER INDEX ibexa_user_invitations_hash_uindex RENAME TO ibexa_user_invitation_hash_uindex +ALTER INDEX ibexa_user_invitations_hash_uindex RENAME TO ibexa_user_invitation_hash_uindex; -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitations_assignments RENAME TO ibexa_user_invitation_assignment +ALTER TABLE ibexa_user_invitations_assignments RENAME TO ibexa_user_invitation_assignment; -- ibexa:sql-statement-separator -ALTER SEQUENCE ibexa_user_invitations_assignments_id_seq RENAME TO ibexa_user_invitation_assignment_id_seq +ALTER SEQUENCE ibexa_user_invitations_assignments_id_seq RENAME TO ibexa_user_invitation_assignment_id_seq; -- ibexa:sql-statement-separator -ALTER INDEX IDX_DA5A7872A35D7AF0 RENAME TO IDX_9E1E6F70A35D7AF0 +ALTER INDEX IDX_DA5A7872A35D7AF0 RENAME TO IDX_9E1E6F70A35D7AF0; -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitation_assignment DROP CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk +ALTER TABLE ibexa_user_invitation_assignment DROP CONSTRAINT ibexa_user_invitations_assignments_ibexa_user_invitations_id_fk; -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitation_assignment ADD CONSTRAINT ibexa_user_invitation_assignment_ibexa_user_invitation_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitation(id) ON DELETE CASCADE ON UPDATE CASCADE +ALTER TABLE ibexa_user_invitation_assignment ADD CONSTRAINT ibexa_user_invitation_assignment_ibexa_user_invitation_id_fk FOREIGN KEY (invitation_id) REFERENCES ibexa_user_invitation(id) ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/src/bundle/Migration/sql/rename-schema-to-5-0-sqlite.sql b/src/bundle/Migration/sql/rename-schema-to-5-0-sqlite.sql index 534471d..907664f 100644 --- a/src/bundle/Migration/sql/rename-schema-to-5-0-sqlite.sql +++ b/src/bundle/Migration/sql/rename-schema-to-5-0-sqlite.sql @@ -1,23 +1,23 @@ -ALTER TABLE ibexa_user_invitations RENAME TO ibexa_user_invitation +ALTER TABLE ibexa_user_invitations RENAME TO ibexa_user_invitation; -- ibexa:sql-statement-separator -DROP INDEX ibexa_user_invitations_email_idx +DROP INDEX ibexa_user_invitations_email_idx; -- ibexa:sql-statement-separator -CREATE INDEX ibexa_user_invitation_email_idx ON ibexa_user_invitation (email) +CREATE INDEX ibexa_user_invitation_email_idx ON ibexa_user_invitation (email); -- ibexa:sql-statement-separator -DROP INDEX ibexa_user_invitations_hash_idx +DROP INDEX ibexa_user_invitations_hash_idx; -- ibexa:sql-statement-separator -CREATE INDEX ibexa_user_invitation_hash_idx ON ibexa_user_invitation (hash) +CREATE INDEX ibexa_user_invitation_hash_idx ON ibexa_user_invitation (hash); -- ibexa:sql-statement-separator -DROP INDEX ibexa_user_invitations_email_uindex +DROP INDEX ibexa_user_invitations_email_uindex; -- ibexa:sql-statement-separator -CREATE UNIQUE INDEX ibexa_user_invitation_email_uindex ON ibexa_user_invitation (email) +CREATE UNIQUE INDEX ibexa_user_invitation_email_uindex ON ibexa_user_invitation (email); -- ibexa:sql-statement-separator -DROP INDEX ibexa_user_invitations_hash_uindex +DROP INDEX ibexa_user_invitations_hash_uindex; -- ibexa:sql-statement-separator -CREATE UNIQUE INDEX ibexa_user_invitation_hash_uindex ON ibexa_user_invitation (hash) +CREATE UNIQUE INDEX ibexa_user_invitation_hash_uindex ON ibexa_user_invitation (hash); -- ibexa:sql-statement-separator -ALTER TABLE ibexa_user_invitations_assignments RENAME TO ibexa_user_invitation_assignment +ALTER TABLE ibexa_user_invitations_assignments RENAME TO ibexa_user_invitation_assignment; -- ibexa:sql-statement-separator -DROP INDEX IDX_DA5A7872A35D7AF0 +DROP INDEX IDX_DA5A7872A35D7AF0; -- ibexa:sql-statement-separator -CREATE INDEX IDX_9E1E6F70A35D7AF0 ON ibexa_user_invitation_assignment (invitation_id) +CREATE INDEX IDX_9E1E6F70A35D7AF0 ON ibexa_user_invitation_assignment (invitation_id); From 76ee1d83fe85f994ed13d4f2f4c49e97eda6831d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Niedzielski?= Date: Thu, 23 Jul 2026 16:49:37 +0200 Subject: [PATCH 7/9] IBX-11939: Added schema-presence guards to skip already-applied migrations Checks $schema (already the live, introspected database) before running, and skipIf()s when the tables/columns/FK targets this migration would create already exist -- so installs that built their schema the old way (SchemaBuilderEvent) can adopt Doctrine Migrations without every migration aborting or duplicating existing schema objects. --- src/bundle/Migration/InstallSchemaMigration.php | 2 ++ src/bundle/Migration/RenameSchemaTo5_0Migration.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/bundle/Migration/InstallSchemaMigration.php b/src/bundle/Migration/InstallSchemaMigration.php index cb953b2..c6af1ed 100644 --- a/src/bundle/Migration/InstallSchemaMigration.php +++ b/src/bundle/Migration/InstallSchemaMigration.php @@ -35,6 +35,8 @@ public function up(Schema $schema): void { $this->abortIfUnsupportedPlatform(SqlPlatform::MYSQL, SqlPlatform::POSTGRESQL, SqlPlatform::SQLITE); + $this->skipIf($schema->hasTable('ibexa_user_invitation'), 'Schema already migrated: table "ibexa_user_invitation" already exists.'); + if ($this->isMySQL()) { $this->addSqlFile(__DIR__ . '/sql/install-schema-mysql.sql'); } elseif ($this->isPostgreSQL()) { diff --git a/src/bundle/Migration/RenameSchemaTo5_0Migration.php b/src/bundle/Migration/RenameSchemaTo5_0Migration.php index 78ce94d..dfc1b75 100644 --- a/src/bundle/Migration/RenameSchemaTo5_0Migration.php +++ b/src/bundle/Migration/RenameSchemaTo5_0Migration.php @@ -35,6 +35,8 @@ public function up(Schema $schema): void { $this->abortIfUnsupportedPlatform(SqlPlatform::MYSQL, SqlPlatform::POSTGRESQL, SqlPlatform::SQLITE); + $this->skipIf($schema->hasTable('ibexa_user_invitation'), 'Schema already migrated: table "ibexa_user_invitation" already exists.'); + if ($this->isMySQL()) { $this->addSqlFile(__DIR__ . '/sql/rename-schema-to-5-0-mysql.sql'); } elseif ($this->isPostgreSQL()) { From 441302ac19c61c5cea1748179fe6f351391fef12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Niedzielski?= Date: Thu, 23 Jul 2026 18:36:57 +0200 Subject: [PATCH 8/9] IBX-11939: Recorded schema-guarded migrations as applied, not skipped Doctrine Migrations only calls MetadataStorage::complete() (the write to doctrine_migration_versions) when a migration's up() returns normally -- never when it throws SkipMigration. So every migration using skipIf() was being silently re-evaluated on every future doctrine:migrations:migrate run instead of being permanently recorded as applied, even though its guard condition (the schema already being in place) never changes back. Replaces every `$this->skipIf($condition, $message);` with `if ($condition) { return; }`: up() now returns normally with zero queued SQL when the guard fires, so the migration is correctly recorded as executed (with a "did not result in any SQL statements" warning logged, which is expected and harmless) and never re-evaluated again. Verified end-to-end: fresh ibexa:install (schema_builder_event enabled) followed by doctrine:migrations:migrate now records all 44 tagged migrations in doctrine_migration_versions in one pass, and a second migrate run does zero work at all ("Already at the latest version"). --- src/bundle/Migration/InstallSchemaMigration.php | 4 +++- src/bundle/Migration/RenameSchemaTo5_0Migration.php | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/bundle/Migration/InstallSchemaMigration.php b/src/bundle/Migration/InstallSchemaMigration.php index c6af1ed..fcae31e 100644 --- a/src/bundle/Migration/InstallSchemaMigration.php +++ b/src/bundle/Migration/InstallSchemaMigration.php @@ -35,7 +35,9 @@ public function up(Schema $schema): void { $this->abortIfUnsupportedPlatform(SqlPlatform::MYSQL, SqlPlatform::POSTGRESQL, SqlPlatform::SQLITE); - $this->skipIf($schema->hasTable('ibexa_user_invitation'), 'Schema already migrated: table "ibexa_user_invitation" already exists.'); + if ($schema->hasTable('ibexa_user_invitation')) { + return; + } if ($this->isMySQL()) { $this->addSqlFile(__DIR__ . '/sql/install-schema-mysql.sql'); diff --git a/src/bundle/Migration/RenameSchemaTo5_0Migration.php b/src/bundle/Migration/RenameSchemaTo5_0Migration.php index dfc1b75..dcd7e6c 100644 --- a/src/bundle/Migration/RenameSchemaTo5_0Migration.php +++ b/src/bundle/Migration/RenameSchemaTo5_0Migration.php @@ -35,7 +35,9 @@ public function up(Schema $schema): void { $this->abortIfUnsupportedPlatform(SqlPlatform::MYSQL, SqlPlatform::POSTGRESQL, SqlPlatform::SQLITE); - $this->skipIf($schema->hasTable('ibexa_user_invitation'), 'Schema already migrated: table "ibexa_user_invitation" already exists.'); + if ($schema->hasTable('ibexa_user_invitation')) { + return; + } if ($this->isMySQL()) { $this->addSqlFile(__DIR__ . '/sql/rename-schema-to-5-0-mysql.sql'); From 18d47e16257ee282f328a05c00892fdbd79ae50b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Niedzielski?= Date: Mon, 27 Jul 2026 17:24:39 +0200 Subject: [PATCH 9/9] IBX-11939: Removed ibexa/doctrine-migrations VCS repository entry ibexa/doctrine-migrations is now published on Packagist (which mirrors all of its branches, not just tags), so the explicit VCS repository pointing composer directly at GitHub is no longer needed to resolve the dev-branch require constraint. --- composer.json | 6 ------ 1 file changed, 6 deletions(-) diff --git a/composer.json b/composer.json index 7ac0567..5a6dfb9 100644 --- a/composer.json +++ b/composer.json @@ -20,12 +20,6 @@ "Ibexa\\Tests\\Integration\\User\\": "tests/integration/" } }, - "repositories": [ - { - "type": "vcs", - "url": "https://github.com/ibexa/doctrine-migrations.git" - } - ], "require": { "php": " >=8.3", "ibexa/content-forms": "~6.0.x-dev",