From 18a315123ca5b32627906c74a77c22355dbee9f1 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Thu, 10 Sep 2026 10:12:46 -0400 Subject: [PATCH v5 3/4] pg_plan_advice: Disallow empty sublists within JOIN_ORDER() Commit 8c9c2e5c09aeda713640ccb26bfca0fdccc310d5 fixed a similar issue for FOREIGN_JOIN(). Handle this case similar to the way that commit handled that case. Backpatch-through: 19 Discussion: https://postgr.es/m/CA+TgmoYmXy-jiP5qDhqNEiYFEBzQsArO6O2d9E8szNZqi1bePQ@mail.gmail.com --- contrib/pg_plan_advice/expected/syntax.out | 7 +++++++ contrib/pg_plan_advice/pgpa_parser.y | 6 ++++++ contrib/pg_plan_advice/sql/syntax.sql | 4 ++++ 3 files changed, 17 insertions(+) diff --git a/contrib/pg_plan_advice/expected/syntax.out b/contrib/pg_plan_advice/expected/syntax.out index d53d9598634..6062f245307 100644 --- a/contrib/pg_plan_advice/expected/syntax.out +++ b/contrib/pg_plan_advice/expected/syntax.out @@ -212,6 +212,13 @@ DETAIL: Could not parse advice: FOREIGN_JOIN targets must contain more than one SET pg_plan_advice.advice = 'FOREIGN_JOIN(())'; ERROR: invalid value for parameter "pg_plan_advice.advice": "FOREIGN_JOIN(())" DETAIL: Could not parse advice: FOREIGN_JOIN targets must contain more than one relation identifier at or near ")" +-- Join order requires at least one relation identifier. +SET pg_plan_advice.advice = 'JOIN_ORDER(())'; +ERROR: invalid value for parameter "pg_plan_advice.advice": "JOIN_ORDER(())" +DETAIL: Could not parse advice: JOIN_ORDER targets must contain at least one relation identifier at or near ")" +SET pg_plan_advice.advice = 'JOIN_ORDER(a ({}))'; +ERROR: invalid value for parameter "pg_plan_advice.advice": "JOIN_ORDER(a ({}))" +DETAIL: Could not parse advice: JOIN_ORDER targets must contain at least one relation identifier at or near "}" -- Tag keywords used as alias names work fine, because the 'identifier' -- nonterminal accepts all token types. SET pg_plan_advice.advice = 'SEQ_SCAN(hash_join)'; diff --git a/contrib/pg_plan_advice/pgpa_parser.y b/contrib/pg_plan_advice/pgpa_parser.y index 295f16ad064..8ffa1f1dd40 100644 --- a/contrib/pg_plan_advice/pgpa_parser.y +++ b/contrib/pg_plan_advice/pgpa_parser.y @@ -257,12 +257,18 @@ join_order_sublist: $$ = palloc0_object(pgpa_advice_target); $$->ttype = PGPA_TARGET_ORDERED_LIST; $$->children = $2; + if ($2 == NIL) + pgpa_yyerror(result, parse_error_msg_p, yyscanner, + "JOIN_ORDER targets must contain at least one relation identifier"); } | '{' simple_target_list '}' { $$ = palloc0_object(pgpa_advice_target); $$->ttype = PGPA_TARGET_UNORDERED_LIST; $$->children = $2; + if ($2 == NIL) + pgpa_yyerror(result, parse_error_msg_p, yyscanner, + "JOIN_ORDER targets must contain at least one relation identifier"); } ; diff --git a/contrib/pg_plan_advice/sql/syntax.sql b/contrib/pg_plan_advice/sql/syntax.sql index de11e8c6fc2..c762b8b19b2 100644 --- a/contrib/pg_plan_advice/sql/syntax.sql +++ b/contrib/pg_plan_advice/sql/syntax.sql @@ -75,6 +75,10 @@ SET pg_plan_advice.advice = 'FOREIGN_JOIN(a)'; SET pg_plan_advice.advice = 'FOREIGN_JOIN((a))'; SET pg_plan_advice.advice = 'FOREIGN_JOIN(())'; +-- Join order requires at least one relation identifier. +SET pg_plan_advice.advice = 'JOIN_ORDER(())'; +SET pg_plan_advice.advice = 'JOIN_ORDER(a ({}))'; + -- Tag keywords used as alias names work fine, because the 'identifier' -- nonterminal accepts all token types. SET pg_plan_advice.advice = 'SEQ_SCAN(hash_join)'; -- 2.51.0