diff --git a/src/backend/columnar/columnar_customscan.c b/src/backend/columnar/columnar_customscan.c index fa7274f2f..2a3e3cc44 100644 --- a/src/backend/columnar/columnar_customscan.c +++ b/src/backend/columnar/columnar_customscan.c @@ -16,14 +16,14 @@ #include "miscadmin.h" -#include "nodes/execnodes.h" /* for ExprState, ExprContext, etc. */ -#include "executor/executor.h" /* for ExecInitExprWithParams(), ExecEvalExpr() */ -#include "commands/explain_format.h" /* for ExplainPropertyInteger() */ #include "access/amapi.h" #include "access/skey.h" #include "catalog/pg_am.h" #include "catalog/pg_statistic.h" #include "commands/defrem.h" +#include "commands/explain_format.h" /* for ExplainPropertyInteger() */ +#include "executor/executor.h" /* for ExecInitExprWithParams(), ExecEvalExpr() */ +#include "nodes/execnodes.h" /* for ExprState, ExprContext, etc. */ #include "nodes/extensible.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" diff --git a/src/backend/distributed/connection/worker_log_messages.c b/src/backend/distributed/connection/worker_log_messages.c index e233340c0..7bce64050 100644 --- a/src/backend/distributed/connection/worker_log_messages.c +++ b/src/backend/distributed/connection/worker_log_messages.c @@ -11,11 +11,11 @@ #include "postgres.h" #include "utils/elog.h" +#include "utils/memutils.h" /* for TopTransactionContext */ #include "distributed/connection_management.h" #include "distributed/error_codes.h" #include "distributed/errormessage.h" -#include "utils/memutils.h" /* for TopTransactionContext */ #include "distributed/log_utils.h" #include "distributed/worker_log_messages.h" diff --git a/src/backend/distributed/operations/worker_copy_table_to_node_udf.c b/src/backend/distributed/operations/worker_copy_table_to_node_udf.c index 43a405f1c..60cbf8ed0 100644 --- a/src/backend/distributed/operations/worker_copy_table_to_node_udf.c +++ b/src/backend/distributed/operations/worker_copy_table_to_node_udf.c @@ -13,6 +13,7 @@ #include "postgres.h" +#include "executor/executor.h" /* for CreateExecutorState(), FreeExecutorState(), CreateExprContext(), etc. */ #include "utils/builtins.h" #include "utils/lsyscache.h" diff --git a/src/backend/distributed/planner/multi_explain.c b/src/backend/distributed/planner/multi_explain.c index 2dcd7f839..687a204d3 100644 --- a/src/backend/distributed/planner/multi_explain.c +++ b/src/backend/distributed/planner/multi_explain.c @@ -2269,7 +2269,7 @@ ExplainWorkerPlan(PlannedStmt *plannedstmt, DestReceiver *dest, ExplainState *es /* Create textual dump of plan tree */ ExplainPrintPlan(es, queryDesc); -#if PG_VERSION_NUM >= PG_VERSION_17 +#if PG_VERSION_NUM >= PG_VERSION_17 && PG_VERSION_NUM < PG_VERSION_18 /* Show buffer and/or memory usage in planning */ if (peek_buffer_usage(es, bufusage) || mem_counters) { @@ -2315,7 +2315,7 @@ ExplainWorkerPlan(PlannedStmt *plannedstmt, DestReceiver *dest, ExplainState *es if (es->costs) ExplainPrintJITSummary(es, queryDesc); -#if PG_VERSION_NUM >= PG_VERSION_17 +#if PG_VERSION_NUM >= PG_VERSION_17 && PG_VERSION_NUM < PG_VERSION_1 if (es->serialize != EXPLAIN_SERIALIZE_NONE) { /* the SERIALIZE option requires its own tuple receiver */ @@ -2382,7 +2382,7 @@ elapsed_time(instr_time *starttime) } -#if PG_VERSION_NUM >= PG_VERSION_17 +#if PG_VERSION_NUM >= PG_VERSION_17 && PG_VERSION_NUM < PG_VERSION_18 /* * Return whether show_buffer_usage would have anything to print, if given * the same 'usage' data. Note that when the format is anything other than diff --git a/src/backend/distributed/planner/multi_physical_planner.c b/src/backend/distributed/planner/multi_physical_planner.c index dee3464cf..e0f4c4332 100644 --- a/src/backend/distributed/planner/multi_physical_planner.c +++ b/src/backend/distributed/planner/multi_physical_planner.c @@ -1418,8 +1418,24 @@ ExtractColumns(RangeTblEntry *callingRTE, int rangeTableId, int subLevelsUp = 0; int location = -1; bool includeDroppedColumns = false; - expandRTE(callingRTE, rangeTableId, subLevelsUp, location, includeDroppedColumns, - columnNames, columnVars); +#if PG_VERSION_NUM >= PG_VERSION_18 + expandRTE(callingRTE, + rangeTableId, + subLevelsUp, + VAR_RETURNING_DEFAULT, /* new argument on PG 18+ */ + location, + includeDroppedColumns, + columnNames, + columnVars); +#else + expandRTE(callingRTE, + rangeTableId, + subLevelsUp, + location, + includeDroppedColumns, + columnNames, + columnVars); +#endif } diff --git a/src/backend/distributed/shared_library_init.c b/src/backend/distributed/shared_library_init.c index 430eb8555..59a5090c4 100644 --- a/src/backend/distributed/shared_library_init.c +++ b/src/backend/distributed/shared_library_init.c @@ -383,6 +383,33 @@ static const struct config_enum_entry metadata_sync_mode_options[] = { /* *INDENT-ON* */ +/*----------------------------------------------------------------------* +* On PG 18+ the hook signatures changed; we wrap the old Citus handlers +* in fresh functions that match the new typedefs exactly. +*----------------------------------------------------------------------*/ +#if PG_VERSION_NUM >= PG_VERSION_18 +static bool +citus_executor_start_adapter(QueryDesc *queryDesc, int eflags) +{ + /* call the original Citus hook (void) and always return “true” */ + CitusExecutorStart(queryDesc, eflags); + return true; +} + + +static void +citus_executor_run_adapter(QueryDesc *queryDesc, + ScanDirection direction, + uint64 count) +{ + /* call the original Citus hook (which still expects the old 4-arg form) */ + CitusExecutorRun(queryDesc, direction, count, true); +} + + +#endif + + /* shared library initialization function */ void _PG_init(void) @@ -457,8 +484,13 @@ _PG_init(void) set_rel_pathlist_hook = multi_relation_restriction_hook; get_relation_info_hook = multi_get_relation_info_hook; set_join_pathlist_hook = multi_join_restriction_hook; +#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 ExplainOneQuery_hook = CitusExplainOneQuery; prev_ExecutorEnd = ExecutorEnd_hook; ExecutorEnd_hook = CitusAttributeToEnd; diff --git a/src/backend/distributed/test/fake_am.c b/src/backend/distributed/test/fake_am.c index e7dc61397..75b7a9fb2 100644 --- a/src/backend/distributed/test/fake_am.c +++ b/src/backend/distributed/test/fake_am.c @@ -485,6 +485,7 @@ fake_estimate_rel_size(Relation rel, int32 *attr_widths, * Executor related callbacks for the fake AM * ------------------------------------------------------------------------ */ +#if PG_VERSION_NUM < PG_VERSION_18 static bool fake_scan_bitmap_next_block(TableScanDesc scan, TBMIterateResult *tbmres) @@ -502,6 +503,8 @@ fake_scan_bitmap_next_tuple(TableScanDesc scan, } +#endif + static bool fake_scan_sample_next_block(TableScanDesc scan, SampleScanState *scanstate) diff --git a/src/backend/distributed/test/fake_fdw.c b/src/backend/distributed/test/fake_fdw.c index 90b205b1e..fdf673154 100644 --- a/src/backend/distributed/test/fake_fdw.c +++ b/src/backend/distributed/test/fake_fdw.c @@ -91,11 +91,23 @@ FakeGetForeignPaths(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid) Cost startup_cost = 0; Cost total_cost = startup_cost + baserel->rows; - add_path(baserel, (Path *) create_foreignscan_path_compat(root, baserel, NULL, - baserel->rows, - startup_cost, total_cost, - NIL, - NULL, NULL, NIL, NIL)); + add_path(baserel, + (Path *) create_foreignscan_path_compat( + root, + baserel, + baserel->reltarget, /* ← PathTarget* is the rel’s reltarget */ + baserel->rows, + 0, /* ← disabled_nodes (only used in PG18+) */ + startup_cost, + total_cost, + NIL, /* pathkeys */ + NULL, /* required_outer */ + NULL, /* fdw_outerpath */ + NIL, /* fdw_restrictinfo (PG18+) */ + NIL, /* fdw_private */ + NIL /* fdw_scan_tlist (PG15–17) */ + ) + ); } diff --git a/src/backend/distributed/transaction/relation_access_tracking.c b/src/backend/distributed/transaction/relation_access_tracking.c index 0ffa68d95..8066f5404 100644 --- a/src/backend/distributed/transaction/relation_access_tracking.c +++ b/src/backend/distributed/transaction/relation_access_tracking.c @@ -21,6 +21,7 @@ #include "common/hashfn.h" #include "utils/hsearch.h" #include "utils/lsyscache.h" +#include "utils/memutils.h" /* for ALLOCSET_DEFAULT_MINSIZE, _INITSIZE, _MAXSIZE */ #include "pg_version_constants.h" diff --git a/src/backend/distributed/utils/aggregate_utils.c b/src/backend/distributed/utils/aggregate_utils.c index 3fd584df9..51f5b9b4f 100644 --- a/src/backend/distributed/utils/aggregate_utils.c +++ b/src/backend/distributed/utils/aggregate_utils.c @@ -918,7 +918,7 @@ TypecheckWorkerPartialAggArgType(FunctionCallInfo fcinfo, StypeBox *box) true, 'i', &argtypesNull); Assert(!argtypesNull); TupleDesc tupleDesc = box->aggregationArgumentContext->tupleDesc; - if (argType != tupleDesc->attrs[aggregateArgIndex].atttypid) + if (argType != TupleDescAttr(tupleDesc, aggregateArgIndex)->atttypid) { return false; } diff --git a/src/backend/distributed/utils/background_jobs.c b/src/backend/distributed/utils/background_jobs.c index 911880dc7..6d491a6b3 100644 --- a/src/backend/distributed/utils/background_jobs.c +++ b/src/backend/distributed/utils/background_jobs.c @@ -1906,7 +1906,32 @@ ExecuteSqlString(const char *sql) /* Don't display the portal in pg_cursors */ portal->visible = false; - PortalDefineQuery(portal, NULL, sql, commandTag, plantree_list, NULL); + + #if PG_VERSION_NUM >= PG_VERSION_18 + + /* PG18+ added a seventh “plansource” argument */ + 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 + + /* PG17-: 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 + PortalStart(portal, NULL, 0, InvalidSnapshot); int16 format[] = { 1 }; PortalSetResultFormat(portal, lengthof(format), format); /* binary format */ @@ -1923,7 +1948,28 @@ ExecuteSqlString(const char *sql) /* Here's where we actually execute the command. */ QueryCompletion qc = { 0 }; - (void) PortalRun(portal, FETCH_ALL, isTopLevel, true, receiver, receiver, &qc); + +/* Execute the portal, dropping the `run_once` arg on PG18+ */ +#if PG_VERSION_NUM >= PG_VERSION_18 + (void) PortalRun( + portal, + FETCH_ALL, /* count */ + isTopLevel, /* isTopLevel */ + receiver, /* DestReceiver *dest */ + receiver, /* DestReceiver *altdest */ + &qc /* QueryCompletion *qc */ + ); +#else + (void) PortalRun( + portal, + FETCH_ALL, /* count */ + isTopLevel, /* isTopLevel */ + true, /* run_once */ + receiver, /* DestReceiver *dest */ + receiver, /* DestReceiver *altdest */ + &qc /* QueryCompletion *qc */ + ); +#endif /* Clean up the receiver. */ (*receiver->rDestroy)(receiver); diff --git a/src/backend/distributed/utils/citus_depended_object.c b/src/backend/distributed/utils/citus_depended_object.c index bc14490b5..4492d8a07 100644 --- a/src/backend/distributed/utils/citus_depended_object.c +++ b/src/backend/distributed/utils/citus_depended_object.c @@ -42,6 +42,7 @@ #include "parser/parse_type.h" #include "storage/large_object.h" #include "utils/lsyscache.h" +#include "utils/memutils.h" #include "utils/syscache.h" #include "distributed/citus_depended_object.h" diff --git a/src/backend/distributed/utils/citus_nodefuncs.c b/src/backend/distributed/utils/citus_nodefuncs.c index 076e8ce6a..d93879cdb 100644 --- a/src/backend/distributed/utils/citus_nodefuncs.c +++ b/src/backend/distributed/utils/citus_nodefuncs.c @@ -324,6 +324,16 @@ GetRangeTblKind(RangeTblEntry *rte) break; } + #if PG_VERSION_NUM >= PG_VERSION_18 + + /* new in PG18: GROUP RTE, just map it straight through */ + case RTE_GROUP: + { + rteKind = (CitusRTEKind) rte->rtekind; + break; + } + + #endif case RTE_FUNCTION: { /* diff --git a/src/backend/distributed/utils/colocation_utils.c b/src/backend/distributed/utils/colocation_utils.c index e2af11a1d..5f031b2b5 100644 --- a/src/backend/distributed/utils/colocation_utils.c +++ b/src/backend/distributed/utils/colocation_utils.c @@ -1362,9 +1362,21 @@ DeleteColocationGroupLocally(uint32 colocationId) * https://github.com/citusdata/citus/pull/2855#discussion_r313628554 * https://github.com/citusdata/citus/issues/1890 */ - Relation replicaIndex = - index_open(RelationGetPrimaryKeyIndex(pgDistColocation), - AccessShareLock); +#if PG_VERSION_NUM >= PG_VERSION_18 + + /* PG 18+ expects a second “deferrable_ok” flag */ + Relation replicaIndex = index_open( + RelationGetPrimaryKeyIndex(pgDistColocation, false), + AccessShareLock + ); +#else + + /* PG 17- had a single-arg signature */ + Relation replicaIndex = index_open( + RelationGetPrimaryKeyIndex(pgDistColocation), + AccessShareLock + ); +#endif simple_heap_delete(pgDistColocation, &(heapTuple->t_self)); CitusInvalidateRelcacheByRelid(DistColocationRelationId()); diff --git a/src/include/pg_version_compat.h b/src/include/pg_version_compat.h index 92e969837..2a04fd3bb 100644 --- a/src/include/pg_version_compat.h +++ b/src/include/pg_version_compat.h @@ -384,9 +384,71 @@ getStxstattarget_compat(HeapTuple tup) #define matched_compat(a) (a->matchKind == MERGE_WHEN_MATCHED) -#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) +#include "nodes/pg_list.h" /* for List */ +#include "nodes/plannodes.h" /* for ForeignScan */ +#include "optimizer/pathnode.h" /* for create_foreignscan_path, ForeignPath */ + +/* + * A single entry point for Citus code to build ForeignPath + * using the *full* superset of parameters: + * + * root, rel, target, rows, + * disabled_nodes, startup_cost, total_cost, + * pathkeys, required_outer, + * fdw_outerpath, fdw_restrictinfo, + * fdw_private, fdw_scan_tlist + */ +static inline ForeignPath * +create_foreignscan_path_compat(PlannerInfo *root, + RelOptInfo *rel, + PathTarget *target, + double rows, + int disabled_nodes, + Cost startup_cost, + Cost total_cost, + List *pathkeys, + Relids required_outer, + Path *fdw_outerpath, + List *fdw_restrictinfo, + List *fdw_private, + List *fdw_scan_tlist) +{ +#if PG_VERSION_NUM >= PG_VERSION_18 + + /* PG 18+ signature: 12 args */ + return create_foreignscan_path( + root, + rel, + target, + rows, + disabled_nodes, + startup_cost, + total_cost, + pathkeys, + required_outer, + fdw_outerpath, + fdw_restrictinfo, + fdw_private + ); +#else + + /* PG 17- signature: 11 args */ + return create_foreignscan_path( + root, + rel, + target, + rows, + startup_cost, + total_cost, + pathkeys, + required_outer, + fdw_outerpath, + fdw_private, + fdw_scan_tlist + ); +#endif +} + #define getProcNo_compat(a) (a->vxid.procNumber) #define getLxid_compat(a) (a->vxid.lxid) @@ -421,10 +483,6 @@ getStxstattarget_compat(HeapTuple tup) #define matched_compat(a) (a->matched) -#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, k) - #define getProcNo_compat(a) (a->pgprocno) #define getLxid_compat(a) (a->lxid)