Skip to content

Commit

Permalink
Bind type handlers lazily (#3824)
Browse files Browse the repository at this point in the history
Closes #3816
Closes #2263
Part of #3300
  • Loading branch information
roji committed Jun 11, 2021
1 parent 543764e commit 98e7af8
Show file tree
Hide file tree
Showing 20 changed files with 620 additions and 268 deletions.
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<PackageVersion Include="System.ValueTuple" Version="4.5.0" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="5.0.0" />
<PackageVersion Include="Microsoft.Bcl.HashCode" Version="1.1.1" />
<PackageVersion Include="System.Collections.Immutable" Version="5.0.0" />

<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="3.9.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.2" />
Expand Down
4 changes: 2 additions & 2 deletions src/Npgsql/Internal/NpgsqlConnector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -567,8 +567,8 @@ internal async Task Open(NpgsqlTimeout timeout, bool async, CancellationToken ca
}
}

DatabaseInfo = database!;
TypeMapper.Bind(DatabaseInfo);
DatabaseInfo = TypeMapper.DatabaseInfo = database!;
TypeMapper.Reset();
}

internal async ValueTask<ClusterState> QueryClusterState(
Expand Down
27 changes: 27 additions & 0 deletions src/Npgsql/Internal/NpgsqlDatabaseInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,33 @@ protected NpgsqlDatabaseInfo(string host, int port, string databaseName, Version
Version = version;
}

internal PostgresType GetPostgresTypeByName(string pgName)
{
// Full type name with namespace
if (pgName.IndexOf('.') > -1)
{
if (ByFullName.TryGetValue(pgName, out var pgType))
return pgType;
}
// No dot, partial type name
else if (ByName.TryGetValue(pgName, out var pgType))
{
if (pgType is not null)
return pgType;

// If the name was found but the value is null, that means that there are
// two db types with the same name (different schemas).
// Try to fall back to pg_catalog, otherwise fail.
if (ByFullName.TryGetValue($"pg_catalog.{pgName}", out pgType))
return pgType;

throw new ArgumentException($"More than one PostgreSQL type was found with the name {pgName}, " +
"please specify a full name including schema");
}

throw new ArgumentException($"A PostgreSQL type with the name {pgName} was not found in the database");
}

internal void ProcessTypes()
{
foreach (var type in GetTypes())
Expand Down
2 changes: 2 additions & 0 deletions src/Npgsql/Internal/TypeHandlers/UnknownTypeHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ public override ValueTask<string> Read(NpgsqlReadBuffer buf, int byteLen, bool a
throw new Exception($"Received an unknown field but {nameof(fieldDescription)} is null (i.e. COPY mode)");

if (fieldDescription.IsBinaryFormat)
{
// At least get the name of the PostgreSQL type for the exception
throw new NotSupportedException(
_connector.TypeMapper.DatabaseInfo.ByOID.TryGetValue(fieldDescription.TypeOID, out var pgType)
? $"The field '{fieldDescription.Name}' has type '{pgType.DisplayName}', which is currently unknown to Npgsql. You can retrieve it as a string by marking it as unknown, please see the FAQ."
: $"The field '{fieldDescription.Name}' has a type currently unknown to Npgsql (OID {fieldDescription.TypeOID}). You can retrieve it as a string by marking it as unknown, please see the FAQ."
);
}

return base.Read(buf, byteLen, async, fieldDescription);
}
Expand Down
1 change: 1 addition & 0 deletions src/Npgsql/Npgsql.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' OR '$(TargetFramework)' == 'netstandard2.1' ">
<PackageReference Include="System.Text.Json" />
<PackageReference Include="System.Threading.Channels" />
<PackageReference Include="System.Collections.Immutable" />
</ItemGroup>
</Project>
1 change: 1 addition & 0 deletions src/Npgsql/NpgsqlConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ async Task OpenAsync(bool async, CancellationToken cancellationToken)
EnlistTransaction(enlistToTransaction);

timeout = new NpgsqlTimeout(connectionTimeout);

// Since this connector was last used, PostgreSQL types (e.g. enums) may have been added
// (and ReloadTypes() called), or global mappings may have changed by the user.
// Bring this up to date if needed.
Expand Down
24 changes: 12 additions & 12 deletions src/Npgsql/NpgsqlSchema.cs
Original file line number Diff line number Diff line change
Expand Up @@ -539,8 +539,8 @@ static DataTable GetDataTypes(NpgsqlConnection conn)

foreach (var baseType in connector.DatabaseInfo.BaseTypes)
{
if (!connector.TypeMapper.InternalMappings.TryGetValue(baseType.Name, out var mapping) &&
!connector.TypeMapper.InternalMappings.TryGetValue(baseType.FullName, out mapping))
if (!connector.TypeMapper.MappingsByName.TryGetValue(baseType.Name, out var mapping) &&
!connector.TypeMapper.MappingsByName.TryGetValue(baseType.FullName, out mapping))
continue;

var row = table.Rows.Add();
Expand All @@ -556,8 +556,8 @@ static DataTable GetDataTypes(NpgsqlConnection conn)

foreach (var arrayType in connector.DatabaseInfo.ArrayTypes)
{
if (!connector.TypeMapper.InternalMappings.TryGetValue(arrayType.Element.Name, out var elementMapping) &&
!connector.TypeMapper.InternalMappings.TryGetValue(arrayType.Element.FullName, out elementMapping))
if (!connector.TypeMapper.MappingsByName.TryGetValue(arrayType.Element.Name, out var elementMapping) &&
!connector.TypeMapper.MappingsByName.TryGetValue(arrayType.Element.FullName, out elementMapping))
continue;

var row = table.Rows.Add();
Expand All @@ -577,8 +577,8 @@ static DataTable GetDataTypes(NpgsqlConnection conn)

foreach (var rangeType in connector.DatabaseInfo.RangeTypes)
{
if (!connector.TypeMapper.InternalMappings.TryGetValue(rangeType.Subtype.Name, out var elementMapping) &&
!connector.TypeMapper.InternalMappings.TryGetValue(rangeType.Subtype.FullName, out elementMapping))
if (!connector.TypeMapper.MappingsByName.TryGetValue(rangeType.Subtype.Name, out var elementMapping) &&
!connector.TypeMapper.MappingsByName.TryGetValue(rangeType.Subtype.FullName, out elementMapping))
continue;

var row = table.Rows.Add();
Expand All @@ -598,8 +598,8 @@ static DataTable GetDataTypes(NpgsqlConnection conn)

foreach (var enumType in connector.DatabaseInfo.EnumTypes)
{
if (!connector.TypeMapper.InternalMappings.TryGetValue(enumType.Name, out var mapping) &&
!connector.TypeMapper.InternalMappings.TryGetValue(enumType.FullName, out mapping))
if (!connector.TypeMapper.MappingsByName.TryGetValue(enumType.Name, out var mapping) &&
!connector.TypeMapper.MappingsByName.TryGetValue(enumType.FullName, out mapping))
continue;

var row = table.Rows.Add();
Expand All @@ -613,8 +613,8 @@ static DataTable GetDataTypes(NpgsqlConnection conn)

foreach (var compositeType in connector.DatabaseInfo.CompositeTypes)
{
if (!connector.TypeMapper.InternalMappings.TryGetValue(compositeType.Name, out var mapping) &&
!connector.TypeMapper.InternalMappings.TryGetValue(compositeType.FullName, out mapping))
if (!connector.TypeMapper.MappingsByName.TryGetValue(compositeType.Name, out var mapping) &&
!connector.TypeMapper.MappingsByName.TryGetValue(compositeType.FullName, out mapping))
continue;

var row = table.Rows.Add();
Expand All @@ -628,8 +628,8 @@ static DataTable GetDataTypes(NpgsqlConnection conn)

foreach (var domainType in connector.DatabaseInfo.DomainTypes)
{
if (!connector.TypeMapper.InternalMappings.TryGetValue(domainType.BaseType.Name, out var baseMapping) &&
!connector.TypeMapper.InternalMappings.TryGetValue(domainType.BaseType.FullName, out baseMapping))
if (!connector.TypeMapper.MappingsByName.TryGetValue(domainType.BaseType.Name, out var baseMapping) &&
!connector.TypeMapper.MappingsByName.TryGetValue(domainType.BaseType.FullName, out baseMapping))
continue;

var row = table.Rows.Add();
Expand Down
Loading

0 comments on commit 98e7af8

Please sign in to comment.