Don't replace_all fields of token_transfers on_conflict

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.
pull/985/head
Luke Imhoff 6 years ago
parent 7f7cdf753d
commit e4aa6ff5a7
  1. 23
      apps/explorer/lib/explorer/chain/import/token_transfers.ex

@ -5,6 +5,8 @@ defmodule Explorer.Chain.Import.TokenTransfers do
require Ecto.Query require Ecto.Query
import Ecto.Query, only: [from: 2]
alias Ecto.{Changeset, Multi} alias Ecto.{Changeset, Multi}
alias Explorer.Chain.{Import, TokenTransfer} alias Explorer.Chain.{Import, TokenTransfer}
@ -46,7 +48,7 @@ defmodule Explorer.Chain.Import.TokenTransfers do
{:ok, [TokenTransfer.t()]} {:ok, [TokenTransfer.t()]}
| {:error, [Changeset.t()]} | {:error, [Changeset.t()]}
def insert(changes_list, %{timeout: timeout, timestamps: timestamps} = options) when is_list(changes_list) do 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 # 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}) 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 timestamps: timestamps
) )
end 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 end

Loading…
Cancel
Save