PG17 Compatibility - Fix HideCitusDependentObjects function (#7796)

There is a crash when running vanilla tests because of the
`citus.hide_citus_dependent_objects` GUC. We turn on this GUC only for
the pg vanilla tests. This GUC runs the following function
`HideCitusDependentObjectsOnQueriesOfPgMetaTables`. This function
doesn't take into account the new `mergeJoinCondition`. I rewrote the
function such that it checks for merge join conditions as well.

Relevant PG commit:
https://github.com/postgres/postgres/commit/0294df2f1

The crash could be reproduced locally like the following:
```SQL
SET citus.hide_citus_dependent_objects TO on;

CREATE OR REPLACE FUNCTION
    pg_catalog.is_citus_depended_object(oid,oid)
    RETURNS bool
    LANGUAGE C
    AS 'citus', $$is_citus_depended_object$$;

-- try a system catalog
MERGE INTO pg_class c
USING (SELECT 'pg_depend'::regclass AS oid) AS j
ON j.oid = c.oid
WHEN MATCHED THEN
UPDATE SET reltuples = reltuples + 1
RETURNING j.oid;

CREATE VIEW classv AS SELECT * FROM pg_class;

MERGE INTO classv c
USING pg_namespace n
ON n.oid = c.relnamespace
WHEN MATCHED AND c.oid = 'pg_depend'::regclass THEN
UPDATE SET reltuples = reltuples - 1
RETURNING c.oid;
-- crash happens here
```
pull/7797/head
Naisila Puka 2024-12-20 17:59:09 +03:00 committed by GitHub
parent e4d48dc5da
commit 61d11ec2d4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 26 additions and 4 deletions

View File

@ -243,12 +243,24 @@ HideCitusDependentObjectsOnQueriesOfPgMetaTables(Node *node, void *context)
if (OidIsValid(metaTableOid))
{
bool mergeJoinCondition = false;
#if PG_VERSION_NUM >= PG_VERSION_17
/*
* In Postgres 17, the query tree has a specific field for the merge condition.
* So we shouldn't modify the jointree, but rather the mergeJoinCondition here
* Relevant PG17 commit: 0294df2f1
*/
mergeJoinCondition = query->mergeJoinCondition;
#endif
/*
* We found a valid pg meta class in query,
* so we assert below conditions.
*/
Assert(query->jointree != NULL);
Assert(query->jointree->fromlist != NULL);
Assert(mergeJoinCondition ||
(query->jointree != NULL &&
query->jointree->fromlist != NULL));
Node *citusDependentObjExpr =
CreateCitusDependentObjectExpr(varno, metaTableOid);
@ -257,8 +269,18 @@ HideCitusDependentObjectsOnQueriesOfPgMetaTables(Node *node, void *context)
* We do not use security quals because a postgres vanilla test fails
* with a change of order for its result.
*/
query->jointree->quals = make_and_qual(
query->jointree->quals, citusDependentObjExpr);
if (!mergeJoinCondition)
{
query->jointree->quals = make_and_qual(
query->jointree->quals, citusDependentObjExpr);
}
else
{
#if PG_VERSION_NUM >= PG_VERSION_17
query->mergeJoinCondition = make_and_qual(
query->mergeJoinCondition, citusDependentObjExpr);
#endif
}
}
MemoryContextSwitchTo(originalContext);