From 5845bc795551d0c738dc8ca59890b074ed2e3906 Mon Sep 17 00:00:00 2001
From: Nikita Malakhov <n.malakhov@postgrespro.ru>
Date: Fri, 15 May 2026 14:39:41 +0300
Subject: [PATCH] JSON_TABLE PLAN Clause (2/3)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This patch adds the PLAN clauses for JSON_TABLE, which allow the user
to specify how data from nested paths are joined, allowing
considerable freedom in shaping the tabular output of JSON_TABLE.
PLAN DEFAULT allows the user to specify the global strategies when
dealing with sibling or child nested paths. The is often sufficient
to achieve the necessary goal, and is considerably simpler than the
full PLAN clause, which allows the user to specify the strategy to be
used for each named nested path.

The second patch in series provides test cases and results changes
for PLAN clause.

Author: Nikita Glukhov <n.gluhov@postgrespro.ru>
Author: Teodor Sigaev <teodor@sigaev.ru>
Author: Oleg Bartunov <obartunov@gmail.com>
Author: Alexander Korotkov <aekorotkov@gmail.com>
Author: Andrew Dunstan <andrew@dunslane.net>
Author: Amit Langote <amitlangote09@gmail.com>
Author: Anton Melnikov <a.melnikov@postgrespro.ru>
Author: Nikita Malakhov <n.malakhov@postgrespro.ru>

Reviewers have included (in no particular order) Andres Freund, Alexander
Korotkov, Pavel Stehule, Andrew Alsup, Erik Rijkers, Zihong Yu,
Himanshu Upadhyaya, Daniel Gustafsson, Justin Pryzby, Álvaro Herrera,
jian he

Discussion: https://postgr.es/m/cd0bb935-0158-78a7-08b5-904886deac4b@postgrespro.ru
Discussion: https://postgr.es/m/20220616233130.rparivafipt6doj3@alap3.anarazel.de
Discussion: https://postgr.es/m/abd9b83b-aa66-f230-3d6d-734817f0995d%40postgresql.org
Discussion: https://postgr.es/m/CA+HiwqE4XTdfb1nW=Ojoy_tQSRhYt-q_kb6i5d4xcKyrLC1Nbg@mail.gmail.com
---
 .../regress/expected/sqljson_jsontable.out    | 635 +++++++++++++++++-
 src/test/regress/sql/sqljson_jsontable.sql    | 417 ++++++++++++
 2 files changed, 1051 insertions(+), 1 deletion(-)

