Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vzVNk-00143I-0D for pgsql-hackers@arkaria.postgresql.org; Mon, 09 Mar 2026 07:50:28 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vzVNi-00EnmW-1l for pgsql-hackers@arkaria.postgresql.org; Mon, 09 Mar 2026 07:50:27 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vzVNi-00EnmN-0R for pgsql-hackers@lists.postgresql.org; Mon, 09 Mar 2026 07:50:26 +0000 Received: from mail-yw1-x1136.google.com ([2607:f8b0:4864:20::1136]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1vzVNg-00000001FcJ-2YXV for pgsql-hackers@postgresql.org; Mon, 09 Mar 2026 07:50:25 +0000 Received: by mail-yw1-x1136.google.com with SMTP id 00721157ae682-79860421382so107355297b3.0 for ; Mon, 09 Mar 2026 00:50:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1773042624; cv=none; d=google.com; s=arc-20240605; b=AMqhbnCKtldmbFsAd6GLHDgYWeQ/o3ViPvfc49nN42ohP9LRZ6idafPO3rI8dGXwpS 2EJJJCvOdN63seWmwA9+hOjASriPPpw5BN+OSsRXf+smSVH7HCWy4D4O/dko5W9eraxz OyCvZkH6iUGAHqN0I78f3HMDIrc5rW8pRMhlU1OLbD2z609pNbJwIh9ODPWUHbvslhRR cYvDttT98EsIY1BoOdcEZMAQuHN60gT6K216NNWtRe/2MJH8GUtk7VUOm/3i+kItYpPf mAW2qxohMAKnMwbHuuHuU3DpoEn7aEbA1ongQwTg55CUJeEg6HlTVgfEvfMifYYJbXjK b41A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=CGwhlE0yWcGAaJWDVO6ENPhVaiGitZxIedMsWAWxj7c=; fh=tqUUi4OQHPrELXZmtrPElQhPO5h2UDJFLcSGe/9x2+o=; b=Sg8qF50DQrY7OOrtk75oF1L/EkG62QVZDyYbro8XlYBEXjSZWFXX3TMG1JnEgQMdKF 23nsoM950moxHeswZKN8XS7oLGVpKF11Om0vJ9tq5Zoc8haptTgHGuM217NAeGo4n8Ka 5xSpoTmWhOOJIbeWw4x6VSvZHW7zhObpY7n6ktnuiAJaAd5JFDqHib7t7KyCITgK4LLj L1yEmLzjDucAaApdHX5ZNlI4rgNx4XZolz4otxzK/TP33ceZC6DwAXOUVNXlyLp0WmEH 9hMU0ZAaAZXRWVpGde4zx8EngEPfLhAFyqyqKsY23bpXoqu1+UdGTJT9wdsJOG6d5XpA 6ZiQ==; darn=postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773042624; x=1773647424; darn=postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=CGwhlE0yWcGAaJWDVO6ENPhVaiGitZxIedMsWAWxj7c=; b=Q2D77FOa8MnuruI/ftkH3wS64t5UwvyGlHW/t4p0HcQjQSl5SwVU+uINoyzENoKJ7k B45ST50g1BZJna7uOLIHK/3QKwaKG9B5PWe4FHCRzmL9iQ4RAanrgW/v+ocCO8Vzyo2Y vZ8YxkoHxsmJR7Nzkr3FvC7a6tfIf67xzGMy1N+QYBaPZcSK3dZIgU3lPTZpVRAlSkko 2suHlA8iI4zr/Ws9ELiyuhyZF0fCaEfAggRgNdu/9Ck64r/k1hsCM1SCiatFxxPqfPT8 5kIkpfB2DEM2FaAIibkgeMHYfmS3fP+uTM99FwejM68vfT5dGh6Du7adEvEuJ/ddwaC1 ZN7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773042624; x=1773647424; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=CGwhlE0yWcGAaJWDVO6ENPhVaiGitZxIedMsWAWxj7c=; b=EZ/FA9xCBn4gyhwyBd1XEJGu69BuDRtchlSPCyExdSezA6PTaLx00baYc02Na2KsxD gT+oTZ9L+ll+EDb8BcTOC4Yc3zygjssozWNk1AvitvoLi+u5/f9sQQhD+EXuLJKeVmL1 LNmCea79g1a8nlv5dMJwtyFcXxeT4jI7DwQiwhO1Mjun6TyG9hlc6WmTnj93PrUqzVjR 2gJyZV7fJ9sZSvZq4Tay5qNMv2eyBdaU2gAfl5WqU3N6LFrb2aE1npEbzXUsrV7jIEsb PQ8Z/8n1Sds3454DQtPPsH74SUNn8XXEy6PXBiPBJrdICTb+3D1X+fG8NL0F5saxlIGp 7gYw== X-Forwarded-Encrypted: i=1; AJvYcCXRNhr02fj5vwkzwR47h6eKYVJat6KLlUY7OxgxKtlcXNnJ9QKKgqS+ieqwZm7FCCqUXLN9uDMkPvMF1cTV@postgresql.org X-Gm-Message-State: AOJu0Yx/HFE++Z7UvuZjmuO3Mu16AFFaIQjq8j9tNrcEcaQIyt+nGdyw FW3y62JDWGVR37kr7pj/zt83sMfz4ZTRV9LUa2phUMivmS9LYBt2n7dQhguaiVZgAMW057lDKHS xNcTidc4COe7JxCu0kjYij+U+IEU6ueY= X-Gm-Gg: ATEYQzzaSC67fl13LAohN7kGFxULuhlcktd7cftH7EHxKQcgcQ2ecZ6BlGE1nCMOEIz cv3Vd23AKTn6LSvxrHPR7nKd1pxCZJ37hYS4Kgf9EGzAtWWFFP66GhNBY94CyfUgyBV7obB2cjB YE//O/xyLmOXbfe39VFFzKlyHShMv5N4picAUNrJxCio3Tq54rdz7a8dHabFkW/p0eASkZSH6XL g+SyIgunljPD3e4/8K75MUvO7/dJX4Ai0qzxBtFyT6TReS2bUUKmQXB0hZwvl0Eak2DP3ZiH3Io N1Pp+w== X-Received: by 2002:a05:690c:6d81:b0:799:1fb:9a7a with SMTP id 00721157ae682-79901fba578mr6449327b3.28.1773042624047; Mon, 09 Mar 2026 00:50:24 -0700 (PDT) MIME-Version: 1.0 References: <57388743-e380-4145-8b77-86ed23b062de@vondra.me> In-Reply-To: <57388743-e380-4145-8b77-86ed23b062de@vondra.me> From: Ayush Tiwari Date: Mon, 9 Mar 2026 13:20:13 +0530 X-Gm-Features: AaiRm53boPQuap_yJYK-LnE_-8BxEgnHvzmavbsI0OJEQi4G0IozOjWaF9klTUM Message-ID: Subject: Re: tid_blockno() and tid_offset() accessor functions To: Tomas Vondra Cc: Alexandre Felipe , pgsql-hackers@postgresql.org Content-Type: multipart/alternative; boundary="000000000000c72ecc064c92a76a" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --000000000000c72ecc064c92a76a Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hello, Thanks for the review! On the return types: I chose int8 for tid_block() deliberately because BlockNumber is uint32. If we used int4, block numbers >=3D 2^31 would silently appear as negative values, which seems worse than using the wider type. PostgreSQL already uses bigint to represent uint32 values in other catalog/system functions (e.g., pg_control_checkpoint). The wrapping test actually demonstrates exactly this =E2=80=94 (-1,0) correctly shows 4294967= 295 rather than -1. For tid_offset(), int4 is the natural safe mapping for uint16 (OffsetNumber). You're right that practical offsets are well below 2^13, but int4 costs nothing extra and is consistent. Happy to hear other opinions on the type choices though! Regards, Ayush On Mon, 9 Mar 2026 at 01:01, Tomas Vondra wrote: > On 3/8/26 18:17, Alexandre Felipe wrote: > > That was something I was surprised to learn, that we can check TID, do > > queries by TID intervals, but we can't get pages from TID, when I was > > trying to analyse how many pages on average a certain query would touch > > for different users. > > True. The conversion to "point" is the traditional way to do this, but > having functions to access the fields is cleared I think. > > > I think it would be nice to also support > > SELECT * FROM table WHERE tid_block(tid) BETWEEN b1 AND b2; > > > > Not sure. Functions are opaque for the scan, i.e. it can't treat it as a > scan key easily, because it could do anything. So this would require > teaching the TidScan that "tid_block" is a special case. > > I believe this should be doable through "support procedures", which can > be attached to pg_proc entries. So tid_block would have a "prosupport" > pointing at a function, implementing SupportRequestIndexCondition. Which > would translate the clause on tid_block() to a range condition on the > underlying tid. > > For inspiration see starts_with(), and text_starts_with_support support > procedure (or rather like_regex_support). > > However, that seems out of scope for this initial patch. > > > I wouldn't bother to support block number above 2^31 or block offsets > > above 2^15. > > > > This test shows that it assumes wrapping > > -- (-1,0) wraps to blockno 4294967295 > > SELECT tid_block('(-1,0)'::tid); > > tid_block > > ------------ > > 4294967295 > > > > You could just stick with that, I am sure that someone with a table > > having more than 2B pages on a table will understand that. > > for tid_offset I don't think it is even possible. If the maximum page > > size is limited to 2^15, must have a header and each offset has a line > > pointer aren't offsets limited to something smaller than 2^13? > > > > No opinion. For displaying the bogus TID value (like "(-1,0)") it's > probably OK to show values that are a bit weird. If anything, we should > be more careful on input, it's too late for tid_block() to decide what > to do with an "impossible" TID value. > > regards > > -- > Tomas Vondra > > --000000000000c72ecc064c92a76a Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hello,

Thanks for the review!

On the return = types: I chose int8 for tid_block() deliberately because BlockNumber is uin= t32. If we used int4, block numbers >=3D 2^31 would silently appear as n= egative values, which seems worse than using the wider type. PostgreSQL alr= eady uses bigint to represent uint32 values in other catalog/system functio= ns (e.g., pg_control_checkpoint). The wrapping test actually demonstrates e= xactly this =E2=80=94 (-1,0) correctly shows 4294967295 rather than -1.
=
For tid_offset(), int4 is the natural safe mapping for uint16 (OffsetNu= mber). You're right that practical offsets are well below 2^13, but int= 4 costs nothing extra and is consistent.

Happy to hear other opinion= s on the type choices though!

Regards,
Ayush

On Mon, 9 Mar 2026 at 01:01, Tomas Vondra <tomas@vondra.me> wrote:
On 3/8/26 18:17, Alexandre Felipe wrote:
> That was something I was surprised to learn, that we can check TID, do=
> queries by TID intervals, but we can't get pages from TID, when I = was
> trying to analyse how many pages on average a certain query would touc= h
> for different users.

True. The conversion to "point" is the traditional way to do this= , but
having functions to access the fields is cleared I think.

> I think it would be nice to also support=C2=A0
> SELECT * FROM table WHERE tid_block(tid) BETWEEN b1 AND b2;
>

Not sure. Functions are opaque for the scan, i.e. it can't treat it as = a
scan key easily, because it could do anything. So this would require
teaching the TidScan that "tid_block" is a special case.

I believe this should be doable through "support procedures", whi= ch can
be attached to pg_proc entries. So tid_block would have a "prosupport&= quot;
pointing at a function, implementing SupportRequestIndexCondition. Which would translate the clause on tid_block() to a range condition on the
underlying tid.

For inspiration see starts_with(), and text_starts_with_support support
procedure (or rather like_regex_support).

However, that seems out of scope for this initial patch.

> I wouldn't bother to support block number above 2^31 or block offs= ets
> above 2^15.
>
> This test shows that it assumes wrapping
> -- (-1,0) wraps to blockno 4294967295
> SELECT tid_block('(-1,0)'::tid);
> =C2=A0tid_block =C2=A0
> ------------
> =C2=A04294967295
>
> You could just stick with that, I am sure that someone with a table > having more than 2B pages on a table will understand that.
> for tid_offset I don't think it is even possible. If the maximum p= age
> size is limited to 2^15, must have a header and each offset has a line=
> pointer aren't offsets limited to something smaller than 2^13?
>

No opinion. For displaying the bogus TID value (like "(-1,0)") it= 's
probably OK to show values that are a bit weird. If anything, we should
be more careful on input, it's too late for tid_block() to decide what<= br> to do with an "impossible" TID value.

regards

--
Tomas Vondra

--000000000000c72ecc064c92a76a--