Skip to content

Commit 9e42f3f

Browse files
authored
Add PG 18Beta1 compatibility (Build + RuleUtils) (#7981)
This PR provides successful build against PG18Beta1. RuleUtils PR was reviewed separately: #8010 ## PG 18Beta1–related changes for building Citus ### TupleDesc / Attr layout **What changed in PG:** Postgres consolidated the `TupleDescData.attrs[]` array into a more compact representation. Direct field access (tupdesc->attrs[i]) was replaced by the new `TupleDescAttr()` API. **Citus adaptation:** Everywhere we previously used `tupdesc->attrs[...]`, we now call `TupleDescAttr(tupdesc, idx)` (or our own `Attr()` macro) under a compatibility guard. * postgres/postgres@5983a4c General Logic: * Use `Attr(...)` in places where `columnar_version_compat.h` is included. This avoids the need to sprinkle `#if PG_VERSION_NUM` guards around each attribute access. * Use `TupleDescAttr(tupdesc, i)` when the relevant PostgreSQL header is already included and the additional macro indirection is unnecessary. ### Collation‐aware `LIKE` **What changed in PG:** The `textlike` operator now requires an explicit collation, to avoid ambiguous‐collation errors. Core code switched from `DirectFunctionCall2(textlike, ...)` to `DirectFunctionCall2Coll(textlike, DEFAULT_COLLATION_OID, ...)`. **Citus adaptation:** In `remote_commands.c` and any other LIKE call, we now use `DirectFunctionCall2Coll(textlike, DEFAULT_COLLATION_OID, ...)` and `#include <utils/pg_collation.h>`. * postgres/postgres@85b7efa ### Columnar storage API * Adapt `columnar_relation_set_new_filelocator` (and related init routines) for PG 18’s revised SMGR and storage-initialization hooks. * Pull in the new headers (`explain_format.h`, `columnar_version_compat.h`) so the columnar module compiles cleanly against PG 18. - heap_modify_tuple + heap_inplace_update only exist on PG < 18; on PG18 the in-place helper was removed upstream - postgres/postgres@a07e03f ### OpenSSL / TLS integration **What changed in PG:** Moved from the legacy `SSL_library_init()` to `OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL)`, updated certificate API calls (`X509_getm_notBefore`, `X509_getm_notAfter`), and standardized on `TLS_method()`. **Citus adaptation:** We now `#include <openssl/opensslv.h>` and use `#if OPENSSL_VERSION_NUMBER >= 0x10100000L` to choose between` OPENSSL_init_ssl()` or `SSL_library_init()`, and wrap` X509_gmtime_adj()` calls around the new accessor functions. * postgres/postgres@6c66b74 ### Adapt `ExtractColumns()` to the new PG-18 `expandRTE()` signature PostgreSQL 18 postgres/postgres@80feb72 added a fourth argument of type `VarReturningType` to `expandRTE()`, so calls that used the old 7-parameter form no longer compile. This patch: * Wraps the `expandRTE(...)` call in a `#if PG_VERSION_NUM >= 180000` guard. * On PG 18+ passes the new `VAR_RETURNING_DEFAULT` argument before `location`. * On PG 15–17 continues to call the original 7-arg form. * Adds the necessary includes (`parser/parse_relation.h` for `expandRTE` and `VarReturningType`, and `pg_version_constants.h` for `PG_VERSION_NUM`). ### Adapt `ExecutorStart`/`ExecutorRun` hooks to PG-18’s new signatures PostgreSQL 18 postgres/postgres@525392d changed the signatures of the executor hooks: * `ExecutorStart_hook` now returns `bool` instead of `void`, and * `ExecutorRun_hook` drops its old `run_once` argument. This patch preserves Citus’s existing hook logic by: 1. **Adding two adapter functions** under `#if PG_VERSION_NUM >= PG_VERSION_18`: * `citus_executor_start_adapter(QueryDesc *queryDesc, int eflags)` Calls the old `CitusExecutorStart(queryDesc, eflags)` and then returns `true` to satisfy the new hook’s `bool` return type. * `citus_executor_run_adapter(QueryDesc *queryDesc, ScanDirection direction, uint64 count)` Calls the old `CitusExecutorRun(queryDesc, direction, count, true)` (passing `true` for the dropped `run_once` argument), and returns `void`. 2. **Installing the adapters** in `_PG_init()` instead of the original hooks when building against PG 18+: ```c #if PG_VERSION_NUM >= PG_VERSION_18 ExecutorStart_hook = citus_executor_start_adapter; ExecutorRun_hook = citus_executor_run_adapter; #else ExecutorStart_hook = CitusExecutorStart; ExecutorRun_hook = CitusExecutorRun; #endif ``` ### Adapt to PG-18’s removal of the “run\_once” flag from ExecutorRun/PortalRun PostgreSQL commit [[3eea7a0](https://github.com/postgres/postgres/commit/3eea7a0c97e94f9570af87317ce3f6a41eb62768)](https://github.com/postgres/postgres/commit/3eea7a0c97e94f9570af87317ce3f6a41eb62768) rationalized the executor’s parallelism logic by moving the “execute a plan only once” check into `ExecutePlan()` itself and dropping the old `bool run_once` argument from the public APIs: ```diff - void ExecutorRun(QueryDesc *queryDesc, - ScanDirection direction, - uint64 count, - bool run_once); + void ExecutorRun(QueryDesc *queryDesc, + ScanDirection direction, + uint64 count); ``` (and similarly for `PortalRun()`). To stay compatible across PG 15–18, Citus now: 1. **Updates all internal calls** to `ExecutorRun(...)` and `PortalRun(...)`: * On PG 18+, use the new three-argument form (`ExecutorRun(qd, dir, count)`). * On PG 15–17, keep the old four-arg form (`ExecutorRun(qd, dir, count, true)`) under a `#if PG_VERSION_NUM < 180000` guard. 2. **Guards the dispatcher hooks** via the adapter functions (from the earlier patch) so that Citus’s executor hooks continue to work under both the old and new signatures. ### Adapt to PG-18’s shortened PortalRun signature PostgreSQL 18’s refactoring (see commit [3eea7a0](postgres/postgres@3eea7a0)) also removed the old run_once and alternate‐dest arguments from the public PortalRun() API. The signature changed from: ```diff - bool PortalRun(Portal portal, - long count, - bool isTopLevel, - bool run_once, - DestReceiver *dest, - DestReceiver *altdest, - QueryCompletion *qc); + bool PortalRun(Portal portal, + long count, + bool isTopLevel, + DestReceiver *dest, + DestReceiver *altdest, + QueryCompletion *qc); ``` To support both versions in Citus, we: 1. **Version-guard each call** to `PortalRun()`: * **On PG 18+** invoke the new 6-argument form. * **On PG 15–17** fall back to the legacy 7-argument form, passing `true` for `run_once`. ### Add support for PG-18’s new `plansource` argument in `PortalDefineQuery`** PostgreSQL 18 extended the `PortalDefineQuery` API to carry a `CachedPlanSource *plansource` pointer so that the portal machinery can track cached‐plan invalidation (as introduced alongside deferred-locking in commit postgres/postgres@525392d. To remain compatible across PG 15–18, Citus now wraps its calls under a version guard: ```diff - PortalDefineQuery(portal, NULL, sql, commandTag, plantree_list, NULL); +#if PG_VERSION_NUM >= 180000 + /* PG 18+: seven-arg signature (adds plansource) */ + PortalDefineQuery( + portal, + NULL, /* no prepared-stmt name */ + sql, /* the query text */ + commandTag, /* the CommandTag */ + plantree_list, /* List of PlannedStmt* */ + NULL, /* no CachedPlan */ + NULL /* no CachedPlanSource */ + ); +#else + /* PG 15–17: six-arg signature */ + PortalDefineQuery( + portal, + NULL, /* no prepared-stmt name */ + sql, /* the query text */ + commandTag, /* the CommandTag */ + plantree_list, /* List of PlannedStmt* */ + NULL /* no CachedPlan */ + ); +#endif ``` ### Adapt ExecInitRangeTable() calls to PG-18’s new signature PostgreSQL commit [cbc127917e04a978a788b8bc9d35a70244396d5b](postgres/postgres@cbc1279) overhauled the planner API for range‐table initialization: **PG 18+**: added a fourth `Bitmapset *unpruned_relids` argument to support deferred partition pruning In Citus’s `create_estate_for_relation()` (in `columnar_metadata.c`), we now wrap the call in a compile‐time guard so that the code compiles correctly on all supported PostgreSQL versions: ``` /* Prepare permission info on PG 16+ */ #if PG_VERSION_NUM >= PG_VERSION_16 List *perminfos = NIL; addRTEPermissionInfo(&perminfos, rte); #else List *perminfos = NIL; /* unused on PG 15 */ #endif /* Initialize the range table, with the right signature for each PG version */ #if PG_VERSION_NUM >= PG_VERSION_18 /* PG 18+: four‐arg signature (adds unpruned_relids) */ ExecInitRangeTable( estate, list_make1(rte), perminfos, NULL /* unpruned_relids: not used by columnar */ ); #elif PG_VERSION_NUM >= PG_VERSION_16 /* PG 16–17: three‐arg signature (permInfos) */ ExecInitRangeTable( estate, list_make1(rte), perminfos ); #else /* PG 15: two‐arg signature */ ExecInitRangeTable( estate, list_make1(rte) ); #endif estate->es_output_cid = GetCurrentCommandId(true); ``` ### Adapt `pgstat_report_vacuum()` to PG-18’s new timestamp argument PostgreSQL commit [[30a6ed0ce4bb18212ec38cdb537ea4b43bc99b83](https://github.com/postgres/postgres/commit/30a6ed0ce4bb18212ec38cdb537ea4b43bc99b83)](https://github.com/postgres/postgres/commit/30a6ed0ce4bb18212ec38cdb537ea4b43bc99b83) extended the `pgstat_report_vacuum()` API by adding a `TimestampTz start_time` parameter at the end so that the VACUUM statistics collector can record when the operation began: ```diff /* PG ≤17: four-arg signature */ - void pgstat_report_vacuum(Oid tableoid, - bool shared, - double num_live_tuples, - double num_dead_tuples); +/* PG ≥18: five-arg signature adds a start_time */ + void pgstat_report_vacuum(Oid tableoid, + bool shared, + double num_live_tuples, + double num_dead_tuples, + TimestampTz start_time); ``` To support both versions, we now wrap the call in `columnar_tableam.c` with a version guard, supplying `GetCurrentTimestamp()` for PG-18+: ```c #if PG_VERSION_NUM >= 180000 /* PG 18+: include start_timestamp */ pgstat_report_vacuum( RelationGetRelid(rel), rel->rd_rel->relisshared, Max(new_live_tuples, 0), /* live tuples */ 0, /* dead tuples */ GetCurrentTimestamp() /* start time */ ); #else /* PG 15–17: original signature */ pgstat_report_vacuum( RelationGetRelid(rel), rel->rd_rel->relisshared, Max(new_live_tuples, 0), /* live tuples */ 0 /* dead tuples */ ); #endif ``` ### Adapt `ExecuteTaskPlan()` to PG-18’s expanded `CreateQueryDesc()` signature PostgreSQL 18 changed `CreateQueryDesc()` from an eight-argument to a nine-argument call by inserting a `CachedPlan *cplan` parameter immediately after the `PlannedStmt *plannedstmt` argument (see commit postgres/postgres@525392d). To remain compatible with PG 15–17, Citus now wraps its invocation in `local_executor.c` with a version guard: ```diff - /* PG15–17: eight-arg CreateQueryDesc without cached plan */ - QueryDesc *queryDesc = CreateQueryDesc( - taskPlan, /* PlannedStmt *plannedstmt */ - queryString, /* const char *sourceText */ - GetActiveSnapshot(),/* Snapshot snapshot */ - InvalidSnapshot, /* Snapshot crosscheck_snapshot */ - destReceiver, /* DestReceiver *dest */ - paramListInfo, /* ParamListInfo params */ - queryEnv, /* QueryEnvironment *queryEnv */ - 0 /* int instrument_options */ - ); +#if PG_VERSION_NUM >= 180000 + /* PG18+: nine-arg CreateQueryDesc with a CachedPlan slot */ + QueryDesc *queryDesc = CreateQueryDesc( + taskPlan, /* PlannedStmt *plannedstmt */ + NULL, /* CachedPlan *cplan (none) */ + queryString, /* const char *sourceText */ + GetActiveSnapshot(),/* Snapshot snapshot */ + InvalidSnapshot, /* Snapshot crosscheck_snapshot */ + destReceiver, /* DestReceiver *dest */ + paramListInfo, /* ParamListInfo params */ + queryEnv, /* QueryEnvironment *queryEnv */ + 0 /* int instrument_options */ + ); +#else + /* PG15–17: eight-arg CreateQueryDesc without cached plan */ + QueryDesc *queryDesc = CreateQueryDesc( + taskPlan, /* PlannedStmt *plannedstmt */ + queryString, /* const char *sourceText */ + GetActiveSnapshot(),/* Snapshot snapshot */ + InvalidSnapshot, /* Snapshot crosscheck_snapshot */ + destReceiver, /* DestReceiver *dest */ + paramListInfo, /* ParamListInfo params */ + queryEnv, /* QueryEnvironment *queryEnv */ + 0 /* int instrument_options */ + ); +#endif ``` ### Adapt `RelationGetPrimaryKeyIndex()` to PG-18’s new “deferrable\_ok” flag PostgreSQL commit postgres/postgres@14e87ff added a new Boolean `deferrable_ok` parameter to `RelationGetPrimaryKeyIndex()` so that the lock manager can defer unique‐constraint locks when requested. The API changed from: ```c RelationGetPrimaryKeyIndex(Relation relation) ``` to: ```c RelationGetPrimaryKeyIndex(Relation relation, bool deferrable_ok) ``` ```diff diff --git a/src/backend/distributed/metadata/node_metadata.c b/src/backend/distributed/metadata/node_metadata.c index e3a1b2c..f4d5e6f 100644 --- a/src/backend/distributed/metadata/node_metadata.c +++ b/src/backend/distributed/metadata/node_metadata.c @@ -2965,8 +2965,18 @@ */ - Relation replicaIndex = index_open(RelationGetPrimaryKeyIndex(pgDistNode), - AccessShareLock); + #if PG_VERSION_NUM >= PG_VERSION_18 + /* PG 18+ adds a bool "deferrable_ok" parameter */ + Relation replicaIndex = + index_open( + RelationGetPrimaryKeyIndex(pgDistNode, false), + AccessShareLock); + #else + Relation replicaIndex = + index_open( + RelationGetPrimaryKeyIndex(pgDistNode), + AccessShareLock); + #endif ScanKeyInit(&scanKey[0], Anum_pg_dist_node_nodename, BTEqualStrategyNumber, F_TEXTEQ, CStringGetTextDatum(nodeName)); ``` ```diff diff --git a/src/backend/distributed/operations/node_protocol.c b/src/backend/distributed/operations/node_protocol.c index e3a1b2c..f4d5e6f 100644 --- a/src/backend/distributed/operations/node_protocol.c +++ b/src/backend/distributed/operations/node_protocol.c @@ -746,7 +746,12 @@ if (!OidIsValid(idxoid)) { - idxoid = RelationGetPrimaryKeyIndex(rel); + /* Determine the index OID of the primary key (PG18 adds a second parameter) */ +#if PG_VERSION_NUM >= PG_VERSION_18 + idxoid = RelationGetPrimaryKeyIndex(rel, false); +#else + idxoid = RelationGetPrimaryKeyIndex(rel); +#endif } return idxoid; ``` Because Citus has always taken the lock immediately—just as the old two-arg call did—we pass `false` to keep that same immediate-lock behavior. Passing `true` would switch to deferred locking, which we don’t want. ### Adapt `ExplainOnePlan()` to PG-18’s expanded API PostgreSQL 18 extended postgres/postgres@525392d the `ExplainOnePlan()` function to carry the `CachedPlan *` and `CachedPlanSource *` pointers plus an explicit `query_index`, letting the EXPLAIN machinery track plan‐source invalidation. The old signature: ```c /* PG ≤17 */ void ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, struct ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv, const instr_time *planduration, const BufferUsage *bufusage); ``` became, in PG 18: ```c /* PG ≥18 */ void ExplainOnePlan(PlannedStmt *plannedstmt, CachedPlan *cplan, CachedPlanSource *plansource, int query_index, IntoClause *into, struct ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv, const instr_time *planduration, const BufferUsage *bufusage, const MemoryContextCounters *mem_counters); ``` To compile under both versions, Citus now wraps each call in `multi_explain.c` with: ```c #if PG_VERSION_NUM >= PG_VERSION_18 /* PG 18+: pass NULL for the new cached‐plan fields and zero for query_index */ ExplainOnePlan( plan, /* PlannedStmt *plannedstmt */ NULL, /* CachedPlan *cplan */ NULL, /* CachedPlanSource *plansource */ 0, /* query_index */ into, /* IntoClause *into */ es, /* ExplainState *es */ queryString, /* const char *queryString */ params, /* ParamListInfo params */ NULL, /* QueryEnvironment *queryEnv */ &planduration,/* const instr_time *planduration */ (es->buffers ? &bufusage : NULL), (es->memory ? &mem_counters : NULL) ); #elif PG_VERSION_NUM >= PG_VERSION_17 /* PG 17: same as before, plus passing mem_counters if enabled */ ExplainOnePlan( plan, into, es, queryString, params, queryEnv, &planduration, (es->buffers ? &bufusage : NULL), (es->memory ? &mem_counters : NULL) ); #else /* PG 15–16: original seven-arg form */ ExplainOnePlan( plan, into, es, queryString, params, queryEnv, &planduration, (es->buffers ? &bufusage : NULL) ); #endif ``` ### Adapt to the unified “index interpretation” API in PG 18 (commit a8025f544854) PostgreSQL commit postgres/postgres@a8025f5 generalized the old btree‐specific operator‐interpretation API into a single “index interpretation” interface: * **Renamed type**: `OpBtreeInterpretation` → `OpIndexInterpretation` * **Renamed function**: `get_op_btree_interpretation(opno)` → `get_op_index_interpretation(opno)` * **Unified field**: Each interpretation now carries `cmptype` instead of `strategy`. To build cleanly on PG 18 while still supporting PG 15–17, Citus’s shard‐pruning code now wraps these changes: ```c #include "pg_version_constants.h" #if PG_VERSION_NUM >= PG_VERSION_18 /* On PG 18+ the btree‐only APIs vanished; alias them to the new generic versions */ typedef OpIndexInterpretation OpBtreeInterpretation; #define get_op_btree_interpretation(opno) get_op_index_interpretation(opno) #define ROWCOMPARE_NE COMPARE_NE #endif /* … later, when checking an interpretation … */ OpBtreeInterpretation *interp = (OpBtreeInterpretation *) lfirst(cell); #if PG_VERSION_NUM >= PG_VERSION_18 /* use cmptype on PG 18+ */ if (interp->cmptype == ROWCOMPARE_NE) #else /* use strategy on PG 15–17 */ if (interp->strategy == ROWCOMPARE_NE) #endif { /* … */ } ``` ### Adapt `create_foreignscan_path()` for PG-18’s revised signature PostgreSQL commit postgres/postgres@e222534 reordered and removed a couple of parameters in the FDW‐path builder: * **PG 15–17 signature (11 args)** ```c create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel, PathTarget *target, double rows, Cost startup_cost, Cost total_cost, List *pathkeys, Relids required_outer, Path *fdw_outerpath, List *fdw_restrictinfo, List *fdw_private); ``` * **PG 18+ signature (9 args)** ```c create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel, PathTarget *target, double rows, int disabled_nodes, Cost startup_cost, Cost total_cost, Relids required_outer, Path *fdw_outerpath, List *fdw_private); ``` To support both, Citus now defines a compatibility macro in `pg_version_compat.h`: ```c #include "nodes/bitmapset.h" /* for Relids */ #include "nodes/pg_list.h" /* for List */ #include "optimizer/pathnode.h" /* for create_foreignscan_path() */ #if PG_VERSION_NUM >= PG_VERSION_18 /* PG18+: drop pathkeys & fdw_restrictinfo, add disabled_nodes */ #define create_foreignscan_path_compat(a, b, c, d, e, f, g, h, i, j, k) \ create_foreignscan_path( \ (a), /* root */ \ (b), /* rel */ \ (c), /* target */ \ (d), /* rows */ \ (0), /* disabled_nodes (unused by Citus) */ \ (e), /* startup_cost */ \ (f), /* total_cost */ \ (g), /* required_outer */ \ (h), /* fdw_outerpath */ \ (k) /* fdw_private */ \ ) #else /* PG15–17: original signature */ #define create_foreignscan_path_compat(a, b, c, d, e, f, g, h, i, j, k) \ create_foreignscan_path( \ (a), (b), (c), (d), \ (e), (f), \ (g), (h), (i), (j), (k) \ ) #endif ``` Now every call to `create_foreignscan_path_compat(...)`—even in tests like `fake_fdw.c`—automatically picks the correct argument list for PG 15 through PG 18. ### Drop the obsolete bitmap‐scan hooks on PG 18+ PostgreSQL commit postgres/postgres@c395322 cleaned up the `TableAmRoutine` API by removing the two bitmap‐scan callback slots: * `scan_bitmap_next_block` * `scan_bitmap_next_tuple` Since those hook‐slots no longer exist in PG 18, Citus now wraps their NULL‐initialization in a `#if PG_VERSION_NUM < PG_VERSION_18` guard. On PG 15–17 we still explicitly set them to `NULL` (to satisfy the old struct layout), and on PG 18+ we omit them entirely: ```c #if PG_VERSION_NUM < PG_VERSION_18 /* PG 15–17 only: these fields were removed upstream in PG 18 */ .scan_bitmap_next_block = NULL, .scan_bitmap_next_tuple = NULL, #endif ``` ### Adapt `vac_update_relstats()` invocation to PG-18’s new “all\_frozen” argument PostgreSQL commit postgres/postgres@99f8f3f extended the `vac_update_relstats()` API by inserting a `num_all_frozen_pages` parameter between the existing `num_all_visible_pages` and `hasindex` arguments: ```diff - /* PG ≤17: */ - void - vac_update_relstats(Relation relation, - BlockNumber num_pages, - double num_tuples, - BlockNumber num_all_visible_pages, - bool hasindex, - TransactionId frozenxid, - MultiXactId minmulti, - bool *frozenxid_updated, - bool *minmulti_updated, - bool in_outer_xact); + /* PG ≥18: adds num_all_frozen_pages */ + void + vac_update_relstats(Relation relation, + BlockNumber num_pages, + double num_tuples, + BlockNumber num_all_visible_pages, + BlockNumber num_all_frozen_pages, + bool hasindex, + TransactionId frozenxid, + MultiXactId minmulti, + bool *frozenxid_updated, + bool *minmulti_updated, + bool in_outer_xact); ``` To compile cleanly on both PG 15–17 and PG 18+, Citus wraps its call in a version guard and supplies a zero placeholder for the new field: ```c #if PG_VERSION_NUM >= 180000 /* PG 18+: supply explicit “all_frozen” count */ vac_update_relstats( rel, new_rel_pages, new_live_tuples, new_rel_allvisible, /* allvisible */ 0, /* all_frozen */ nindexes > 0, newRelFrozenXid, newRelminMxid, &frozenxid_updated, &minmulti_updated, false /* in_outer_xact */ ); #else /* PG 15–17: original signature */ vac_update_relstats( rel, new_rel_pages, new_live_tuples, new_rel_allvisible, nindexes > 0, newRelFrozenXid, newRelminMxid, &frozenxid_updated, &minmulti_updated, false /* in_outer_xact */ ); #endif ``` **Why all_frozen = 0?** Columnar storage never embeds transaction IDs in its pages, so it never needs to track “all‐frozen” pages the way a heap does. Setting both allvisible and allfrozen to zero simply tells Postgres “there are no pages with the visibility or frozen‐status bits set,” matching our existing behavior. This change ensures Citus’s VACUUM‐statistic updates work unmodified across all supported Postgres versions.
1 parent 5deaf9a commit 9e42f3f

32 files changed

+10885
-86
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ src/backend/distributed/utils/citus_outfuncs.c -citus-style
2828
src/backend/distributed/deparser/ruleutils_15.c -citus-style
2929
src/backend/distributed/deparser/ruleutils_16.c -citus-style
3030
src/backend/distributed/deparser/ruleutils_17.c -citus-style
31+
src/backend/distributed/deparser/ruleutils_18.c -citus-style
3132
src/backend/distributed/commands/index_pg_source.c -citus-style
3233

3334
src/include/distributed/citus_nodes.h -citus-style

src/backend/columnar/columnar_customscan.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@
2121
#include "catalog/pg_am.h"
2222
#include "catalog/pg_statistic.h"
2323
#include "commands/defrem.h"
24+
25+
#include "columnar/columnar_version_compat.h"
26+
#if PG_VERSION_NUM >= PG_VERSION_18
27+
#include "commands/explain_format.h"
28+
#endif
29+
#include "executor/executor.h" /* for ExecInitExprWithParams(), ExecEvalExpr() */
30+
#include "nodes/execnodes.h" /* for ExprState, ExprContext, etc. */
2431
#include "nodes/extensible.h"
2532
#include "nodes/makefuncs.h"
2633
#include "nodes/nodeFuncs.h"

src/backend/columnar/columnar_metadata.c

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -645,10 +645,10 @@ SaveStripeSkipList(RelFileLocator relfilelocator, uint64 stripe,
645645
{
646646
values[Anum_columnar_chunk_minimum_value - 1] =
647647
PointerGetDatum(DatumToBytea(chunk->minimumValue,
648-
&tupleDescriptor->attrs[columnIndex]));
648+
Attr(tupleDescriptor, columnIndex)));
649649
values[Anum_columnar_chunk_maximum_value - 1] =
650650
PointerGetDatum(DatumToBytea(chunk->maximumValue,
651-
&tupleDescriptor->attrs[columnIndex]));
651+
Attr(tupleDescriptor, columnIndex)));
652652
}
653653
else
654654
{
@@ -803,9 +803,9 @@ ReadStripeSkipList(RelFileLocator relfilelocator, uint64 stripe,
803803
datumArray[Anum_columnar_chunk_maximum_value - 1]);
804804

805805
chunk->minimumValue =
806-
ByteaToDatum(minValue, &tupleDescriptor->attrs[columnIndex]);
806+
ByteaToDatum(minValue, Attr(tupleDescriptor, columnIndex));
807807
chunk->maximumValue =
808-
ByteaToDatum(maxValue, &tupleDescriptor->attrs[columnIndex]);
808+
ByteaToDatum(maxValue, Attr(tupleDescriptor, columnIndex));
809809

810810
chunk->hasMinMax = true;
811811
}
@@ -1414,16 +1414,28 @@ UpdateStripeMetadataRow(uint64 storageId, uint64 stripeId, bool *update,
14141414
storageId, stripeId)));
14151415
}
14161416

