Skip to content

Drop PG16 support #8750

Description

Drop PostgreSQL 16 support from main, making PG17 the minimum supported version (supported: 17, 18, and 19 in flight).

Follows the same shape as the PG15 drop: #8351 / #8372 (62a919066) plus the follow-up cleanup #8377 (529b303b6).

Plan — two PRs

PR 1 — build, source, and CI drop

Build / version plumbing

  • configure.ac + configure: != '16' -a != '17' -a != '18'!= '17' -a != '18'
  • src/include/pg_version_constants.h: delete #define PG_VERSION_16
  • .gitattributes: drop the ruleutils_16.c -citus-style line

Source

  • Delete src/backend/distributed/deparser/ruleutils_16.c (~9.2k lines)
  • Rename metadata/pg_get_object_address_16_17_18.cpg_get_object_address_17_18.c
  • src/include/pg_version_compat.h: collapse the #elif PG_VERSION_NUM >= PG_VERSION_17 branch to #else; unconditionalize the large #if PG_VERSION_NUM >= PG_VERSION_17 block and delete its legacy #else half
  • 21 .c files / ~60 guard sites: #if PG_VERSION_NUM >= PG_VERSION_17 becomes unconditional, #if PG_VERSION_NUM < PG_VERSION_17 blocks are removed. Heaviest: multi_explain.c (31 sites), recursive_planning.c (3), and 2 each in role.c, merge_planner.c, shardsplit_decoder.c, columnar_tableam.c, citus_depended_object.c
  • recursive_planning.c L512–538: the "Distributed queries with outer joins and pseudoconstant quals are not supported in PG16" error path becomes dead code and is removed

Deprecated GUC (see "GUC handling" below)

  • citus.enable_outer_joins_with_pseudoconstant_quals_pre_pg17 stays defined but inert, gains a deprecation warning via a check hook, and gets a rewritten description

CI / dev env

  • .github/workflows/build_and_test.yml: remove pg16_version, its 5 matrix entries, the citus-upgrade PG16 entry, and pg-upgrade pairs 16→17 / 16→18; set upgrade_pg_versions: "17.10-18.4"
  • .github/workflows/flaky_test_debugging.yml: pg16_versionpg17_version
  • .devcontainer/Dockerfile: drop the pg16 build stage and its COPY

PR 2 — test output and helper cleanup

  • src/test/regress/bin/normalize.sed: remove the block explicitly flagged # can be removed when dropping PG16 support (L293–306), plus the CHECK-constraint-parens and CREATE MATERIALIZED VIEW DEBUG rules
  • Remove server_version_ge_17 gates from grant_on_table_propagation, multi_alter_table_add_constraints, multi_mx_create_table, multi_mx_hide_shard_names, multi_schema_support, pg15, pg17, pg17_json and regenerate the .out files
  • pg17.sql: drop the three SET/RESET citus.enable_outer_joins_with_pseudoconstant_quals_pre_pg17 pairs (L223/231, 247/253, 273/281). They are PG16-era scaffolding that is already a no-op on PG17+, and leaving them would make every run emit the new deprecation warning.
  • Delete now-unreachable alternative outputs: columnar_chunk_filtering_0.out, subquery_in_where_0.out, pg17_0.out, multi_mx_hide_shard_names_0.out, and friends
  • Retire helpers explain_with_pg16_subplan_format and initplan_references_to_pg17, plus the %3$s -- >= pg16 options argument in multi_test_helpers.sql and columnar_test_helpers.sql
  • Fold create_drop_database_propagation_pg16.sql into the main test file and update multi_1_schedule
  • Delete src/test/regress/{sql,expected}/pg16.* and remove test: pg16 from multi_1_create_citus_schedule
  • Opportunistic, while in the same files: delete the stale create_drop_database_propagation_pg15.{sql,out} left behind by the PG15 drop, and fix the ruleutils_17.c L12 reference to ruleutils_16.c plus the incorrect #endif comment at ruleutils_18.c L10359

