68 lines
		
	
	
	
		
			2 KiB
		
	
	
	
		
			Elixir
		
	
	
	
	
	
			
		
		
	
	
			68 lines
		
	
	
	
		
			2 KiB
		
	
	
	
		
			Elixir
		
	
	
	
	
	
| defmodule Pleroma.Repo.Migrations.DataMigrationPopulateUserRelationships do
 | |
|   use Ecto.Migration
 | |
| 
 | |
|   alias Ecto.Adapters.SQL
 | |
|   alias Pleroma.Repo
 | |
| 
 | |
|   require Logger
 | |
| 
 | |
|   def up do
 | |
|     Enum.each(
 | |
|       [blocks: 1, mutes: 2, muted_reblogs: 3, muted_notifications: 4, subscribers: 5],
 | |
|       fn {field, relationship_type_code} ->
 | |
|         migrate(field, relationship_type_code)
 | |
| 
 | |
|         if field == :subscribers do
 | |
|           drop_if_exists(index(:users, [:subscribers]))
 | |
|         end
 | |
|       end
 | |
|     )
 | |
|   end
 | |
| 
 | |
|   def down, do: :noop
 | |
| 
 | |
|   defp migrate(field, relationship_type_code) do
 | |
|     Logger.info("Processing users.#{field}...")
 | |
| 
 | |
|     {:ok, %{rows: field_rows}} =
 | |
|       SQL.query(Repo, "SELECT id, #{field} FROM users WHERE #{field} != '{}'")
 | |
| 
 | |
|     target_ap_ids =
 | |
|       Enum.flat_map(
 | |
|         field_rows,
 | |
|         fn [_, ap_ids] -> ap_ids end
 | |
|       )
 | |
|       |> Enum.uniq()
 | |
| 
 | |
|     # Selecting ids of all targets at once in order to reduce the number of SELECT queries
 | |
|     {:ok, %{rows: target_ap_id_id}} =
 | |
|       SQL.query(Repo, "SELECT ap_id, id FROM users WHERE ap_id = ANY($1)", [target_ap_ids])
 | |
| 
 | |
|     target_id_by_ap_id = Enum.into(target_ap_id_id, %{}, fn [k, v] -> {k, v} end)
 | |
| 
 | |
|     Enum.each(
 | |
|       field_rows,
 | |
|       fn [source_id, target_ap_ids] ->
 | |
|         source_uuid = Ecto.UUID.cast!(source_id)
 | |
| 
 | |
|         for target_ap_id <- target_ap_ids do
 | |
|           target_id = target_id_by_ap_id[target_ap_id]
 | |
| 
 | |
|           with {:ok, target_uuid} <- target_id && Ecto.UUID.cast(target_id) do
 | |
|             execute("""
 | |
|             INSERT INTO user_relationships(
 | |
|               source_id, target_id, relationship_type, inserted_at
 | |
|             )
 | |
|             VALUES(
 | |
|               '#{source_uuid}'::uuid, '#{target_uuid}'::uuid, #{relationship_type_code}, now()
 | |
|             )
 | |
|             ON CONFLICT (source_id, relationship_type, target_id) DO NOTHING
 | |
|             """)
 | |
|           else
 | |
|             _ -> Logger.warn("Unresolved #{field} reference: (#{source_uuid}, #{target_id})")
 | |
|           end
 | |
|         end
 | |
|       end
 | |
|     )
 | |
|   end
 | |
| end
 | 
