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.96) (envelope-from ) id 1wxObz-002gpQ-05 for pgsql-bugs@arkaria.postgresql.org; Fri, 21 Aug 2026 12:44:43 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wxObx-00DJP6-02 for pgsql-bugs@arkaria.postgresql.org; Fri, 21 Aug 2026 12:44:41 +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.96) (envelope-from ) id 1wxLTs-00CYRW-1m for pgsql-bugs@lists.postgresql.org; Fri, 21 Aug 2026 09:24:08 +0000 Received: from mahout.postgresql.org ([2001:4800:3e1:1::227]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1wxLTq-00000001ier-1kZE for pgsql-bugs@lists.postgresql.org; Fri, 21 Aug 2026 09:24:07 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=postgresql.org; s=20171124; h=Message-ID:Date:Reply-To:Cc:From:To:Subject: Content-Transfer-Encoding:MIME-Version:Content-Type:Sender:Content-ID: Content-Description:In-Reply-To:References; bh=o+7ZIyIkDcc9efaFt/D89/57KPC5T9ShLjvaGjrM2IE=; b=35h70F27YbdiFSnkfhQRWDXKWB 0FJfypFwZn+EYa/Af3XlAPdwBLGWSXqZMZo9SRRESdIULJtrucQJ6O88rwUKVqzAYmhWgjzUW7e6I G3+a9mCJfdUH+XuZ8+PFKwr20r32ujR7Cy7PHBp+DzPRpPkPkoKLDJe1uU6FP8n0Zu6TC+MHcFc9R sCtXJG4hsUQiGqOODYYlDxByAbLj9JyIA4W2hTczw/qKhbBWzuMDJHdMWVuNmSILatkszZGW5ghj5 rgM1h39c7+mpV59Tfj3RZ7FenOeHkq9Z2M+rXBWzYxcXvCjR8nAT7yxkVSZWMJA5781rlLBWc2oii PxSisC3Q==; Received: from wrigleys.postgresql.org ([2a02:16a8:dc51::60]) by mahout.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wxLTp-0059ho-17 for pgsql-bugs@lists.postgresql.org; Fri, 21 Aug 2026 09:24:06 +0000 Received: from localhost ([127.0.0.1] helo=wrigleys.postgresql.org) by wrigleys.postgresql.org with esmtp (Exim 4.98.2) (envelope-from ) id 1wxLTo-0000000DiVT-19sb for pgsql-bugs@lists.postgresql.org; Fri, 21 Aug 2026 09:24:04 +0000 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: BUG #19636: heap_fill_tuple misses short varlena conversion after EOH_flatten_into, causing 3-byte waste per row To: pgsql-bugs@lists.postgresql.org From: PG Bug reporting form Cc: 17801022106@163.com Reply-To: 17801022106@163.com, pgsql-bugs@lists.postgresql.org Date: Fri, 21 Aug 2026 09:23:51 +0000 Message-ID: <19636-c44abe40ca7e2c4d@postgresql.org> X-Auto-Response-Suppress: All Auto-Submitted: auto-generated List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk The following bug has been logged on the website: Bug reference: 19636 Logged by: anliuan Email address: 17801022106@163.com PostgreSQL version: 19beta1 Operating system: centos Description: =20 When a PL/pgSQL function/procedure inserts an array value that arrives as an expanded object (via EOH_flatten_into), the resulting tuple stores the varlena with a 4-byte header instead of converting it to a 1-byte short varlena header, wasting 3 bytes per row for arrays <=3D 127 bytes total size. Plain INSERT correctly uses the short varlena format; only the PL/pgSQL expanded-object path is affected. Steps to reproduce: CREATE TABLE tt2(a text[]); INSERT INTO tt2 VALUES('{aaaaa}'); -- plain INSERT CREATE OR REPLACE FUNCTION call_insert_acl(racl text[]) RETURNS int AS $$ BEGIN INSERT INTO tt2 VALUES(racl); RETURN 1; END; $$ LANGUAGE plpgsql; SELECT call_insert_acl('{aaaaa}'); -- PL/pgSQL INSERT SELECT a, pg_column_size(a) FROM tt2; Expected result: Both rows should have the same pg_column_size (33 bytes = =E2=80=94 short varlena with 1-byte header). Actual result: =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=AC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=AC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=90 =E2=94=82 row =E2=94=82 pg_column_size =E2=94=82 head= er format =E2=94=82 =E2=94=9C=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=BC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=BC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=A4 =E2=94=82 plain INSERT =E2=94=82 33 =E2=94=82 short varlen= a (1-byte header) =E2=94=82 =E2=94=9C=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=BC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=BC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=A4 =E2=94=82 PL/pgSQL INSERT =E2=94=82 36 =E2=94=82 4-byte heade= r =E2=94=82 =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=B4=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=B4=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=98 Root cause: In src/backend/access/common/heaptuple.c, heap_fill_tuple has four varlena paths. The EOH_flatten_into path (for expanded objects) produces a 4-byte-header varlena and writes it directly, without checking VARATT_CAN_MAKE_SHORT: /* Current code =E2=80=94 line ~229 */ if (VARATT_IS_EXTERNAL_EXPANDED(val)) { ExpandedObjectHeader *eoh =3D DatumGetEOHP(values[i]); data =3D (char *) ATT_ALIGN_NOMINAL(data, att[i]->attalign); data_length =3D EOH_get_flat_size(eoh); EOH_flatten_into(eoh, data, data_length); /* BUG: no VARATT_CAN_MAKE_SHORT check here */ } The normal 4-byte-header path correctly performs this check: /* Normal path =E2=80=94 line ~240 */ else if (VARLENA_ATT_IS_PACKABLE(att[i]) && VARATT_CAN_MAKE_SHORT(val)) { data_length =3D VARATT_CONVERTED_SHORT_SIZE(val); SET_VARSIZE_SHORT(data, data_length); } heap_compute_data_size has the same omission =E2=80=94 it uses EOH_get_fl= at_size() without considering the short-header size reduction, so the size calculation and fill logic are consistently wrong (no memory overrun, just wasted space).