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 1wDBRS-002gZ7-1p for pgsql-hackers@arkaria.postgresql.org; Thu, 16 Apr 2026 01:22:51 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wDBRQ-0031FI-1k for pgsql-hackers@arkaria.postgresql.org; Thu, 16 Apr 2026 01:22:48 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wDBRQ-0031FA-0a for pgsql-hackers@lists.postgresql.org; Thu, 16 Apr 2026 01:22:48 +0000 Received: from mail-pf1-x434.google.com ([2607:f8b0:4864:20::434]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wDBRN-00000001KAl-34zg for pgsql-hackers@lists.postgresql.org; Thu, 16 Apr 2026 01:22:47 +0000 Received: by mail-pf1-x434.google.com with SMTP id d2e1a72fcca58-82f431c0ab6so1817365b3a.0 for ; Wed, 15 Apr 2026 18:22:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776302564; x=1776907364; darn=lists.postgresql.org; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:from:to:cc:subject:date:message-id:reply-to; bh=ijvqsTy1gTmVKbt6qCCeAVX8cIYmQgUCUJnbhBXi3JA=; b=FySefeamlj0S20qDH9A9tPT1Z+6BwyKYEV3CwiPRt6v5Ml8vTE492tv8L8CmV71q6w pcXleNqZU8C/RHVUV42zow9DGwBRLOxdtUA2yTUnxZyBzArqGNz87k/HwOVk7T7RQpnW Efoz7xD/I0pdivz2CT7thPedwvkhmHfyCEu7v8Zc1tQOyda434mrIPD3QWqk0zEKf8oT gF683Shnx7+JxJB+Y0AIEQ1WzG2lEQytfhLbu7QaR8bJHahSC2hHFNpo+RdZmRDEvIhv cqdmshH/uvTzmSXzuuREkg9JbHPV2GzrpHzI22R3LB53wsdcqUadVVqBBqSirYzqjluN jLRg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776302564; x=1776907364; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=ijvqsTy1gTmVKbt6qCCeAVX8cIYmQgUCUJnbhBXi3JA=; b=Y2DI+GeNtTbgFaBY2H1CFwTgBYrA1eyyF0WyNmjXg7yy6+HxdVL1nQVqhosPbuz9YE qcQl8wt9DwfiEKCizEdYe54uupneC6N4u9ycFS+R4uKTzdqohAo29R+NTz5Yit/ySzF/ tElf87CfoDhtFLHbRTV6Du+PEic5nUNSG1W36jZJO/rK8Rykp2v4hEQm+AWzsoZpH6CI uO3eo9JXIKZE9nYMZ0LrNDq/Hu09WfFU0iuKlcbF1yMgWyB5/R+WcwtacnQJ+XeEcDut QaMPSRo/gbr+x9ZEbG5s6iuu3uwj93jbarRLCjtYw1LYOKhvLvu/4+RkJVpLjXo0JOVp LeAg== X-Forwarded-Encrypted: i=1; AFNElJ8yznOC25KDbnq45NfU8cRB+IVQ8g5Qs6dwy5Fb8xVWsc4lAijttWW/9Q747jkkHvB+QXwUuyhnBufCCEr/@lists.postgresql.org X-Gm-Message-State: AOJu0YyMiqU3QDTeVepNz2wNXpDrd1b/FWzajkc84rSr6PPM+QaoBUzi oMIsugIEwZkka3r2sL/XaXtio4aKBvEzKOK+uzAbXhRZwfuIbjCABCKN X-Gm-Gg: AeBDiesYYpwcgRrS7jc7bghbF3CjofahtqX8oKqRR0MC7cl5USuW7U0/e082Q75jaNH eqeqlZYCMDt5NfsljR6b70C6XUVhoycTG7kY9wv4eO/idEoxVeJPPy9d+H5OhlJkUGHMHzVikRH yxMOn6bm3AsPg6VZ97YWtYf02+KnAI2TlYHU1kx0+tA6/mvSfVPC9zNFhiJYS5ZHytY/KuIjHeC mHZa7MLvnQXGE/WMxnBm0te+7jscOrB0z27H44zE4cxzR7IAfBSCnV0Jlt251ZWrvuAS5jO1wXp KsSBAE8eO0y6Q4wNN02DdWoai68y4nJjvLrTFdMtIDGA9JIiIM1TeWypZwIMPCMX+6uTqXRS66V m4NKNV6MJbTb1VMN3e/RV8ud/G77xH1mfQLdgp6QAUSl61e1oTgkxNBJMxh3S4aBesWIESNOwPv 8UpirPBfjzCTwp/68LjF0I4dup4xdy1cA= X-Received: by 2002:a05:6a00:32c5:b0:82c:d7c4:4c56 with SMTP id d2e1a72fcca58-82f0c274ecfmr22349202b3a.15.1776302563518; Wed, 15 Apr 2026 18:22:43 -0700 (PDT) Received: from smtpclient.apple ([45.32.121.103]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82f670791fasm3513077b3a.20.2026.04.15.18.22.40 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 15 Apr 2026 18:22:42 -0700 (PDT) From: Chao Li Message-Id: Content-Type: multipart/mixed; boundary="Apple-Mail=_B3FEF0FF-B59F-4764-9977-DDBFBC98AAD5" Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3864.400.21\)) Subject: Re: pg_overexplain produces invalid JSON with RANGE_TABLE option Date: Thu, 16 Apr 2026 09:22:03 +0800 In-Reply-To: Cc: SATYANARAYANA NARLAPURAM , PostgreSQL Hackers To: Amit Langote References: X-Mailer: Apple Mail (2.3864.400.21) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --Apple-Mail=_B3FEF0FF-B59F-4764-9977-DDBFBC98AAD5 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 > On Apr 16, 2026, at 08:06, Amit Langote = wrote: >=20 > Hi, >=20 > On Thu, Apr 16, 2026 at 6:36=E2=80=AFAM SATYANARAYANA NARLAPURAM > wrote: >>=20 >> Hi Hackers, >>=20 >> It appears that pg_overexplain produces invalid JSON output when >> EXPLAIN (FORMAT JSON, RANGE_TABLE) is used. The "Unprunable RTIs" and >> "Result RTIs" properties are emitted as key:value pairs directly = inside >> the "Range Table" JSON array, which is structurally invalid. >=20 > Thanks for the report and the patch. That makes sense. >=20 >> Attempted to fix this by moving ExplainCloseGroup() before the two = overexplain_bitmapset() >> calls, so the properties are emitted as siblings of "Range Table" in = the parent object rather >> than inside the array. >>=20 >> Attached a patch to address this which also includes a test. >=20 > I have added a commit message. Will commit shortly to master and v18. >=20 > --=20 > Thanks, Amit Langote > Hi Amit, as the commit message mentions YAML format as well, but I = don=E2=80=99t find a test case in pg_overexplain.sql, would it make = sense to also add a test case for YAML. I tried to add one, see the = attached diff file. Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/ --Apple-Mail=_B3FEF0FF-B59F-4764-9977-DDBFBC98AAD5 Content-Disposition: attachment; filename=yaml_test.diff Content-Type: application/octet-stream; x-unix-mode=0644; name="yaml_test.diff" Content-Transfer-Encoding: 7bit diff --git a/contrib/pg_overexplain/expected/pg_overexplain.out b/contrib/pg_overexplain/expected/pg_overexplain.out index 12ab92629ab..f331c236ae4 100644 --- a/contrib/pg_overexplain/expected/pg_overexplain.out +++ b/contrib/pg_overexplain/expected/pg_overexplain.out @@ -419,6 +419,102 @@ $$); ] (1 row) +-- Test YAML format with RANGE_TABLE to verify valid YAML structure. +SELECT explain_filter($$ +EXPLAIN (RANGE_TABLE, FORMAT YAML, COSTS OFF) +SELECT genus, array_agg(name ORDER BY name) FROM vegetables GROUP BY genus +$$); + explain_filter +----------------------------------------------- + - Plan: + + Node Type: "Aggregate" + + Strategy: "Sorted" + + Partial Mode: "Simple" + + Parallel Aware: false + + Async Capable: false + + Disabled: false + + Group Key: + + - "vegetables.genus" + + Plans: + + - Node Type: "Sort" + + Parent Relationship: "Outer" + + Parallel Aware: false + + Async Capable: false + + Disabled: false + + Sort Key: + + - "vegetables.genus" + + - "vegetables.name" + + Plans: + + - Node Type: "Append" + + Parent Relationship: "Outer" + + Parallel Aware: false + + Async Capable: false + + Disabled: false + + Append RTIs: "1" + + Child Append RTIs: "none" + + Subplans Removed: 0 + + Plans: + + - Node Type: "Seq Scan" + + Parent Relationship: "Member"+ + Parallel Aware: false + + Async Capable: false + + Relation Name: "brassica" + + Alias: "vegetables_1" + + Disabled: false + + Scan RTI: 3 + + - Node Type: "Seq Scan" + + Parent Relationship: "Member"+ + Parallel Aware: false + + Async Capable: false + + Relation Name: "daucus" + + Alias: "vegetables_2" + + Disabled: false + + Scan RTI: 4 + + Range Table: + + - RTI: 1 + + Kind: "relation" + + Inherited: true + + In From Clause: true + + Eref: "vegetables (id, name, genus)" + + Relation: "vegetables" + + Relation Kind: "partitioned_table" + + Relation Lock Mode: "AccessShareLock" + + Permission Info Index: 1 + + Security Barrier: false + + Lateral: false + + - RTI: 2 + + Kind: "group" + + Inherited: false + + In From Clause: false + + Eref: "\"*GROUP*\" (genus)" + + Security Barrier: false + + Lateral: false + + - RTI: 3 + + Kind: "relation" + + Inherited: false + + In From Clause: true + + Alias: "vegetables (id, name, genus)" + + Eref: "vegetables (id, name, genus)" + + Relation: "brassica" + + Relation Kind: "relation" + + Relation Lock Mode: "AccessShareLock" + + Security Barrier: false + + Lateral: false + + - RTI: 4 + + Kind: "relation" + + Inherited: false + + In From Clause: true + + Alias: "vegetables (id, name, genus)" + + Eref: "vegetables (id, name, genus)" + + Relation: "daucus" + + Relation Kind: "relation" + + Relation Lock Mode: "AccessShareLock" + + Security Barrier: false + + Lateral: false + + Unprunable RTIs: "1 3 4" + + Result RTIs: "none" +(1 row) + -- Test just the DEBUG option. Verify that it shows information about -- disabled nodes, parallel safety, and the parallelModeNeeded flag. SET enable_seqscan = false; diff --git a/contrib/pg_overexplain/sql/pg_overexplain.sql b/contrib/pg_overexplain/sql/pg_overexplain.sql index 3f17b61a2da..8cb6f2718fb 100644 --- a/contrib/pg_overexplain/sql/pg_overexplain.sql +++ b/contrib/pg_overexplain/sql/pg_overexplain.sql @@ -72,6 +72,12 @@ EXPLAIN (RANGE_TABLE, FORMAT JSON, COSTS OFF) SELECT genus, array_agg(name ORDER BY name) FROM vegetables GROUP BY genus $$); +-- Test YAML format with RANGE_TABLE to verify valid YAML structure. +SELECT explain_filter($$ +EXPLAIN (RANGE_TABLE, FORMAT YAML, COSTS OFF) +SELECT genus, array_agg(name ORDER BY name) FROM vegetables GROUP BY genus +$$); + -- Test just the DEBUG option. Verify that it shows information about -- disabled nodes, parallel safety, and the parallelModeNeeded flag. SET enable_seqscan = false; --Apple-Mail=_B3FEF0FF-B59F-4764-9977-DDBFBC98AAD5--