diff --git a/src/test/regress/expected/sqljson_jsontable.out b/src/test/regress/expected/sqljson_jsontable.out
index 458c5aaa5b0..2ec30d37264 100644
--- a/src/test/regress/expected/sqljson_jsontable.out
+++ b/src/test/regress/expected/sqljson_jsontable.out
@@ -774,6 +774,222 @@ SELECT * FROM JSON_TABLE(
 ERROR:  duplicate JSON_TABLE column or path name: a
 LINE 10:    NESTED PATH '$' AS a
                                ^
+-- JSON_TABLE: nested paths and plans
+-- Should fail (JSON_TABLE columns must contain explicit AS path
+-- specifications if explicit PLAN clause is used)
+SELECT * FROM JSON_TABLE(
+       jsonb '[]', '$' -- AS <path name> required here
+       COLUMNS (
+               foo int PATH '$'
+       )
+       PLAN DEFAULT (UNION)
+) jt;
+ERROR:  invalid JSON_TABLE expression
+LINE 2:        jsonb '[]', '$' -- AS <path name> required here
+                           ^
+DETAIL:  JSON_TABLE path must contain explicit AS pathname specification if explicit PLAN clause is used
+SELECT * FROM JSON_TABLE(
+       jsonb '[]', '$' AS path1
+       COLUMNS (
+               NESTED PATH '$' COLUMNS ( -- AS <path name> required here
+                       foo int PATH '$'
+               )
+       )
+       PLAN DEFAULT (UNION)
+) jt;
+ foo 
+-----
+    
+(1 row)
+
+-- JSON_TABLE: plan validation
+SELECT * FROM JSON_TABLE(
+       jsonb 'null', '$[*]' AS p0
+       COLUMNS (
+               NESTED PATH '$' AS p1 COLUMNS (
+                       NESTED PATH '$' AS p11 COLUMNS ( foo int ),
+                       NESTED PATH '$' AS p12 COLUMNS ( bar int )
+               ),
+               NESTED PATH '$' AS p2 COLUMNS (
+                       NESTED PATH '$' AS p21 COLUMNS ( baz int )
+               )
+       )
+       PLAN (p1)
+) jt;
+ERROR:  invalid JSON_TABLE plan
+LINE 12:        PLAN (p1)
+                      ^
+DETAIL:  PATH name mismatch: expected p0 but p1 is given.
+SELECT * FROM JSON_TABLE(
+       jsonb 'null', '$[*]' AS p0
+       COLUMNS (
+               NESTED PATH '$' AS p1 COLUMNS (
+                       NESTED PATH '$' AS p11 COLUMNS ( foo int ),
+                       NESTED PATH '$' AS p12 COLUMNS ( bar int )
+               ),
+               NESTED PATH '$' AS p2 COLUMNS (
+                       NESTED PATH '$' AS p21 COLUMNS ( baz int )
+               )
+       )
+       PLAN (p0)
+) jt;
+ERROR:  invalid JSON_TABLE specification
+LINE 4:                NESTED PATH '$' AS p1 COLUMNS (
+                       ^
+DETAIL:  PLAN clause for nested path p1 was not found.
+SELECT * FROM JSON_TABLE(
+       jsonb 'null', '$[*]' AS p0
+       COLUMNS (
+               NESTED PATH '$' AS p1 COLUMNS (
+                       NESTED PATH '$' AS p11 COLUMNS ( foo int ),
+                       NESTED PATH '$' AS p12 COLUMNS ( bar int )
+               ),
+               NESTED PATH '$' AS p2 COLUMNS (
+                       NESTED PATH '$' AS p21 COLUMNS ( baz int )
+               )
+       )
+       PLAN (p0 OUTER p3)
+) jt;
+ERROR:  invalid JSON_TABLE specification
+LINE 4:                NESTED PATH '$' AS p1 COLUMNS (
+                       ^
+DETAIL:  PLAN clause for nested path p1 was not found.
+SELECT * FROM JSON_TABLE(
+       jsonb 'null', '$[*]' AS p0
+       COLUMNS (
+               NESTED PATH '$' AS p1 COLUMNS (
+                       NESTED PATH '$' AS p11 COLUMNS ( foo int ),
+                       NESTED PATH '$' AS p12 COLUMNS ( bar int )
+               ),
+               NESTED PATH '$' AS p2 COLUMNS (
+                       NESTED PATH '$' AS p21 COLUMNS ( baz int )
+               )
+       )
+       PLAN (p0 UNION p1 UNION p11)
+) jt;
+ERROR:  invalid JSON_TABLE plan clause
+LINE 12:        PLAN (p0 UNION p1 UNION p11)
+                      ^
+DETAIL:  Expected INNER or OUTER.
+SELECT * FROM JSON_TABLE(
+       jsonb 'null', '$[*]' AS p0
+       COLUMNS (
+               NESTED PATH '$' AS p1 COLUMNS (
+                       NESTED PATH '$' AS p11 COLUMNS ( foo int ),
+                       NESTED PATH '$' AS p12 COLUMNS ( bar int )
+               ),
+               NESTED PATH '$' AS p2 COLUMNS (
+                       NESTED PATH '$' AS p21 COLUMNS ( baz int )
+               )
+       )
+       PLAN (p0 OUTER (p1 CROSS p13))
+) jt;
+ERROR:  invalid JSON_TABLE specification
+LINE 8:                NESTED PATH '$' AS p2 COLUMNS (
+                       ^
+DETAIL:  PLAN clause for nested path p2 was not found.
+SELECT * FROM JSON_TABLE(
+       jsonb 'null', '$[*]' AS p0
+       COLUMNS (
+               NESTED PATH '$' AS p1 COLUMNS (
+                       NESTED PATH '$' AS p11 COLUMNS ( foo int ),
+                       NESTED PATH '$' AS p12 COLUMNS ( bar int )
+               ),
+               NESTED PATH '$' AS p2 COLUMNS (
+                       NESTED PATH '$' AS p21 COLUMNS ( baz int )
+               )
+       )
+       PLAN (p0 OUTER (p1 CROSS p2))
+) jt;
+ERROR:  invalid JSON_TABLE specification
+LINE 5:                        NESTED PATH '$' AS p11 COLUMNS ( foo ...
+                               ^
+DETAIL:  PLAN clause for nested path p11 was not found.
+SELECT * FROM JSON_TABLE(
+       jsonb 'null', '$[*]' AS p0
+       COLUMNS (
+               NESTED PATH '$' AS p1 COLUMNS (
+                       NESTED PATH '$' AS p11 COLUMNS ( foo int ),
+                       NESTED PATH '$' AS p12 COLUMNS ( bar int )
+               ),
+               NESTED PATH '$' AS p2 COLUMNS (
+                       NESTED PATH '$' AS p21 COLUMNS ( baz int )
+               )
+       )
+       PLAN (p0 OUTER ((p1 UNION p11) CROSS p2))
+) jt;
+ERROR:  invalid JSON_TABLE plan clause
+LINE 12:        PLAN (p0 OUTER ((p1 UNION p11) CROSS p2))
+                               ^
+DETAIL:  PLAN clause contains some extra or duplicate sibling nodes.
+SELECT * FROM JSON_TABLE(
+       jsonb 'null', '$[*]' AS p0
+       COLUMNS (
+               NESTED PATH '$' AS p1 COLUMNS (
+                       NESTED PATH '$' AS p11 COLUMNS ( foo int ),
+                       NESTED PATH '$' AS p12 COLUMNS ( bar int )
+               ),
+               NESTED PATH '$' AS p2 COLUMNS (
+                       NESTED PATH '$' AS p21 COLUMNS ( baz int )
+               )
+       )
+       PLAN (p0 OUTER ((p1 INNER p11) CROSS p2))
+) jt;
+ERROR:  invalid JSON_TABLE specification
+LINE 6:                        NESTED PATH '$' AS p12 COLUMNS ( bar ...
+                               ^
+DETAIL:  PLAN clause for nested path p12 was not found.
+SELECT * FROM JSON_TABLE(
+       jsonb 'null', '$[*]' AS p0
+       COLUMNS (
+               NESTED PATH '$' AS p1 COLUMNS (
+                       NESTED PATH '$' AS p11 COLUMNS ( foo int ),
+                       NESTED PATH '$' AS p12 COLUMNS ( bar int )
+               ),
+               NESTED PATH '$' AS p2 COLUMNS (
+                       NESTED PATH '$' AS p21 COLUMNS ( baz int )
+               )
+       )
+       PLAN (p0 OUTER ((p1 INNER (p12 CROSS p11)) CROSS p2))
+) jt;
+ERROR:  invalid JSON_TABLE specification
+LINE 9:                        NESTED PATH '$' AS p21 COLUMNS ( baz ...
+                               ^
+DETAIL:  PLAN clause for nested path p21 was not found.
+SELECT * FROM JSON_TABLE(
+       jsonb 'null', 'strict $[*]' AS p0
+       COLUMNS (
+               NESTED PATH '$' AS p1 COLUMNS (
+                       NESTED PATH '$' AS p11 COLUMNS ( foo int ),
+                       NESTED PATH '$' AS p12 COLUMNS ( bar int )
+               ),
+               NESTED PATH '$' AS p2 COLUMNS (
+                       NESTED PATH '$' AS p21 COLUMNS ( baz int )
+               )
+       )
+       PLAN (p0 OUTER ((p1 INNER (p12 CROSS p11)) CROSS (p2 INNER p21)))
+) jt;
+ bar | foo | baz 
+-----+-----+-----
+(0 rows)
+
+SELECT * FROM JSON_TABLE(
+       jsonb 'null', 'strict $[*]' -- without root path name
+       COLUMNS (
+               NESTED PATH '$' AS p1 COLUMNS (
+                       NESTED PATH '$' AS p11 COLUMNS ( foo int ),
+                       NESTED PATH '$' AS p12 COLUMNS ( bar int )
+               ),
+               NESTED PATH '$' AS p2 COLUMNS (
+                       NESTED PATH '$' AS p21 COLUMNS ( baz int )
+               )
+       )
+       PLAN ((p1 INNER (p12 CROSS p11)) CROSS (p2 INNER p21))
+) jt;
+ERROR:  invalid JSON_TABLE expression
+LINE 2:        jsonb 'null', 'strict $[*]' -- without root path name
+                             ^
+DETAIL:  JSON_TABLE path must contain explicit AS pathname specification if explicit PLAN clause is used
 -- JSON_TABLE: plan execution
 CREATE TEMP TABLE jsonb_table_test (js jsonb);
 INSERT INTO jsonb_table_test
@@ -813,6 +1029,325 @@ from
  4 | -1 |    2 | 2 |      |   
 (11 rows)
 
+-- default plan (outer, union)
+select
+       jt.*
+from
+       jsonb_table_test jtt,
+       json_table (
+               jtt.js,'strict $[*]' as p
+               columns (
+                       n for ordinality,
+                       a int path 'lax $.a' default -1 on empty,
+                       nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
+                       nested path 'strict $.c[*]' as pc columns ( c int path '$' )
+               )
+               plan default (outer, union)
+       ) jt;
+ n | a  | b | c  
+---+----+---+----
+ 1 |  1 |   |   
+ 2 |  2 | 1 |   
+ 2 |  2 | 2 |   
+ 2 |  2 | 3 |   
+ 2 |  2 |   | 10
+ 2 |  2 |   |   
+ 2 |  2 |   | 20
+ 3 |  3 | 1 |   
+ 3 |  3 | 2 |   
+ 4 | -1 | 1 |   
+ 4 | -1 | 2 |   
+(11 rows)
+
+-- specific plan (p outer (pb union pc))
+select
+       jt.*
+from
+       jsonb_table_test jtt,
+       json_table (
+               jtt.js,'strict $[*]' as p
+               columns (
+                       n for ordinality,
+                       a int path 'lax $.a' default -1 on empty,
+                       nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
+                       nested path 'strict $.c[*]' as pc columns ( c int path '$' )
+               )
+               plan (p outer (pb union pc))
+       ) jt;
+ n | a  | b | c  
+---+----+---+----
+ 1 |  1 |   |   
+ 2 |  2 | 1 |   
+ 2 |  2 | 2 |   
+ 2 |  2 | 3 |   
+ 2 |  2 |   | 10
+ 2 |  2 |   |   
+ 2 |  2 |   | 20
+ 3 |  3 | 1 |   
+ 3 |  3 | 2 |   
+ 4 | -1 | 1 |   
+ 4 | -1 | 2 |   
+(11 rows)
+
+-- specific plan (p outer (pc union pb))
+select
+       jt.*
+from
+       jsonb_table_test jtt,
+       json_table (
+               jtt.js,'strict $[*]' as p
+               columns (
+                       n for ordinality,
+                       a int path 'lax $.a' default -1 on empty,
+                       nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
+                       nested path 'strict $.c[*]' as pc columns ( c int path '$' )
+               )
+               plan (p outer (pc union pb))
+       ) jt;
+ n | a  | c  | b 
+---+----+----+---
+ 1 |  1 |    |  
+ 2 |  2 | 10 |  
+ 2 |  2 |    |  
+ 2 |  2 | 20 |  
+ 2 |  2 |    | 1
+ 2 |  2 |    | 2
+ 2 |  2 |    | 3
+ 3 |  3 |    | 1
+ 3 |  3 |    | 2
+ 4 | -1 |    | 1
+ 4 | -1 |    | 2
+(11 rows)
+
+-- default plan (inner, union)
+select
+       jt.*
+from
+       jsonb_table_test jtt,
+       json_table (
+               jtt.js,'strict $[*]' as p
+               columns (
+                       n for ordinality,
+                       a int path 'lax $.a' default -1 on empty,
+                       nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
+                       nested path 'strict $.c[*]' as pc columns ( c int path '$' )
+               )
+               plan default (inner)
+       ) jt;
+ n | a  | b | c  
+---+----+---+----
+ 2 |  2 | 1 |   
+ 2 |  2 | 2 |   
+ 2 |  2 | 3 |   
+ 2 |  2 |   | 10
+ 2 |  2 |   |   
+ 2 |  2 |   | 20
+ 3 |  3 | 1 |   
+ 3 |  3 | 2 |   
+ 4 | -1 | 1 |   
+ 4 | -1 | 2 |   
+(10 rows)
+
+-- specific plan (p inner (pb union pc))
+select
+       jt.*
+from
+       jsonb_table_test jtt,
+       json_table (
+               jtt.js,'strict $[*]' as p
+               columns (
+                       n for ordinality,
+                       a int path 'lax $.a' default -1 on empty,
+                       nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
+                       nested path 'strict $.c[*]' as pc columns ( c int path '$' )
+               )
+               plan (p inner (pb union pc))
+       ) jt;
+ n | a  | b | c  
+---+----+---+----
+ 2 |  2 | 1 |   
+ 2 |  2 | 2 |   
+ 2 |  2 | 3 |   
+ 2 |  2 |   | 10
+ 2 |  2 |   |   
+ 2 |  2 |   | 20
+ 3 |  3 | 1 |   
+ 3 |  3 | 2 |   
+ 4 | -1 | 1 |   
+ 4 | -1 | 2 |   
+(10 rows)
+
+-- default plan (inner, cross)
+select
+       jt.*
+from
+       jsonb_table_test jtt,
+       json_table (
+               jtt.js,'strict $[*]' as p
+               columns (
+                       n for ordinality,
+                       a int path 'lax $.a' default -1 on empty,
+                       nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
+                       nested path 'strict $.c[*]' as pc columns ( c int path '$' )
+               )
+               plan default (cross, inner)
+       ) jt;
+ n | a | b | c  
+---+---+---+----
+ 2 | 2 | 1 | 10
+ 2 | 2 | 1 |   
+ 2 | 2 | 1 | 20
+ 2 | 2 | 2 | 10
+ 2 | 2 | 2 |   
+ 2 | 2 | 2 | 20
+ 2 | 2 | 3 | 10
+ 2 | 2 | 3 |   
+ 2 | 2 | 3 | 20
+(9 rows)
+
+-- specific plan (p inner (pb cross pc))
+select
+       jt.*
+from
+       jsonb_table_test jtt,
+       json_table (
+               jtt.js,'strict $[*]' as p
+               columns (
+                       n for ordinality,
+                       a int path 'lax $.a' default -1 on empty,
+                       nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
+                       nested path 'strict $.c[*]' as pc columns ( c int path '$' )
+               )
+               plan (p inner (pb cross pc))
+       ) jt;
+ n | a | b | c  
+---+---+---+----
+ 2 | 2 | 1 | 10
+ 2 | 2 | 1 |   
+ 2 | 2 | 1 | 20
+ 2 | 2 | 2 | 10
+ 2 | 2 | 2 |   
+ 2 | 2 | 2 | 20
+ 2 | 2 | 3 | 10
+ 2 | 2 | 3 |   
+ 2 | 2 | 3 | 20
+(9 rows)
+
+-- default plan (outer, cross)
+select
+       jt.*
+from
+       jsonb_table_test jtt,
+       json_table (
+               jtt.js,'strict $[*]' as p
+               columns (
+                       n for ordinality,
+                       a int path 'lax $.a' default -1 on empty,
+                       nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
+                       nested path 'strict $.c[*]' as pc columns ( c int path '$' )
+               )
+               plan default (outer, cross)
+       ) jt;
+ n | a  | b | c  
+---+----+---+----
+ 1 |  1 |   |   
+ 2 |  2 | 1 | 10
+ 2 |  2 | 1 |   
+ 2 |  2 | 1 | 20
+ 2 |  2 | 2 | 10
+ 2 |  2 | 2 |   
+ 2 |  2 | 2 | 20
+ 2 |  2 | 3 | 10
+ 2 |  2 | 3 |   
+ 2 |  2 | 3 | 20
+ 3 |  3 |   |   
+ 4 | -1 |   |   
+(12 rows)
+
+-- specific plan (p outer (pb cross pc))
+select
+       jt.*
+from
+       jsonb_table_test jtt,
+       json_table (
+               jtt.js,'strict $[*]' as p
+               columns (
+                       n for ordinality,
+                       a int path 'lax $.a' default -1 on empty,
+                       nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
+                       nested path 'strict $.c[*]' as pc columns ( c int path '$' )
+               )
+               plan (p outer (pb cross pc))
+       ) jt;
+ n | a  | b | c  
+---+----+---+----
+ 1 |  1 |   |   
+ 2 |  2 | 1 | 10
+ 2 |  2 | 1 |   
+ 2 |  2 | 1 | 20
+ 2 |  2 | 2 | 10
+ 2 |  2 | 2 |   
+ 2 |  2 | 2 | 20
+ 2 |  2 | 3 | 10
+ 2 |  2 | 3 |   
+ 2 |  2 | 3 | 20
+ 3 |  3 |   |   
+ 4 | -1 |   |   
+(12 rows)
+
+select
+       jt.*, b1 + 100 as b
+from
+       json_table (jsonb
+               '[
+                       {"a":  1,  "b": [[1, 10], [2], [3, 30, 300]], "c": [1, null, 2]},
+                       {"a":  2,  "b": [10, 20], "c": [1, null, 2]},
+                       {"x": "3", "b": [11, 22, 33, 44]}
+                ]',
+               '$[*]' as p
+               columns (
+                       n for ordinality,
+                       a int path 'lax $.a' default -1 on error,
+                       nested path 'strict $.b[*]' as pb columns (
+                               b text format json path '$',
+                               nested path 'strict $[*]' as pb1 columns (
+                                       b1 int path '$'
+                               )
+                       ),
+                       nested path 'strict $.c[*]' as pc columns (
+                               c text format json path '$',
+                               nested path 'strict $[*]' as pc1 columns (
+                                       c1 int path '$'
+                               )
+                       )
+               )
+               --plan default(outer, cross)
+               plan(p outer ((pb inner pb1) cross (pc outer pc1)))
+       ) jt;
+ n | a |      b       | b1  |  c   | c1 |  b  
+---+---+--------------+-----+------+----+-----
+ 1 | 1 | [1, 10]      |   1 | 1    |    | 101
+ 1 | 1 | [1, 10]      |   1 | null |    | 101
+ 1 | 1 | [1, 10]      |   1 | 2    |    | 101
+ 1 | 1 | [1, 10]      |  10 | 1    |    | 110
+ 1 | 1 | [1, 10]      |  10 | null |    | 110
+ 1 | 1 | [1, 10]      |  10 | 2    |    | 110
+ 1 | 1 | [2]          |   2 | 1    |    | 102
+ 1 | 1 | [2]          |   2 | null |    | 102
+ 1 | 1 | [2]          |   2 | 2    |    | 102
+ 1 | 1 | [3, 30, 300] |   3 | 1    |    | 103
+ 1 | 1 | [3, 30, 300] |   3 | null |    | 103
+ 1 | 1 | [3, 30, 300] |   3 | 2    |    | 103
+ 1 | 1 | [3, 30, 300] |  30 | 1    |    | 130
+ 1 | 1 | [3, 30, 300] |  30 | null |    | 130
+ 1 | 1 | [3, 30, 300] |  30 | 2    |    | 130
+ 1 | 1 | [3, 30, 300] | 300 | 1    |    | 400
+ 1 | 1 | [3, 30, 300] | 300 | null |    | 400
+ 1 | 1 | [3, 30, 300] | 300 | 2    |    | 400
+ 2 | 2 |              |     |      |    |    
+ 3 |   |              |     |      |    |    
+(20 rows)
+
 -- PASSING arguments are passed to nested paths and their columns' paths
 SELECT *
 FROM
@@ -876,6 +1411,7 @@ SELECT * FROM
 			)
 		)
 	);
+CREATE DOMAIN jsonb_test_domain AS text CHECK (value <> 'foo');
 \sv jsonb_table_view_nested
 CREATE OR REPLACE VIEW public.jsonb_table_view_nested AS
  SELECT id,
@@ -912,8 +1448,104 @@ CREATE OR REPLACE VIEW public.jsonb_table_view_nested AS
                     )
                 )
             )
+            PLAN (json_table_path_0 OUTER ((p1 OUTER "p1 1") UNION (p2 OUTER ("p2:1" UNION p22))))
         )
+CREATE OR REPLACE VIEW public.jsonb_table_view AS
+ SELECT id,
+    "int",
+    text,
+    "char(4)",
+    bool,
+    "numeric",
+    domain,
+    js,
+    jb,
+    jst,
+    jsc,
+    jsv,
+    jsb,
+    jsbq,
+    aaa,
+    aaa1,
+    exists1,
+    exists2,
+    exists3,
+    js2,
+    jsb2w,
+    jsb2q,
+    ia,
+    ta,
+    jba,
+    a1,
+    b1,
+    a11,
+    a21,
+    a22
+   FROM JSON_TABLE(
+            'null'::jsonb, '$[*]' AS json_table_path_1
+            PASSING
+                1 + 2 AS a,
+                '"foo"'::json AS "b c"
+            COLUMNS (
+                id FOR ORDINALITY,
+                "int" integer PATH '$',
+                text text PATH '$',
+                "char(4)" character(4) PATH '$',
+                bool boolean PATH '$',
+                "numeric" numeric PATH '$',
+                domain jsonb_test_domain PATH '$',
+                js json PATH '$',
+                jb jsonb PATH '$',
+                jst text FORMAT JSON PATH '$',
+                jsc character(4) FORMAT JSON PATH '$',
+                jsv character varying(4) FORMAT JSON PATH '$',
+                jsb jsonb PATH '$',
+                jsbq jsonb PATH '$' OMIT QUOTES,
+                aaa integer PATH '$."aaa"',
+                aaa1 integer PATH '$."aaa"',
+                exists1 boolean EXISTS PATH '$."aaa"',
+                exists2 integer EXISTS PATH '$."aaa"' TRUE ON ERROR,
+                exists3 text EXISTS PATH 'strict $."aaa"' UNKNOWN ON ERROR,
+                js2 json PATH '$',
+                jsb2w jsonb PATH '$' WITH UNCONDITIONAL WRAPPER,
+                jsb2q jsonb PATH '$' OMIT QUOTES,
+                ia integer[] PATH '$',
+                ta text[] PATH '$',
+                jba jsonb[] PATH '$',
+                NESTED PATH '$[1]' AS p1
+                COLUMNS (
+                    a1 integer PATH '$."a1"',
+                    b1 text PATH '$."b1"',
+                    NESTED PATH '$[*]' AS "p1 1"
+                    COLUMNS (
+                        a11 text PATH '$."a11"'
+                    )
+                ),
+                NESTED PATH '$[2]' AS p2
+                COLUMNS (
+                    NESTED PATH '$[*]' AS "p2:1"
+                    COLUMNS (
+                        a21 text PATH '$."a21"'
+                    ),
+                    NESTED PATH '$[*]' AS p22
+                    COLUMNS (
+                        a22 text PATH '$."a22"'
+                    )
+                )
+            )
+            PLAN (json_table_path_1 OUTER ((p1 OUTER "p1 1") UNION (p2 OUTER ("p2:1" UNION p22))))
+        );
+EXPLAIN (COSTS OFF, VERBOSE) SELECT * FROM jsonb_table_view;
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 QUERY PLAN                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Table Function Scan on "json_table"
+   Output: "json_table".id, "json_table"."int", "json_table".text, "json_table"."char(4)", "json_table".bool, "json_table"."numeric", "json_table".domain, "json_table".js, "json_table".jb, "json_table".jst, "json_table".jsc, "json_table".jsv, "json_table".jsb, "json_table".jsbq, "json_table".aaa, "json_table".aaa1, "json_table".exists1, "json_table".exists2, "json_table".exists3, "json_table".js2, "json_table".jsb2w, "json_table".jsb2q, "json_table".ia, "json_table".ta, "json_table".jba, "json_table".a1, "json_table".b1, "json_table".a11, "json_table".a21, "json_table".a22
+   Table Function Call: JSON_TABLE('null'::jsonb, '$[*]' AS json_table_path_1 PASSING 3 AS a, '"foo"'::jsonb AS "b c" COLUMNS (id FOR ORDINALITY, "int" integer PATH '$', text text PATH '$', "char(4)" character(4) PATH '$', bool boolean PATH '$', "numeric" numeric PATH '$', domain jsonb_test_domain PATH '$', js json PATH '$' WITHOUT WRAPPER KEEP QUOTES, jb jsonb PATH '$' WITHOUT WRAPPER KEEP QUOTES, jst text FORMAT JSON PATH '$' WITHOUT WRAPPER KEEP QUOTES, jsc character(4) FORMAT JSON PATH '$' WITHOUT WRAPPER KEEP QUOTES, jsv character varying(4) FORMAT JSON PATH '$' WITHOUT WRAPPER KEEP QUOTES, jsb jsonb PATH '$' WITHOUT WRAPPER KEEP QUOTES, jsbq jsonb PATH '$' WITHOUT WRAPPER OMIT QUOTES, aaa integer PATH '$."aaa"', aaa1 integer PATH '$."aaa"', exists1 boolean EXISTS PATH '$."aaa"', exists2 integer EXISTS PATH '$."aaa"' TRUE ON ERROR, exists3 text EXISTS PATH 'strict $."aaa"' UNKNOWN ON ERROR, js2 json PATH '$' WITHOUT WRAPPER KEEP QUOTES, jsb2w jsonb PATH '$' WITH UNCONDITIONAL WRAPPER KEEP QUOTES, jsb2q jsonb PATH '$' WITHOUT WRAPPER OMIT QUOTES, ia integer[] PATH '$' WITHOUT WRAPPER KEEP QUOTES, ta text[] PATH '$' WITHOUT WRAPPER KEEP QUOTES, jba jsonb[] PATH '$' WITHOUT WRAPPER KEEP QUOTES, NESTED PATH '$[1]' AS p1 COLUMNS (a1 integer PATH '$."a1"', b1 text PATH '$."b1"', NESTED PATH '$[*]' AS "p1 1" COLUMNS (a11 text PATH '$."a11"')), NESTED PATH '$[2]' AS p2 COLUMNS ( NESTED PATH '$[*]' AS "p2:1" COLUMNS (a21 text PATH '$."a21"'), NESTED PATH '$[*]' AS p22 COLUMNS (a22 text PATH '$."a22"'))) PLAN (json_table_path_1 OUTER ((p1 OUTER "p1 1") UNION (p2 OUTER ("p2:1" UNION p22)))))
+(3 rows)
+
+DROP VIEW jsonb_table_view;
 DROP VIEW jsonb_table_view_nested;
