Re: Use pg_current_xact_id() instead of deprecated txid_current()

From: Shinya Kato <shinya11(dot)kato(at)gmail(dot)com>
To: lin teletele <teletele(dot)lin(at)gmail(dot)com>
Cc: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, Álvaro Herrera <alvherre(at)kurilemu(dot)de>, pgsql-hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Use pg_current_xact_id() instead of deprecated txid_current()
Date: 2026-05-31 04:51:10
Message-ID: CAOzEurT0--=ZzOJMX1dKH9pj4ozeR_k6jgA0nZAWpnOmnY2XLA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Thu, May 28, 2026 at 2:08 AM lin teletele <teletele(dot)lin(at)gmail(dot)com> wrote:
>
> Hi Shinya,
>
> Thanks for the patches. I read v4-0001 and have a few small observations
> from going through the arithmetic functions. I tested the suggestions
> below locally on top of v4 — they pass the existing xid regression tests
> and produce identical output on the boundary cases listed in section 3.

Thanks for the review!

> 1. xid8pl / xid8mi could reuse the helpers in common/int.h
> ----------------------------------------------------
> xid8pl currently rolls its own overflow detection on a mixed-sign
> addition:
>
> result = val + (uint64) delta;
> if ((delta > 0 && result < val) || (delta < 0 && result > val))
> ereport(ERROR, ...);
>
> This is correct, but it's the only place in the tree that takes this
> approach, and the (uint64)-of-a-signed-value plus sign-aware compare
> takes a moment to convince oneself of. common/int.h already provides
> pg_add_u64_overflow / pg_sub_u64_overflow, plus pg_abs_s64 which returns
> uint64 and explicitly handles INT64_MIN, so xid8pl could be written as:
>
> uint64 abs_delta = pg_abs_s64(delta);
> bool overflow;
>
> if (delta >= 0)
> overflow = pg_add_u64_overflow(val, abs_delta, &result);
> else
> overflow = pg_sub_u64_overflow(val, abs_delta, &result);
>
> if (overflow)
> ereport(ERROR, ...);
>
> And xid8mi symmetrically (add/sub swapped):
>
> uint64 abs_delta = pg_abs_s64(delta);
> bool overflow;
>
> if (delta >= 0)
> overflow = pg_sub_u64_overflow(val, abs_delta, &result);
> else
> overflow = pg_add_u64_overflow(val, abs_delta, &result);
>
> if (overflow)
> ereport(ERROR, ...);
>
> This keeps the code inside the standard PG overflow-check idiom, and as
> a side effect handles a delta of INT64_MIN cleanly (pg_abs_s64 returns
> 2^63 in that case without invoking UB).

Agreed. v5 rewrites xid8pl and xid8mi along the lines you suggested.

> 2. INT64_MIN boundary in xid8_mi_xid8
> ----------------------------------------------------
> In the val1 < val2 branch:
>
> if (val2 - val1 > (uint64) PG_INT64_MAX + 1)
> ereport(ERROR, ...);
> PG_RETURN_INT64(-((int64) (val2 - val1)));
>
> The bound permits val2 - val1 == 2^63 (e.g. '0'::xid8 -
> '9223372036854775808'::xid8). When val2 - val1 == 2^63, the cast
> (int64)(val2 - val1) is implementation-defined (the value doesn't fit in
> int64), and -INT64_MIN is signed overflow (UB). In practice on
> two's-complement targets the answer comes out as INT64_MIN, which is the
> correct value, but it relies on UB.
>
> Pulling out the boundary explicitly keeps the same observable behavior
> without the UB:
>
> uint64 diff = val2 - val1;
>
> if (diff > (uint64) PG_INT64_MAX + 1)
> ereport(ERROR, ...);
> /* diff == 2^63 maps to INT64_MIN */
> if (diff > (uint64) PG_INT64_MAX)
> PG_RETURN_INT64(PG_INT64_MIN);
> PG_RETURN_INT64(-(int64) diff);

Fixed.

> 3. Test coverage
> ----------------------------------------------------
> The regression tests in xid.sql exercise the positive overflow side
> nicely but miss a few boundaries on the negative side:
>
> -- xid8 - xid8 at the INT64_MIN boundary (#2 above)
> select '0'::xid8 - '9223372036854775808'::xid8;
>
> -- xid8 + int8 / xid8 - int8 with INT64_MAX / INT64_MIN deltas
> select '0'::xid8 + 9223372036854775807::bigint;
> select '0'::xid8 - (-9223372036854775807 - 1)::bigint;
> select '9223372036854775807'::xid8 - (-9223372036854775807 - 1)::bigint;
>
> It would be good to pin those down in the expected output.

Added in v5. I also threw in '0'::xid8 - '9223372036854775809'::xid8.

> 4. Documentation
> ----------------------------------------------------
> v4-0001 adds four user-visible operators but doesn't touch doc/src/sgml/.
> pg_lsn's arithmetic operators are documented in datatype.sgml around the
> "pg_lsn Type" section -- it would be nice for the new xid8 operators to
> get analogous coverage in the nearby xid8 paragraph.

Done in v5. A paragraph modeled on the pg_lsn one is now placed
immediately after the existing xid8 paragraph in datatype.sgml.

> As a separate observation (probably better as a follow-up thread rather
> than expanding the scope of this one): xid8 currently has only hash and
> btree opclasses, no BRIN. Since xid8 is strictly monotonic and never
> wraps, BRIN minmax looks like a natural fit -- I'll raise that
> separately if there's interest.

Agreed it's a natural fit, and it deserves its own thread rather than
expanding this one.

0001 carries all of the changes above. 0002 is unchanged from v4 apart
from the rebase.

--
Best regards,
Shinya Kato
NTT OSS Center

Attachment Content-Type Size
v5-0001-Add-arithmetic-operators-for-xid8.patch application/octet-stream 10.8 KB
v5-0002-Use-pg_current_xact_id-instead-of-deprecated-txid.patch application/octet-stream 13.3 KB

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Dilip Kumar 2026-05-31 06:02:51 Re: Proposal: Conflict log history table for Logical Replication
Previous Message Ewan Young 2026-05-31 04:36:45 autovacuum launcher crash: assert in pgstat_count_io_op (IOOP_EXTEND on pg_database's VM)