1417+
1418+
/*
1419+
* heap_modify_tuple + heap_inplace_update only exist on PG < 18;
1420+
* on PG18 the in-place helper was removed upstream, so we skip the whole block.
1421+
*/
1422+
#if PG_VERSION_NUM < PG_VERSION_18
1423+
14171424
/*
14181425
* heap_inplace_update already doesn't allow changing size of the original
14191426
* tuple, so we don't allow setting any Datum's to NULL values.
14201427
*/
14211428
bool newNulls[Natts_columnar_stripe] = { false };
14221429
TupleDesc tupleDescriptor = RelationGetDescr(columnarStripes);
1423-
HeapTuple modifiedTuple = heap_modify_tuple(oldTuple, tupleDescriptor,
1424-
newValues, newNulls, update);
1430+
HeapTuple modifiedTuple = heap_modify_tuple(oldTuple,
1431+
tupleDescriptor,
1432+
newValues,
1433+
newNulls,
1434+
update);
14251435

14261436
heap_inplace_update(columnarStripes, modifiedTuple);
1437+
#endif
1438+
14271439

14281440
/*
14291441
* Existing tuple now contains modifications, because we used
@@ -1727,12 +1739,37 @@ create_estate_for_relation(Relation rel)
17271739
rte->relkind = rel->rd_rel->relkind;
17281740
rte->rellockmode = AccessShareLock;
17291741

1742+
/* Prepare permission info on PG 16+ */
17301743
#if PG_VERSION_NUM >= PG_VERSION_16
17311744
List *perminfos = NIL;
17321745
addRTEPermissionInfo(&perminfos, rte);
1733-
ExecInitRangeTable(estate, list_make1(rte), perminfos);
1746+
#endif
1747+
1748+
/* Initialize the range table, with the right signature for each PG version */
1749+
#if PG_VERSION_NUM >= PG_VERSION_18
1750+
1751+
/* PG 18+ needs four arguments (unpruned_relids) */
1752+
ExecInitRangeTable(
1753+
estate,
1754+
list_make1(rte),
1755+
perminfos,
1756+
NULL /* unpruned_relids: not used by columnar */
1757+
);
1758+
#elif PG_VERSION_NUM >= PG_VERSION_16
1759+
1760+
/* PG 16–17: three-arg signature (permInfos) */
1761+
ExecInitRangeTable(
1762+
estate,
1763+
list_make1(rte),
1764+
perminfos
1765+
);
17341766
#else
1735-
ExecInitRangeTable(estate, list_make1(rte));
1767+
1768+
/* PG 15: two-arg signature */
1769+
ExecInitRangeTable(
1770+
estate,
1771+
list_make1(rte)
1772+
);
17361773
#endif
17371774

