-
Notifications
You must be signed in to change notification settings - Fork 225
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
Schema enums follow up (part 2) #685
Schema enums follow up (part 2) #685
Conversation
25fa864
to
5dd2e73
Compare
f477f3b
to
f126ae1
Compare
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.
Just few nits.
@roji You asked previously about some code that looked like this: // Alter operations may not have a default schema attached. If not, try to attach one for schema-qualified types.
if (operation[RelationalAnnotationNames.DefaultSchema] == null)
operation[RelationalAnnotationNames.DefaultSchema] = model[RelationalAnnotationNames.DefaultSchema]; I think my previous answer was incomplete. Completely removing that code in #626 worked because #605 had some (unintentionally) hackish code that covered up the root of the issue by accessing the model as a fallback when a schema was unavailable for an enum. It was a bit confusing to unwind, but I think the root of the issue is that we weren't yielding the default schema annotation from I've changed that here, such that |
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.
It looks good, thanks! I'd just like to understand about the DefaultSchema
annotation not being present in SqlServerMigrationsAnnotationProvider... Can you please try to take a look?
src/EFCore.PG/Migrations/Internal/NpgsqlMigrationsAnnotationProvider.cs
Outdated
Show resolved
Hide resolved
c9757ca
to
fc3f00a
Compare
fc3f00a
to
28b58b1
Compare
@roji I think this is very close to ready, but there are some changes since your last review that I'd like to get your OK on before merging. Specifically:
These changes are focused on simplifying Also note I've split changes that were unrelated to the annotations into #724. |
@austindrenski thanks for continuing to work on this. I'm not going to review again because of the DefaultSchema binding question - see my comment above. Once we resolve all that I'll give this another full review. |
28b58b1
to
5ecd3da
Compare
@roji Handling this via
I've put together a pair of PRs to update |
Opened #730 to discuss the ModelDiffer/custom migration question again. |
2b2e67d
to
a38c333
Compare
I recognize that these are departures from the previous design, and I can roll back some of it (e.g. file layout), but we do need some of these changes. For example, Regarding the mutability of With those questions outstanding, and since we don't (yet!) support altering enums, I would rather keep these as immutable as possible, at least until we start to support alter operations on them.
That works for me. But I think that this does require something like I'm open to other ways to accomplish this, but I settled on the current design because it reduced the need to duplicate annotation logic and kept the "serialization" logic inside of I've updated the PR to rollback some of the obvious stuff and rework the point of access for the default schema. Let me know how that looks, or if you think more needs to be rolled back (i.e. if settable properties are critical). I'll update the other PRs now, but don't worry about looking at them yet, I just want to make sure the patterns/logic look good in the other metadata classes too. |
My point was that this was not actually something we should be doing - I took back my idea of translating the model enum annotation into a different annotation for the migrations... The reasoning is that if the user doesn't specify a schema for the enum, then the generated migration should actually not contain the default schema (again, I reversed what I had previously written). Instead, the migration code should contain null for the schema - just like table and sequence do - and the binding should only occur very late, at the SQL migration phase. I recommend taking a look at Sequence.cs for inspiration on how PostgresEnum.cs should look like, even if they're not going to be identical. Just to be extra clear: my change of mind here really stemmed from a misunderstanding of how EF Core works... If a user doesn't specify a schema, the resulting migration should not contain a schema - even if the actual object gets creating in the default schema - and if the default schema later changes, then EF Core moves the object from the old default schema to the new one, at that very moment. Keeping the schema null is in fact required in order to be able to detect objects which were created in the (previous) default schema; if the schema were baked into the annotation, we wouldn't be able to know whether the user specified it (in which case it shouldn't move) or whether it was just the default (in which case it should).
That's a valid question... I think that the mutability of the metadata (i.e. the annotations) isn't the same as our capability to carry out the corresponding change in the database. In other words, there may be scenarios where the metadata is simply built incrementally by the user, i.e. they interact directly with PostgresEnum to build the list of values based on some logic, rather than using the I'll really try to be available tonight (your morning) so we can have some online time together to discuss all this. |
OK, it sounds like you're recommending this approach: protected virtual void GenerateCreateEnum(
[NotNull] PostgresEnum enumType,
[NotNull] IModel model,
[NotNull] MigrationCommandListBuilder builder)
{
var schema = enumType.Schema ?? model.Relational().DefaultSchema; If so, this approach will definitely work, and it doesn't require any modifications to the annotation provider (or individual annotations).
Ah, that sounds very obvious now, but I was working under the impression that these were more or less public-for-internal-use (e.g. us or other downstream providers) rather than public-for-public-use (e.g. end users). If we intend end users to build these incrementally, then mutable properties make more sense. |
Shoot. I've botched that last push. Hold off on review, I'll post back once fixed. |
78d9aa4
to
fef03ad
Compare
OK, cleaned up and ready for review. |
fef03ad
to
9a09bae
Compare
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.
This is looking almost ready. I don't have time at the moment for a full review but will be a bit more available later - see a minor comment below. In general, I think we should try to make this as close as possible EF Core's Sequence implementation.
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.
Check out my comments again, I think we're pretty close. I'll be available in the coming hours to discuss.
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.
Somehow my comments got split into two reviews, strange...
Refactors `PostgresEnum` to properly handle schema qualification without breaking the standard patterns for migration operations. Schema-qualified enums are now yielded from the annotation provider with the default schema "baked in" such that migration operations are self-contained. To get this right, `PostgresEnum` is refactored to be less mutable, with simpler access patterns. The `GetData()` and `SetData(...)` functions are removed in support this simpler, more immutable enum representation. Address review comments: - Rollback some of the layout changes - Move the "get or add" logic back into `GetOrAddPostgresEnum` - Move default schema access back into `PostgresEnum` - Note that this depends on `CreateAnnotation` (or similar)
- Late-access default schema (SQL generation time). - Return `IReadOnlyList<string>` for `PostgresEnum.Labels` since items of that collection are not writable (i.e. returns a copy from the annotation value). - Revert changes in the annotation provider. If the default schema is late-accessed for SQL generation, then we can return an unmodified annotation. - Match the semantics of `Sequence.cs` such that `PostgresEnum.Schema` returns the annotation's schema when it is not null, otherwise attempts to find the annotatable's default schema annotation. This is not, however, used for any of the migration operations, so that the the default schema is only implied when `PostgresEnum.Schema == null`.
9a09bae
to
cdb5e90
Compare
OK, the only notable divergence in the public API is the removal of the schema-free overload to Personally, I don't see the value in that overload since the annotation classes provide user-friendly overloads, but I can revert to include it if you think it still has some value. |
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.
OK, barring the two minor comments I think we're good to go...! Thanks for all of your patience with this.
Do you want to submit the same for range and extensions? FYI I'm pretty much done on my side, as soon as we finish up all of this I'll proceed to releasing...
@roji Just updated. Are you able to initiate the release of |
Looks good @austindrenski, go ahead and merge. I'll start release for Npgsql 4.0.4. |
Follow-up to #605 and #626.