Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split the two discussion_id -> post_id migrations into 4 total #80

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,15 @@
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Schema\Builder;

// Split 1/2 of 2023_07_08_000000_rename_polls_discussion_id_column.php
return [
'up' => function (Builder $schema) {
$schema->table('polls', function (Blueprint $table) {
$table->dropForeign(['discussion_id']);
$table->renameColumn('discussion_id', 'post_id');
});
},
'down' => function (Builder $schema) {
$schema->table('polls', function (Blueprint $table) {
$table->renameColumn('post_id', 'discussion_id');
$table->foreign('discussion_id')->references('id')->on('discussions')->onDelete('cascade');
});
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/*
* This file is part of fof/polls.
*
* Copyright (c) FriendsOfFlarum.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Schema\Builder;

// Split 2/2 of 2023_07_08_000000_rename_polls_discussion_id_column.php
return [
'up' => function (Builder $schema) {
// Do not run this migration if the column was already renamed before the split
if ($schema->hasColumn('polls', 'post_id')) {
return;
}

$schema->table('polls', function (Blueprint $table) {
$table->renameColumn('discussion_id', 'post_id');
});
},
'down' => function (Builder $schema) {
$schema->table('polls', function (Blueprint $table) {
$table->renameColumn('post_id', 'discussion_id');
});
},
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

/*
* This file is part of fof/polls.
*
* Copyright (c) FriendsOfFlarum.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Illuminate\Database\Query\JoinClause;
use Illuminate\Database\Schema\Builder;

// Split 1/2 of 2023_07_08_000001_update_polls_discussion_relation_to_first_post.php
return [
'up' => function (Builder $schema) {
$db = $schema->getConnection();

// Do not run this migration if the values were already updated before the split
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")]);
});
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -9,80 +9,17 @@
* file that was distributed with this source code.
*/

use Illuminate\Database\Query\JoinClause;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Schema\Builder;

// 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']);
});
Expand Down