+DROP DOMAIN jsonb_test_domain;
 CREATE TABLE s (js jsonb);
 INSERT INTO s VALUES
 	('{"a":{"za":[{"z1": [11,2222]},{"z21": [22, 234,2345]},{"z22": [32, 204,145]}]},"c": 3}'),
@@ -1103,6 +1735,7 @@ CREATE OR REPLACE VIEW public.jsonb_table_view7 AS
                     )
                 )
             )
+            PLAN (c1 OUTER ((((json_table_path_0 OUTER z22) UNION json_table_path_1) UNION (json_table_path_2 OUTER z1)) UNION (json_table_path_3 OUTER z21)))
         ) sub
 DROP VIEW jsonb_table_view7;
 DROP TABLE s;
@@ -1152,7 +1785,7 @@ CREATE OR REPLACE VIEW public.json_table_view9 AS
    FROM JSON_TABLE(
             '"a"'::text, '$' AS json_table_path_0
             COLUMNS (
-                a text PATH '$'
+                a text PATH '$' NULL ON EMPTY
             ) ERROR ON ERROR
         )
 DROP VIEW json_table_view8, json_table_view9;
diff --git a/src/test/regress/sql/sqljson_jsontable.sql b/src/test/regress/sql/sqljson_jsontable.sql
index 154eea79c76..27b86d8a281 100644
--- a/src/test/regress/sql/sqljson_jsontable.sql
+++ b/src/test/regress/sql/sqljson_jsontable.sql
@@ -376,6 +376,170 @@ SELECT * FROM JSON_TABLE(
 	)
 ) jt;
 
