postgres.git / summary / log / commit / refs

commit    120ea65b8a0c7fd5c8f45030ec6a7fd979eaafc3
Author:   Tom Lane <tgl@sss.pgh.pa.us>
Date:     Wed Jun 21 15:07:11 2023 +0000

    Avoid Assert failure when processing empty statement in aborted xact.
    
    exec_parse_message() wants to create a cached plan in all cases,
    including for empty input.  The empty-input path does not have
    a test for being in an aborted transaction, making it possible
    that plancache.c will fail due to trying to do database lookups
    even though there's no real work to do.
    
    One solution would be to throw an aborted-transaction error in
    this path too, but it's not entirely clear whether the lack of
    such an error was intentional or whether some clients might be
    relying on non-error behavior.  Instead, let's hack plancache.c
    so that it treats empty statements with the same logic it
    already had for transaction control commands, ensuring that it
    can soldier through even in an already-aborted transaction.
    
    Per bug #17983 from Alexander Lakhin.  Back-patch to all
    supported branches.
    
    Discussion: https://postgr.es/m/17983-da4569fcb878672e@postgresql.org


src/backend/utils/cache/plancache.c | 4 +++- src/test/regress/expected/psql.out | 11 +++++++++++ src/test/regress/sql/psql.sql | 8 ++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c index 6767eae8f20..e1a873967f0 100644 --- a/src/backend/utils/cache/plancache.c +++ b/src/backend/utils/cache/plancache.c @@ -78,9 +78,11 @@ /* * We must skip "overhead" operations that involve database access when the * cached plan's subject statement is a transaction control command. + * For the convenience of postgres.c, treat empty statements as control + * commands too. */ #define IsTransactionStmtPlan(plansource) \ - ((plansource)->raw_parse_tree && \ + ((plansource)->raw_parse_tree == NULL || \ IsA((plansource)->raw_parse_tree->stmt, TransactionStmt)) /* diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out index a15db7c78ed..265518de1ff 100644 --- a/src/test/regress/expected/psql.out +++ b/src/test/regress/expected/psql.out @@ -237,6 +237,17 @@ SELECT 3 AS x, 'Hello', 4 AS y, true AS "dirty\name" \gdesc \g 3 | Hello | 4 | t (1 row) +-- test for server bug #17983 with empty statement in aborted transaction +set search_path = default; +begin; +bogus; +ERROR: syntax error at or near "bogus" +LINE 1: bogus; + ^ +; +\gdesc +The command has no result, or the result has no columns. +rollback; -- \gexec create temporary table gexec_test(a int, b text, c date, d float); select format('create index on gexec_test(%I)', attname) diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql index 338a904ec77..26ffe064403 100644 --- a/src/test/regress/sql/psql.sql +++ b/src/test/regress/sql/psql.sql @@ -119,6 +119,14 @@ SELECT 1 AS x, 'Hello', 2 AS y, true AS "dirty\name" -- all on one line SELECT 3 AS x, 'Hello', 4 AS y, true AS "dirty\name" \gdesc \g +-- test for server bug #17983 with empty statement in aborted transaction +set search_path = default; +begin; +bogus; +; +\gdesc +rollback; + -- \gexec create temporary table gexec_test(a int, b text, c date, d float); [parent: 2634926906de]