Skip to content

Commit d1162cf

Browse files
Add pg_column_toast_chunk_id().
This function returns the chunk_id of an on-disk TOASTed value. If the value is un-TOASTed or not on-disk, it returns NULL. This is useful for identifying which values are actually TOASTed and for investigating "unexpected chunk number" errors. Bumps catversion. Author: Yugo Nagata Reviewed-by: Jian He Discussion: https://postgr.es/m/20230329105507.d764497456eeac1ca491b5bd%40sraoss.co.jp
1 parent 84c18ac commit d1162cf

File tree

6 files changed

+90
-1
lines changed

6 files changed

+90
-1
lines changed

doc/src/sgml/func.sgml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28552,6 +28552,23 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset
2855228552
</para></entry>
2855328553
</row>
2855428554

28555+
<row>
28556+
<entry role="func_table_entry"><para role="func_signature">
28557+
<indexterm>
28558+
<primary>pg_column_toast_chunk_id</primary>
28559+
</indexterm>
28560+
<function>pg_column_toast_chunk_id</function> ( <type>"any"</type> )
28561+
<returnvalue>oid</returnvalue>
28562+
</para>
28563+
<para>
28564+
Shows the <structfield>chunk_id</structfield> of an on-disk
28565+
<acronym>TOAST</acronym>ed value. Returns <literal>NULL</literal>
28566+
if the value is un-<acronym>TOAST</acronym>ed or not on-disk. See
28567+
<xref linkend="storage-toast"/> for more information about
28568+
<acronym>TOAST</acronym>.
28569+
</para></entry>
28570+
</row>
28571+
2855528572
<row>
2855628573
<entry role="func_table_entry"><para role="func_signature">
2855728574
<indexterm>

src/backend/utils/adt/varlena.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5105,6 +5105,47 @@ pg_column_compression(PG_FUNCTION_ARGS)
51055105
PG_RETURN_TEXT_P(cstring_to_text(result));
51065106
}
51075107

5108+
/*
5109+
* Return the chunk_id of the on-disk TOASTed value. Return NULL if the value
5110+
* is un-TOASTed or not on-disk.
5111+
*/
5112+
Datum
5113+
pg_column_toast_chunk_id(PG_FUNCTION_ARGS)
5114+
{
5115+
int typlen;
5116+
struct varlena *attr;
5117+
struct varatt_external toast_pointer;
5118+
5119+
/* On first call, get the input type's typlen, and save at *fn_extra */
5120+
if (fcinfo->flinfo->fn_extra == NULL)
5121+
{
5122+
/* Lookup the datatype of the supplied argument */
5123+
Oid argtypeid = get_fn_expr_argtype(fcinfo->flinfo, 0);
5124+
5125+
typlen = get_typlen(argtypeid);
5126+
if (typlen == 0) /* should not happen */
5127+
elog(ERROR, "cache lookup failed for type %u", argtypeid);
5128+
5129+
fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
5130+
sizeof(int));
5131+
*((int *) fcinfo->flinfo->fn_extra) = typlen;
5132+
}
5133+
else
5134+
typlen = *((int *) fcinfo->flinfo->fn_extra);
5135+
5136+
if (typlen != -1)
5137+
PG_RETURN_NULL();
5138+
5139+
attr = (struct varlena *) DatumGetPointer(PG_GETARG_DATUM(0));
5140+
5141+
if (!VARATT_IS_EXTERNAL_ONDISK(attr))
5142+
PG_RETURN_NULL();
5143+
5144+
VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
5145+
5146+
PG_RETURN_OID(toast_pointer.va_valueid);
5147+
}
5148+
51085149
/*
51095150
* string_agg - Concatenates values and returns string.
51105151
*

src/include/catalog/catversion.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,6 @@
5757
*/
5858

5959
/* yyyymmddN */
60-
#define CATALOG_VERSION_NO 202403132
60+
#define CATALOG_VERSION_NO 202403141
6161

6262
#endif

src/include/catalog/pg_proc.dat

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7447,6 +7447,9 @@
74477447
{ oid => '2121', descr => 'compression method for the compressed datum',
74487448
proname => 'pg_column_compression', provolatile => 's', prorettype => 'text',
74497449
proargtypes => 'any', prosrc => 'pg_column_compression' },
7450+
{ oid => '8393', descr => 'chunk ID of on-disk TOASTed value',
7451+
proname => 'pg_column_toast_chunk_id', provolatile => 's', prorettype => 'oid',
7452+
proargtypes => 'any', prosrc => 'pg_column_toast_chunk_id' },
74507453
{ oid => '2322',
74517454
descr => 'total disk space usage for the specified tablespace',
74527455
proname => 'pg_tablespace_size', provolatile => 'v', prorettype => 'int8',

src/test/regress/expected/misc_functions.out

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,3 +703,19 @@ SELECT has_function_privilege('regress_current_logfile',
703703
(1 row)
704704

705705
DROP ROLE regress_current_logfile;
706+
-- pg_column_toast_chunk_id
707+
CREATE TABLE test_chunk_id (a TEXT, b TEXT STORAGE EXTERNAL);
708+
INSERT INTO test_chunk_id VALUES ('x', repeat('x', 8192));
709+
SELECT t.relname AS toastrel FROM pg_class c
710+
LEFT JOIN pg_class t ON c.reltoastrelid = t.oid
711+
WHERE c.relname = 'test_chunk_id'
712+
\gset
713+
SELECT pg_column_toast_chunk_id(a) IS NULL,
714+
pg_column_toast_chunk_id(b) IN (SELECT chunk_id FROM pg_toast.:toastrel)
715+
FROM test_chunk_id;
716+
?column? | ?column?
717+
----------+----------
718+
t | t
719+
(1 row)
720+
721+
DROP TABLE test_chunk_id;

src/test/regress/sql/misc_functions.sql

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,3 +265,15 @@ GRANT pg_monitor TO regress_current_logfile;
265265
SELECT has_function_privilege('regress_current_logfile',
266266
'pg_current_logfile()', 'EXECUTE');
267267
DROP ROLE regress_current_logfile;
268+
269+
-- pg_column_toast_chunk_id
270+
CREATE TABLE test_chunk_id (a TEXT, b TEXT STORAGE EXTERNAL);
271+
INSERT INTO test_chunk_id VALUES ('x', repeat('x', 8192));
272+
SELECT t.relname AS toastrel FROM pg_class c
273+
LEFT JOIN pg_class t ON c.reltoastrelid = t.oid
274+
WHERE c.relname = 'test_chunk_id'
275+
\gset
276+
SELECT pg_column_toast_chunk_id(a) IS NULL,
277+
pg_column_toast_chunk_id(b) IN (SELECT chunk_id FROM pg_toast.:toastrel)
278+
FROM test_chunk_id;
279+
DROP TABLE test_chunk_id;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy