Skip to content

Better Ergonomics For Psycopg2#36

Merged
marcelofern merged 1 commit into
mainfrom
better-ergonomics-for-psycopg-2
May 20, 2025
Merged

Better Ergonomics For Psycopg2#36
marcelofern merged 1 commit into
mainfrom
better-ergonomics-for-psycopg-2

Conversation

@marcelofern
Copy link
Copy Markdown
Collaborator

@marcelofern marcelofern commented May 19, 2025

Prior to this change, this package was relying on the default behaviour of Psycopg for cursor instantiation.

The problem is that there are differences between Psycopg 2 and Psycopg 3 that make this unfeasible for this library, which supports both versions.

For example, when a cursor is instantiated from the connection context manager, Psycopg 2 starts a transaction automatically [1][2], whereas Psycopg 3 doesn't.

  with connection.cursor() as cur:
      # There is already an implicit "BEGIN;" here on Psycopg 2.
      # But not on Psycopg 3
      ...

This problem came up when testing Psycopack locally using Psycopg 2.

The following ABORT call had to be added or else the procedure would fail when creating indexes CONCURRENTLY, as that can't happen inside a transaction.

  from psycopack import psycopack, get_db_connection

  with get_db_connection("postgresql://user:password@host:port/db") as conn:
      with conn.cursor() as cur:
          cur.execute("ABORT;")
          psycopack = Psycopack(
              batch_size=50_000,
              conn=conn,
              cur=cur,
              schema="public",
              table="to_psycopack",
              # Set this argument and Psycopack will do the conversion
              # automatically.
              convert_pk_to_bigint=True,
          )
          psycopack.sync_schemas()

In any case, Psycopack handles its own transactions and does not need to rely on arbitrary library designs.

@github-actions
Copy link
Copy Markdown

Coverage Report Results

Name Stmts Miss Branch BrPart Cover
src/psycopack/__init__.py 6 0 0 0 100%
src/psycopack/_commands.py 109 0 8 0 100%
src/psycopack/_conn.py 5 0 0 0 100%
src/psycopack/_const.py 3 0 0 0 100%
src/psycopack/_cur.py 21 0 0 0 100%
src/psycopack/_identifiers.py 12 0 2 0 100%
src/psycopack/_introspect.py 155 0 12 0 100%
src/psycopack/_logging.py 4 0 0 0 100%
src/psycopack/_psycopg.py 5 0 0 0 100%
src/psycopack/_registry.py 58 0 6 0 100%
src/psycopack/_repack.py 346 0 114 0 100%
src/psycopack/_tracker.py 165 0 36 0 100%
tests/conftest.py 19 0 0 0 100%
tests/factories.py 33 0 4 0 100%
tests/test_cur.py 20 0 2 0 100%
tests/test_fixtures.py 5 0 0 0 100%
tests/test_package.py 3 0 0 0 100%
tests/test_repack.py 675 0 0 0 100%
TOTAL 1644 0 184 0 100%

1 empty file skipped.

@marcelofern marcelofern requested a review from a team May 19, 2025 22:09
@marcelofern marcelofern marked this pull request as ready for review May 19, 2025 22:09
Copy link
Copy Markdown
Contributor

@timb07 timb07 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Comment thread src/psycopack/_cur.py Outdated
Prior to this change, this package was relying on the default behaviour
of Psycopg for cursor instantiation.

The problem is that there are differences between Psycopg 2 and Psycopg
3 that make this unfeasible for this library, which supports both
versions.

For example, when a cursor is instantiated from the connection context
manager, Psycopg 2 starts a transaction automatically [1][2], whereas
Psycopg 3 doesn't.

  with connection.cursor() as cur:
      # There is already an implicit "BEGIN;" here on Psycopg 2.
      # But not on Psycopg 3
      ...

This problem came up when testing Psycopack locally using Psycopg 2.

The following ABORT call had to be added or else the procedure would
fail when creating indexes CONCURRENTLY, as that can't happen inside a
transaction.

  from psycopack import psycopack, get_db_connection

  with get_db_connection("postgresql://user:password@host:port/db") as conn:
      with conn.cursor() as cur:
          cur.execute("ABORT;")
          psycopack = Psycopack(
              batch_size=50_000,
              conn=conn,
              cur=cur,
              schema="public",
              table="to_psycopack",
              # Set this argument and Psycopack will do the conversion
              # automatically.
              convert_pk_to_bigint=True,
          )
          psycopack.sync_schemas()

In any case, Psycopack handles its own transactions and does not need to
rely on arbitrary library designs.

- [1] psycopg/psycopg2#941 (comment)
- [2] psycopg/psycopg2#1305 (comment)
@marcelofern marcelofern force-pushed the better-ergonomics-for-psycopg-2 branch from 3465b07 to 26b812a Compare May 20, 2025 00:37
@marcelofern marcelofern merged commit 673e6e0 into main May 20, 2025
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants