feat(migration): update blog schema to add new fields and improve migration handling
This commit is contained in:
@@ -29,8 +29,11 @@ if [ "${RUN_INIT:-1}" = "1" ]; then
|
|||||||
php bin/console cache:clear --no-warmup
|
php bin/console cache:clear --no-warmup
|
||||||
php bin/console cache:warmup
|
php bin/console cache:warmup
|
||||||
|
|
||||||
# Apply pending migrations. --all-or-nothing wraps them in a transaction.
|
# Apply pending migrations. NOT --all-or-nothing: MariaDB auto-commits on DDL
|
||||||
php bin/console doctrine:migrations:migrate --all-or-nothing --no-interaction
|
# (ALTER TABLE), which releases the transaction's savepoint mid-migration and
|
||||||
|
# then fails with "SAVEPOINT DOCTRINE_2 does not exist". Same reason liara_pre_start.sh
|
||||||
|
# omits it. DDL can't be rolled back on MariaDB anyway, so the flag only adds breakage.
|
||||||
|
php bin/console doctrine:migrations:migrate --no-interaction
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exec "$@"
|
exec "$@"
|
||||||
|
|||||||
@@ -17,23 +17,35 @@ final class Version20260723171254 extends AbstractMigration
|
|||||||
return 'Add medical-review gate fields to blogs (sources, review_status, reviewer, reviewed_at, review_note, topic_slug)';
|
return 'Add medical-review gate fields to blogs (sources, review_status, reviewer, reviewed_at, review_note, topic_slug)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MariaDB auto-commits on DDL, so wrapping this migration in a transaction only
|
||||||
|
// creates savepoints that the first ALTER destroys ("SAVEPOINT DOCTRINE_2 does
|
||||||
|
// not exist"). Run it outside a transaction; the statements are idempotent.
|
||||||
|
public function isTransactional(): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public function up(Schema $schema): void
|
public function up(Schema $schema): void
|
||||||
{
|
{
|
||||||
// Scoped to the blogs table only. Unrelated project-wide schema drift that
|
// Scoped to the blogs table only. Unrelated project-wide schema drift that
|
||||||
// doctrine:diff also emitted (messenger_messages, date_overrides, …) is
|
// doctrine:diff also emitted (messenger_messages, date_overrides, …) is
|
||||||
// deliberately left out — it belongs to other migrations, not this feature.
|
// deliberately left out — it belongs to other migrations, not this feature.
|
||||||
|
// Idempotent (MariaDB IF [NOT] EXISTS): a prior failed --all-or-nothing run
|
||||||
|
// can leave columns applied while the version record was rolled back, so a
|
||||||
|
// re-run must heal a partial state instead of erroring on "duplicate column".
|
||||||
// Nullable columns first (safe on a table with existing rows).
|
// Nullable columns first (safe on a table with existing rows).
|
||||||
$this->addSql('ALTER TABLE blogs ADD review_status VARCHAR(20) DEFAULT NULL, ADD reviewed_at INT DEFAULT NULL, ADD review_note VARCHAR(500) DEFAULT NULL, ADD topic_slug VARCHAR(255) DEFAULT NULL, ADD reviewer_id INT DEFAULT NULL');
|
$this->addSql('ALTER TABLE blogs ADD COLUMN IF NOT EXISTS review_status VARCHAR(20) DEFAULT NULL, ADD COLUMN IF NOT EXISTS reviewed_at INT DEFAULT NULL, ADD COLUMN IF NOT EXISTS review_note VARCHAR(500) DEFAULT NULL, ADD COLUMN IF NOT EXISTS topic_slug VARCHAR(255) DEFAULT NULL, ADD COLUMN IF NOT EXISTS reviewer_id INT DEFAULT NULL');
|
||||||
// `sources` is JSON NOT NULL: adding it directly to a table that already
|
// `sources` is JSON NOT NULL: adding it directly to a table that already has
|
||||||
// has rows fails the json_valid CHECK (empty backfill is invalid JSON).
|
// rows fails the json_valid CHECK (empty backfill is invalid JSON).
|
||||||
// Add nullable, backfill '[]', then enforce NOT NULL.
|
// Add nullable, backfill '[]', then enforce NOT NULL.
|
||||||
$this->addSql('ALTER TABLE blogs ADD sources JSON DEFAULT NULL');
|
$this->addSql('ALTER TABLE blogs ADD COLUMN IF NOT EXISTS sources JSON DEFAULT NULL');
|
||||||
$this->addSql("UPDATE blogs SET sources = '[]'");
|
$this->addSql("UPDATE blogs SET sources = '[]' WHERE sources IS NULL");
|
||||||
$this->addSql('ALTER TABLE blogs MODIFY sources JSON NOT NULL');
|
$this->addSql('ALTER TABLE blogs MODIFY sources JSON NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE blogs DROP FOREIGN KEY IF EXISTS FK_F41BCA7070574616');
|
||||||
$this->addSql('ALTER TABLE blogs ADD CONSTRAINT FK_F41BCA7070574616 FOREIGN KEY (reviewer_id) REFERENCES users (id) ON DELETE SET NULL');
|
$this->addSql('ALTER TABLE blogs ADD CONSTRAINT FK_F41BCA7070574616 FOREIGN KEY (reviewer_id) REFERENCES users (id) ON DELETE SET NULL');
|
||||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_F41BCA70A076FAD7 ON blogs (topic_slug)');
|
$this->addSql('CREATE UNIQUE INDEX IF NOT EXISTS UNIQ_F41BCA70A076FAD7 ON blogs (topic_slug)');
|
||||||
$this->addSql('CREATE INDEX IDX_F41BCA7070574616 ON blogs (reviewer_id)');
|
$this->addSql('CREATE INDEX IF NOT EXISTS IDX_F41BCA7070574616 ON blogs (reviewer_id)');
|
||||||
$this->addSql('CREATE INDEX idx_blogs_review_status ON blogs (review_status, created_at)');
|
$this->addSql('CREATE INDEX IF NOT EXISTS idx_blogs_review_status ON blogs (review_status, created_at)');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function down(Schema $schema): void
|
public function down(Schema $schema): void
|
||||||
|
|||||||
@@ -17,21 +17,33 @@ final class Version20260723174500 extends AbstractMigration
|
|||||||
return 'Add SEO fields, scheduling (scheduled_at) and representative ownership (representation_id) to blogs';
|
return 'Add SEO fields, scheduling (scheduled_at) and representative ownership (representation_id) to blogs';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MariaDB auto-commits on DDL — run outside a transaction to avoid the broken
|
||||||
|
// savepoint path. Statements are idempotent (IF [NOT] EXISTS) so re-runs heal.
|
||||||
|
public function isTransactional(): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public function up(Schema $schema): void
|
public function up(Schema $schema): void
|
||||||
{
|
{
|
||||||
// Scoped to the blogs table only. Unrelated project-wide schema drift that
|
// Scoped to the blogs table only. Idempotent (MariaDB IF [NOT] EXISTS) so a
|
||||||
// doctrine:diff also emitted is deliberately left out of this feature migration.
|
// re-run after a failed --all-or-nothing deploy heals a partial state rather
|
||||||
|
// than erroring on duplicate columns/indexes.
|
||||||
// Nullable columns + representation FK column.
|
// Nullable columns + representation FK column.
|
||||||
$this->addSql('ALTER TABLE blogs ADD meta_title VARCHAR(255) DEFAULT NULL, ADD meta_description VARCHAR(500) DEFAULT NULL, ADD primary_keyword VARCHAR(255) DEFAULT NULL, ADD reading_time INT DEFAULT NULL, ADD canonical_url VARCHAR(500) DEFAULT NULL, ADD og_image VARCHAR(500) DEFAULT NULL, ADD scheduled_at INT DEFAULT NULL, ADD representation_id INT DEFAULT NULL');
|
$this->addSql('ALTER TABLE blogs ADD COLUMN IF NOT EXISTS meta_title VARCHAR(255) DEFAULT NULL, ADD COLUMN IF NOT EXISTS meta_description VARCHAR(500) DEFAULT NULL, ADD COLUMN IF NOT EXISTS primary_keyword VARCHAR(255) DEFAULT NULL, ADD COLUMN IF NOT EXISTS reading_time INT DEFAULT NULL, ADD COLUMN IF NOT EXISTS canonical_url VARCHAR(500) DEFAULT NULL, ADD COLUMN IF NOT EXISTS og_image VARCHAR(500) DEFAULT NULL, ADD COLUMN IF NOT EXISTS scheduled_at INT DEFAULT NULL, ADD COLUMN IF NOT EXISTS representation_id INT DEFAULT NULL');
|
||||||
// JSON NOT NULL columns can't be added directly to a table with rows (the
|
// JSON NOT NULL columns can't be added directly to a table with rows (the
|
||||||
// empty backfill fails json_valid). Add nullable, backfill '[]', then enforce.
|
// empty backfill fails json_valid). Add nullable, backfill '[]', then enforce.
|
||||||
$this->addSql('ALTER TABLE blogs ADD secondary_keywords JSON DEFAULT NULL, ADD faq JSON DEFAULT NULL, ADD internal_links JSON DEFAULT NULL, ADD external_links JSON DEFAULT NULL');
|
$this->addSql('ALTER TABLE blogs ADD COLUMN IF NOT EXISTS secondary_keywords JSON DEFAULT NULL, ADD COLUMN IF NOT EXISTS faq JSON DEFAULT NULL, ADD COLUMN IF NOT EXISTS internal_links JSON DEFAULT NULL, ADD COLUMN IF NOT EXISTS external_links JSON DEFAULT NULL');
|
||||||
$this->addSql("UPDATE blogs SET secondary_keywords = '[]', faq = '[]', internal_links = '[]', external_links = '[]'");
|
$this->addSql("UPDATE blogs SET secondary_keywords = '[]' WHERE secondary_keywords IS NULL");
|
||||||
|
$this->addSql("UPDATE blogs SET faq = '[]' WHERE faq IS NULL");
|
||||||
|
$this->addSql("UPDATE blogs SET internal_links = '[]' WHERE internal_links IS NULL");
|
||||||
|
$this->addSql("UPDATE blogs SET external_links = '[]' WHERE external_links IS NULL");
|
||||||
$this->addSql('ALTER TABLE blogs MODIFY secondary_keywords JSON NOT NULL, MODIFY faq JSON NOT NULL, MODIFY internal_links JSON NOT NULL, MODIFY external_links JSON NOT NULL');
|
$this->addSql('ALTER TABLE blogs MODIFY secondary_keywords JSON NOT NULL, MODIFY faq JSON NOT NULL, MODIFY internal_links JSON NOT NULL, MODIFY external_links JSON NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE blogs DROP FOREIGN KEY IF EXISTS FK_F41BCA7046CE82F4');
|
||||||
$this->addSql('ALTER TABLE blogs ADD CONSTRAINT FK_F41BCA7046CE82F4 FOREIGN KEY (representation_id) REFERENCES representations (id) ON DELETE SET NULL');
|
$this->addSql('ALTER TABLE blogs ADD CONSTRAINT FK_F41BCA7046CE82F4 FOREIGN KEY (representation_id) REFERENCES representations (id) ON DELETE SET NULL');
|
||||||
$this->addSql('CREATE INDEX IDX_F41BCA7046CE82F4 ON blogs (representation_id)');
|
$this->addSql('CREATE INDEX IF NOT EXISTS IDX_F41BCA7046CE82F4 ON blogs (representation_id)');
|
||||||
$this->addSql('CREATE INDEX idx_blogs_scheduled_at ON blogs (scheduled_at)');
|
$this->addSql('CREATE INDEX IF NOT EXISTS idx_blogs_scheduled_at ON blogs (scheduled_at)');
|
||||||
$this->addSql('CREATE INDEX idx_blogs_representation ON blogs (representation_id, created_at)');
|
$this->addSql('CREATE INDEX IF NOT EXISTS idx_blogs_representation ON blogs (representation_id, created_at)');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function down(Schema $schema): void
|
public function down(Schema $schema): void
|
||||||
|
|||||||
Reference in New Issue
Block a user