Split out of #398 / #402.
PostgresqlProvider.GetTypeMapping picks a mapping for a CLR type with:
NpgsqlTypeMapper.Mappings.LastOrDefault(mapping => mapping.ClrTypes.Contains(type));
LastOrDefault only means something over an ordered sequence. NpgsqlTypeMapper.Mappings is a JasperFx.Core.Cache, which is backed by an ImHashMap — enumeration is in hash-tree order, not insertion order:
first 8 in enumeration order : <2 custom>, Bigint, Boolean, Box, Bytea, Circle, Char
source declares : Smallint, Integer, Bigint, Real, Double, Numeric, Money, Text
Today exactly one CLR type is claimed by two mappings — IPNetwork, in both Cidr (line 85) and Inet (line 86–87):
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 incidentally. The source declares Cidr before Inet, so under genuine insertion order LastOrDefault would return inet and that test would fail. It passes because the hash layout happens to enumerate Cidr last.
That makes the result a function of the current key set rather than of anything declared. Adding mappings — which consuming code is explicitly invited to do — can rebalance the tree.
Suggested fix: drop the stray typeof(IPNetwork) from the Inet mapping so no CLR type is claimed twice, and make the ambiguity structurally impossible rather than order-dependent. IPAddress, NpgsqlInet and the (IPAddress, int) tuple stay on Inet. Worth also considering whether GetTypeMapping should assert on a double claim instead of silently picking one.
Split out of #398 / #402.
PostgresqlProvider.GetTypeMappingpicks a mapping for a CLR type with:LastOrDefaultonly means something over an ordered sequence.NpgsqlTypeMapper.Mappingsis aJasperFx.Core.Cache, which is backed by anImHashMap— enumeration is in hash-tree order, not insertion order:Today exactly one CLR type is claimed by two mappings —
IPNetwork, in bothCidr(line 85) andInet(line 86–87):cidris the right answer, andipnetwork_resolves_to_cidrpasses — but only incidentally. The source declaresCidrbeforeInet, so under genuine insertion orderLastOrDefaultwould returninetand that test would fail. It passes because the hash layout happens to enumerateCidrlast.That makes the result a function of the current key set rather than of anything declared. Adding mappings — which consuming code is explicitly invited to do — can rebalance the tree.
Suggested fix: drop the stray
typeof(IPNetwork)from theInetmapping so no CLR type is claimed twice, and make the ambiguity structurally impossible rather than order-dependent.IPAddress,NpgsqlInetand the(IPAddress, int)tuple stay onInet. Worth also considering whetherGetTypeMappingshould assert on a double claim instead of silently picking one.