Explicitly out of scope

No SQL migration. This drop touches no files under src/backend/distributed/sql/. The PG15 drop (62a919066) set that precedent, and keeping it migration-free keeps the risk profile low.

Two related items were split out rather than bundled:

GUC handling

citus.enable_outer_joins_with_pseudoconstant_quals_pre_pg17 is not removed in 15.0. Removing it outright would make existing postgresql.conf / ALTER SYSTEM / ALTER DATABASE ... SET entries fail on startup. Instead it is left defined but inert, and anyone who still sets it gets told it is going away.

Implemented with a check hook, matching the existing WarnIfDeprecatedExecutorUsed / NoticeIfSubqueryPushdownEnabled pattern in shared_library_init.c:

/*
 * WarnIfDeprecatedPseudoconstantQualsGucIsSet emits a deprecation warning when
 * citus.enable_outer_joins_with_pseudoconstant_quals_pre_pg17 is set explicitly.
 * The GUC only ever applied to PG16, which Citus no longer supports.
 */
static bool
WarnIfDeprecatedPseudoconstantQualsGucIsSet(bool *newval, void **extra,
                                            GucSource source)
{
    if (source != PGC_S_DEFAULT)
    {
        ereport(WARNING, (errcode(ERRCODE_WARNING_DEPRECATED_FEATURE),
                          errmsg("citus.enable_outer_joins_with_pseudoconstant_"
                                 "quals_pre_pg17 has no effect and is deprecated"),
                          errdetail("This setting only applied to PostgreSQL 16, "
                                    "which Citus no longer supports."),
                          errhint("Remove it from your configuration. It will be "
                                  "removed in a future Citus release.")));
    }

    return true;
}

Behaviour notes:

  • source != PGC_S_DEFAULT means it fires for SET, ALTER SYSTEM, ALTER DATABASE/ROLE ... SET, and postgresql.conf — i.e. any environment where a customer has actually set it — but never for the built-in default, so a clean install is silent.
  • It fires regardless of whether the value is on or off, because either way the entry should be removed.
  • RESET / SET ... TO DEFAULT restores reset_val without re-invoking the check hook, so it does not double-warn. Worth confirming during implementation.
  • Set in postgresql.conf, this logs once per backend start. That is intentional nagging for a setting nobody should still have.

The description is rewritten so \dconfig-style introspection also reflects the state:

gettext_noop("This setting has no effect and is deprecated."),
gettext_noop("It only applied to PostgreSQL 16, which Citus no longer "
             "supports. The setting is retained so existing configurations "
             "keep loading, and will be removed in a future Citus release."),

Actual removal of the GUC, its backing variable EnableOuterJoinsWithPseudoconstantQualsPrePG17, and this hook is tracked in #8751 for 15.1.

Cross-repo impact

Required, blocking — citusdata/the-process
Sister PR needed, merged before PR 1 so the rebuilt CI images and new image_suffix are available (the PG15 sister PR citusdata/the-process#178 merged 3 days ahead).

  • circleci/images/PG_VERSIONS: remove PG16=16.14
  • circleci/images/Makefile: remove CITUS_UPGRADE_VERSIONS_16=v12.1.14

No change now — citusdata/packaging
The dockerfiles/*-pg16 build environments are still required by release-13.x (PG15/16/17) and release-12.1 (PG14/15/16). At Citus 15.0 release time, add 15.0: postgres_versions: [ 17, 18 ] to postgres-matrix.yml.

No change now — citusdata/docker
postgres-16/Dockerfile on master images released Citus 14.1.0, which still supports PG16. Retire once PG16 images are no longer published.

No change now — citusdata/tools
packaging_automation/publish_docker.py carries a postgres_16 enum entry and templates/docker/postgres-16/postgres-16.tmpl.dockerfile. Coupled to the docker repo; retire together.

No change — citusdata/test-automation
No PG16 references found.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions