Files
Robert Haas e0b37905ac pg_plan_advice: DO_NOT_SCAN is a simple tag, not a generic one.
Generic tags allow sublists, e.g. MERGE_JOIN((x y)), but simple
tags do not, e.g. SEQ_SCAN(x) is valid but SEQ_SCAN((x)) is not.
DO_NOT_SCAN was intended to be simple tag, but was accidentally
implemented as a generic one. This could result in assertion
failures. Repair.

Reported-by: Nikita Kalinin <[email protected]>
Analyzed-by: Tender Wang <[email protected]>
Analyzed-by: Ayush Tiwari <[email protected]>
Discussion: http://postgr.es/m/[email protected]
2026-05-29 13:51:09 -04:00

89 lines
3.4 KiB
SQL

LOAD 'pg_plan_advice';
-- An empty string is allowed. Empty target lists are allowed for most advice
-- tags, but not for JOIN_ORDER. "Supplied Plan Advice" should be omitted in
-- text format when there is no actual advice, but not in non-text format.
SET pg_plan_advice.advice = '';
EXPLAIN (COSTS OFF) SELECT 1;
SET pg_plan_advice.advice = 'SEQ_SCAN()';
EXPLAIN (COSTS OFF) SELECT 1;
SET pg_plan_advice.advice = 'NESTED_LOOP_PLAIN()';
EXPLAIN (COSTS OFF, FORMAT JSON) SELECT 1;
SET pg_plan_advice.advice = 'JOIN_ORDER()';
-- Test assorted variations in capitalization, whitespace, and which parts of
-- the relation identifier are included. These should all work.
SET pg_plan_advice.advice = 'SEQ_SCAN(x)';
EXPLAIN (COSTS OFF) SELECT 1;
SET pg_plan_advice.advice = 'seq_scan(x@y)';
EXPLAIN (COSTS OFF) SELECT 1;
SET pg_plan_advice.advice = 'SEQ_scan(x#2)';
EXPLAIN (COSTS OFF) SELECT 1;
SET pg_plan_advice.advice = 'SEQ_SCAN (x/y)';
EXPLAIN (COSTS OFF) SELECT 1;
SET pg_plan_advice.advice = ' SEQ_SCAN ( x / y . z ) ';
EXPLAIN (COSTS OFF) SELECT 1;
SET pg_plan_advice.advice = 'SEQ_SCAN("x"#2/"y"."z"@"t")';
EXPLAIN (COSTS OFF) SELECT 1;
-- Syntax errors.
SET pg_plan_advice.advice = 'SEQUENTIAL_SCAN(x)';
SET pg_plan_advice.advice = 'SEQ_SCAN';
SET pg_plan_advice.advice = 'SEQ_SCAN(';
SET pg_plan_advice.advice = 'SEQ_SCAN("';
SET pg_plan_advice.advice = 'SEQ_SCAN("")';
SET pg_plan_advice.advice = 'SEQ_SCAN("a"';
SET pg_plan_advice.advice = 'SEQ_SCAN(#';
SET pg_plan_advice.advice = '()';
SET pg_plan_advice.advice = '123';
-- Tags like SEQ_SCAN and NO_GATHER don't allow sublists at all; other tags,
-- except for JOIN_ORDER, allow at most one level of sublist. Hence, these
-- examples should error out.
SET pg_plan_advice.advice = 'SEQ_SCAN((x))';
SET pg_plan_advice.advice = 'DO_NOT_SCAN((x))';
SET pg_plan_advice.advice = 'GATHER(((x)))';
-- Legal comments.
SET pg_plan_advice.advice = '/**/';
EXPLAIN (COSTS OFF) SELECT 1;
SET pg_plan_advice.advice = 'HASH_JOIN(_)/***/';
EXPLAIN (COSTS OFF) SELECT 1;
SET pg_plan_advice.advice = '/* comment */ HASH_JOIN(/*x*/y)';
EXPLAIN (COSTS OFF) SELECT 1;
SET pg_plan_advice.advice = '/* comment */ HASH_JOIN(y//*x*/z)';
EXPLAIN (COSTS OFF) SELECT 1;
-- Unterminated comments.
SET pg_plan_advice.advice = '/*';
SET pg_plan_advice.advice = 'JOIN_ORDER("fOO") /* oops';
-- Nested comments are not supported, so the first of these is legal and
-- the second is not.
SET pg_plan_advice.advice = '/*/*/';
EXPLAIN (COSTS OFF) SELECT 1;
SET pg_plan_advice.advice = '/*/* stuff */*/';
-- Foreign join requires multiple relation identifiers.
SET pg_plan_advice.advice = 'FOREIGN_JOIN(a)';
SET pg_plan_advice.advice = 'FOREIGN_JOIN((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)';
EXPLAIN (COSTS OFF) SELECT 1;
SET pg_plan_advice.advice = 'SEQ_SCAN(seq_scan)';
EXPLAIN (COSTS OFF) SELECT 1;
SET pg_plan_advice.advice = 'SEQ_SCAN(gather)';
EXPLAIN (COSTS OFF) SELECT 1;
SET pg_plan_advice.advice = 'SEQ_SCAN(join_order)';
EXPLAIN (COSTS OFF) SELECT 1;
-- Tag keywords used as partition names or plan names should also work,
-- since pgpa_identifier_string() can generate these from real partition
-- and subquery names.
SET pg_plan_advice.advice = 'SEQ_SCAN(t/public.hash_join)';
SET pg_plan_advice.advice = 'SEQ_SCAN(t/hash_join.foo)';
SET pg_plan_advice.advice = 'SEQ_SCAN(t@hash_join)';
SET pg_plan_advice.advice = 'SEQ_SCAN(t@seq_scan)';