From e4aa6ff5a7d4e08fe0b81d38fe23748e5636cd4b Mon Sep 17 00:00:00 2001 From: Luke Imhoff Date: Wed, 24 Oct 2018 13:04:50 -0500 Subject: [PATCH] Don't replace_all fields of token_transfers on_conflict MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace all field except the primary key and timestamps.  For the primary key fields (transaction_hash, log_index), leave them as is as they are the conflict target and have not changed by definition.  For the timestamps that the least inserted_at and the greatest updated_at to preserve the bounds of the timeline. This is a port of the change made to internal_transactions. --- .../explorer/chain/import/token_transfers.ex | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/apps/explorer/lib/explorer/chain/import/token_transfers.ex b/apps/explorer/lib/explorer/chain/import/token_transfers.ex index 860fd10c78..bbc2129e5f 100644 --- a/apps/explorer/lib/explorer/chain/import/token_transfers.ex +++ b/apps/explorer/lib/explorer/chain/import/token_transfers.ex @@ -5,6 +5,8 @@ defmodule Explorer.Chain.Import.TokenTransfers do require Ecto.Query + import Ecto.Query, only: [from: 2] + alias Ecto.{Changeset, Multi} alias Explorer.Chain.{Import, TokenTransfer} @@ -46,7 +48,7 @@ defmodule Explorer.Chain.Import.TokenTransfers do {:ok, [TokenTransfer.t()]} | {:error, [Changeset.t()]} def insert(changes_list, %{timeout: timeout, timestamps: timestamps} = options) when is_list(changes_list) do - on_conflict = Map.get(options, :on_conflict, :replace_all) + on_conflict = Map.get_lazy(options, :on_conflict, &default_on_conflict/0) # order so that row ShareLocks are grabbed in a consistent order ordered_changes_list = Enum.sort_by(changes_list, &{&1.transaction_hash, &1.log_index}) @@ -62,4 +64,23 @@ defmodule Explorer.Chain.Import.TokenTransfers do timestamps: timestamps ) end + + defp default_on_conflict do + from( + token_transfer in TokenTransfer, + update: [ + set: [ + # Don't update `transaction_hash` as it is part of the composite primary key and used for the conflict target + # Don't update `log_index` as it is part of the composite primary key and used for the conflict target + amount: fragment("EXCLUDED.amount"), + from_address_hash: fragment("EXCLUDED.from_address_hash"), + to_address_hash: fragment("EXCLUDED.to_address_hash"), + token_contract_address_hash: fragment("EXCLUDED.token_contract_address_hash"), + token_id: fragment("EXCLUDED.token_id"), + inserted_at: fragment("LEAST(?, EXCLUDED.inserted_at)", token_transfer.inserted_at), + updated_at: fragment("GREATEST(?, EXCLUDED.updated_at)", token_transfer.updated_at) + ] + ] + ) + end end