+-- JSON_TABLE: nested paths and plans
+-- Should fail (JSON_TABLE columns must contain explicit AS path
+-- specifications if explicit PLAN clause is used)
+SELECT * FROM JSON_TABLE(
+       jsonb '[]', '$' -- AS <path name> required here
+       COLUMNS (
+               foo int PATH '$'
+       )
+       PLAN DEFAULT (UNION)
+) jt;
+SELECT * FROM JSON_TABLE(
+       jsonb '[]', '$' AS path1
+       COLUMNS (
+               NESTED PATH '$' COLUMNS ( -- AS <path name> required here
+                       foo int PATH '$'
+               )
+       )
+       PLAN DEFAULT (UNION)
+) jt;
+
+-- JSON_TABLE: plan validation
+SELECT * FROM JSON_TABLE(
+       jsonb 'null', '$[*]' AS p0
+       COLUMNS (
+               NESTED PATH '$' AS p1 COLUMNS (
+                       NESTED PATH '$' AS p11 COLUMNS ( foo int ),
+                       NESTED PATH '$' AS p12 COLUMNS ( bar int )
+               ),
+               NESTED PATH '$' AS p2 COLUMNS (
+                       NESTED PATH '$' AS p21 COLUMNS ( baz int )
+               )
+       )
+       PLAN (p1)
+) jt;
+SELECT * FROM JSON_TABLE(
+       jsonb 'null', '$[*]' AS p0
+       COLUMNS (
+               NESTED PATH '$' AS p1 COLUMNS (
+                       NESTED PATH '$' AS p11 COLUMNS ( foo int ),
+                       NESTED PATH '$' AS p12 COLUMNS ( bar int )
+               ),
+               NESTED PATH '$' AS p2 COLUMNS (
+                       NESTED PATH '$' AS p21 COLUMNS ( baz int )
+               )
+       )
+       PLAN (p0)
+) jt;
+SELECT * FROM JSON_TABLE(
+       jsonb 'null', '$[*]' AS p0
+       COLUMNS (
+               NESTED PATH '$' AS p1 COLUMNS (
+                       NESTED PATH '$' AS p11 COLUMNS ( foo int ),
+                       NESTED PATH '$' AS p12 COLUMNS ( bar int )
+               ),
+               NESTED PATH '$' AS p2 COLUMNS (
+                       NESTED PATH '$' AS p21 COLUMNS ( baz int )
+               )
+       )
+       PLAN (p0 OUTER p3)
+) jt;
+SELECT * FROM JSON_TABLE(
+       jsonb 'null', '$[*]' AS p0
+       COLUMNS (
+               NESTED PATH '$' AS p1 COLUMNS (
+                       NESTED PATH '$' AS p11 COLUMNS ( foo int ),
+                       NESTED PATH '$' AS p12 COLUMNS ( bar int )
+               ),
+               NESTED PATH '$' AS p2 COLUMNS (
+                       NESTED PATH '$' AS p21 COLUMNS ( baz int )
+               )
+       )
+       PLAN (p0 UNION p1 UNION p11)
+) jt;
+SELECT * FROM JSON_TABLE(
+       jsonb 'null', '$[*]' AS p0
+       COLUMNS (
+               NESTED PATH '$' AS p1 COLUMNS (
+                       NESTED PATH '$' AS p11 COLUMNS ( foo int ),
+                       NESTED PATH '$' AS p12 COLUMNS ( bar int )
+               ),
+               NESTED PATH '$' AS p2 COLUMNS (
+                       NESTED PATH '$' AS p21 COLUMNS ( baz int )
+               )
+       )
+       PLAN (p0 OUTER (p1 CROSS p13))
+) jt;
+SELECT * FROM JSON_TABLE(
+       jsonb 'null', '$[*]' AS p0
+       COLUMNS (
+               NESTED PATH '$' AS p1 COLUMNS (
+                       NESTED PATH '$' AS p11 COLUMNS ( foo int ),
+                       NESTED PATH '$' AS p12 COLUMNS ( bar int )
+               ),
+               NESTED PATH '$' AS p2 COLUMNS (
+                       NESTED PATH '$' AS p21 COLUMNS ( baz int )
+               )
+       )
+       PLAN (p0 OUTER (p1 CROSS p2))
+) jt;
+SELECT * FROM JSON_TABLE(
+       jsonb 'null', '$[*]' AS p0
+       COLUMNS (
+               NESTED PATH '$' AS p1 COLUMNS (
+                       NESTED PATH '$' AS p11 COLUMNS ( foo int ),
+                       NESTED PATH '$' AS p12 COLUMNS ( bar int )
+               ),
+               NESTED PATH '$' AS p2 COLUMNS (
+                       NESTED PATH '$' AS p21 COLUMNS ( baz int )
+               )
+       )
+       PLAN (p0 OUTER ((p1 UNION p11) CROSS p2))
+) jt;
+SELECT * FROM JSON_TABLE(
+       jsonb 'null', '$[*]' AS p0
+       COLUMNS (
+               NESTED PATH '$' AS p1 COLUMNS (
+                       NESTED PATH '$' AS p11 COLUMNS ( foo int ),
+                       NESTED PATH '$' AS p12 COLUMNS ( bar int )
+               ),
+               NESTED PATH '$' AS p2 COLUMNS (
+                       NESTED PATH '$' AS p21 COLUMNS ( baz int )
+               )
+       )
+       PLAN (p0 OUTER ((p1 INNER p11) CROSS p2))
+) jt;
+SELECT * FROM JSON_TABLE(
+       jsonb 'null', '$[*]' AS p0
+       COLUMNS (
+               NESTED PATH '$' AS p1 COLUMNS (
+                       NESTED PATH '$' AS p11 COLUMNS ( foo int ),
+                       NESTED PATH '$' AS p12 COLUMNS ( bar int )
+               ),
+               NESTED PATH '$' AS p2 COLUMNS (
+                       NESTED PATH '$' AS p21 COLUMNS ( baz int )
+               )
+       )
+       PLAN (p0 OUTER ((p1 INNER (p12 CROSS p11)) CROSS p2))
+) jt;
+SELECT * FROM JSON_TABLE(
+       jsonb 'null', 'strict $[*]' AS p0
+       COLUMNS (
+               NESTED PATH '$' AS p1 COLUMNS (
+                       NESTED PATH '$' AS p11 COLUMNS ( foo int ),
+                       NESTED PATH '$' AS p12 COLUMNS ( bar int )
+               ),
+               NESTED PATH '$' AS p2 COLUMNS (
+                       NESTED PATH '$' AS p21 COLUMNS ( baz int )
+               )
+       )
+       PLAN (p0 OUTER ((p1 INNER (p12 CROSS p11)) CROSS (p2 INNER p21)))
+) jt;
+SELECT * FROM JSON_TABLE(
+       jsonb 'null', 'strict $[*]' -- without root path name
+       COLUMNS (
+               NESTED PATH '$' AS p1 COLUMNS (
+                       NESTED PATH '$' AS p11 COLUMNS ( foo int ),
+                       NESTED PATH '$' AS p12 COLUMNS ( bar int )
+               ),
+               NESTED PATH '$' AS p2 COLUMNS (
+                       NESTED PATH '$' AS p21 COLUMNS ( baz int )
+               )
+       )
+       PLAN ((p1 INNER (p12 CROSS p11)) CROSS (p2 INNER p21))
+) jt;
 
 -- JSON_TABLE: plan execution
 
