mirror of
https://github.com/postgres/postgres.git
synced 2026-03-23 19:04:11 -04:00
TOK_IDENT allows only non-keywords; identifier should be used any place where either keywords or non-keywords should be accepted. Hence, without this commit, any string that happens to be a keyword can't be used as a partition schema, partition name, or plan name, which is incorrect. Author: Lukas Fittl <lukas@fittl.com> Discussion: http://postgr.es/m/CAP53PkzKeD=t90OfeMsniYrcRe2THQbUx3g6wV17Y=ZtiwmWTQ@mail.gmail.com
237 lines
8.4 KiB
Text
237 lines
8.4 KiB
Text
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;
|
|
QUERY PLAN
|
|
------------
|
|
Result
|
|
(1 row)
|
|
|
|
SET pg_plan_advice.advice = 'SEQ_SCAN()';
|
|
EXPLAIN (COSTS OFF) SELECT 1;
|
|
QUERY PLAN
|
|
------------
|
|
Result
|
|
(1 row)
|
|
|
|
SET pg_plan_advice.advice = 'NESTED_LOOP_PLAIN()';
|
|
EXPLAIN (COSTS OFF, FORMAT JSON) SELECT 1;
|
|
QUERY PLAN
|
|
--------------------------------
|
|
[ +
|
|
{ +
|
|
"Plan": { +
|
|
"Node Type": "Result", +
|
|
"Parallel Aware": false,+
|
|
"Async Capable": false, +
|
|
"Disabled": false +
|
|
}, +
|
|
"Supplied Plan Advice": ""+
|
|
} +
|
|
]
|
|
(1 row)
|
|
|
|
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 must have at least one target at or near ")"
|
|
-- 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;
|
|
QUERY PLAN
|
|
---------------------------------
|
|
Result
|
|
Supplied Plan Advice:
|
|
SEQ_SCAN(x) /* not matched */
|
|
(3 rows)
|
|
|
|
SET pg_plan_advice.advice = 'seq_scan(x@y)';
|
|
EXPLAIN (COSTS OFF) SELECT 1;
|
|
QUERY PLAN
|
|
-----------------------------------
|
|
Result
|
|
Supplied Plan Advice:
|
|
SEQ_SCAN(x@y) /* not matched */
|
|
(3 rows)
|
|
|
|
SET pg_plan_advice.advice = 'SEQ_scan(x#2)';
|
|
EXPLAIN (COSTS OFF) SELECT 1;
|
|
QUERY PLAN
|
|
-----------------------------------
|
|
Result
|
|
Supplied Plan Advice:
|
|
SEQ_SCAN(x#2) /* not matched */
|
|
(3 rows)
|
|
|
|
SET pg_plan_advice.advice = 'SEQ_SCAN (x/y)';
|
|
EXPLAIN (COSTS OFF) SELECT 1;
|
|
QUERY PLAN
|
|
-----------------------------------
|
|
Result
|
|
Supplied Plan Advice:
|
|
SEQ_SCAN(x/y) /* not matched */
|
|
(3 rows)
|
|
|
|
SET pg_plan_advice.advice = ' SEQ_SCAN ( x / y . z ) ';
|
|
EXPLAIN (COSTS OFF) SELECT 1;
|
|
QUERY PLAN
|
|
-------------------------------------
|
|
Result
|
|
Supplied Plan Advice:
|
|
SEQ_SCAN(x/y.z) /* not matched */
|
|
(3 rows)
|
|
|
|
SET pg_plan_advice.advice = 'SEQ_SCAN("x"#2/"y"."z"@"t")';
|
|
EXPLAIN (COSTS OFF) SELECT 1;
|
|
QUERY PLAN
|
|
-----------------------------------------
|
|
Result
|
|
Supplied Plan Advice:
|
|
SEQ_SCAN(x#2/y.z@t) /* not matched */
|
|
(3 rows)
|
|
|
|
-- Syntax errors.
|
|
SET pg_plan_advice.advice = 'SEQUENTIAL_SCAN(x)';
|
|
ERROR: invalid value for parameter "pg_plan_advice.advice": "SEQUENTIAL_SCAN(x)"
|
|
DETAIL: Could not parse advice: syntax error at or near "SEQUENTIAL_SCAN"
|
|
SET pg_plan_advice.advice = 'SEQ_SCAN';
|
|
ERROR: invalid value for parameter "pg_plan_advice.advice": "SEQ_SCAN"
|
|
DETAIL: Could not parse advice: syntax error at end of input
|
|
SET pg_plan_advice.advice = 'SEQ_SCAN(';
|
|
ERROR: invalid value for parameter "pg_plan_advice.advice": "SEQ_SCAN("
|
|
DETAIL: Could not parse advice: syntax error at end of input
|
|
SET pg_plan_advice.advice = 'SEQ_SCAN("';
|
|
ERROR: invalid value for parameter "pg_plan_advice.advice": "SEQ_SCAN(""
|
|
DETAIL: Could not parse advice: unterminated quoted identifier at end of input
|
|
SET pg_plan_advice.advice = 'SEQ_SCAN("")';
|
|
ERROR: invalid value for parameter "pg_plan_advice.advice": "SEQ_SCAN("")"
|
|
DETAIL: Could not parse advice: zero-length delimited identifier at or near """
|
|
SET pg_plan_advice.advice = 'SEQ_SCAN("a"';
|
|
ERROR: invalid value for parameter "pg_plan_advice.advice": "SEQ_SCAN("a""
|
|
DETAIL: Could not parse advice: syntax error at end of input
|
|
SET pg_plan_advice.advice = 'SEQ_SCAN(#';
|
|
ERROR: invalid value for parameter "pg_plan_advice.advice": "SEQ_SCAN(#"
|
|
DETAIL: Could not parse advice: syntax error at or near "#"
|
|
SET pg_plan_advice.advice = '()';
|
|
ERROR: invalid value for parameter "pg_plan_advice.advice": "()"
|
|
DETAIL: Could not parse advice: syntax error at or near "("
|
|
SET pg_plan_advice.advice = '123';
|
|
ERROR: invalid value for parameter "pg_plan_advice.advice": "123"
|
|
DETAIL: Could not parse advice: syntax error at or near "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))';
|
|
ERROR: invalid value for parameter "pg_plan_advice.advice": "SEQ_SCAN((x))"
|
|
DETAIL: Could not parse advice: syntax error at or near "("
|
|
SET pg_plan_advice.advice = 'GATHER(((x)))';
|
|
ERROR: invalid value for parameter "pg_plan_advice.advice": "GATHER(((x)))"
|
|
DETAIL: Could not parse advice: syntax error at or near "("
|
|
-- Legal comments.
|
|
SET pg_plan_advice.advice = '/**/';
|
|
EXPLAIN (COSTS OFF) SELECT 1;
|
|
QUERY PLAN
|
|
------------
|
|
Result
|
|
(1 row)
|
|
|
|
SET pg_plan_advice.advice = 'HASH_JOIN(_)/***/';
|
|
EXPLAIN (COSTS OFF) SELECT 1;
|
|
QUERY PLAN
|
|
----------------------------------
|
|
Result
|
|
Supplied Plan Advice:
|
|
HASH_JOIN(_) /* not matched */
|
|
(3 rows)
|
|
|
|
SET pg_plan_advice.advice = '/* comment */ HASH_JOIN(/*x*/y)';
|
|
EXPLAIN (COSTS OFF) SELECT 1;
|
|
QUERY PLAN
|
|
----------------------------------
|
|
Result
|
|
Supplied Plan Advice:
|
|
HASH_JOIN(y) /* not matched */
|
|
(3 rows)
|
|
|
|
SET pg_plan_advice.advice = '/* comment */ HASH_JOIN(y//*x*/z)';
|
|
EXPLAIN (COSTS OFF) SELECT 1;
|
|
QUERY PLAN
|
|
------------------------------------
|
|
Result
|
|
Supplied Plan Advice:
|
|
HASH_JOIN(y/z) /* not matched */
|
|
(3 rows)
|
|
|
|
-- Unterminated comments.
|
|
SET pg_plan_advice.advice = '/*';
|
|
ERROR: invalid value for parameter "pg_plan_advice.advice": "/*"
|
|
DETAIL: Could not parse advice: unterminated comment at end of input
|
|
SET pg_plan_advice.advice = 'JOIN_ORDER("fOO") /* oops';
|
|
ERROR: invalid value for parameter "pg_plan_advice.advice": "JOIN_ORDER("fOO") /* oops"
|
|
DETAIL: Could not parse advice: unterminated comment at end of input
|
|
-- 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;
|
|
QUERY PLAN
|
|
------------
|
|
Result
|
|
(1 row)
|
|
|
|
SET pg_plan_advice.advice = '/*/* stuff */*/';
|
|
ERROR: invalid value for parameter "pg_plan_advice.advice": "/*/* stuff */*/"
|
|
DETAIL: Could not parse advice: syntax error at or near "*"
|
|
-- Foreign join requires multiple relation identifiers.
|
|
SET pg_plan_advice.advice = 'FOREIGN_JOIN(a)';
|
|
ERROR: invalid value for parameter "pg_plan_advice.advice": "FOREIGN_JOIN(a)"
|
|
DETAIL: Could not parse advice: FOREIGN_JOIN targets must contain more than one relation identifier at or near ")"
|
|
SET pg_plan_advice.advice = 'FOREIGN_JOIN((a))';
|
|
ERROR: invalid value for parameter "pg_plan_advice.advice": "FOREIGN_JOIN((a))"
|
|
DETAIL: Could not parse advice: FOREIGN_JOIN targets must contain more than 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)';
|
|
EXPLAIN (COSTS OFF) SELECT 1;
|
|
QUERY PLAN
|
|
-----------------------------------------
|
|
Result
|
|
Supplied Plan Advice:
|
|
SEQ_SCAN(hash_join) /* not matched */
|
|
(3 rows)
|
|
|
|
SET pg_plan_advice.advice = 'SEQ_SCAN(seq_scan)';
|
|
EXPLAIN (COSTS OFF) SELECT 1;
|
|
QUERY PLAN
|
|
----------------------------------------
|
|
Result
|
|
Supplied Plan Advice:
|
|
SEQ_SCAN(seq_scan) /* not matched */
|
|
(3 rows)
|
|
|
|
SET pg_plan_advice.advice = 'SEQ_SCAN(gather)';
|
|
EXPLAIN (COSTS OFF) SELECT 1;
|
|
QUERY PLAN
|
|
--------------------------------------
|
|
Result
|
|
Supplied Plan Advice:
|
|
SEQ_SCAN(gather) /* not matched */
|
|
(3 rows)
|
|
|
|
SET pg_plan_advice.advice = 'SEQ_SCAN(join_order)';
|
|
EXPLAIN (COSTS OFF) SELECT 1;
|
|
QUERY PLAN
|
|
------------------------------------------
|
|
Result
|
|
Supplied Plan Advice:
|
|
SEQ_SCAN(join_order) /* not matched */
|
|
(3 rows)
|
|
|
|
-- 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)';
|