View Source Electric.Postgres.Xid (electric v1.0.1)
Summary
Functions
In Postgres, any 32-bit xid has ~2 billion values preceding it and ~2 billion values following it. Regular autovacuuming maintains this invariant. When we see a difference between two xids that is larger than 2^31, we know there's been at least one transaction ID wraparound. Given the invariant mentioned earlier, we assume there's been only one wraparound and so the xid whose value is larger precedes the other one (or, equivalently, the smaller xid belongs to a more recent transaction).
Types
@type anyxid() :: pos_integer()
@type cmp_result() :: :lt | :eq | :gt
Functions
@spec compare(anyxid(), anyxid()) :: cmp_result()
In Postgres, any 32-bit xid has ~2 billion values preceding it and ~2 billion values following it. Regular autovacuuming maintains this invariant. When we see a difference between two xids that is larger than 2^31, we know there's been at least one transaction ID wraparound. Given the invariant mentioned earlier, we assume there's been only one wraparound and so the xid whose value is larger precedes the other one (or, equivalently, the smaller xid belongs to a more recent transaction).
For 64-bit xids (Postgres type xid8
), the regular integer comparison is used because those
xids include the epoch number that tracks the number of xid wraparounds that have happened.
If any one or both arguments are 32-bit xids, the comparison is performed modulo-2^32, the same way it's done in Postgres: https://github.com/postgres/postgres/blob/302cf15759233e654512979286ce1a5c3b36625f/src/backend/access/transam/transam.c#L276-L293
Tests
iex> compare(3, 3) :eq
iex> compare(2, 1) :gt
iex> compare(2, 2) :eq
iex> compare(2, 3) :lt
iex> compare(4294967295, 4294967295) :eq
iex> compare(1, 2147483648) :lt
iex> compare(1, 2147483649) :lt
iex> compare(1, 2147483650) :gt
iex> compare(1, 4294967295) :gt
iex> compare(4294967295, 1) :lt
iex> compare(2147483648, 1) :gt
iex> compare(2147483649, 1) :lt
iex> compare(2147483648, 4294967295) :lt
iex> compare(2147483647, 4294967295) :lt
iex> compare(2147483646, 4294967295) :gt
Any of the two arguments can be 64-bit, the order doesn't matter:
iex> compare(1, 70866960384) :lt
iex> compare(1, 70866960385) :lt
iex> compare(1, 70866960386) :gt
iex> compare(70866960384, 1) :gt
iex> compare(70866960385, 1) :lt
When both numbers are 64-bit, regular comparison rules apply:
iex> compare(70866960386, 70866960385) :gt
iex> compare(70866960384, 73014444034) :lt