@@ -405,6 +569,170 @@ from
 		)
 	) jt;
 
+-- default plan (outer, union)
+select
+       jt.*
+from
+       jsonb_table_test jtt,
+       json_table (
+               jtt.js,'strict $[*]' as p
+               columns (
+                       n for ordinality,
+                       a int path 'lax $.a' default -1 on empty,
+                       nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
+                       nested path 'strict $.c[*]' as pc columns ( c int path '$' )
+               )
+               plan default (outer, union)
+       ) jt;
+-- specific plan (p outer (pb union pc))
+select
+       jt.*
+from
+       jsonb_table_test jtt,
+       json_table (
+               jtt.js,'strict $[*]' as p
+               columns (
+                       n for ordinality,
+                       a int path 'lax $.a' default -1 on empty,
+                       nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
+                       nested path 'strict $.c[*]' as pc columns ( c int path '$' )
+               )
+               plan (p outer (pb union pc))
+       ) jt;
+-- specific plan (p outer (pc union pb))
+select
+       jt.*
+from
+       jsonb_table_test jtt,
+       json_table (
+               jtt.js,'strict $[*]' as p
+               columns (
+                       n for ordinality,
+                       a int path 'lax $.a' default -1 on empty,
+                       nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
+                       nested path 'strict $.c[*]' as pc columns ( c int path '$' )
+               )
+               plan (p outer (pc union pb))
+       ) jt;
+-- default plan (inner, union)
+select
+       jt.*
+from
+       jsonb_table_test jtt,
+       json_table (
+               jtt.js,'strict $[*]' as p
+               columns (
+                       n for ordinality,
+                       a int path 'lax $.a' default -1 on empty,
+                       nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
+                       nested path 'strict $.c[*]' as pc columns ( c int path '$' )
+               )
+               plan default (inner)
+       ) jt;
+-- specific plan (p inner (pb union pc))
+select
+       jt.*
+from
+       jsonb_table_test jtt,
+       json_table (
+               jtt.js,'strict $[*]' as p
+               columns (
+                       n for ordinality,
+                       a int path 'lax $.a' default -1 on empty,
+                       nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
+                       nested path 'strict $.c[*]' as pc columns ( c int path '$' )
+               )
+               plan (p inner (pb union pc))
+       ) jt;
+-- default plan (inner, cross)
+select
+       jt.*
+from
+       jsonb_table_test jtt,
+       json_table (
+               jtt.js,'strict $[*]' as p
+               columns (
+                       n for ordinality,
+                       a int path 'lax $.a' default -1 on empty,
+                       nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
+                       nested path 'strict $.c[*]' as pc columns ( c int path '$' )
+               )
+               plan default (cross, inner)
+       ) jt;
+-- specific plan (p inner (pb cross pc))
+select
+       jt.*
+from
+       jsonb_table_test jtt,
+       json_table (
+               jtt.js,'strict $[*]' as p
+               columns (
+                       n for ordinality,
+                       a int path 'lax $.a' default -1 on empty,
+                       nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
+                       nested path 'strict $.c[*]' as pc columns ( c int path '$' )
+               )
+               plan (p inner (pb cross pc))
+       ) jt;
+-- default plan (outer, cross)
+select
+       jt.*
+from
+       jsonb_table_test jtt,
+       json_table (
+               jtt.js,'strict $[*]' as p
+               columns (
+                       n for ordinality,
+                       a int path 'lax $.a' default -1 on empty,
+                       nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
+                       nested path 'strict $.c[*]' as pc columns ( c int path '$' )
+               )
+               plan default (outer, cross)
+       ) jt;
+-- specific plan (p outer (pb cross pc))
+select
+       jt.*
+from
+       jsonb_table_test jtt,
+       json_table (
+               jtt.js,'strict $[*]' as p
+               columns (
+                       n for ordinality,
+                       a int path 'lax $.a' default -1 on empty,
+                       nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
+                       nested path 'strict $.c[*]' as pc columns ( c int path '$' )
+               )
+               plan (p outer (pb cross pc))
+       ) jt;
+select
+       jt.*, b1 + 100 as b
+from
+       json_table (jsonb
+               '[
+                       {"a":  1,  "b": [[1, 10], [2], [3, 30, 300]], "c": [1, null, 2]},
+                       {"a":  2,  "b": [10, 20], "c": [1, null, 2]},
+                       {"x": "3", "b": [11, 22, 33, 44]}
+                ]',
+               '$[*]' as p
+               columns (
+                       n for ordinality,
+                       a int path 'lax $.a' default -1 on error,
+                       nested path 'strict $.b[*]' as pb columns (
+                               b text format json path '$',
+                               nested path 'strict $[*]' as pb1 columns (
+                                       b1 int path '$'
+                               )
+                       ),
+                       nested path 'strict $.c[*]' as pc columns (
+                               c text format json path '$',
+                               nested path 'strict $[*]' as pc1 columns (
+                                       c1 int path '$'
+                               )
+                       )
+               )
+               --plan default(outer, cross)
+               plan(p outer ((pb inner pb1) cross (pc outer pc1)))
+       ) jt;
 
 -- PASSING arguments are passed to nested paths and their columns' paths
 SELECT *
