mirror of https://github.com/citusdata/citus.git
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. *pull/8034/head5983a4cffcGeneral 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>`. *85b7efa1cd### 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 -a07e03fd8f### 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. *6c66b7443c### Adapt `ExtractColumns()` to the new PG-18 `expandRTE()` signature PostgreSQL 1880feb727c8added 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 18525392d572changed 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](3eea7a0c97) 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](3eea7a0c97)) 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 commit525392d572. 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](cbc127917e) 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](30a6ed0ce4) 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 commit525392d572). 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 commit14e87ffa5cadded 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 extended525392d572the `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 commita8025f5448generalized 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 commite222534679reordered 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 commitc3953226a0cleaned 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 commit99f8f3fbbcextended 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.
parent
5deaf9a616
commit
9e42f3f2c4
|
|
@ -28,6 +28,7 @@ src/backend/distributed/utils/citus_outfuncs.c -citus-style
|
|||
src/backend/distributed/deparser/ruleutils_15.c -citus-style
|
||||
src/backend/distributed/deparser/ruleutils_16.c -citus-style
|
||||
src/backend/distributed/deparser/ruleutils_17.c -citus-style
|
||||
src/backend/distributed/deparser/ruleutils_18.c -citus-style
|
||||
src/backend/distributed/commands/index_pg_source.c -citus-style
|
||||
|
||||
src/include/distributed/citus_nodes.h -citus-style
|
||||
|
|
|
|||
|
|
@ -21,6 +21,13 @@
|
|||
#include "catalog/pg_am.h"
|
||||
#include "catalog/pg_statistic.h"
|
||||
#include "commands/defrem.h"
|
||||
|
||||
#include "columnar/columnar_version_compat.h"
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
#include "commands/explain_format.h"
|
||||
#endif
|
||||
#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"
|
||||
|
|
|
|||
|
|
@ -645,10 +645,10 @@ SaveStripeSkipList(RelFileLocator relfilelocator, uint64 stripe,
|
|||
{
|
||||
values[Anum_columnar_chunk_minimum_value - 1] =
|
||||
PointerGetDatum(DatumToBytea(chunk->minimumValue,
|
||||
&tupleDescriptor->attrs[columnIndex]));
|
||||
Attr(tupleDescriptor, columnIndex)));
|
||||
values[Anum_columnar_chunk_maximum_value - 1] =
|
||||
PointerGetDatum(DatumToBytea(chunk->maximumValue,
|
||||
&tupleDescriptor->attrs[columnIndex]));
|
||||
Attr(tupleDescriptor, columnIndex)));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -803,9 +803,9 @@ ReadStripeSkipList(RelFileLocator relfilelocator, uint64 stripe,
|
|||
datumArray[Anum_columnar_chunk_maximum_value - 1]);
|
||||
|
||||
chunk->minimumValue =
|
||||
ByteaToDatum(minValue, &tupleDescriptor->attrs[columnIndex]);
|
||||
ByteaToDatum(minValue, Attr(tupleDescriptor, columnIndex));
|
||||
chunk->maximumValue =
|
||||
ByteaToDatum(maxValue, &tupleDescriptor->attrs[columnIndex]);
|
||||
ByteaToDatum(maxValue, Attr(tupleDescriptor, columnIndex));
|
||||
|
||||
chunk->hasMinMax = true;
|
||||
}
|
||||
|
|
@ -1414,16 +1414,28 @@ UpdateStripeMetadataRow(uint64 storageId, uint64 stripeId, bool *update,
|
|||
storageId, stripeId)));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* heap_modify_tuple + heap_inplace_update only exist on PG < 18;
|
||||
* on PG18 the in-place helper was removed upstream, so we skip the whole block.
|
||||
*/
|
||||
#if PG_VERSION_NUM < PG_VERSION_18
|
||||
|
||||
/*
|
||||
* heap_inplace_update already doesn't allow changing size of the original
|
||||
* tuple, so we don't allow setting any Datum's to NULL values.
|
||||
*/
|
||||
bool newNulls[Natts_columnar_stripe] = { false };
|
||||
TupleDesc tupleDescriptor = RelationGetDescr(columnarStripes);
|
||||
HeapTuple modifiedTuple = heap_modify_tuple(oldTuple, tupleDescriptor,
|
||||
newValues, newNulls, update);
|
||||
HeapTuple modifiedTuple = heap_modify_tuple(oldTuple,
|
||||
tupleDescriptor,
|
||||
newValues,
|
||||
newNulls,
|
||||
update);
|
||||
|
||||
heap_inplace_update(columnarStripes, modifiedTuple);
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Existing tuple now contains modifications, because we used
|
||||
|
|
@ -1727,12 +1739,37 @@ create_estate_for_relation(Relation rel)
|
|||
rte->relkind = rel->rd_rel->relkind;
|
||||
rte->rellockmode = AccessShareLock;
|
||||
|
||||
/* Prepare permission info on PG 16+ */
|
||||
#if PG_VERSION_NUM >= PG_VERSION_16
|
||||
List *perminfos = NIL;
|
||||
addRTEPermissionInfo(&perminfos, rte);
|
||||
ExecInitRangeTable(estate, list_make1(rte), perminfos);
|
||||
#endif
|
||||
|
||||
/* Initialize the range table, with the right signature for each PG version */
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
|
||||
/* PG 18+ needs four arguments (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
|
||||
ExecInitRangeTable(estate, list_make1(rte));
|
||||
|
||||
/* PG 15: two-arg signature */
|
||||
ExecInitRangeTable(
|
||||
estate,
|
||||
list_make1(rte)
|
||||
);
|
||||
#endif
|
||||
|
||||
estate->es_output_cid = GetCurrentCommandId(true);
|
||||
|
|
|
|||
|
|
@ -1012,7 +1012,7 @@ NeededColumnsList(TupleDesc tupdesc, Bitmapset *attr_needed)
|
|||
|
||||
for (int i = 0; i < tupdesc->natts; i++)
|
||||
{
|
||||
if (tupdesc->attrs[i].attisdropped)
|
||||
if (Attr(tupdesc, i)->attisdropped)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1121,10 +1121,27 @@ columnar_vacuum_rel(Relation rel, VacuumParams *params,
|
|||
bool frozenxid_updated;
|
||||
bool minmulti_updated;
|
||||
|
||||
/* for PG 18+, vac_update_relstats gained a new “all_frozen” param */
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
|
||||
/* all frozen pages are always 0, because columnar stripes never store XIDs */
|
||||
BlockNumber new_rel_allfrozen = 0;
|
||||
|
||||
vac_update_relstats(rel, new_rel_pages, new_live_tuples,
|
||||
new_rel_allvisible, /* allvisible */
|
||||
new_rel_allfrozen, /* all_frozen */
|
||||
nindexes > 0,
|
||||
newRelFrozenXid, newRelminMxid,
|
||||
&frozenxid_updated, &minmulti_updated,
|
||||
false);
|
||||
#else
|
||||
vac_update_relstats(rel, new_rel_pages, new_live_tuples,
|
||||
new_rel_allvisible, nindexes > 0,
|
||||
newRelFrozenXid, newRelminMxid,
|
||||
&frozenxid_updated, &minmulti_updated, false);
|
||||
&frozenxid_updated, &minmulti_updated,
|
||||
false);
|
||||
#endif
|
||||
|
||||
#else
|
||||
TransactionId oldestXmin;
|
||||
TransactionId freezeLimit;
|
||||
|
|
@ -1187,10 +1204,19 @@ columnar_vacuum_rel(Relation rel, VacuumParams *params,
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
pgstat_report_vacuum(RelationGetRelid(rel),
|
||||
rel->rd_rel->relisshared,
|
||||
Max(new_live_tuples, 0), /* live tuples */
|
||||
0, /* dead tuples */
|
||||
GetCurrentTimestamp()); /* start time */
|
||||
#else
|
||||
pgstat_report_vacuum(RelationGetRelid(rel),
|
||||
rel->rd_rel->relisshared,
|
||||
Max(new_live_tuples, 0),
|
||||
0);
|
||||
#endif
|
||||
|
||||
pgstat_progress_end_command();
|
||||
}
|
||||
|
||||
|
|
@ -1225,7 +1251,7 @@ LogRelationStats(Relation rel, int elevel)
|
|||
GetTransactionSnapshot());
|
||||
for (uint32 column = 0; column < skiplist->columnCount; column++)
|
||||
{
|
||||
bool attrDropped = tupdesc->attrs[column].attisdropped;
|
||||
bool attrDropped = Attr(tupdesc, column)->attisdropped;
|
||||
for (uint32 chunk = 0; chunk < skiplist->chunkCount; chunk++)
|
||||
{
|
||||
ColumnChunkSkipNode *skipnode =
|
||||
|
|
@ -2564,8 +2590,13 @@ static const TableAmRoutine columnar_am_methods = {
|
|||
|
||||
.relation_estimate_size = columnar_estimate_rel_size,
|
||||
|
||||
#if PG_VERSION_NUM < PG_VERSION_18
|
||||
|
||||
/* these two fields were removed in PG 18 */
|
||||
.scan_bitmap_next_block = NULL,
|
||||
.scan_bitmap_next_tuple = NULL,
|
||||
#endif
|
||||
|
||||
.scan_sample_next_block = columnar_scan_sample_next_block,
|
||||
.scan_sample_next_tuple = columnar_scan_sample_next_tuple
|
||||
};
|
||||
|
|
@ -2603,7 +2634,7 @@ detoast_values(TupleDesc tupleDesc, Datum *orig_values, bool *isnull)
|
|||
|
||||
for (int i = 0; i < tupleDesc->natts; i++)
|
||||
{
|
||||
if (!isnull[i] && tupleDesc->attrs[i].attlen == -1 &&
|
||||
if (!isnull[i] && Attr(tupleDesc, i)->attlen == -1 &&
|
||||
VARATT_IS_EXTENDED(values[i]))
|
||||
{
|
||||
/* make a copy */
|
||||
|
|
|
|||
|
|
@ -3049,7 +3049,7 @@ CitusCopySelect(CopyStmt *copyStatement)
|
|||
|
||||
for (int i = 0; i < tupleDescriptor->natts; i++)
|
||||
{
|
||||
Form_pg_attribute attr = &tupleDescriptor->attrs[i];
|
||||
Form_pg_attribute attr = TupleDescAttr(tupleDescriptor, i);
|
||||
|
||||
if (attr->attisdropped ||
|
||||
attr->attgenerated
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include "miscadmin.h"
|
||||
#include "pgstat.h"
|
||||
|
||||
#include "catalog/pg_collation.h"
|
||||
#include "lib/stringinfo.h"
|
||||
#include "storage/latch.h"
|
||||
#include "utils/builtins.h"
|
||||
|
|
@ -371,7 +372,8 @@ CommandMatchesLogGrepPattern(const char *command)
|
|||
if (GrepRemoteCommands && strnlen(GrepRemoteCommands, NAMEDATALEN) > 0)
|
||||
{
|
||||
Datum boolDatum =
|
||||
DirectFunctionCall2(textlike, CStringGetTextDatum(command),
|
||||
DirectFunctionCall2Coll(textlike, DEFAULT_COLLATION_OID,
|
||||
CStringGetTextDatum(command),
|
||||
CStringGetTextDatum(GrepRemoteCommands));
|
||||
|
||||
return DatumGetBool(boolDatum);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include "postgres.h"
|
||||
|
||||
#include "utils/elog.h"
|
||||
#include "utils/memutils.h" /* for TopTransactionContext */
|
||||
|
||||
#include "distributed/connection_management.h"
|
||||
#include "distributed/error_codes.h"
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -755,13 +755,48 @@ ExecuteTaskPlan(PlannedStmt *taskPlan, char *queryString,
|
|||
CreateDestReceiver(DestNone);
|
||||
|
||||
/* Create a QueryDesc for the query */
|
||||
QueryDesc *queryDesc = CreateQueryDesc(taskPlan, queryString,
|
||||
GetActiveSnapshot(), InvalidSnapshot,
|
||||
destReceiver, paramListInfo,
|
||||
queryEnv, 0);
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
|
||||
/* 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 CachedPlan */
|
||||
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
|
||||
|
||||
|
||||
ExecutorStart(queryDesc, eflags);
|
||||
|
||||
/* run the plan: count = 0 (all rows) */
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
|
||||
/* PG 18+ dropped the “execute_once” boolean */
|
||||
ExecutorRun(queryDesc, scanDirection, 0L);
|
||||
#else
|
||||
|
||||
/* PG 17 and prevs still expect the 4th ‘once’ argument */
|
||||
ExecutorRun(queryDesc, scanDirection, 0L, true);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We'll set the executorState->es_processed later, for now only remember
|
||||
|
|
|
|||
|
|
@ -235,7 +235,20 @@ CitusExecutorRun(QueryDesc *queryDesc,
|
|||
/* postgres will switch here again and will restore back on its own */
|
||||
MemoryContextSwitchTo(oldcontext);
|
||||
|
||||
standard_ExecutorRun(queryDesc, direction, count, execute_once);
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
|
||||
/* PG18+ drops the “execute_once” argument */
|
||||
standard_ExecutorRun(queryDesc,
|
||||
direction,
|
||||
count);
|
||||
#else
|
||||
|
||||
/* PG17-: original four-arg signature */
|
||||
standard_ExecutorRun(queryDesc,
|
||||
direction,
|
||||
count,
|
||||
execute_once);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (totalTime)
|
||||
|
|
@ -688,15 +701,55 @@ ExecutePlanIntoDestReceiver(PlannedStmt *queryPlan, ParamListInfo params,
|
|||
/* don't display the portal in pg_cursors, it is for internal use only */
|
||||
portal->visible = false;
|
||||
|
||||
PortalDefineQuery(portal,
|
||||
NULL,
|
||||
"",
|
||||
CMDTAG_SELECT,
|
||||
list_make1(queryPlan),
|
||||
NULL);
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
|
||||
/* PostgreSQL 18+ adds a seventh “plansource” argument */
|
||||
PortalDefineQuery(
|
||||
portal,
|
||||
NULL, /* no prepared statement name */
|
||||
"", /* query text */
|
||||
CMDTAG_SELECT, /* command tag */
|
||||
list_make1(queryPlan),/* list of PlannedStmt* */
|
||||
NULL, /* no CachedPlan */
|
||||
NULL /* no CachedPlanSource */
|
||||
);
|
||||
#else
|
||||
|
||||
/* PostgreSQL 17-: six-arg signature */
|
||||
PortalDefineQuery(
|
||||
portal,
|
||||
NULL, /* no prepared statement name */
|
||||
"", /* query text */
|
||||
CMDTAG_SELECT, /* command tag */
|
||||
list_make1(queryPlan),/* list of PlannedStmt* */
|
||||
NULL /* no CachedPlan */
|
||||
);
|
||||
#endif
|
||||
|
||||
PortalStart(portal, params, eflags, GetActiveSnapshot());
|
||||
PortalRun(portal, count, false, true, dest, dest, NULL);
|
||||
|
||||
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
|
||||
/* PG 18+: six-arg signature (drop the run_once bool) */
|
||||
PortalRun(portal,
|
||||
count, /* how many rows to fetch */
|
||||
false, /* isTopLevel */
|
||||
dest, /* DestReceiver *dest */
|
||||
dest, /* DestReceiver *altdest */
|
||||
NULL); /* QueryCompletion *qc */
|
||||
#else
|
||||
|
||||
/* PG 17-: original seven-arg signature */
|
||||
PortalRun(portal,
|
||||
count, /* how many rows to fetch */
|
||||
false, /* isTopLevel */
|
||||
true, /* run_once */
|
||||
dest, /* DestReceiver *dest */
|
||||
dest, /* DestReceiver *altdest */
|
||||
NULL); /* QueryCompletion *qc */
|
||||
#endif
|
||||
|
||||
PortalDrop(portal, false);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -242,7 +242,27 @@ worker_partition_query_result(PG_FUNCTION_ARGS)
|
|||
allowNullPartitionColumnValues);
|
||||
|
||||
/* execute the query */
|
||||
PortalRun(portal, FETCH_ALL, false, true, dest, dest, NULL);
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
|
||||
/* PG18+: drop the “run_once” bool */
|
||||
PortalRun(portal,
|
||||
FETCH_ALL, /* count */
|
||||
false, /* isTopLevel */
|
||||
dest, /* dest receiver */
|
||||
dest, /* alternative dest */
|
||||
NULL); /* QueryCompletion *qc */
|
||||
#else
|
||||
|
||||
/* PG15–17: original seven‐arg signature */
|
||||
PortalRun(portal,
|
||||
FETCH_ALL, /* count */
|
||||
false, /* isTopLevel */
|
||||
true, /* run_once */
|
||||
dest, /* dest receiver */
|
||||
dest, /* alternative dest */
|
||||
NULL); /* QueryCompletion *qc */
|
||||
#endif
|
||||
|
||||
|
||||
/* construct the output result */
|
||||
TupleDesc returnTupleDesc = NULL;
|
||||
|
|
@ -295,8 +315,31 @@ StartPortalForQueryExecution(const char *queryString)
|
|||
/* don't display the portal in pg_cursors, it is for internal use only */
|
||||
portal->visible = false;
|
||||
|
||||
PortalDefineQuery(portal, NULL, queryString, CMDTAG_SELECT,
|
||||
list_make1(queryPlan), NULL);
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
|
||||
/* PG 18+: new CachedPlanSource slot */
|
||||
PortalDefineQuery(
|
||||
portal,
|
||||
NULL, /* no prepared‐stmt name */
|
||||
queryString, /* the SQL text */
|
||||
CMDTAG_SELECT, /* we’re running a SELECT */
|
||||
list_make1(queryPlan), /* plan trees */
|
||||
NULL, /* no CachedPlan */
|
||||
NULL /* no CachedPlanSource */
|
||||
);
|
||||
#else
|
||||
|
||||
/* PG 15–17: six‐arg signature */
|
||||
PortalDefineQuery(
|
||||
portal,
|
||||
NULL,
|
||||
queryString,
|
||||
CMDTAG_SELECT,
|
||||
list_make1(queryPlan),
|
||||
NULL /* no CachedPlan */
|
||||
);
|
||||
#endif
|
||||
|
||||
int eflags = 0;
|
||||
PortalStart(portal, NULL, eflags, GetActiveSnapshot());
|
||||
|
||||
|
|
|
|||
|
|
@ -2965,8 +2965,18 @@ DeleteNodeRow(char *nodeName, int32 nodePort)
|
|||
* https://github.com/citusdata/citus/pull/2855#discussion_r313628554
|
||||
* https://github.com/citusdata/citus/issues/1890
|
||||
*/
|
||||
Relation replicaIndex = index_open(RelationGetPrimaryKeyIndex(pgDistNode),
|
||||
#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));
|
||||
|
|
|
|||
|
|
@ -746,7 +746,12 @@ GetRelationIdentityOrPK(Relation rel)
|
|||
|
||||
if (!OidIsValid(idxoid))
|
||||
{
|
||||
/* Determine the index OID of the primary key (PG18 adds a second parameter) */
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
idxoid = RelationGetPrimaryKeyIndex(rel, false /* deferred_ok */);
|
||||
#else
|
||||
idxoid = RelationGetPrimaryKeyIndex(rel);
|
||||
#endif
|
||||
}
|
||||
|
||||
return idxoid;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "executor/executor.h" /* for CreateExecutorState(), FreeExecutorState(), CreateExprContext(), etc. */
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/lsyscache.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,11 @@
|
|||
#include "utils/snapmgr.h"
|
||||
|
||||
#include "pg_version_constants.h"
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
#include "commands/explain_dr.h" /* CreateExplainSerializeDestReceiver() */
|
||||
#include "commands/explain_format.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include "distributed/citus_depended_object.h"
|
||||
#include "distributed/citus_nodefuncs.h"
|
||||
|
|
@ -134,7 +139,7 @@ typedef struct ExplainAnalyzeDestination
|
|||
TupleDesc lastSavedExplainAnalyzeTupDesc;
|
||||
} ExplainAnalyzeDestination;
|
||||
|
||||
#if PG_VERSION_NUM >= PG_VERSION_17
|
||||
#if PG_VERSION_NUM >= PG_VERSION_17 && PG_VERSION_NUM < PG_VERSION_18
|
||||
|
||||
/*
|
||||
* Various places within need to convert bytes to kilobytes. Round these up
|
||||
|
|
@ -529,19 +534,53 @@ ExplainSubPlans(DistributedPlan *distributedPlan, ExplainState *es)
|
|||
|
||||
ExplainOpenGroup("PlannedStmt", "PlannedStmt", false, es);
|
||||
|
||||
/* Capture memory stats on PG17+ */
|
||||
#if PG_VERSION_NUM >= PG_VERSION_17
|
||||
if (es->memory)
|
||||
{
|
||||
MemoryContextSwitchTo(saved_ctx);
|
||||
MemoryContextMemConsumed(planner_ctx, &mem_counters);
|
||||
}
|
||||
#endif
|
||||
|
||||
ExplainOnePlan(plan, into, es, queryString, params, NULL, &planduration,
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
ExplainOnePlan(
|
||||
plan, /* PlannedStmt *plannedstmt */
|
||||
NULL, /* CachedPlan *cplan */
|
||||
NULL, /* CachedPlanSource *plansource */
|
||||
0, /* query_index */
|
||||
into, /* IntoClause *into */
|
||||
es, /* struct ExplainState *es */
|
||||
queryString, /* const char *queryString */
|
||||
params, /* ParamListInfo params */
|
||||
NULL, /* QueryEnvironment *queryEnv */
|
||||
&planduration, /* const instr_time *planduration */
|
||||
(es->buffers ? &bufusage : NULL),/* const BufferUsage *bufusage */
|
||||
(es->memory ? &mem_counters : NULL) /* const MemoryContextCounters *mem_counters */
|
||||
);
|
||||
#elif PG_VERSION_NUM >= PG_VERSION_17
|
||||
ExplainOnePlan(
|
||||
plan,
|
||||
into,
|
||||
es,
|
||||
queryString,
|
||||
params,
|
||||
NULL, /* QueryEnvironment *queryEnv */
|
||||
&planduration,
|
||||
(es->buffers ? &bufusage : NULL),
|
||||
(es->memory ? &mem_counters : NULL));
|
||||
(es->memory ? &mem_counters : NULL)
|
||||
);
|
||||
#else
|
||||
ExplainOnePlan(plan, into, es, queryString, params, NULL, &planduration,
|
||||
(es->buffers ? &bufusage : NULL));
|
||||
ExplainOnePlan(
|
||||
plan,
|
||||
into,
|
||||
es,
|
||||
queryString,
|
||||
params,
|
||||
NULL, /* QueryEnvironment *queryEnv */
|
||||
&planduration,
|
||||
(es->buffers ? &bufusage : NULL)
|
||||
);
|
||||
#endif
|
||||
|
||||
ExplainCloseGroup("PlannedStmt", "PlannedStmt", false, es);
|
||||
|
|
@ -1558,22 +1597,55 @@ CitusExplainOneQuery(Query *query, int cursorOptions, IntoClause *into,
|
|||
BufferUsageAccumDiff(&bufusage, &pgBufferUsage, &bufusage_start);
|
||||
}
|
||||
|
||||
/* capture memory stats on PG17+ */
|
||||
#if PG_VERSION_NUM >= PG_VERSION_17
|
||||
if (es->memory)
|
||||
{
|
||||
MemoryContextSwitchTo(saved_ctx);
|
||||
MemoryContextMemConsumed(planner_ctx, &mem_counters);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* run it (if needed) and produce output */
|
||||
ExplainOnePlan(plan, into, es, queryString, params, queryEnv,
|
||||
&planduration, (es->buffers ? &bufusage : NULL),
|
||||
(es->memory ? &mem_counters : NULL));
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
ExplainOnePlan(
|
||||
plan, /* PlannedStmt *plannedstmt */
|
||||
NULL, /* no CachedPlan */
|
||||
NULL, /* no CachedPlanSource */
|
||||
0, /* query_index */
|
||||
into, /* IntoClause *into */
|
||||
es, /* struct ExplainState *es */
|
||||
queryString, /* const char *queryString */
|
||||
params, /* ParamListInfo params */
|
||||
queryEnv, /* QueryEnvironment *queryEnv */
|
||||
&planduration, /* const instr_time *planduration */
|
||||
(es->buffers ? &bufusage : NULL), /* const BufferUsage *bufusage */
|
||||
(es->memory ? &mem_counters : NULL) /* const MemoryContextCounters *mem_counters */
|
||||
);
|
||||
#elif PG_VERSION_NUM >= PG_VERSION_17
|
||||
|
||||
/* PostgreSQL 17 signature (9 args: includes mem_counters) */
|
||||
ExplainOnePlan(
|
||||
plan,
|
||||
into,
|
||||
es,
|
||||
queryString,
|
||||
params,
|
||||
queryEnv,
|
||||
&planduration,
|
||||
(es->buffers ? &bufusage : NULL),
|
||||
(es->memory ? &mem_counters : NULL)
|
||||
);
|
||||
#else
|
||||
|
||||
/* run it (if needed) and produce output */
|
||||
ExplainOnePlan(plan, into, es, queryString, params, queryEnv,
|
||||
&planduration, (es->buffers ? &bufusage : NULL));
|
||||
ExplainOnePlan(
|
||||
plan,
|
||||
into,
|
||||
es,
|
||||
queryString,
|
||||
params,
|
||||
queryEnv,
|
||||
&planduration,
|
||||
(es->buffers ? &bufusage : NULL)
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -1805,7 +1877,7 @@ WrapQueryForExplainAnalyze(const char *queryString, TupleDesc tupleDesc,
|
|||
appendStringInfoString(columnDef, ", ");
|
||||
}
|
||||
|
||||
Form_pg_attribute attr = &tupleDesc->attrs[columnIndex];
|
||||
Form_pg_attribute attr = TupleDescAttr(tupleDesc, columnIndex);
|
||||
char *attrType = format_type_extended(attr->atttypid, attr->atttypmod,
|
||||
FORMAT_TYPE_TYPEMOD_GIVEN |
|
||||
FORMAT_TYPE_FORCE_QUALIFY);
|
||||
|
|
@ -2026,21 +2098,55 @@ ExplainOneQuery(Query *query, int cursorOptions,
|
|||
BufferUsageAccumDiff(&bufusage, &pgBufferUsage, &bufusage_start);
|
||||
}
|
||||
|
||||
/* 1) Capture memory counters on PG17+ only once: */
|
||||
#if PG_VERSION_NUM >= PG_VERSION_17
|
||||
if (es->memory)
|
||||
{
|
||||
MemoryContextSwitchTo(saved_ctx);
|
||||
MemoryContextMemConsumed(planner_ctx, &mem_counters);
|
||||
}
|
||||
/* run it (if needed) and produce output */
|
||||
ExplainOnePlan(plan, into, es, queryString, params, queryEnv,
|
||||
&planduration, (es->buffers ? &bufusage : NULL),
|
||||
(es->memory ? &mem_counters : NULL));
|
||||
#else
|
||||
/* run it (if needed) and produce output */
|
||||
ExplainOnePlan(plan, into, es, queryString, params, queryEnv,
|
||||
&planduration, (es->buffers ? &bufusage : NULL));
|
||||
#endif
|
||||
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
ExplainOnePlan(
|
||||
plan, /* PlannedStmt *plannedstmt */
|
||||
NULL, /* CachedPlan *cplan */
|
||||
NULL, /* CachedPlanSource *plansource */
|
||||
0, /* query_index */
|
||||
into, /* IntoClause *into */
|
||||
es, /* struct ExplainState *es */
|
||||
queryString, /* const char *queryString */
|
||||
params, /* ParamListInfo params */
|
||||
queryEnv, /* QueryEnvironment *queryEnv */
|
||||
&planduration, /* const instr_time *planduration */
|
||||
(es->buffers ? &bufusage : NULL),
|
||||
(es->memory ? &mem_counters: NULL)
|
||||
);
|
||||
#elif PG_VERSION_NUM >= PG_VERSION_17
|
||||
ExplainOnePlan(
|
||||
plan,
|
||||
into,
|
||||
es,
|
||||
queryString,
|
||||
params,
|
||||
queryEnv,
|
||||
&planduration,
|
||||
(es->buffers ? &bufusage : NULL),
|
||||
(es->memory ? &mem_counters: NULL)
|
||||
);
|
||||
#else
|
||||
ExplainOnePlan(
|
||||
plan,
|
||||
into,
|
||||
es,
|
||||
queryString,
|
||||
params,
|
||||
queryEnv,
|
||||
&planduration,
|
||||
(es->buffers ? &bufusage : NULL)
|
||||
);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2102,9 +2208,30 @@ ExplainWorkerPlan(PlannedStmt *plannedstmt, DestReceiver *dest, ExplainState *es
|
|||
UpdateActiveSnapshotCommandId();
|
||||
|
||||
/* Create a QueryDesc for the query */
|
||||
queryDesc = CreateQueryDesc(plannedstmt, queryString,
|
||||
GetActiveSnapshot(), InvalidSnapshot,
|
||||
dest, params, queryEnv, instrument_option);
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
queryDesc = CreateQueryDesc(
|
||||
plannedstmt, /* PlannedStmt *plannedstmt */
|
||||
NULL, /* CachedPlan *cplan (none) */
|
||||
queryString, /* const char *sourceText */
|
||||
GetActiveSnapshot(), /* Snapshot snapshot */
|
||||
InvalidSnapshot, /* Snapshot crosscheck_snapshot */
|
||||
dest, /* DestReceiver *dest */
|
||||
params, /* ParamListInfo params */
|
||||
queryEnv, /* QueryEnvironment *queryEnv */
|
||||
instrument_option /* int instrument_options */
|
||||
);
|
||||
#else
|
||||
queryDesc = CreateQueryDesc(
|
||||
plannedstmt, /* PlannedStmt *plannedstmt */
|
||||
queryString, /* const char *sourceText */
|
||||
GetActiveSnapshot(), /* Snapshot snapshot */
|
||||
InvalidSnapshot, /* Snapshot crosscheck_snapshot */
|
||||
dest, /* DestReceiver *dest */
|
||||
params, /* ParamListInfo params */
|
||||
queryEnv, /* QueryEnvironment *queryEnv */
|
||||
instrument_option /* int instrument_options */
|
||||
);
|
||||
#endif
|
||||
|
||||
/* Select execution options */
|
||||
if (es->analyze)
|
||||
|
|
@ -2121,7 +2248,14 @@ ExplainWorkerPlan(PlannedStmt *plannedstmt, DestReceiver *dest, ExplainState *es
|
|||
ScanDirection dir = ForwardScanDirection;
|
||||
|
||||
/* run the plan */
|
||||
/* run the plan: count = 0 (all rows) */
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
/* PG 18+ dropped the “execute_once” boolean */
|
||||
ExecutorRun(queryDesc, dir, 0L);
|
||||
#else
|
||||
/* PG 17- still expect the 4th ‘once’ argument */
|
||||
ExecutorRun(queryDesc, dir, 0L, true);
|
||||
#endif
|
||||
|
||||
/* run cleanup too */
|
||||
ExecutorFinish(queryDesc);
|
||||
|
|
@ -2135,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)
|
||||
{
|
||||
|
|
@ -2181,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_18
|
||||
if (es->serialize != EXPLAIN_SERIALIZE_NONE)
|
||||
{
|
||||
/* the SERIALIZE option requires its own tuple receiver */
|
||||
|
|
@ -2248,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
|
||||
|
|
@ -2560,7 +2694,7 @@ ExplainPrintSerialize(ExplainState *es, SerializeMetrics *metrics)
|
|||
ExplainPropertyFloat("Time", "ms",
|
||||
1000.0 * INSTR_TIME_GET_DOUBLE(metrics->timeSpent),
|
||||
3, es);
|
||||
ExplainPropertyUInteger("Output Volume", "kB",
|
||||
ExplainPropertyInteger("Output Volume", "kB",
|
||||
BYTES_TO_KILOBYTES(metrics->bytesSent), es);
|
||||
ExplainPropertyText("Format", format, es);
|
||||
if (es->buffers)
|
||||
|
|
|
|||
|
|
@ -35,6 +35,10 @@
|
|||
#include "utils/syscache.h"
|
||||
|
||||
#include "pg_version_constants.h"
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
typedef OpIndexInterpretation OpBtreeInterpretation;
|
||||
#endif
|
||||
|
||||
|
||||
#include "distributed/citus_clauses.h"
|
||||
#include "distributed/colocation_utils.h"
|
||||
|
|
@ -2293,7 +2297,12 @@ OperatorImplementsEquality(Oid opno)
|
|||
{
|
||||
OpBtreeInterpretation *btreeIntepretation = (OpBtreeInterpretation *)
|
||||
lfirst(btreeInterpretationCell);
|
||||
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
if (btreeIntepretation->cmptype == BTEqualStrategyNumber)
|
||||
#else
|
||||
if (btreeIntepretation->strategy == BTEqualStrategyNumber)
|
||||
#endif
|
||||
{
|
||||
equalityOperator = true;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -85,6 +85,10 @@
|
|||
#include "utils/ruleutils.h"
|
||||
|
||||
#include "pg_version_constants.h"
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
typedef OpIndexInterpretation OpBtreeInterpretation;
|
||||
#endif
|
||||
|
||||
|
||||
#include "distributed/distributed_planner.h"
|
||||
#include "distributed/listutils.h"
|
||||
|
|
@ -1078,7 +1082,11 @@ IsValidPartitionKeyRestriction(OpExpr *opClause)
|
|||
OpBtreeInterpretation *btreeInterpretation =
|
||||
(OpBtreeInterpretation *) lfirst(btreeInterpretationCell);
|
||||
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
if (btreeInterpretation->cmptype == ROWCOMPARE_NE)
|
||||
#else
|
||||
if (btreeInterpretation->strategy == ROWCOMPARE_NE)
|
||||
#endif
|
||||
{
|
||||
/* TODO: could add support for this, if we feel like it */
|
||||
return false;
|
||||
|
|
@ -1130,7 +1138,11 @@ AddPartitionKeyRestrictionToInstance(ClauseWalkerContext *context, OpExpr *opCla
|
|||
OpBtreeInterpretation *btreeInterpretation =
|
||||
(OpBtreeInterpretation *) lfirst(btreeInterpretationCell);
|
||||
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
switch (btreeInterpretation->cmptype)
|
||||
#else
|
||||
switch (btreeInterpretation->strategy)
|
||||
#endif
|
||||
{
|
||||
case BTLessStrategyNumber:
|
||||
{
|
||||
|
|
@ -1299,7 +1311,11 @@ IsValidHashRestriction(OpExpr *opClause)
|
|||
OpBtreeInterpretation *btreeInterpretation =
|
||||
(OpBtreeInterpretation *) lfirst(btreeInterpretationCell);
|
||||
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
if (btreeInterpretation->cmptype == BTGreaterEqualStrategyNumber)
|
||||
#else
|
||||
if (btreeInterpretation->strategy == BTGreaterEqualStrategyNumber)
|
||||
#endif
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -383,6 +383,54 @@ 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)
|
||||
{
|
||||
/* PG18+ expects a bool return */
|
||||
CitusExecutorStart(queryDesc, eflags);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
citus_executor_run_adapter(QueryDesc *queryDesc,
|
||||
ScanDirection direction,
|
||||
uint64 count)
|
||||
{
|
||||
/* PG18+ has no run_once flag
|
||||
* call the original Citus hook (which still expects the old 4-arg form) */
|
||||
CitusExecutorRun(queryDesc, direction, count, true);
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
/* PG15–17: adapter signatures must match the *old* typedefs */
|
||||
static void
|
||||
citus_executor_start_adapter(QueryDesc *queryDesc, int eflags)
|
||||
{
|
||||
CitusExecutorStart(queryDesc, eflags);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
citus_executor_run_adapter(QueryDesc *queryDesc,
|
||||
ScanDirection direction,
|
||||
uint64 count,
|
||||
bool run_once)
|
||||
{
|
||||
CitusExecutorRun(queryDesc, direction, count, run_once);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* shared library initialization function */
|
||||
void
|
||||
_PG_init(void)
|
||||
|
|
@ -457,8 +505,8 @@ _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;
|
||||
ExecutorStart_hook = CitusExecutorStart;
|
||||
ExecutorRun_hook = CitusExecutorRun;
|
||||
ExecutorStart_hook = citus_executor_start_adapter;
|
||||
ExecutorRun_hook = citus_executor_run_adapter;
|
||||
ExplainOneQuery_hook = CitusExplainOneQuery;
|
||||
prev_ExecutorEnd = ExecutorEnd_hook;
|
||||
ExecutorEnd_hook = CitusAttributeToEnd;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -578,8 +581,13 @@ static const TableAmRoutine fake_methods = {
|
|||
|
||||
.relation_estimate_size = fake_estimate_rel_size,
|
||||
|
||||
#if PG_VERSION_NUM < PG_VERSION_18
|
||||
|
||||
/* these two fields were removed in PG 18 */
|
||||
.scan_bitmap_next_block = fake_scan_bitmap_next_block,
|
||||
.scan_bitmap_next_tuple = fake_scan_bitmap_next_tuple,
|
||||
#endif
|
||||
|
||||
.scan_sample_next_block = fake_scan_sample_next_block,
|
||||
.scan_sample_next_tuple = fake_scan_sample_next_tuple
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -514,8 +514,9 @@ PendingWorkerTransactionList(MultiConnection *connection)
|
|||
List *transactionNames = NIL;
|
||||
int32 coordinatorId = GetLocalGroupId();
|
||||
|
||||
appendStringInfo(command, "SELECT gid FROM pg_prepared_xacts "
|
||||
"WHERE gid LIKE 'citus\\_%d\\_%%' and database = current_database()",
|
||||
appendStringInfo(command,
|
||||
"SELECT gid FROM pg_prepared_xacts "
|
||||
"WHERE gid COLLATE pg_catalog.default LIKE 'citus\\_%d\\_%%' COLLATE pg_catalog.default AND database = current_database()",
|
||||
coordinatorId);
|
||||
|
||||
int querySent = SendRemoteCommand(connection, command->data);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
{
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -239,18 +239,28 @@ CreateCertificatesWhenNeeded()
|
|||
SSL_CTX *sslContext = NULL;
|
||||
|
||||
/*
|
||||
* Since postgres might not have initialized ssl at this point we need to initialize
|
||||
* it our self to be able to create a context. This code is less extensive then
|
||||
* postgres' initialization but that will happen when postgres reloads its
|
||||
* configuration with ssl enabled.
|
||||
* Ensure the OpenSSL library is initialized so we can create our SSL context.
|
||||
* On OpenSSL ≥ 1.1.0 we call OPENSSL_init_ssl() (which also loads the default
|
||||
* config), and on older versions we fall back to SSL_library_init().
|
||||
* PostgreSQL itself will perform its full SSL setup when it reloads
|
||||
* its configuration with ssl enabled.
|
||||
*/
|
||||
#ifdef HAVE_OPENSSL_INIT_SSL
|
||||
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||
|
||||
/* OpenSSL 1.1.0+ */
|
||||
OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
|
||||
#else
|
||||
|
||||
/* OpenSSL < 1.1.0 */
|
||||
SSL_library_init();
|
||||
#endif
|
||||
|
||||
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||
sslContext = SSL_CTX_new(TLS_method());
|
||||
#else
|
||||
sslContext = SSL_CTX_new(SSLv23_method());
|
||||
#endif
|
||||
|
||||
if (!sslContext)
|
||||
{
|
||||
ereport(WARNING, (errmsg("unable to create ssl context, please verify ssl "
|
||||
|
|
@ -379,8 +389,17 @@ CreateCertificate(EVP_PKEY *privateKey)
|
|||
* would fail right after an upgrade. Instead of working until the certificate
|
||||
* expiration date and then suddenly erroring out.
|
||||
*/
|
||||
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||
|
||||
/* New mutable accessors (present in 1.1, 3.x). */
|
||||
X509_gmtime_adj(X509_getm_notBefore(certificate), 0);
|
||||
X509_gmtime_adj(X509_getm_notAfter(certificate), 0);
|
||||
#else
|
||||
|
||||
/* Legacy functions kept for 1.0.x compatibility. */
|
||||
X509_gmtime_adj(X509_get_notBefore(certificate), 0);
|
||||
X509_gmtime_adj(X509_get_notAfter(certificate), 0);
|
||||
#endif
|
||||
|
||||
/* Set the public key for our certificate */
|
||||
X509_set_pubkey(certificate, privateKey);
|
||||
|
|
|
|||
|
|
@ -9,14 +9,28 @@
|
|||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef COLUMNAR_COMPAT_H
|
||||
#define COLUMNAR_COMPAT_H
|
||||
#ifndef COLUMNAR_VERSION_COMPAT_H
|
||||
#define COLUMNAR_VERSION_COMPAT_H
|
||||
|
||||
#include "pg_version_constants.h"
|
||||
|
||||
/* for PG_VERSION_NUM and TupleDescAttr() */
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/htup_details.h"
|
||||
|
||||
|
||||
#define ACLCHECK_OBJECT_TABLE OBJECT_TABLE
|
||||
|
||||
#define ExplainPropertyLong(qlabel, value, es) \
|
||||
ExplainPropertyInteger(qlabel, NULL, value, es)
|
||||
|
||||
|
||||
/* tuple-descriptor attributes moved in PostgreSQL 18: */
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
#define Attr(tupdesc, colno) TupleDescAttr((tupdesc), (colno))
|
||||
#else
|
||||
#define Attr(tupdesc, colno) (&((tupdesc)->attrs[(colno)]))
|
||||
#endif
|
||||
|
||||
#endif /* COLUMNAR_COMPAT_H */
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ IsNodeWideObjectClass(ObjectClass objectClass)
|
|||
* If new object classes are added and none of them are node-wide, then update
|
||||
* this assertion check based on latest supported major Postgres version.
|
||||
*/
|
||||
StaticAssertStmt(PG_MAJORVERSION_NUM <= 17,
|
||||
StaticAssertStmt(PG_MAJORVERSION_NUM <= 18,
|
||||
"better to check if any of newly added ObjectClass'es are node-wide");
|
||||
|
||||
switch (objectClass)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,38 @@
|
|||
|
||||
#include "pg_version_constants.h"
|
||||
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
#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 */ \
|
||||
(e), /* startup_cost */ \
|
||||
(f), /* total_cost */ \
|
||||
(g), /* pathkeys */ \
|
||||
(h), /* required_outer */ \
|
||||
(i), /* fdw_outerpath */ \
|
||||
(j), /* fdw_restrictinfo*/ \
|
||||
(k) /* fdw_private */ \
|
||||
)
|
||||
|
||||
/* PG-18 introduced get_op_index_interpretation, old name was get_op_btree_interpretation */
|
||||
#define get_op_btree_interpretation(opno) get_op_index_interpretation(opno)
|
||||
|
||||
/* PG-18 unified row-compare operator codes under COMPARE_* */
|
||||
#define ROWCOMPARE_NE COMPARE_NE
|
||||
|
||||
#elif PG_VERSION_NUM >= PG_VERSION_17
|
||||
#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
|
||||
|
||||
#if PG_VERSION_NUM >= PG_VERSION_17
|
||||
|
||||
#include "catalog/pg_am.h"
|
||||
|
|
@ -384,10 +416,6 @@ 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)
|
||||
|
||||
#define getProcNo_compat(a) (a->vxid.procNumber)
|
||||
#define getLxid_compat(a) (a->vxid.lxid)
|
||||
|
||||
|
|
|
|||
|
|
@ -15,5 +15,6 @@
|
|||
#define PG_VERSION_16 160000
|
||||
#define PG_VERSION_17 170000
|
||||
#define PG_VERSION_18 180000
|
||||
#define PG_VERSION_19 190000
|
||||
|
||||
#endif /* PG_VERSION_CONSTANTS */
|
||||
|
|
|
|||
Loading…
Reference in New Issue