Skip to content

Commit

Permalink
remove attribute and apply cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
WhatzGames committed Dec 18, 2024
1 parent 5b55da2 commit 8fcd68b
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ public static class NpgsqlForeignKeyBuilderExtensions
/// Configure the matching strategy to be used with the foreign key.
/// </summary>
/// <param name="builder">The builder for the foreign key being configured.</param>
/// <param name="matchStrategy">The <see cref="PostgresMatchStrategy"/> defining the used matching strategy.</param>
/// <param name="matchStrategy">The <see cref="PostgresMatchStrategy" /> defining the used matching strategy.</param>
/// <remarks>
/// <see href="https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES"/>
/// <see href="https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES" />
/// </remarks>
public static ReferenceReferenceBuilder UsesMatchStrategy(this ReferenceReferenceBuilder builder, PostgresMatchStrategy matchStrategy){
public static ReferenceReferenceBuilder UsesMatchStrategy(this ReferenceReferenceBuilder builder, PostgresMatchStrategy matchStrategy)
{
Check.NotNull(builder, nameof(builder));
Check.IsDefined(matchStrategy);
Check.IsDefined(matchStrategy, nameof(matchStrategy));
builder.Metadata.SetMatchStrategy(matchStrategy);
return builder;
}
Expand All @@ -27,26 +28,29 @@ public static ReferenceReferenceBuilder UsesMatchStrategy(this ReferenceReferenc
/// Configure the matching strategy to be used with the foreign key.
/// </summary>
/// <param name="builder">The builder for the foreign key being configured.</param>
/// <param name="matchStrategy">The <see cref="PostgresMatchStrategy"/> defining the used matching strategy.</param>
/// <param name="matchStrategy">The <see cref="PostgresMatchStrategy" /> defining the used matching strategy.</param>
/// <remarks>
/// <see href="https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES"/>
/// <see href="https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES" />
/// </remarks>
public static ReferenceReferenceBuilder<TEntity, TRelatedEntity> UsesMatchStrategy<TEntity, TRelatedEntity>(this ReferenceReferenceBuilder<TEntity, TRelatedEntity> builder, PostgresMatchStrategy matchStrategy)
public static ReferenceReferenceBuilder<TEntity, TRelatedEntity> UsesMatchStrategy<TEntity, TRelatedEntity>(
this ReferenceReferenceBuilder<TEntity, TRelatedEntity> builder,
PostgresMatchStrategy matchStrategy)
where TEntity : class
where TRelatedEntity : class
=> (ReferenceReferenceBuilder<TEntity, TRelatedEntity>)UsesMatchStrategy((ReferenceReferenceBuilder)builder, matchStrategy);
=> (ReferenceReferenceBuilder<TEntity, TRelatedEntity>)UsesMatchStrategy((ReferenceReferenceBuilder)builder, matchStrategy);

/// <summary>
/// Configure the matching strategy to be used with the foreign key.
/// </summary>
/// <param name="builder">The builder for the foreign key being configured.</param>
/// <param name="matchStrategy">The <see cref="PostgresMatchStrategy"/> defining the used matching strategy.</param>
/// <param name="matchStrategy">The <see cref="PostgresMatchStrategy" /> defining the used matching strategy.</param>
/// <remarks>
/// <see href="https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES"/>
/// <see href="https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES" />
/// </remarks>
public static ReferenceCollectionBuilder UsesMatchStrategy(this ReferenceCollectionBuilder builder, PostgresMatchStrategy matchStrategy){
public static ReferenceCollectionBuilder UsesMatchStrategy(this ReferenceCollectionBuilder builder, PostgresMatchStrategy matchStrategy)
{
Check.NotNull(builder, nameof(builder));
Check.IsDefined(matchStrategy);
Check.IsDefined(matchStrategy, nameof(matchStrategy));
builder.Metadata.SetMatchStrategy(matchStrategy);
return builder;
}
Expand All @@ -55,12 +59,14 @@ public static ReferenceCollectionBuilder UsesMatchStrategy(this ReferenceCollect
/// Configure the matching strategy to be used with the foreign key.
/// </summary>
/// <param name="builder">The builder for the foreign key being configured.</param>
/// <param name="matchStrategy">The <see cref="PostgresMatchStrategy"/> defining the used matching strategy.</param>
/// <param name="matchStrategy">The <see cref="PostgresMatchStrategy" /> defining the used matching strategy.</param>
/// <remarks>
/// <see href="https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES"/>
/// <see href="https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES" />
/// </remarks>
public static ReferenceCollectionBuilder UsesMatchStrategy<TEntity, TRelatedEntity>(this ReferenceCollectionBuilder<TEntity, TRelatedEntity> builder, PostgresMatchStrategy matchStrategy)
public static ReferenceCollectionBuilder UsesMatchStrategy<TEntity, TRelatedEntity>(
this ReferenceCollectionBuilder<TEntity, TRelatedEntity> builder,
PostgresMatchStrategy matchStrategy)
where TEntity : class
where TRelatedEntity : class
=> (ReferenceCollectionBuilder<TEntity, TRelatedEntity>)UsesMatchStrategy((ReferenceCollectionBuilder)builder, matchStrategy);
}
}
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@

// ReSharper disable once CheckNamespace
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata.Internal;
// ReSharper disable once CheckNamespace

namespace Microsoft.EntityFrameworkCore;

/// <summary>
/// Npgsql specific extension methods for <see cref="IForeignKey"/>.
/// Npgsql specific extension methods for <see cref="IForeignKey" />.
/// </summary>
public static class NpgsqlForeignKeyExtensions
{
/// <summary>
/// Sets the <see cref="PostgresMatchStrategy"/> for a foreign key.
/// Sets the <see cref="PostgresMatchStrategy" /> for a foreign key.
/// </summary>
/// <param name="foreignKey">the foreign key being configured.</param>
/// <param name="matchStrategy">the <see cref="PostgresMatchStrategy"/> defining the used matching strategy.</param>
/// <param name="matchStrategy">the <see cref="PostgresMatchStrategy" /> defining the used matching strategy.</param>
/// <remarks>
/// <see href="https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES"/>
/// <see href="https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES" />
/// </remarks>
public static void SetMatchStrategy(this IMutableForeignKey foreignKey, PostgresMatchStrategy matchStrategy)
=> foreignKey.SetOrRemoveAnnotation(NpgsqlAnnotationNames.MatchStrategy, matchStrategy);

/// <summary>
/// Returns the assigned <see cref="PostgresMatchStrategy"/> for the provided foreign key
/// Returns the assigned <see cref="PostgresMatchStrategy" /> for the provided foreign key
/// </summary>
/// <param name="foreignKey">the foreign key</param>
/// <returns>the <see cref="PostgresMatchStrategy"/> if assigned, null otherwise</returns>
public static PostgresMatchStrategy? GetMatchStrategy(this IReadOnlyForeignKey foreignKey) =>
(PostgresMatchStrategy?)foreignKey[NpgsqlAnnotationNames.MatchStrategy];
}
/// <returns>the <see cref="PostgresMatchStrategy" /> if assigned, null otherwise</returns>
public static PostgresMatchStrategy? GetMatchStrategy(this IReadOnlyForeignKey foreignKey)
=> (PostgresMatchStrategy?)foreignKey[NpgsqlAnnotationNames.MatchStrategy];
}
5 changes: 3 additions & 2 deletions src/EFCore.PG/Metadata/Internal/NpgsqlAnnotationProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,15 +206,16 @@ public override IEnumerable<IAnnotation> For(ITableIndex index, bool designTime)
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public override IEnumerable<IAnnotation> For(IForeignKeyConstraint foreignKey, bool designTime){
public override IEnumerable<IAnnotation> For(IForeignKeyConstraint foreignKey, bool designTime)
{
if (!designTime)
{
yield break;
}

foreach (var item in foreignKey.MappedForeignKeys)
{
if (item.GetMatchStrategy() is {} match)
if (item.GetMatchStrategy() is { } match)
{
yield return new Annotation(NpgsqlAnnotationNames.MatchStrategy, match);
}
Expand Down
6 changes: 4 additions & 2 deletions src/EFCore.PG/Metadata/PostgresMatchStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,22 @@ namespace Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
/// Matching strategies for a foreign key.
/// </summary>
/// <remarks>
/// <see href="https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES"/>
/// <see href="https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-REFERENCES" />
/// </remarks>
public enum PostgresMatchStrategy
{
/// <summary>
/// The default matching strategy, allows any foreign key column to be NULL.
/// </summary>
Simple = 0,

/// <summary>
/// Currently not implemented in PostgreSQL.
/// </summary>
Partial = 1,

/// <summary>
/// Requires the foreign key to either have all columns to be set or all columns to be NULL.
/// </summary>
Full = 2
}
}
13 changes: 6 additions & 7 deletions src/EFCore.PG/Migrations/NpgsqlMigrationsSqlGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1448,12 +1448,11 @@ protected virtual void GenerateDropRange(PostgresRange rangeType, IModel? model,

#endregion Range management


#region MatchingStrategy management


/// <inheritdoc/>
protected override void ForeignKeyConstraint(AddForeignKeyOperation operation, IModel? model, MigrationCommandListBuilder builder){
/// <inheritdoc />
protected override void ForeignKeyConstraint(AddForeignKeyOperation operation, IModel? model, MigrationCommandListBuilder builder)
{
if (operation.Name != null)
{
builder.Append("CONSTRAINT ").Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name)).Append(" ");
Expand All @@ -1470,7 +1469,6 @@ protected override void ForeignKeyConstraint(AddForeignKeyOperation operation, I
{
builder.Append(" MATCH ")
.Append(TranslateMatchStrategy(matchStrategy));

}

if (operation.OnUpdate != 0)
Expand All @@ -1486,8 +1484,9 @@ protected override void ForeignKeyConstraint(AddForeignKeyOperation operation, I
}
}

private string TranslateMatchStrategy(PostgresMatchStrategy matchStrategy)
=> matchStrategy switch {
private static string TranslateMatchStrategy(PostgresMatchStrategy matchStrategy)
=> matchStrategy switch
{
PostgresMatchStrategy.Simple => "SIMPLE",
PostgresMatchStrategy.Partial => "PARTIAL",
PostgresMatchStrategy.Full => "FULL",
Expand Down
6 changes: 3 additions & 3 deletions src/Shared/Check.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using JetBrains.Annotations;

namespace Microsoft.EntityFrameworkCore.Utilities;
Expand Down Expand Up @@ -130,8 +129,9 @@ public static void DebugAssert([DoesNotReturnIf(false)] bool condition, string m
public static void DebugFail(string message)
=> throw new Exception($"Check.DebugFail failed: {message}");

public static void IsDefined<T>(T value,
[InvokerParameterName, CallerArgumentExpression(nameof(value))] string? parameterName = null)
public static void IsDefined<T>(
T value,
[InvokerParameterName] string parameterName)
where T : struct, Enum
{
if (!Enum.IsDefined(value))
Expand Down
70 changes: 41 additions & 29 deletions test/EFCore.PG.FunctionalTests/Migrations/MigrationsNpgsqlTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1147,7 +1147,8 @@ await Test(
e.Property<int>("Y");
}),
builder => builder.Entity("People").Property<int>("Sum")
.HasComputedColumnSql("""
.HasComputedColumnSql(
"""
"X" + "Y"
""", stored: true),
builder => builder.Entity("People").Property<int>("Sum"),
Expand Down Expand Up @@ -1671,7 +1672,8 @@ await Test(
"People", b =>
{
b.Property<string>("Name");
b.Property<string>("Name2").HasComputedColumnSql("""
b.Property<string>("Name2").HasComputedColumnSql(
"""
"Name"
""", stored: true);
}),
Expand All @@ -1681,7 +1683,8 @@ await Test(
model =>
{
var computedColumn = Assert.Single(Assert.Single(model.Tables).Columns, c => c.Name == "Name2");
Assert.Equal("""
Assert.Equal(
"""
"Name"
""", computedColumn.ComputedColumnSql);
Assert.Equal(NonDefaultCollation, computedColumn.Collation);
Expand Down Expand Up @@ -1938,7 +1941,8 @@ await Test(
_ => { },
builder => builder.Entity("People").HasIndex("Name")
.IncludeProperties("FirstName", "LastName")
.HasFilter("""
.HasFilter(
"""
"Name" IS NOT NULL
"""),
model =>
Expand Down Expand Up @@ -2031,7 +2035,8 @@ await Test(
builder => builder.Entity("People").HasIndex("Name")
.IsUnique()
.IncludeProperties("FirstName", "LastName")
.HasFilter("""
.HasFilter(
"""
"Name" IS NOT NULL
"""),
model =>
Expand Down Expand Up @@ -2466,41 +2471,50 @@ public override async Task Drop_check_constraint()
[InlineData(PostgresMatchStrategy.Full, "FULL", false)]
public async Task Add_foreign_key_with_match_strategy(PostgresMatchStrategy strategy, string matchValue, bool throws)
{
Task runningTest = Test(
builder => {
builder.Entity("Customers", delegate (EntityTypeBuilder e)
{
e.Property<int>("Id");
e.HasKey("Id");
e.Property<int>("AddressId");
});
builder.Entity("Orders", delegate (EntityTypeBuilder e)
{
e.Property<int>("Id");
e.Property<int>("CustomerId");
});
var runningTest = Test(
builder =>
{
builder.Entity(
"Customers", delegate(EntityTypeBuilder e)
{
e.Property<int>("Id");
e.HasKey("Id");
e.Property<int>("AddressId");
});
builder.Entity(
"Orders", delegate(EntityTypeBuilder e)
{
e.Property<int>("Id");
e.Property<int>("CustomerId");
});
},
_ => {},
builder => {
_ => { },
builder =>
{
builder.Entity("Orders")
.HasOne("Customers")
.WithMany()
.HasForeignKey("CustomerId")
.UsesMatchStrategy(strategy)
.HasConstraintName("FK_Foo");
.HasOne("Customers")
.WithMany()
.HasForeignKey("CustomerId")
.UsesMatchStrategy(strategy)
.HasConstraintName("FK_Foo");
},
asserter: null);

if (throws)
{
await Assert.ThrowsAsync<PostgresException>(() => runningTest);
}else{
}
else
{
await runningTest;
}

AssertSql(
"""CREATE INDEX "IX_Orders_CustomerId" ON "Orders" ("CustomerId");""",
$"""ALTER TABLE "Orders" ADD CONSTRAINT "FK_Foo" FOREIGN KEY ("CustomerId") REFERENCES "Customers" ("Id") MATCH {matchValue} ON DELETE CASCADE;""");
//
$"""
ALTER TABLE "Orders" ADD CONSTRAINT "FK_Foo" FOREIGN KEY ("CustomerId") REFERENCES "Customers" ("Id") MATCH {matchValue} ON DELETE CASCADE;
""");
}

#endregion
Expand Down Expand Up @@ -2770,7 +2784,6 @@ SELECT setval(
""");
}


#endregion Data seeding

public override async Task Add_required_primitve_collection_with_custom_default_value_sql_to_existing_table()
Expand Down Expand Up @@ -3268,7 +3281,6 @@ public override async Task Add_required_primitve_collection_with_custom_converte
AssertSql("""ALTER TABLE "Customers" ADD "Numbers" text NOT NULL DEFAULT 'some numbers';""");
}


protected override string NonDefaultCollation
=> "POSIX";

Expand Down

0 comments on commit 8fcd68b

Please sign in to comment.