@@ -450,8 +778,97 @@ SELECT * FROM
 		)
 	);
 
+CREATE DOMAIN jsonb_test_domain AS text CHECK (value <> 'foo');
 \sv jsonb_table_view_nested
+CREATE OR REPLACE VIEW public.jsonb_table_view AS
+ SELECT id,
+    "int",
+    text,
+    "char(4)",
+    bool,
+    "numeric",
+    domain,
+    js,
+    jb,
+    jst,
+    jsc,
+    jsv,
+    jsb,
+    jsbq,
+    aaa,
+    aaa1,
+    exists1,
+    exists2,
+    exists3,
+    js2,
+    jsb2w,
+    jsb2q,
+    ia,
+    ta,
+    jba,
+    a1,
+    b1,
+    a11,
+    a21,
+    a22
+   FROM JSON_TABLE(
+            'null'::jsonb, '$[*]' AS json_table_path_1
+            PASSING
+                1 + 2 AS a,
+                '"foo"'::json AS "b c"
+            COLUMNS (
+                id FOR ORDINALITY,
+                "int" integer PATH '$',
+                text text PATH '$',
+                "char(4)" character(4) PATH '$',
+                bool boolean PATH '$',
+                "numeric" numeric PATH '$',
+                domain jsonb_test_domain PATH '$',
+                js json PATH '$',
+                jb jsonb PATH '$',
+                jst text FORMAT JSON PATH '$',
+                jsc character(4) FORMAT JSON PATH '$',
+                jsv character varying(4) FORMAT JSON PATH '$',
+                jsb jsonb PATH '$',
+                jsbq jsonb PATH '$' OMIT QUOTES,
+                aaa integer PATH '$."aaa"',
+                aaa1 integer PATH '$."aaa"',
+                exists1 boolean EXISTS PATH '$."aaa"',
+                exists2 integer EXISTS PATH '$."aaa"' TRUE ON ERROR,
+                exists3 text EXISTS PATH 'strict $."aaa"' UNKNOWN ON ERROR,
+                js2 json PATH '$',
+                jsb2w jsonb PATH '$' WITH UNCONDITIONAL WRAPPER,
+                jsb2q jsonb PATH '$' OMIT QUOTES,
+                ia integer[] PATH '$',
+                ta text[] PATH '$',
+                jba jsonb[] PATH '$',
+                NESTED PATH '$[1]' AS p1
+                COLUMNS (
+                    a1 integer PATH '$."a1"',
+                    b1 text PATH '$."b1"',
+                    NESTED PATH '$[*]' AS "p1 1"
+                    COLUMNS (
+                        a11 text PATH '$."a11"'
+                    )
+                ),
+                NESTED PATH '$[2]' AS p2
+                COLUMNS (
+                    NESTED PATH '$[*]' AS "p2:1"
+                    COLUMNS (
+                        a21 text PATH '$."a21"'
+                    ),
+                    NESTED PATH '$[*]' AS p22
+                    COLUMNS (
+                        a22 text PATH '$."a22"'
+                    )
+                )
+            )
+            PLAN (json_table_path_1 OUTER ((p1 OUTER "p1 1") UNION (p2 OUTER ("p2:1" UNION p22))))
+        );
+EXPLAIN (COSTS OFF, VERBOSE) SELECT * FROM jsonb_table_view;
+DROP VIEW jsonb_table_view;
 DROP VIEW jsonb_table_view_nested;
+DROP DOMAIN jsonb_test_domain;
 
 CREATE TABLE s (js jsonb);
 INSERT INTO s VALUES
-- 
2.43.0

