Skip to content

fix(db): ComplexHelper must not register enum/composite types on the connection (0.15.1) - #55

Merged
aersam merged 6 commits into
mainfrom
fix-54-complex-registration
Oct 9, 2026
Merged

aersam merged 6 commits into
mainfrom
fix-54-complex-registration

Conversation

@aersam

@aersam aersam commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #54

Bug

ComplexHelper called register_enum / register_composite on the connection. psycopg's registration is global to a connection and so sticks to it in a pool: after any pg_* call with a helper (and since 0.15's complex_helper="auto", any pg_* call on a table with enum/composite columns), a plain SELECT 'idle'::some_enum on the same connection returned psycopg's auto-numbered Enum member instead of the label, and composites came back as namedtuples.

Design

  • Nothing is registered on the connection any more. Writes (pg_insert, pg_update*, pg_upsert*, *_many, and testdb.schema seeding) register the enum/composite adapters on the cursor that runs the statement (psycopg copies the connection's adapters per cursor), and only for columns where a dict/list value had to be converted. New public ComplexHelper.register_on(context, info) for callers of recursive_convert.
  • info.enum / info.python_type (needed by recursive_convert) are materialised in a scratch AdaptersMap that no connection or cursor sees; a module-level make_object keeps psycopg's generated-loader-class cache from growing on every registration (a test covers it).
  • Reads (pg_retrieve*) already use to_jsonb(...) and need no registration. RETURNING of pg_insert/pg_update_dict/pg_upsert_dict now does the same, so results no longer depend on which columns were written.
  • Per-connection cache still holds the catalog lookups (types, column types); it no longer contains any "registered" state. complex_helper="auto", cache=False, clear_cache() unchanged.
  • Also fixed (found while reviewing): a composite whose field is an enum array (create type onlyarr as (ms mood[])) failed with Expected EnumInfo, got CompositeInfo; array types now report their element type's typtype. load_all_complex_types now orders columns by ordinal_position (needed for the raw-tuple RETURNING of pg_update_dict).

Behaviour changes that need a human decision

  1. RETURNING rows with a complex_helper are now plain values (composite as dict, enum as label), like pg_retrieve; in 0.15 a converted column came back as the registered object (composite namedtuple / Enum member), others as text, depending on input. Without a helper: unchanged RETURNING *.
  2. recursive_convert used directly no longer works with a plain con.execute of the converted value: register on the cursor first (await helper.register_on(cur, info)); registering on the connection restores the old global behaviour.
  3. testdb.schema seeding no longer leaves types registered on the connection (reads of seeded enum/composite columns on that connection are now label / text).
  4. ComplexHelper.registered is kept as a deprecated shim (always empty, setter ignored, DeprecationWarning), so this stays a patch release (0.15.1).

Tests

  • Regression for the issue: plain SELECT of an enum / composite / enum[] unchanged before and after every pg_* helper (retrieve, retrieve_many, insert, update, upsert, *_many, with "auto", a helper, cache=False); the issue's snippet; a one-connection PgPool variant (use, release, plain query on the same backend pid); register_on scoped to the cursor incl. nested types; deterministic RETURNING in both orderings; enum-array-in-composite; loader cache does not grow; deprecated shim. Existing complex-type / crud / testdb tests adapted where they asserted the old leaking or object-valued behaviour.
  • Live tests are requires_podman-gated as before; also run locally against a private Postgres 18 (24+ live tests green), ty check and pytest -m "not mssql" green.

Version 0.15.1 (+ uv lock).

🤖 Generated with Claude Code

@aersam
aersam marked this pull request as ready for review October 9, 2026 17:27
@aersam
aersam merged commit 6148267 into main Oct 9, 2026
2 checks passed
aersam and others added 6 commits October 9, 2026 18:04
…ng cursor only, never on the connection (Fixes #54)

Bump to 0.15.1.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…te loader classes, docs wording, more tests

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…_jsonb for complex columns (deterministic plain values); enum[] inside a composite is detected as an enum

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
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.

ComplexHelper registers enums/composites connection-globally: later plain SELECTs return Enum members instead of labels

1 participant