Hi, When detoasting an expanded datum in detoast_attr, we already know it is an expanded datum, but we use deotast_external_attr function which checks VARATT_IS_EXTERNAL_ONDISK & VARATT_IS_EXTERNAL_INDIRECT again which I think it is impossible to true in this case. so I think we should use a more specific code to handle this, see the attached patch.
We already have lots of kind of toast type and some of checks have overlap, this cleanup should make people less confused when reading this code. make check-world passed after applying this patch. Any thought? -- Best Regards Andy Fan
>From 91982d5b55e9f04cb17dd527659d7ecea82436a1 Mon Sep 17 00:00:00 2001 From: Andy Fan <zhihuifan1...@163.com> Date: Tue, 29 Oct 2024 14:05:05 +0800 Subject: [PATCH v1 1/1] Using more specific code when detoasting an expanded datum. In the detoast_attr function, VARATT_IS_EXTERNAL_ONDISK and VARATT_IS_EXTERNAL_INDIRECT are checked first, and then VARATT_IS_EXTERNAL_EXPANDED is checked, However when it's true, detoast_external_attr is called which checks the two cases again. The attached patch uses a more specific code to handle this. --- src/backend/access/common/detoast.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/backend/access/common/detoast.c b/src/backend/access/common/detoast.c index 3547cdba56..af25f589fe 100644 --- a/src/backend/access/common/detoast.c +++ b/src/backend/access/common/detoast.c @@ -89,6 +89,7 @@ detoast_external_attr(struct varlena *attr) resultsize = EOH_get_flat_size(eoh); result = (struct varlena *) palloc(resultsize); EOH_flatten_into(eoh, (void *) result, resultsize); + Assert(!VARATT_IS_EXTENDED(result)); } else { @@ -161,9 +162,15 @@ detoast_attr(struct varlena *attr) /* * This is an expanded-object pointer --- get flat format */ - attr = detoast_external_attr(attr); - /* flatteners are not allowed to produce compressed/short output */ - Assert(!VARATT_IS_EXTENDED(attr)); + ExpandedObjectHeader *eoh; + Size resultsize; + struct varlena *result; + + eoh = DatumGetEOHP(PointerGetDatum(attr)); + resultsize = EOH_get_flat_size(eoh); + result = (struct varlena *) palloc(resultsize); + EOH_flatten_into(eoh, (void *) result, resultsize); + attr = result; } else if (VARATT_IS_COMPRESSED(attr)) { -- 2.45.1