Skip to content

fix(postgresql): stop declaring IPNetwork on both the cidr and inet mappings (weasel#405) - #408

Merged
jeremydmiller merged 1 commit into
masterfrom
fix/405-ipnetwork-double-claimed-mapping
Jul 30, 2026
Merged

fix(postgresql): stop declaring IPNetwork on both the cidr and inet mappings (weasel#405)#408
jeremydmiller merged 1 commit into
masterfrom
fix/405-ipnetwork-double-claimed-mapping

Conversation

@jeremydmiller

Copy link
Copy Markdown
Member

Closes #405.

PostgresqlProvider.GetTypeMapping breaks a CLR-type tie with LastOrDefault:

NpgsqlTypeMapper.Mappings.LastOrDefault(mapping => mapping.ClrTypes.Contains(type));

LastOrDefault only means something over an ordered sequence. Mappings is a JasperFx.Core.Cache backed by an ImHashMap, so it enumerates in hash-tree order:

enumeration order : <custom>, <custom>, Bigint, Boolean, Box, Bytea, Circle, Char
source declares   : Smallint, Integer, Bigint, Real, Double, Numeric, Money, Text

IPNetwork was the one CLR type claimed by two mappings — Cidr (line 85) and Inet (line 86):

mappings claiming IPNetwork : Inet/inet  |  Cidr/cidr   (LastOrDefault wins)
GetDatabaseType(IPNetwork)  : cidr

cidr is the right answer and ipnetwork_resolves_to_cidr passes — but only by accident. The source declares Cidr before Inet, so under genuine insertion order LastOrDefault would return inet and that test would fail today. It passes because the hash layout happens to enumerate Cidr last, which is a function of the current key set — and consuming code is explicitly invited to add mappings.

Change

Drop the stray typeof(IPNetwork) from the Inet mapping. IPAddress, NpgsqlInet and the (IPAddress, int) tuple stay on Inet. Resolution becomes unambiguous and order-independent.

Two guards so this cannot silently come back:

  • ipnetwork_is_claimed_by_exactly_one_mapping
  • no_clr_type_is_claimed_by_more_than_one_mapping — general, reports offenders as Type <- Mapping, Mapping

Counterfactual — restoring the duplicate fails both:

PostgresqlProviderTests.ipnetwork_is_claimed_by_exactly_one_mapping [FAIL]
PostgresqlProviderTests.no_clr_type_is_claimed_by_more_than_one_mapping [FAIL]

Verification

All four CI matrix legs (net9.0/net10.0 × case-sensitive true/false): 788 passed, 0 failed, 3 skipped.

One unrelated intermittent failure surfaced during validation — DatabaseWithTablesTests.detect_and_apply_schema_changes, which races other collections over the shared public schema. Confirmed pre-existing on clean master (reproduced in 3 runs there) and filed separately as #407. It is not affected by this change.

🤖 Generated with Claude Code

…appings (weasel#405)

GetTypeMapping resolves a CLR type with

    NpgsqlTypeMapper.Mappings.LastOrDefault(m => m.ClrTypes.Contains(type))

and LastOrDefault only means something over an ordered sequence. Mappings is
a JasperFx.Core.Cache backed by an ImHashMap, so it enumerates in hash-tree
order, not insertion order:

    enumeration : <custom>, <custom>, Bigint, Boolean, Box, Bytea, Circle, Char
    declared    : Smallint, Integer, Bigint, Real, Double, Numeric, Money, Text

IPNetwork was the one CLR type claimed by two mappings, cidr and inet. cidr
is correct and `ipnetwork_resolves_to_cidr` passes -- but only incidentally:
the source declares Cidr *before* Inet, so under real insertion order
LastOrDefault would return "inet" and that test would fail. It passed
because the hash layout happens to put Cidr last, which is a function of the
current key set rather than of anything declared. Consuming code is
explicitly invited to add mappings.

Drop the stray typeof(IPNetwork) from the inet mapping. IPAddress,
NpgsqlInet and the (IPAddress, int) tuple stay. Resolution is now
unambiguous and order-independent.

Two guards added: one pinning IPNetwork to exactly one mapping, and a
general one asserting no CLR type is claimed twice, so the ambiguity cannot
come back silently. Both fail if the duplicate is restored.

Postgres suite green on all four CI matrix legs, 788 passed each.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jeremydmiller
jeremydmiller merged commit fe46857 into master Jul 30, 2026
16 checks passed
@jeremydmiller
jeremydmiller deleted the fix/405-ipnetwork-double-claimed-mapping branch July 30, 2026 15:55
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.

GetTypeMapping resolves a doubly-claimed CLR type by LastOrDefault over an unordered map (IPNetwork)

1 participant