Packages
electric
1.0.0-beta.14
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.10
1.6.9
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.5.1
1.5.0
1.4.16
1.4.16-beta-1
1.4.15
1.4.14
1.4.13
1.4.12
1.4.11
1.4.10
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.4
1.3.3
1.3.2
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.1.14
1.1.13
1.1.12
1.1.11
1.1.10
1.1.9
1.1.8
1.1.7
1.1.6
retired
1.1.5
retired
1.1.4
retired
1.1.3
retired
1.1.2
1.1.1
1.1.0
1.0.24
1.0.23
1.0.22
1.0.21
1.0.20
1.0.19
1.0.18
1.0.17
1.0.15
1.0.13
1.0.12
1.0.11
1.0.10
1.0.9
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
1.0.0-beta.23
1.0.0-beta.22
1.0.0-beta.20
1.0.0-beta.19
1.0.0-beta.18
1.0.0-beta.17
1.0.0-beta.16
1.0.0-beta.15
1.0.0-beta.14
1.0.0-beta.13
1.0.0-beta.12
1.0.0-beta.11
1.0.0-beta.10
1.0.0-beta.9
1.0.0-beta.8
1.0.0-beta.7
1.0.0-beta.6
1.0.0-beta.5
1.0.0-beta.4
1.0.0-beta.3
1.0.0-beta.2
1.0.0-beta.1
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.1
0.8.0
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.3
0.6.2
0.6.1
0.5.2
0.4.4
Postgres sync engine. Sync little subsets of your Postgres data into local apps and services.
Current section
Files
Jump to
Current section
Files
lib/electric/postgres/xid.ex
defmodule Electric.Postgres.Xid do
import Bitwise
@int32_max 0xFFFFFFFF
@int32_half_max 0x7FFFFFFF
@type anyxid :: pos_integer
@type cmp_result :: :lt | :eq | :gt
defguardp int32?(int) when abs(int) <= @int32_max
# This is a specialized guard for that specifically determines whether the 32-bit first
# argument is less than the xid8 argument. For the general principle this is based on, look
# at the implementation of `compare/2` below.
defguard xid_lt_xid8(xid, xid8)
when int32?(xid) and
((xid - band(xid8, @int32_max) <= @int32_half_max and
xid < band(xid8, @int32_max)) or
(xid - band(xid8, @int32_max) > @int32_half_max and
xid > band(xid8, @int32_max)))
@spec compare(anyxid, anyxid) :: cmp_result
def compare(xid, xid), do: :eq
# When both arguments are 32-bit integers or both have values that don't fit in 32 bits, use the
# direct comparison.
def compare(xid_l, xid_r)
when (int32?(xid_l) and int32?(xid_r)) or not (int32?(xid_l) or int32?(xid_r)),
do: direct_cmp(xid_l, xid_r)
# When one of the arguments is 32-bit and the other one has a value that doesn't fit in 32 bits,
# perform the comparison on masked values.
#
# In Postgres, any xid has ~2 billion values preceding it and ~2 billion values following it.
# Regular autovacuuming maintains this invariant. So when we see a difference between two
# xids that is larger than 2^31, it means the 32-bit argument is a wrapped value, so it
# must be the most recent one.
def compare(xid8, xid) when int32?(xid) do
compare(xid, xid8)
|> reverse_cmp_result()
end
def compare(xid, xid8) when int32?(xid) do
xid8_masked = band(xid8, @int32_max)
diff = xid - xid8_masked
wrapped? = diff > @int32_half_max
diff_to_cmp_result(wrapped?, diff)
end
@spec diff_to_cmp_result(wrapped? :: boolean, diff :: integer) :: cmp_result
defp diff_to_cmp_result(false, diff) when diff > 0, do: :gt
defp diff_to_cmp_result(false, diff) when diff < 0, do: :lt
defp diff_to_cmp_result(true, diff) when diff > 0, do: :lt
defp diff_to_cmp_result(true, diff) when diff < 0, do: :gt
###
defp direct_cmp(xid_l, xid_r) when xid_l < xid_r, do: :lt
defp direct_cmp(xid_l, xid_r) when xid_l > xid_r, do: :gt
defp reverse_cmp_result(:lt), do: :gt
defp reverse_cmp_result(:gt), do: :lt
end