On Fri, 7 Jul 2023 17:21:36 +0900 Yugo NAGATA <nag...@sraoss.co.jp> wrote:
> Hi Nikita, > > On Wed, 5 Jul 2023 17:49:20 +0300 > Nikita Malakhov <huku...@gmail.com> wrote: > > > Hi! > > > > I like the idea of having a standard function which shows a TOAST value ID > > for a row. I've used my own to handle TOAST errors. Just, maybe, more > > correct > > name would be "...value_id", because you actually retrieve valueid field > > from the TOAST pointer, and chunk ID consists of valueid + chunk_seq. > > Thank you for your review! > > Although, the retrieved field is "va_valueid" and it is called "value ID" in > the > code, I chose the name "..._chunk_id" because I found the description in the > documentation as followings: > > ------------- > Every TOAST table has the columns chunk_id (an OID identifying the particular > TOASTed value), chunk_seq (a sequence number for the chunk within its value), > and chunk_data (the actual data of the chunk). A unique index on chunk_id and > chunk_seq provides fast retrieval of the values. A pointer datum representing > an out-of-line on-disk TOASTed value therefore needs to store the OID of the > TOAST table in which to look and the OID of the specific value (its chunk_id) > ------------- > https://www.postgresql.org/docs/devel/storage-toast.html > > Here, chunk_id defined separately from chunk_seq. Therefore, I wonder > pg_column_toast_chunk_id would be ok. However, I don't insist on this > and I would be happy to change it if the other name is more natural for users. I attached v2 patch that contains the documentation fix. Regards, Yugo Nagata > > Regards, > Yugo Nagata > > > > > -- > > Regards, > > Nikita Malakhov > > Postgres Professional > > The Russian Postgres Company > > https://postgrespro.ru/ > > > -- > Yugo NAGATA <nag...@sraoss.co.jp> > > -- Yugo NAGATA <nag...@sraoss.co.jp>
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 5a47ce4343..c2c3156cd4 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -27608,6 +27608,20 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset </para></entry> </row> + <row> + <entry role="func_table_entry"><para role="func_signature"> + <indexterm> + <primary>pg_column_toast_chunk_id</primary> + </indexterm> + <function>pg_column_toast_chunk_id</function> ( <type>"any"</type> ) + <returnvalue>oid</returnvalue> + </para> + <para> + Returns the chunk id of the TOASTed value, or <literal>NULL</literal> + if the value is not TOASTed. + </para></entry> + </row> + <row> <entry role="func_table_entry"><para role="func_signature"> <indexterm> diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index 884bfbc8ce..fe8788c1b1 100644 --- a/src/backend/utils/adt/varlena.c +++ b/src/backend/utils/adt/varlena.c @@ -5069,6 +5069,47 @@ pg_column_compression(PG_FUNCTION_ARGS) PG_RETURN_TEXT_P(cstring_to_text(result)); } +/* + * Return the chunk id of the TOASTed value. + * Return NULL for unTOASTed value. + */ +Datum +pg_column_toast_chunk_id(PG_FUNCTION_ARGS) +{ + int typlen; + struct varlena *attr; + struct varatt_external toast_pointer; + + /* On first call, get the input type's typlen, and save at *fn_extra */ + if (fcinfo->flinfo->fn_extra == NULL) + { + /* Lookup the datatype of the supplied argument */ + Oid argtypeid = get_fn_expr_argtype(fcinfo->flinfo, 0); + + typlen = get_typlen(argtypeid); + if (typlen == 0) /* should not happen */ + elog(ERROR, "cache lookup failed for type %u", argtypeid); + + fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, + sizeof(int)); + *((int *) fcinfo->flinfo->fn_extra) = typlen; + } + else + typlen = *((int *) fcinfo->flinfo->fn_extra); + + if (typlen != -1) + PG_RETURN_NULL(); + + attr = (struct varlena *) DatumGetPointer(PG_GETARG_DATUM(0)); + + if (!VARATT_IS_EXTERNAL_ONDISK(attr)) + PG_RETURN_NULL(); + + VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr); + + PG_RETURN_OID(toast_pointer.va_valueid); +} + /* * string_agg - Concatenates values and returns string. * diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 6996073989..0cacd0391d 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -7403,6 +7403,9 @@ { oid => '2121', descr => 'compression method for the compressed datum', proname => 'pg_column_compression', provolatile => 's', prorettype => 'text', proargtypes => 'any', prosrc => 'pg_column_compression' }, +{ oid => '8393', descr => 'chunk ID of TOASTed value', + proname => 'pg_column_toast_chunk_id', provolatile => 's', prorettype => 'oid', + proargtypes => 'any', prosrc => 'pg_column_toast_chunk_id' }, { oid => '2322', descr => 'total disk space usage for the specified tablespace', proname => 'pg_tablespace_size', provolatile => 'v', prorettype => 'int8',