Skip to content

Providers: Make psycopg (v3) the default synchronous Postgres driver#69526

Open
Dev-iL wants to merge 6 commits into
apache:mainfrom
Dev-iL:2607/ppg3_providers
Open

Providers: Make psycopg (v3) the default synchronous Postgres driver#69526
Dev-iL wants to merge 6 commits into
apache:mainfrom
Dev-iL:2607/ppg3_providers

Conversation

@Dev-iL

@Dev-iL Dev-iL commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

closes:

related:


What changed (6 commits, one per package)

  1. providers/postgrespsycopg2-binary moves from a hard dependency to an optional [psycopg2] extra. The psycopg2-specific connection/cursor/execute_values imports are now lazy/guarded, raising a clear AirflowOptionalProviderFeatureException if genuinely needed but missing.
  2. providers/celery — the [celery] result_backend derivation from a driverless sql_alchemy_conn now targets postgresql+psycopg:// (matching the new sync default) when psycopg (v3) is importable, falling back to postgresql+psycopg2:// otherwise — mirroring the same guard PostgresHook uses.
  3. providers/googleBigQueryToPostgresOperator's psycopg2-specific register_adapter(list/dict, Json) now only runs when the resolved PostgresHook connection is actually on psycopg2 (a no-op on psycopg3), so the module imports cleanly without psycopg2 installed.
  4. providers/pgvectorPgVectorIngestOperator._register_vector now calls the registration helper matching the connection's actual driver (pgvector.psycopg2.register_vector vs. pgvector.psycopg.register_vector) instead of always assuming psycopg2, fixing a pre-existing bug.
  5. providers/amazonRedshiftSQLHook.get_sqlalchemy_engine() resolves an explicit driver (prefers psycopg, falls back to psycopg2, clear error if neither) instead of relying on SQLAlchemy's implicit psycopg2 default for a bare postgresql:// URI. get_uri()'s own bare-scheme contract is untouched. Also updates the Batch/ECS/Lambda executor docs' example connection strings to postgresql+psycopg://.
  6. providers/common/sqlDbApiHook.get_sqlalchemy_engine() retries with an explicit driver only for the specific "bare postgresql scheme, driver import failed" case; any other scheme's failure still propagates unchanged, keeping the class DB-agnostic. This is the general safety net: any current or future DbApiHook subclass with a postgres-compatible conn_type that doesn't override sqlalchemy_url is covered by this fix, not just the two concrete cases (amazon, google) found so far.

Test plan

  • New/updated tests per commit cover: the optional-psycopg2 fallback itself, both USE_PSYCOPG3 branches in celery/google/pgvector, PgVectorIngestOperator registering against both a psycopg2-backed and psycopg3-backed connection, and get_sqlalchemy_engine's driver-resolution/retry/re-raise/no-retry-for-other-schemes behavior in both amazon and common.sql.

Was generative AI tooling used to co-author this PR?
  • Yes (please specify the tool below)

  • Read the Pull Request Guidelines for more information. Note: commit author/co-author name and email in commits become permanently public when merged.
  • For fundamental code changes, an Airflow Improvement Proposal (AIP) is needed.
  • When adding dependency, check compliance with the ASF 3rd Party License Policy.
  • For significant user-facing changes create newsfragment: {pr_number}.significant.rst, in airflow-core/newsfragments. You can add this file in a follow-up commit after the PR is created so you know the PR number.

Dev-iL added 6 commits July 7, 2026 15:08
Mirrors the async default switch (apache#69089): PostgresHook no longer
requires psycopg2 at import time. The psycopg2-specific connection,
cursor, and execute_values imports are now lazy/guarded and raise a
clear AirflowOptionalProviderFeatureException if psycopg2 genuinely
needs to be used but isn't installed. psycopg2-binary moves to a new
[psycopg2] extra.

Part of the migration tracked in apache#68453.
The hardcoded fallback that derives [celery] result_backend from
sql_alchemy_conn when a driverless postgresql:// URL is configured
targeted postgresql+psycopg2:// explicitly. Update it to target
postgresql+psycopg:// to match the sync Postgres driver default change
in apache-airflow and apache-airflow-providers-postgres — but only
when psycopg (v3) is actually importable, since providers/celery's own
dependency floor doesn't guarantee SQLAlchemy 2.0+/psycopg, falling
back to postgresql+psycopg2:// otherwise (the same guard PostgresHook
itself uses).

Part of the migration tracked in apache#68453.
register_adapter(list/dict, Json) is psycopg2-specific and previously
ran unconditionally, forcing psycopg2 to be importable even when the
resolved PostgresHook connection is on psycopg3 (a no-op there). Only
import and call it when PostgresHook is actually on the psycopg2 path,
so the module imports cleanly without psycopg2 installed.

Part of the migration tracked in apache#68453.
from pgvector.psycopg2 import register_vector ran unconditionally at
module level, forcing psycopg2 to be importable regardless of which
driver the underlying PostgresHook connection actually uses, and was
always called even when the connection is on psycopg3 — where it's
the wrong helper entirely (psycopg3 has its own pgvector.psycopg
registration API). Make the import lazy, call the helper matching
PostgresHook.USE_PSYCOPG3, and raise a clear
AirflowOptionalProviderFeatureException if the needed driver's
pgvector integration is missing.

Fixes apache#69443.

Part of the migration tracked in apache#68453.
RedshiftSQLHook.get_sqlalchemy_engine() built its SQLAlchemy engine from
a bare postgresql:// URI, relying on SQLAlchemy's implicit default of
the psycopg2 DB-API. Now that apache-airflow-providers-postgres no
longer bundles psycopg2-binary by default, that import fails wherever
psycopg2 genuinely isn't installed. Resolve an explicit driver instead:
prefer psycopg (v3), fall back to psycopg2, and raise a clear error
only if neither is installed.

Also updates the Batch, ECS, and Lambda executor setup guides' example
postgresql+psycopg2:// connection strings to postgresql+psycopg://,
since those stale examples would otherwise break for anyone following
them as-is under the new default.

Part of the migration tracked in apache#68453.
SQLAlchemy resolves a bare postgresql:// scheme to the psycopg2 DB-API
by default, regardless of what Airflow's own config does. Any DbApiHook
subclass whose connection type maps to a bare postgresql:// URI (rather
than delegating to PostgresHook's own driver-aware sqlalchemy_url) broke
once apache-airflow-providers-postgres stopped hard-requiring psycopg2.
get_sqlalchemy_engine() now retries with an explicit driver — psycopg
(v3) preferred, psycopg2 as fallback — only for that specific bare-scheme
failure; any other scheme's error still propagates unchanged.

Part of the migration tracked in apache#68453.
@Dev-iL Dev-iL force-pushed the 2607/ppg3_providers branch from f5b1337 to c8ebd84 Compare July 7, 2026 12:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant