368bc98742f24586a6d6cc0a53bd0eabde4f0684
[anni] / priv / repo / migrations / 20200109123126_add_counter_cache_table.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Repo.Migrations.AddCounterCacheTable do
6   use Ecto.Migration
7
8   def up do
9     create_if_not_exists table(:counter_cache) do
10       add(:name, :string, null: false)
11       add(:count, :bigint, null: false, default: 0)
12     end
13
14     create_if_not_exists(unique_index(:counter_cache, [:name]))
15
16     """
17     CREATE OR REPLACE FUNCTION update_status_visibility_counter_cache()
18     RETURNS TRIGGER AS
19     $$
20       DECLARE
21       BEGIN
22       IF TG_OP = 'INSERT' THEN
23           IF NEW.data->>'type' = 'Create' THEN
24             EXECUTE 'INSERT INTO counter_cache (name, count) VALUES (''status_visibility_' || activity_visibility(NEW.actor, NEW.recipients, NEW.data) || ''', 1) ON CONFLICT (name) DO UPDATE SET count = counter_cache.count + 1';
25           END IF;
26           RETURN NEW;
27       ELSIF TG_OP = 'UPDATE' THEN
28           IF (NEW.data->>'type' = 'Create') and (OLD.data->>'type' = 'Create') and activity_visibility(NEW.actor, NEW.recipients, NEW.data) != activity_visibility(OLD.actor, OLD.recipients, OLD.data) THEN
29              EXECUTE 'INSERT INTO counter_cache (name, count) VALUES (''status_visibility_' || activity_visibility(NEW.actor, NEW.recipients, NEW.data) || ''', 1) ON CONFLICT (name) DO UPDATE SET count = counter_cache.count + 1';
30              EXECUTE 'update counter_cache SET count = counter_cache.count - 1 where count > 0 and name = ''status_visibility_' || activity_visibility(OLD.actor, OLD.recipients, OLD.data) || ''';';
31           END IF;
32           RETURN NEW;
33       ELSIF TG_OP = 'DELETE' THEN
34           IF OLD.data->>'type' = 'Create' THEN
35             EXECUTE 'update counter_cache SET count = counter_cache.count - 1 where count > 0 and name = ''status_visibility_' || activity_visibility(OLD.actor, OLD.recipients, OLD.data) || ''';';
36           END IF;
37           RETURN OLD;
38       END IF;
39       END;
40     $$
41     LANGUAGE 'plpgsql';
42     """
43     |> execute()
44
45     """
46     CREATE TRIGGER status_visibility_counter_cache_trigger BEFORE INSERT OR UPDATE of recipients, data OR DELETE ON activities
47     FOR EACH ROW
48     EXECUTE PROCEDURE update_status_visibility_counter_cache();
49     """
50     |> execute()
51   end
52
53   def down do
54     execute("drop trigger if exists status_visibility_counter_cache_trigger on activities")
55     execute("drop function if exists update_status_visibility_counter_cache()")
56     drop_if_exists(unique_index(:counter_cache, [:name]))
57     drop_if_exists(table(:counter_cache))
58   end
59 end