From 712ab33ff84087b2e23c5040a0c0472ca8533b82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Tue, 4 Aug 2020 11:07:07 +0200 Subject: [PATCH] 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. --- lib/tasks/posts.rake | 141 +++++++++++++++++++------------------------ 1 file changed, 63 insertions(+), 78 deletions(-) diff --git a/lib/tasks/posts.rake b/lib/tasks/posts.rake index 0515f4301bf..a491497380c 100644 --- a/lib/tasks/posts.rake +++ b/lib/tasks/posts.rake @@ -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.", ""