From 78ff79012150bec9f9c0f876c2d06ecaa6566a49 Mon Sep 17 00:00:00 2001 From: David Sevilla Martin Date: Wed, 26 Jul 2023 12:34:46 -0400 Subject: [PATCH] Keep post_id foreign in existing migration & move value updating to an earlier one to avoid foreign key check --- ..._polls_discussion_id_to_post_id_values.php | 87 +++++++++++++++++++ ...olls_discussion_relation_to_first_post.php | 65 ++------------ ...07_08_000002_add_polls_post_id_foreign.php | 39 --------- 3 files changed, 92 insertions(+), 99 deletions(-) create mode 100644 migrations/2023_07_08_000000_update_polls_discussion_id_to_post_id_values.php delete mode 100644 migrations/2023_07_08_000002_add_polls_post_id_foreign.php diff --git a/migrations/2023_07_08_000000_update_polls_discussion_id_to_post_id_values.php b/migrations/2023_07_08_000000_update_polls_discussion_id_to_post_id_values.php new file mode 100644 index 00000000..2b3f84d2 --- /dev/null +++ b/migrations/2023_07_08_000000_update_polls_discussion_id_to_post_id_values.php @@ -0,0 +1,87 @@ + function (Builder $schema) { + $db = $schema->getConnection(); + + if ($db->table('migrations')->where('migration', '2023_07_08_000001_update_polls_discussion_relation_to_first_post')->exists()) { + return; + } + + $db->transaction(function () use ($db) { + $prefix = $db->getTablePrefix(); + + // Don't run through this step if no rows exist in the polls table + if (!$db->table('polls')->exists()) { + return; + } + + // Update polls whose discussions have a clear first post ID associated + $db->table('polls') + ->join('discussions', function (JoinClause $join) { + $join->on('polls.post_id', '=', 'discussions.id') + ->where('discussions.first_post_id', '!=', null); + }) + ->update(['polls.post_id' => $db->raw("{$prefix}discussions.first_post_id")]); + + // Update polls whose discussions have a null first post ID associated + $firstPosts = $db->table('posts') + ->where('number', '=', 1); + + $db->table('polls') + ->join('discussions', function (JoinClause $join) { + $join->on('polls.post_id', '=', 'discussions.id') + ->where('discussions.first_post_id', '=', null); + }) + ->leftJoinSub($firstPosts, 'first_posts', function (JoinClause $join) { + $join->on('first_posts.discussion_id', '=', 'discussions.id'); + }) + ->update(['polls.post_id' => $db->raw("{$prefix}first_posts.id")]); + + // Delete polls that don't have an associated post + $deletingPolls = $db->table('polls') + ->where('post_id', 0); + $count = $deletingPolls->count(); + + if ($count > 0) { + resolve('log')->warning("[fof/polls] deleting {$deletingPolls->count()} polls with no associated post"); + resolve('log')->warning("[fof/polls] |> #{$deletingPolls->pluck('id')->join(', #')}"); + } else { + resolve('log')->info('[fof/polls] no polls to delete in v2 migration'); + } + + $deletingPolls->delete(); + }); + }, + 'down' => function (Builder $schema) { + $db = $schema->getConnection(); + + $db->transaction(function () use ($db) { + $prefix = $db->getTablePrefix(); + + // Don't run through this step if no rows exist in the polls table + if (!$db->table('polls')->exists()) { + return; + } + + // Go back to using discussion IDs. The discussion ID will always exist since the posts' foreign key cascades on delete. + $db->table('polls') + ->join('posts', 'polls.post_id', '=', 'posts.id') + ->update(['polls.post_id' => $db->raw("{$prefix}posts.discussion_id")]); + }); + }, +]; diff --git a/migrations/2023_07_08_000001_update_polls_discussion_relation_to_first_post.php b/migrations/2023_07_08_000001_update_polls_discussion_relation_to_first_post.php index 7b9cd77c..49c6f370 100644 --- a/migrations/2023_07_08_000001_update_polls_discussion_relation_to_first_post.php +++ b/migrations/2023_07_08_000001_update_polls_discussion_relation_to_first_post.php @@ -13,71 +13,16 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Builder; -// Split 1/2 of 2023_07_08_000001_update_polls_discussion_relation_to_first_post.php +// Split 2/2 of 2023_07_08_000001_update_polls_discussion_relation_to_first_post.php return [ 'up' => function (Builder $schema) { - $db = $schema->getConnection(); - - $db->transaction(function () use ($db) { - $prefix = $db->getTablePrefix(); - - // Don't run through this step if no rows exist in the polls table - if (!$db->table('polls')->exists()) { - return; - } - - // Update polls whose discussions have a clear first post ID associated - $db->table('polls') - ->join('discussions', function (JoinClause $join) { - $join->on('polls.post_id', '=', 'discussions.id') - ->where('discussions.first_post_id', '!=', null); - }) - ->update(['polls.post_id' => $db->raw("{$prefix}discussions.first_post_id")]); - - // Update polls whose discussions have a null first post ID associated - $firstPosts = $db->table('posts') - ->where('number', '=', 1); - - $db->table('polls') - ->join('discussions', function (JoinClause $join) { - $join->on('polls.post_id', '=', 'discussions.id') - ->where('discussions.first_post_id', '=', null); - }) - ->leftJoinSub($firstPosts, 'first_posts', function (JoinClause $join) { - $join->on('first_posts.discussion_id', '=', 'discussions.id'); - }) - ->update(['polls.post_id' => $db->raw("{$prefix}first_posts.id")]); - - // Delete polls that don't have an associated post - $deletingPolls = $db->table('polls') - ->where('post_id', 0); - $count = $deletingPolls->count(); - - if ($count > 0) { - resolve('log')->warning("[fof/polls] deleting {$deletingPolls->count()} polls with no associated post"); - resolve('log')->warning("[fof/polls] |> #{$deletingPolls->pluck('id')->join(', #')}"); - } else { - resolve('log')->info('[fof/polls] no polls to delete in v2 migration'); - } - - $deletingPolls->delete(); + $schema->table('polls', function (Blueprint $table) { + $table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade'); }); }, 'down' => function (Builder $schema) { - $db = $schema->getConnection(); - - $db->transaction(function () use ($db) { - $prefix = $db->getTablePrefix(); - - // Don't run through this step if no rows exist in the polls table - if (!$db->table('polls')->exists()) { - return; - } - - // Go back to using discussion IDs. The discussion ID will always exist since the posts' foreign key cascades on delete. - $db->table('polls') - ->join('posts', 'polls.post_id', '=', 'posts.id') - ->update(['polls.post_id' => $db->raw("{$prefix}posts.discussion_id")]); + $schema->table('polls', function (Blueprint $table) { + $table->dropForeign(['post_id']); }); }, ]; diff --git a/migrations/2023_07_08_000002_add_polls_post_id_foreign.php b/migrations/2023_07_08_000002_add_polls_post_id_foreign.php deleted file mode 100644 index 104374aa..00000000 --- a/migrations/2023_07_08_000002_add_polls_post_id_foreign.php +++ /dev/null @@ -1,39 +0,0 @@ - function (Builder $schema) { - // Do not run this migration if the foreign key was already added before the split - $db = $schema->getConnection(); - $foreignKeys = $db->getDoctrineSchemaManager()->listTableForeignKeys("{$db->getTablePrefix()}polls"); - - foreach ($foreignKeys as $foreignKey) { - if (in_array('post_id', $foreignKey->getLocalColumns())) { - return; - } - } - - $schema->table('polls', function (Blueprint $table) { - $table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade'); - }); - }, - 'down' => function (Builder $schema) { - $schema->table('polls', function (Blueprint $table) { - $table->dropForeign(['post_id']); - }); - }, -];