-
Notifications
You must be signed in to change notification settings - Fork 877
Split TypeMapperResolver from TypeHandlerResolver #4973
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Split TypeMapperResolver from TypeHandlerResolver #4973
Conversation
1b4c6a2 to
428875f
Compare
428875f to
311566a
Compare
NinoFloris
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Split looks good and will help me with refactoring the TypeHandlerResolver/TypeHandlers.
As discussed offline there is still quite a bit of unnecessary complication and duplication in the mapping api's and its code but that's not directly the goal to fix in this PR either. (Same goes for the beautiful GetDataTypeNameByValueDependentValue)
0f3a7f2 to
36f9d85
Compare
|
|
||
| var globalMapperResolver = resolverFactories[i].CreateGlobalMapperResolver(); | ||
| if (globalMapperResolver is not null) | ||
| GlobalTypeMapper.Instance.TryAddMapperResolver(globalMapperResolver); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't this mean that if I add some plugin to my specific data source, we change the global type mapper? If so, this is new behavior that I'm not sure we want - the global type mapper config is supposed to flow to the data source, but not vice versa, no? At least up to now, the idea was that you only see mappings on the global type mapper for plugins which you add to it.
See general review comment on where we want to go with NpgsqlParameter type inference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't this mean that if I add some plugin to my specific data source, we change the global type mapper? If so, this is new behavior that I'm not sure we want - the global type mapper config is supposed to flow to the data source, but not vice versa, no? At least up to now, the idea was that you only see mappings on the global type mapper for plugins which you add to it.
Yesn't ![]()
The main problem are ranges (again). In 7.0 we were able to map on them via GlobalTypeMapper automatically (as it was done in BuiltInTypeResolver and TypeMapper). Currently, that's not going to work as (almost) all of that logic was moved to a separate resolver. And we don't really want to add mapping resolver to GlobalTypeMapper because it references NpgsqlRange, which brings a lot of code + trimming warning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that if we need to, it's not the end of the world to not have ranges in the global type mapper. We already don't take into account data source mappings, so it's not like it's a full-featured thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, though the more things we'll move in separate resolvers, the less we'll be able to map from global type mapper.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, though at least in some other cases having a type mapping resolver rooted globally maybe isn't so bad, since the types it references aren't problematic...
So you think it's better to just have the data source mappings impact the global type mapper, with the assumption that there's only one data source in the typical app anyway?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So you think it's better to just have the data source mappings impact the global type mapper, with the assumption that there's only one data source in the typical app anyway?
That pretty much depends on whether we're going to support global type mapper. I personally don't really like this design (having to differentiate between a mapper for local and a mapper for global type mappers, adding a specific mapper to global automatically), but if we're going to support global type mapper (at least for the foreseeable future), we might as well merge this and refactor later (removing the code shouldn't be that hard).
And my assumption was that users aren't going to use multiple data sources with different mappings (e.g. one has ranges, one doesn't, that's probably only going to be true for custom types, which we don't map anyway).
|
Assuming I haven't missed anything, the global-level mapper (mapping) resolvers are there to support NpgsqlParameter type inference, whereas the TypeMapper ones are there to supportNpgsqlSchema.GetDataTypes. The global support - for NpgsqlParmeter type inference - is becoming somewhat less relevant since we have data source; doing type mapping on the global type mapper is now discouraged/deprecated. NpgsqlParameter type inference is also problematic because it doesn't take into account data source-level mappings. So maybe we should thinkg about where we want to go with all this...
/cc @NinoFloris |
That's the reason for having both |
|
Sure, though the point is that we "leak" mappings from the data source to the global. For example, say i have two data sources, one with ranges and one without; parameters will always report that range is supported, even though using them on one of the data sources will actually fail. Maybe this isn't so bad, I dunno... |
roji
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about it some more and I guess I'm OK with it... The global type mapper will mean something like "some data source in the application has this mapping", without any guarantee that this mapping is actually valid everywhere. To be completely accurate, there wasn't even that guarantee before, i.e. a data source created before a global plugin registration wouldn't have it, of course.
Maybe just take a look at the naming suggestion...
Closes #4972
The main idea is that now we have
TypeMapperResolver, which can be created fromTypeHandlerResolverFactory. Now, whenever we initialize aTypeMapper(on datasource bootstrapping) we create a localTypeMapperResolver, which we add to theTypeMapperand a globalTypeMapperResolver, which we try to add toGlobalTypeMapper. This allows us to add global mappings for types user opts into automatically.While most of the time both local and global
TypeMapperResolverare the same, we have to differentiate between them because some mapper resolvers can have state (e.g. json serialization settings), which make them unfit to automatically add toGlobalTypeMapper. But there is an exception to that rule, that is if a user addsTypeHandlerResolverFactorytoGlobalTypeMapperexplicitly, in which case we have to create localTypeMapperResolverand use it inGlobalTypeMapper.This change allows us to move range type mapping fromBuiltInResolver, which saves 120kb on linux (and about 300kb on windows, no idea why such a difference).upd: saves on linux about 340kb