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)