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.94.2) (envelope-from ) id 1rkExh-00BP9q-8l for pgsql-hackers@arkaria.postgresql.org; Wed, 13 Mar 2024 03:07:25 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1rkExf-008be8-3q for pgsql-hackers@arkaria.postgresql.org; Wed, 13 Mar 2024 03:07:23 +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.94.2) (envelope-from ) id 1rkExe-008bZm-Lr for pgsql-hackers@lists.postgresql.org; Wed, 13 Mar 2024 03:07:23 +0000 Received: from mail-il1-x12e.google.com ([2607:f8b0:4864:20::12e]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1rkExa-004DkX-TX for pgsql-hackers@postgresql.org; Wed, 13 Mar 2024 03:07:21 +0000 Received: by mail-il1-x12e.google.com with SMTP id e9e14a558f8ab-3663c6fba33so31188645ab.1 for ; Tue, 12 Mar 2024 20:07:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1710299239; x=1710904039; darn=postgresql.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=75Y+XG/eXKuya+tnbQIBE6sVH9XbSRakepiagcDo26w=; b=J3KeVQNJxzpC3weaw17DSY172nhA5wGfm+OdHVCTRpFkQJY8y54SV1k0JzyR/tBTRD twaRcJqgDw37c/D0FWPsX2ljZAFNkaph09UTbjuObAHguXfn0Rf2WAnENC0G5BQQBA59 tzfoN2mCBw9OZXdhkWzPm+bpip6YgJXVzE/4BSYL6/7x2NX9BKoUguGGrlph3I+Gv1dQ sU2vIM3GRuZcBpCz4LO824VZAmazk97idV5Sg7XZYuurzUJGDvYc7RI8cLxAZS2TT+Jz RVqB+9EayUl/PzS0HCBrpoeBc1YCQP2sjBCDT/Q+KmEm5wHmIXRvjdc9ixZzOTcc9gFJ zIJA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710299239; x=1710904039; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=75Y+XG/eXKuya+tnbQIBE6sVH9XbSRakepiagcDo26w=; b=oGisLqwuSknbtVPhUuvhuhLmEl3DhnrfwgQWsD7FPQ3GcAjlH059L9n0EWTQzzcLzm HgTwm44/jsU2KYSS/EJy47O0r+Ve0c8Iyfxd6GmaFQmUL3/tkN7dlAIZqMjVhx+3fdXT XFvInNClJcW5CIIlWhMOvjcb/fO/m+ntm5Qmp65Cl2IdnN2HTEShsUhGcRR7IIhj3ggU RfJPnNhdVhuKDefV2KUxqfDaIN5AMoS7HdJaqHjtpzudLoPlzOIiiYEmPZwMxHIHrRmz P9iHidJtPyrQtmQWsfh/nC3kXVRw5a+IlF/wQK33KKaGRl7jewFfLpGS9avQLC3zwmra XkYg== X-Forwarded-Encrypted: i=1; AJvYcCVdOFsWqNIuFl5gkkXjSbYhMlbWVNMsaJUmpqRCtxS/g9ZReRDXl4mF3Tg/y8oDzXGLGnfpMG2V6cK6nNbykOyRSj8PdD3s/ILFWXbQ X-Gm-Message-State: AOJu0Yxbu8osGt+tcNBCkfWSS3ZR7LwpsC7p23mqUfG0k8jv4H6cIus4 Q+xBnnX3PqFoP4h7bg4m/YtZ2G4HYctEkXgJRoXhZvQ4E1OElURi X-Google-Smtp-Source: AGHT+IFt04A9jvgn77/W6xOsgRp6DCCYTQ4BStOhUxcKKsBqICPtofN5HxmfjrA6Sc/skHzCpxukUw== X-Received: by 2002:a05:6e02:184f:b0:366:3662:4c09 with SMTP id b15-20020a056e02184f00b0036636624c09mr14999645ilv.3.1710299239272; Tue, 12 Mar 2024 20:07:19 -0700 (PDT) Received: from nathanxps13 (162-195-168-172.lightspeed.stlsmo.sbcglobal.net. [162.195.168.172]) by smtp.gmail.com with ESMTPSA id h5-20020a92c085000000b003639d3e5afdsm2671902ile.10.2024.03.12.20.07.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Mar 2024 20:07:18 -0700 (PDT) Date: Tue, 12 Mar 2024 22:07:17 -0500 From: Nathan Bossart To: Yugo NAGATA Cc: jian he , Sergei Kornilov , Nikita Malakhov , pgsql-hackers@postgresql.org Subject: Re: pg_column_toast_chunk_id: a function to get a chunk ID of a TOASTed value Message-ID: <20240313030717.GA2507890@nathanxps13> References: <20240201134524.d647b3d185e5252162eb0436@sraoss.co.jp> <20240205162823.6c705517ca6898e482b69b9e@sraoss.co.jp> <20240307225617.GA615950@nathanxps13> <20240308153155.4c4b2fee3ed1431203e41016@sraoss.co.jp> <20240308221758.GB1060542@nathanxps13> <20240309115718.deb9209b7f53883cc8e1b4b3@sraoss.co.jp> <20240309145028.GB1111406@nathanxps13> <20240312155119.9341cfd76f2732ac93ecb6a4@sraoss.co.jp> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="IJpNTDwzlM2Ie8A6" Content-Disposition: inline In-Reply-To: <20240312155119.9341cfd76f2732ac93ecb6a4@sraoss.co.jp> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --IJpNTDwzlM2Ie8A6 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline I did some light editing to prepare this for commit. -- Nathan Bossart Amazon Web Services: https://aws.amazon.com --IJpNTDwzlM2Ie8A6 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v10-0001-Add-pg_column_toast_chunk_id.patch" From 38c78bd92a7b4d4600e6f0dbe58283c21ea87d50 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Tue, 12 Mar 2024 22:04:25 -0500 Subject: [PATCH v10 1/1] Add pg_column_toast_chunk_id(). This function returns the chunk_id of an on-disk TOASTed value, or NULL if the value is un-TOASTed or not on-disk. This is useful for identifying which values are actually TOASTed and for investigating "unexpected chunk number" errors. XXX: REQUIRES CATVERSION BUMP Author: Yugo Nagata Reviewed-by: Jian He Discussion: https://postgr.es/m/20230329105507.d764497456eeac1ca491b5bd%40sraoss.co.jp --- doc/src/sgml/func.sgml | 17 ++++++++ src/backend/utils/adt/varlena.c | 41 ++++++++++++++++++++ src/include/catalog/pg_proc.dat | 3 ++ src/test/regress/expected/misc_functions.out | 16 ++++++++ src/test/regress/sql/misc_functions.sql | 12 ++++++ 5 files changed, 89 insertions(+) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 0bb7aeb40e..fe9c1a38b9 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -28552,6 +28552,23 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset + + + + pg_column_toast_chunk_id + + pg_column_toast_chunk_id ( "any" ) + oid + + + Shows the chunk_id of an on-disk + TOASTed value. Returns NULL + if the value is un-TOASTed or not on-disk. See + for more information about + TOAST. + + + diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index 543afb66e5..8d28dd42ce 100644 --- a/src/backend/utils/adt/varlena.c +++ b/src/backend/utils/adt/varlena.c @@ -5105,6 +5105,47 @@ pg_column_compression(PG_FUNCTION_ARGS) PG_RETURN_TEXT_P(cstring_to_text(result)); } +/* + * Return the chunk_id of the on-disk TOASTed value. Return NULL if the value + * is un-TOASTed or not on-disk. + */ +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 291ed876fc..443ca854a6 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -7447,6 +7447,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 on-disk 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', diff --git a/src/test/regress/expected/misc_functions.out b/src/test/regress/expected/misc_functions.out index d5f61dfad9..e0ba9fdafa 100644 --- a/src/test/regress/expected/misc_functions.out +++ b/src/test/regress/expected/misc_functions.out @@ -703,3 +703,19 @@ SELECT has_function_privilege('regress_current_logfile', (1 row) DROP ROLE regress_current_logfile; +-- pg_column_toast_chunk_id +CREATE TABLE test_chunk_id (a TEXT, b TEXT STORAGE EXTERNAL); +INSERT INTO test_chunk_id VALUES ('x', repeat('x', 8192)); +SELECT t.relname AS toastrel FROM pg_class c + LEFT JOIN pg_class t ON c.reltoastrelid = t.oid + WHERE c.relname = 'test_chunk_id' +\gset +SELECT pg_column_toast_chunk_id(a) IS NULL, + pg_column_toast_chunk_id(b) IN (SELECT chunk_id FROM pg_toast.:toastrel) + FROM test_chunk_id; + ?column? | ?column? +----------+---------- + t | t +(1 row) + +DROP TABLE test_chunk_id; diff --git a/src/test/regress/sql/misc_functions.sql b/src/test/regress/sql/misc_functions.sql index 928b04db7f..ff5ed5edde 100644 --- a/src/test/regress/sql/misc_functions.sql +++ b/src/test/regress/sql/misc_functions.sql @@ -265,3 +265,15 @@ GRANT pg_monitor TO regress_current_logfile; SELECT has_function_privilege('regress_current_logfile', 'pg_current_logfile()', 'EXECUTE'); DROP ROLE regress_current_logfile; + +-- pg_column_toast_chunk_id +CREATE TABLE test_chunk_id (a TEXT, b TEXT STORAGE EXTERNAL); +INSERT INTO test_chunk_id VALUES ('x', repeat('x', 8192)); +SELECT t.relname AS toastrel FROM pg_class c + LEFT JOIN pg_class t ON c.reltoastrelid = t.oid + WHERE c.relname = 'test_chunk_id' +\gset +SELECT pg_column_toast_chunk_id(a) IS NULL, + pg_column_toast_chunk_id(b) IN (SELECT chunk_id FROM pg_toast.:toastrel) + FROM test_chunk_id; +DROP TABLE test_chunk_id; -- 2.25.1 --IJpNTDwzlM2Ie8A6--