mirror of https://github.com/citusdata/citus.git
Merge 433e22e995
into 55a0d1f730
commit
dcfd4f7c59
|
@ -108,6 +108,18 @@ RUN mkdir .pgenv-staging/
|
|||
RUN cp -r .pgenv/src .pgenv/pgsql-* .pgenv/config .pgenv-staging/
|
||||
RUN rm .pgenv-staging/config/default.conf
|
||||
|
||||
FROM base AS pg18
|
||||
RUN MAKEFLAGS="-j $(nproc)" pgenv build 18beta1
|
||||
RUN rm .pgenv/src/*.tar*
|
||||
RUN make -C .pgenv/src/postgresql-*/ clean
|
||||
RUN make -C .pgenv/src/postgresql-*/src/include install
|
||||
|
||||
# Stage the pgenv artifacts for PG18
|
||||
RUN mkdir .pgenv-staging/
|
||||
RUN cp -r .pgenv/src .pgenv/pgsql-* .pgenv/config .pgenv-staging/
|
||||
RUN rm .pgenv-staging/config/default.conf
|
||||
|
||||
|
||||
FROM base AS uncrustify-builder
|
||||
|
||||
RUN sudo apt update && sudo apt install -y cmake tree
|
||||
|
@ -201,6 +213,7 @@ COPY --link --from=uncrustify-builder /uncrustify/usr/ /usr/
|
|||
COPY --link --from=pg15 /home/citus/.pgenv-staging/ /home/citus/.pgenv/
|
||||
COPY --link --from=pg16 /home/citus/.pgenv-staging/ /home/citus/.pgenv/
|
||||
COPY --link --from=pg17 /home/citus/.pgenv-staging/ /home/citus/.pgenv/
|
||||
COPY --link --from=pg18 /home/citus/.pgenv-staging/ /home/citus/.pgenv/
|
||||
|
||||
COPY --link --from=pipenv /home/citus/.local/share/virtualenvs/ /home/citus/.local/share/virtualenvs/
|
||||
|
||||
|
@ -216,7 +229,7 @@ COPY --chown=citus:citus .psqlrc .
|
|||
RUN sudo chown --from=root:root citus:citus -R ~
|
||||
|
||||
# sets default pg version
|
||||
RUN pgenv switch 17.5
|
||||
RUN pgenv switch 18beta1
|
||||
|
||||
# make connecting to the coordinator easy
|
||||
ENV PGPORT=9700
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -32,11 +32,12 @@ jobs:
|
|||
style_checker_image_name: "ghcr.io/citusdata/stylechecker"
|
||||
style_checker_tools_version: "0.8.18"
|
||||
sql_snapshot_pg_version: "17.5"
|
||||
image_suffix: "-dev-d28f316"
|
||||
image_suffix: "-dev-aa7482a"
|
||||
pg15_version: '{ "major": "15", "full": "15.13" }'
|
||||
pg16_version: '{ "major": "16", "full": "16.9" }'
|
||||
pg17_version: '{ "major": "17", "full": "17.5" }'
|
||||
upgrade_pg_versions: "15.13-16.9-17.5"
|
||||
pg18_version: '{ "major": "18", "full": "18beta1" }'
|
||||
upgrade_pg_versions: "15.13-16.9-17.5-18beta1"
|
||||
steps:
|
||||
# Since GHA jobs need at least one step we use a noop step here.
|
||||
- name: Set up parameters
|
||||
|
@ -113,6 +114,7 @@ jobs:
|
|||
- ${{ needs.params.outputs.pg15_version }}
|
||||
- ${{ needs.params.outputs.pg16_version }}
|
||||
- ${{ needs.params.outputs.pg17_version }}
|
||||
- ${{ needs.params.outputs.pg18_version }}
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: "${{ matrix.image_name }}:${{ fromJson(matrix.pg_version).full }}${{ matrix.image_suffix }}"
|
||||
|
@ -144,6 +146,7 @@ jobs:
|
|||
- ${{ needs.params.outputs.pg15_version }}
|
||||
- ${{ needs.params.outputs.pg16_version }}
|
||||
- ${{ needs.params.outputs.pg17_version }}
|
||||
- ${{ needs.params.outputs.pg18_version }}
|
||||
make:
|
||||
- check-split
|
||||
- check-multi
|
||||
|
@ -173,6 +176,10 @@ jobs:
|
|||
pg_version: ${{ needs.params.outputs.pg17_version }}
|
||||
suite: regress
|
||||
image_name: ${{ needs.params.outputs.fail_test_image_name }}
|
||||
- make: check-failure
|
||||
pg_version: ${{ needs.params.outputs.pg18_version }}
|
||||
suite: regress
|
||||
image_name: ${{ needs.params.outputs.fail_test_image_name }}
|
||||
- make: check-enterprise-failure
|
||||
pg_version: ${{ needs.params.outputs.pg15_version }}
|
||||
suite: regress
|
||||
|
@ -185,6 +192,10 @@ jobs:
|
|||
pg_version: ${{ needs.params.outputs.pg17_version }}
|
||||
suite: regress
|
||||
image_name: ${{ needs.params.outputs.fail_test_image_name }}
|
||||
- make: check-enterprise-failure
|
||||
pg_version: ${{ needs.params.outputs.pg18_version }}
|
||||
suite: regress
|
||||
image_name: ${{ needs.params.outputs.fail_test_image_name }}
|
||||
- make: check-pytest
|
||||
pg_version: ${{ needs.params.outputs.pg15_version }}
|
||||
suite: regress
|
||||
|
@ -197,6 +208,10 @@ jobs:
|
|||
pg_version: ${{ needs.params.outputs.pg17_version }}
|
||||
suite: regress
|
||||
image_name: ${{ needs.params.outputs.fail_test_image_name }}
|
||||
- make: check-pytest
|
||||
pg_version: ${{ needs.params.outputs.pg18_version }}
|
||||
suite: regress
|
||||
image_name: ${{ needs.params.outputs.fail_test_image_name }}
|
||||
- make: installcheck
|
||||
suite: cdc
|
||||
image_name: ${{ needs.params.outputs.test_image_name }}
|
||||
|
@ -209,6 +224,10 @@ jobs:
|
|||
suite: cdc
|
||||
image_name: ${{ needs.params.outputs.test_image_name }}
|
||||
pg_version: ${{ needs.params.outputs.pg17_version }}
|
||||
- make: installcheck
|
||||
suite: cdc
|
||||
image_name: ${{ needs.params.outputs.test_image_name }}
|
||||
pg_version: ${{ needs.params.outputs.pg18_version }}
|
||||
- make: check-query-generator
|
||||
pg_version: ${{ needs.params.outputs.pg15_version }}
|
||||
suite: regress
|
||||
|
@ -221,6 +240,10 @@ jobs:
|
|||
pg_version: ${{ needs.params.outputs.pg17_version }}
|
||||
suite: regress
|
||||
image_name: ${{ needs.params.outputs.fail_test_image_name }}
|
||||
- make: check-query-generator
|
||||
pg_version: ${{ needs.params.outputs.pg18_version }}
|
||||
suite: regress
|
||||
image_name: ${{ needs.params.outputs.fail_test_image_name }}
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: "${{ matrix.image_name }}:${{ fromJson(matrix.pg_version).full }}${{ needs.params.outputs.image_suffix }}"
|
||||
|
@ -264,6 +287,7 @@ jobs:
|
|||
- ${{ needs.params.outputs.pg15_version }}
|
||||
- ${{ needs.params.outputs.pg16_version }}
|
||||
- ${{ needs.params.outputs.pg17_version }}
|
||||
- ${{ needs.params.outputs.pg18_version }}
|
||||
parallel: [0,1,2,3,4,5] # workaround for running 6 parallel jobs
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
@ -314,6 +338,10 @@ jobs:
|
|||
new_pg_major: 17
|
||||
- old_pg_major: 15
|
||||
new_pg_major: 17
|
||||
- old_pg_major: 17
|
||||
new_pg_major: 18
|
||||
- old_pg_major: 16
|
||||
new_pg_major: 18
|
||||
env:
|
||||
old_pg_major: ${{ matrix.old_pg_major }}
|
||||
new_pg_major: ${{ matrix.new_pg_major }}
|
||||
|
@ -401,7 +429,7 @@ jobs:
|
|||
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ${{ needs.params.outputs.test_image_name }}:${{ fromJson(needs.params.outputs.pg17_version).full }}${{ needs.params.outputs.image_suffix }}
|
||||
image: ${{ needs.params.outputs.test_image_name }}:${{ fromJson(needs.params.outputs.pg18_version).full }}${{ needs.params.outputs.image_suffix }}
|
||||
needs:
|
||||
- params
|
||||
- test-citus
|
||||
|
@ -513,7 +541,7 @@ jobs:
|
|||
name: Test flakyness
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ${{ needs.params.outputs.fail_test_image_name }}:${{ fromJson(needs.params.outputs.pg17_version).full }}${{ needs.params.outputs.image_suffix }}
|
||||
image: ${{ needs.params.outputs.fail_test_image_name }}:${{ fromJson(needs.params.outputs.pg18_version).full }}${{ needs.params.outputs.image_suffix }}
|
||||
options: --user root
|
||||
env:
|
||||
runs: 8
|
||||
|
|
|
@ -29,7 +29,7 @@ jobs:
|
|||
# Postgres versions are stored in .github/workflows/build_and_test.yml
|
||||
# file in json strings with major and full keys.
|
||||
# Below command extracts the versions and get the unique values.
|
||||
pg_versions=$(cat .github/workflows/build_and_test.yml | grep -oE '"major": "[0-9]+", "full": "[0-9.]+"' | sed -E 's/"major": "([0-9]+)", "full": "([0-9.]+)"/\1/g' | sort | uniq | tr '\n', ',')
|
||||
pg_versions=$(cat .github/workflows/build_and_test.yml | grep -oE '"major": "[0-9]+", "full": "[^"]+"' | sed -E 's/.*"major": "([0-9]+)".*/\1/' | sort -n | uniq | tr '\n' ',')
|
||||
pg_versions_array="[ ${pg_versions} ]"
|
||||
echo "Supported PG Versions: ${pg_versions_array}"
|
||||
# Below line is needed to set the output variable to be used in the next job
|
||||
|
|
|
@ -80,7 +80,7 @@ AC_SUBST(with_pg_version_check)
|
|||
|
||||
if test "$with_pg_version_check" = no; then
|
||||
AC_MSG_NOTICE([building against PostgreSQL $version_num (skipped compatibility check)])
|
||||
elif test "$version_num" != '15' -a "$version_num" != '16' -a "$version_num" != '17'; then
|
||||
elif test "$version_num" != '15' -a "$version_num" != '16' -a "$version_num" != '17' -a "$version_num" != '18'; then
|
||||
AC_MSG_ERROR([Citus is not compatible with the detected PostgreSQL version ${version_num}.])
|
||||
else
|
||||
AC_MSG_NOTICE([building against PostgreSQL $version_num])
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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,23 @@ 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
|
||||
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);
|
||||
#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 +1200,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 +1247,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 +2586,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 +2630,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,8 +372,9 @@ CommandMatchesLogGrepPattern(const char *command)
|
|||
if (GrepRemoteCommands && strnlen(GrepRemoteCommands, NAMEDATALEN) > 0)
|
||||
{
|
||||
Datum boolDatum =
|
||||
DirectFunctionCall2(textlike, CStringGetTextDatum(command),
|
||||
CStringGetTextDatum(GrepRemoteCommands));
|
||||
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"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* ruleutils_16.c
|
||||
* ruleutils_17.c
|
||||
* Functions to convert stored expressions/querytrees back to
|
||||
* source text
|
||||
*
|
||||
|
@ -9,7 +9,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/backend/distributed/deparser/ruleutils_16.c
|
||||
* src/backend/distributed/deparser/ruleutils_17.c
|
||||
*
|
||||
* This needs to be closely in sync with the core code.
|
||||
*-------------------------------------------------------------------------
|
||||
|
|
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),
|
||||
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));
|
||||
|
|
|
@ -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);
|
||||
#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,
|
||||
(es->buffers ? &bufusage : NULL),
|
||||
(es->memory ? &mem_counters : NULL));
|
||||
#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)
|
||||
);
|
||||
#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 */
|
||||
ExecutorRun(queryDesc, dir, 0L, true);
|
||||
/* 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"
|
||||
|
@ -61,6 +65,11 @@ typedef struct QualifierWalkerContext
|
|||
} QualifierWalkerContext;
|
||||
|
||||
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
#define get_op_btree_interpretation(opno) get_op_index_interpretation(opno)
|
||||
#endif
|
||||
|
||||
|
||||
/* Function pointer type definition for apply join rule functions */
|
||||
typedef MultiNode *(*RuleApplyFunction) (MultiNode *leftNode, MultiNode *rightNode,
|
||||
List *partitionColumnList, JoinType joinType,
|
||||
|
@ -2293,7 +2302,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"
|
||||
|
@ -177,6 +181,11 @@ typedef struct PruningInstance
|
|||
bool isPartial;
|
||||
} PruningInstance;
|
||||
|
||||
#if PG_VERSION_NUM >= PG_VERSION_18
|
||||
#define get_op_btree_interpretation(opno) get_op_index_interpretation(opno)
|
||||
#define ROWCOMPARE_NE COMPARE_NE
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Partial instances that need to be finished building. This is used to
|
||||
|
@ -1078,7 +1087,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 +1143,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 +1316,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,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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -384,9 +384,35 @@ 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/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
|
||||
#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 */ \
|
||||
)
|
||||
#else
|
||||
#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
|
||||
|
||||
|
||||
#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