Add IDbTypeResolver to allow plugins to control how DbTypes are mapped#6267
Add IDbTypeResolver to allow plugins to control how DbTypes are mapped#6267NinoFloris merged 16 commits intonpgsql:mainfrom
Conversation
|
/cc @NinoFloris |
NinoFloris
left a comment
There was a problem hiding this comment.
Thanks for working on this so quickly, this is a good start.
Take a look at my feedback on the files themselves. Additionally I'd like to see a bit of test coverage of this feature for the DbType and DataTypeName properties.
The tests should assert that when these properties are expected to return resolved results they do so correctly. After ResolveTypeInfo has run a user should be able to observe that their DataTypeName for DbType.String changed from e.g. "text" to "citext".
1ba1424 to
f77aeff
Compare
test/Npgsql.Tests/TypeMapperTests.cs
Outdated
| Assert.That(parameter.NpgsqlDbType, Is.EqualTo(NpgsqlDbType.Uuid)); | ||
| Assert.That(parameter.DataTypeName, Is.EqualTo("uuid")); |
There was a problem hiding this comment.
@NinoFloris here I think we want this:
| Assert.That(parameter.NpgsqlDbType, Is.EqualTo(NpgsqlDbType.Uuid)); | |
| Assert.That(parameter.DataTypeName, Is.EqualTo("uuid")); | |
| Assert.That(parameter.NpgsqlDbType, Is.EqualTo(NpgsqlDbType.Unknow)); | |
| Assert.That(parameter.DataTypeName, Is.EqualTo(type)); |
But since when NpgsqlParameter.DbType is set, _npgsqlDbType is also set I couldn't get this result.
To achieve this DbType would have to take priority in the get of NpgsqlDbType and DataTypeName, or remove this behavior of when one is set the other is also set.
I haven't test this properly but I suspect both approaches would cause regressions.
I will take a closer look at this tomorrow, but if you have any ideias, or see something wrong, let me know.
There was a problem hiding this comment.
Yes they have their own storage now so they can be decoupled.
There was a problem hiding this comment.
When both values are set, like in this test:
We should prioritize the value of NpgsqlDbType? Or let DbType return the value that was explicitly set into it.
There was a problem hiding this comment.
Looks like most of the failing tests are related with the inference of the DbType when NpgsqlDbType and DbType are provided
There was a problem hiding this comment.
Those should be fixed now. If you have anything else to add please let me know. Otherwise it all looks good to me now and I can merge it for 10.0.
There was a problem hiding this comment.
@NinoFloris thank you so much! All looks good to me too.
There was a problem hiding this comment.
Thanks for your work on this!
Fyi, I did just find an issue with the api shape and how it interacts with type reloading, which I didn't quite foresee.
Compared to the lifetime of the rest of the resolver chain (which is generally built once), in an IDbTypeResolver you'd ideally want to be able to use facts about the current database. For example, to only map to citext if it's actually installed. Doing that works in the current design if you do this on every call into the resolver, but it would be pretty suboptimal to do so. Instead you would want to cache that fact inside the IDbTypeResolver instance. However at that point when a user calls ReloadTypes we have no way of getting that cached state reset, as we cannot recreate the resolver chain today (and neither would we want to for the type info resolvers).
So, at a minimum I'll have to change how we track these db type resolvers such that we can recreate when required. But it's likely I'll also tweak the api signatures a bit as we may not need to flow options through the method arguments any longer.
EDIT:
Additionally, lumping this resolver in with the others on PgTypeInfoResolverFactory means we should technically also support this feature through the global type mapper. This is not desired as we don't want to add new functionality to it any longer. All of this points to making DbTypeResolverFactory its own thing.
41d13f0 to
492f658
Compare
fdbbe67 to
563831e
Compare
563831e to
75d2389
Compare
75d2389 to
0151b80
Compare
This comment was marked as outdated.
This comment was marked as outdated.
0151b80 to
c345c91
Compare
|
@NinoFloris Just wanted to let you know that I’ve been testing my applications with Npgsql from this branch with Babelfish, and everything is working flawlessly. I honestly didn’t expect this change to require so much refactoring on your side — thank you so much for taking the time to review and improve it. I really appreciate all your work on this project! |
|
Good to hear it all works as expected. Features in this area always end up being more involved than anticipated. The postgres plugin system really does make npgsql quite a bit more complex when it comes to type mapping than other drivers. So thank you to for taking a shot at a complex issue, hopefully we'll see you back again! |
c4ae65c to
f49844f
Compare
| var param = (NpgsqlParameter)p; | ||
| param.NpgsqlDbType = (NpgsqlDbType)row[SchemaTableColumn.ProviderType]; | ||
| // DbCommandBuilder is going to set DbType.Int32 onto an existing parameter, reset other db type fields. | ||
| if (param.SourceColumnNullMapping) |
There was a problem hiding this comment.
See https://github.com/dotnet/runtime/blob/8f1dc6d3d2ed2918f1c68e285a5f3970e0d4cc91/src/libraries/System.Data.Common/src/System/Data/Common/DBCommandBuilder.cs#L1121. This is the only place that sets this property in the BCL. Why did this have to require heap storage on all parameter instances and couldn't be passed through this ApplyParameterInfo method? Who knows, it's probably very necessary™️
… DbTypes are mapped
This showed up in 'Timestamptz_as_DateTimeOffset_utc_with_DbType_DateTimeOffset' due to the mapping of DbType.DateTimeOffset (which does not have a matching NpgsqlDbType)
…etters # Conflicts: # src/Npgsql/NpgsqlParameter.cs
# Conflicts: # src/Npgsql/NpgsqlDataSourceBuilder.cs # src/Npgsql/NpgsqlSlimDataSourceBuilder.cs
This will allow custom resolvers to only return results under more specific circumstances
a1419af to
4d64c2a
Compare
… implementation compatible with unqualified names
4d64c2a to
208ffe6
Compare
closes #6233