From bb840e58a79f902f7c3b45a28815d6613da325f4 Mon Sep 17 00:00:00 2001 From: Naisila Puka <37271756+naisila@users.noreply.github.com> Date: Wed, 1 Oct 2025 00:09:11 +0300 Subject: [PATCH] Fix crash on create statistics with non-RangeVar type (#8213) This crash has been there for a while but wasn't tested before pg18. PG18 added this test: CREATE STATISTICS tst ON a FROM (VALUES (x)) AS foo; which tries to create statistics on a derived-on-the-fly table (which is not allowed) However Citus assumes we always have a valid table when intercepting CREATE STATISTICS command to check for Citus tables Added a check to return early if needed. pg18 commit: https://github.com/postgres/postgres/commit/3eea4dc2c Fixes #8212 --- src/backend/distributed/commands/statistics.c | 10 +++++++++- src/test/regress/expected/pg18.out | 8 +++++++- src/test/regress/expected/pg18_0.out | 5 +++++ src/test/regress/sql/pg18.sql | 7 ++++++- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/backend/distributed/commands/statistics.c b/src/backend/distributed/commands/statistics.c index b43f6335e..7a77b6b3d 100644 --- a/src/backend/distributed/commands/statistics.c +++ b/src/backend/distributed/commands/statistics.c @@ -69,7 +69,15 @@ PreprocessCreateStatisticsStmt(Node *node, const char *queryString, { CreateStatsStmt *stmt = castNode(CreateStatsStmt, node); - RangeVar *relation = (RangeVar *) linitial(stmt->relations); + Node *relationNode = (Node *) linitial(stmt->relations); + + if (!IsA(relationNode, RangeVar)) + { + return NIL; + } + + RangeVar *relation = (RangeVar *) relationNode; + Oid relationId = RangeVarGetRelid(relation, ShareUpdateExclusiveLock, false); if (!IsCitusTable(relationId) || !ShouldPropagate()) diff --git a/src/test/regress/expected/pg18.out b/src/test/regress/expected/pg18.out index f5d35a47e..fd42f4070 100644 --- a/src/test/regress/expected/pg18.out +++ b/src/test/regress/expected/pg18.out @@ -4,11 +4,17 @@ SHOW server_version \gset SELECT substring(:'server_version', '\d+')::int >= 18 AS server_version_ge_18 \gset +-- test invalid statistics +-- behavior is same among PG versions, error message differs +-- relevant PG18 commit: 3eea4dc2c7 +CREATE STATISTICS tst ON a FROM (VALUES (x)) AS foo; +ERROR: cannot create statistics on the specified relation +DETAIL: CREATE STATISTICS only supports tables, foreign tables and materialized views. \if :server_version_ge_18 \else \q \endif --- PG17-specific tests go here. +-- PG18-specific tests go here. -- -- Purpose: Verify PG18 behavior that NOT NULL constraints are materialized -- as pg_constraint rows with contype = 'n' on both coordinator and diff --git a/src/test/regress/expected/pg18_0.out b/src/test/regress/expected/pg18_0.out index b682ea190..8d8c55727 100644 --- a/src/test/regress/expected/pg18_0.out +++ b/src/test/regress/expected/pg18_0.out @@ -4,6 +4,11 @@ SHOW server_version \gset SELECT substring(:'server_version', '\d+')::int >= 18 AS server_version_ge_18 \gset +-- test invalid statistics +-- behavior is same among PG versions, error message differs +-- relevant PG18 commit: 3eea4dc2c7 +CREATE STATISTICS tst ON a FROM (VALUES (x)) AS foo; +ERROR: only a single relation is allowed in CREATE STATISTICS \if :server_version_ge_18 \else \q diff --git a/src/test/regress/sql/pg18.sql b/src/test/regress/sql/pg18.sql index e18e7455b..94c0ad997 100644 --- a/src/test/regress/sql/pg18.sql +++ b/src/test/regress/sql/pg18.sql @@ -5,12 +5,17 @@ SHOW server_version \gset SELECT substring(:'server_version', '\d+')::int >= 18 AS server_version_ge_18 \gset +-- test invalid statistics +-- behavior is same among PG versions, error message differs +-- relevant PG18 commit: 3eea4dc2c7 +CREATE STATISTICS tst ON a FROM (VALUES (x)) AS foo; + \if :server_version_ge_18 \else \q \endif --- PG17-specific tests go here. +-- PG18-specific tests go here. -- -- Purpose: Verify PG18 behavior that NOT NULL constraints are materialized