17381775
estate->es_output_cid = GetCurrentCommandId(true);

src/backend/columnar/columnar_tableam.c

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,7 +1012,7 @@ NeededColumnsList(TupleDesc tupdesc, Bitmapset *attr_needed)
10121012

10131013
for (int i = 0; i < tupdesc->natts; i++)
10141014
{
1015-
if (tupdesc->attrs[i].attisdropped)
1015+
if (Attr(tupdesc, i)->attisdropped)
10161016
{
10171017
continue;
10181018
}
@@ -1121,10 +1121,27 @@ columnar_vacuum_rel(Relation rel, VacuumParams *params,
11211121
bool frozenxid_updated;
11221122
bool minmulti_updated;
11231123

1124+
/* for PG 18+, vac_update_relstats gained a new “all_frozen” param */
1125+
#if PG_VERSION_NUM >= PG_VERSION_18
1126+
1127+
/* all frozen pages are always 0, because columnar stripes never store XIDs */
1128+
BlockNumber new_rel_allfrozen = 0;
1129+
1130+
vac_update_relstats(rel, new_rel_pages, new_live_tuples,
1131+
new_rel_allvisible, /* allvisible */
1132+
new_rel_allfrozen, /* all_frozen */
1133+
nindexes > 0,
1134+
newRelFrozenXid, newRelminMxid,
1135+
&frozenxid_updated, &minmulti_updated,
1136+
false);
1137+
#else
11241138
vac_update_relstats(rel, new_rel_pages, new_live_tuples,
11251139
new_rel_allvisible, nindexes > 0,
11261140
newRelFrozenXid, newRelminMxid,
1127-
&frozenxid_updated, &minmulti_updated, false);
1141+
&frozenxid_updated, &minmulti_updated,
1142+
false);
1143+
#endif
1144+
11281145
#else
11291146
TransactionId oldestXmin;
11301147
TransactionId freezeLimit;
@@ -1187,10 +1204,19 @@ columnar_vacuum_rel(Relation rel, VacuumParams *params,
11871204
#endif
11881205
#endif
11891206

1207+
#if PG_VERSION_NUM >= PG_VERSION_18
1208+
pgstat_report_vacuum(RelationGetRelid(rel),
1209+
rel->rd_rel->relisshared,
1210+
Max(new_live_tuples, 0), /* live tuples */
1211+
0, /* dead tuples */
1212+
GetCurrentTimestamp()); /* start time */
1213+
#else
11901214
pgstat_report_vacuum(RelationGetRelid(rel),
11911215
rel->rd_rel->relisshared,
11921216
Max(new_live_tuples, 0),
11931217
0);
1218+
#endif
1219+
11941220
pgstat_progress_end_command();
11951221
}
11961222

@@ -1225,7 +1251,7 @@ LogRelationStats(Relation rel, int elevel)
12251251
GetTransactionSnapshot());
12261252
for (uint32 column = 0; column < skiplist->columnCount; column++)
12271253
{
1228-
bool attrDropped = tupdesc->attrs[column].attisdropped;
1254+
bool attrDropped = Attr(tupdesc, column)->attisdropped;
12291255
for (uint32 chunk = 0; chunk < skiplist->chunkCount; chunk++)
12301256
{
12311257
ColumnChunkSkipNode *skipnode =
@@ -2564,8 +2590,13 @@ static const TableAmRoutine columnar_am_methods = {
25642590

25652591
.relation_estimate_size = columnar_estimate_rel_size,
25662592

2593+
#if PG_VERSION_NUM < PG_VERSION_18
2594+
2595+
/* these two fields were removed in PG 18 */
25672596
.scan_bitmap_next_block = NULL,
25682597
.scan_bitmap_next_tuple = NULL,
2598+
#endif
2599+
25692600
.scan_sample_next_block = columnar_scan_sample_next_block,
25702601
.scan_sample_next_tuple = columnar_scan_sample_next_tuple
25712602
};
@@ -2603,7 +2634,7 @@ detoast_values(TupleDesc tupleDesc, Datum *orig_values, bool *isnull)
26032634

26042635
for (int i = 0; i < tupleDesc->natts; i++)
26052636
{
2606-
if (!isnull[i] && tupleDesc->attrs[i].attlen == -1 &&
2637+
if (!isnull[i] && Attr(tupleDesc, i)->attlen == -1 &&
26072638
VARATT_IS_EXTENDED(values[i]))
26082639
{
26092640
/* make a copy */

src/backend/distributed/commands/multi_copy.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3049,7 +3049,7 @@ CitusCopySelect(CopyStmt *copyStatement)
30493049

30503050
for (int i = 0; i < tupleDescriptor->natts; i++)
30513051
{
3052-
Form_pg_attribute attr = &tupleDescriptor->attrs[i];
3052+
Form_pg_attribute attr = TupleDescAttr(tupleDescriptor, i);
30533053

30543054
if (attr->attisdropped ||
30553055
attr->attgenerated

src/backend/distributed/connection/remote_commands.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "miscadmin.h"
1515
#include "pgstat.h"
1616

17+
#include "catalog/pg_collation.h"
1718
#include "lib/stringinfo.h"
1819
#include "storage/latch.h"
1920
#include "utils/builtins.h"
@@ -371,8 +372,9 @@ CommandMatchesLogGrepPattern(const char *command)
371372
if (GrepRemoteCommands && strnlen(GrepRemoteCommands, NAMEDATALEN) > 0)
372373
{
373374
Datum boolDatum =
374-
DirectFunctionCall2(textlike, CStringGetTextDatum(command),
375-
CStringGetTextDatum(GrepRemoteCommands));
375+
DirectFunctionCall2Coll(textlike, DEFAULT_COLLATION_OID,
376+
CStringGetTextDatum(command),
377+
CStringGetTextDatum(GrepRemoteCommands));
376378

377379
return DatumGetBool(boolDatum);
378380
}

src/backend/distributed/connection/worker_log_messages.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "postgres.h"
1212

1313
#include "utils/elog.h"
14+
#include "utils/memutils.h" /* for TopTransactionContext */
1415

1516
#include "distributed/connection_management.h"
1617
#include "distributed/error_codes.h"

0 commit comments

Comments
 (0)