DEV: fix 'posts:reorder' rake task

Running the reorder rake task was triggering the following error:

PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "post_timings_unique"

I re-worked the queries and refactored to use the same couple of queries for all similar tables/columns.
This commit is contained in:
Régis Hanol 2020-08-04 11:07:07 +02:00
parent 4c03a944f6
commit 712ab33ff8
1 changed files with 63 additions and 78 deletions

View File

@ -310,92 +310,77 @@ end
desc 'Reorders all posts based on their creation_date'
task 'posts:reorder_posts', [:topic_id] => [:environment] do |_, args|
Post.transaction do
# update sort_order and flip post_number to prevent
# unique constraint violations when updating post_number
builder = DB.build(<<~SQL)
builder = DB.build <<~SQL
WITH ordered_posts AS (
SELECT
id,
ROW_NUMBER()
OVER (
PARTITION BY topic_id
ORDER BY created_at, post_number ) AS new_post_number
FROM posts
/*where*/
SELECT
id,
ROW_NUMBER() OVER (
PARTITION BY
topic_id
ORDER BY
created_at,
post_number
) AS new_post_number
FROM
posts
/*where*/
)
UPDATE posts AS p
SET sort_order = o.new_post_number,
post_number = p.post_number * -1
FROM ordered_posts AS o
WHERE p.id = o.id AND
p.post_number <> o.new_post_number
UPDATE
posts AS p
SET
sort_order = o.new_post_number,
post_number = p.post_number * -1
FROM
ordered_posts AS o
WHERE
p.id = o.id AND
p.post_number <> o.new_post_number
SQL
builder.where("topic_id = :topic_id") if args[:topic_id]
builder.exec(topic_id: args[:topic_id])
DB.exec(<<~SQL)
UPDATE notifications AS x
SET post_number = p.sort_order
FROM posts AS p
WHERE x.topic_id = p.topic_id AND
x.post_number = ABS(p.post_number) AND
p.post_number < 0
[
["notifications", "post_number"],
["post_timings", "post_number"],
["posts", "reply_to_post_number"],
["topic_users", "last_read_post_number"],
["topic_users", "highest_seen_post_number"],
["topic_users", "last_emailed_post_number"],
].each do |table, column|
DB.exec <<~SQL
UPDATE
#{table} AS x
SET
#{column} = p.sort_order * -1
FROM
posts AS p
WHERE
p.post_number < 0 AND
x.topic_id = p.topic_id AND
x.#{column} = ABS(p.post_number)
SQL
DB.exec <<~SQL
UPDATE
#{table}
SET
#{column} = #{column} * -1
WHERE
#{column} < 0
SQL
end
DB.exec <<~SQL
UPDATE
posts
SET
post_number = sort_order
WHERE
post_number < 0
SQL
DB.exec(<<~SQL)
UPDATE post_timings AS x
SET post_number = x.post_number * -1
FROM posts AS p
WHERE x.topic_id = p.topic_id AND
x.post_number = ABS(p.post_number) AND
p.post_number < 0;
UPDATE post_timings AS t
SET post_number = p.sort_order
FROM posts AS p
WHERE t.topic_id = p.topic_id AND
t.post_number = p.post_number AND
p.post_number < 0;
SQL
DB.exec(<<~SQL)
UPDATE posts AS x
SET reply_to_post_number = p.sort_order
FROM posts AS p
WHERE x.topic_id = p.topic_id AND
x.reply_to_post_number = ABS(p.post_number) AND
p.post_number < 0;
SQL
DB.exec(<<~SQL)
UPDATE topic_users AS x
SET last_read_post_number = p.sort_order
FROM posts AS p
WHERE x.topic_id = p.topic_id AND
x.last_read_post_number = ABS(p.post_number) AND
p.post_number < 0;
UPDATE topic_users AS x
SET highest_seen_post_number = p.sort_order
FROM posts AS p
WHERE x.topic_id = p.topic_id AND
x.highest_seen_post_number = ABS(p.post_number) AND
p.post_number < 0;
UPDATE topic_users AS x
SET last_emailed_post_number = p.sort_order
FROM posts AS p
WHERE x.topic_id = p.topic_id AND
x.last_emailed_post_number = ABS(p.post_number) AND
p.post_number < 0;
SQL
# finally update the post_number
DB.exec(<<~SQL)
UPDATE posts
SET post_number = sort_order
WHERE post_number < 0
SQL
end
puts "", "Done.", ""