Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/EFCore.PG/Extensions/NpgsqlMetadataExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations.Operations;
using Microsoft.EntityFrameworkCore.Scaffolding.Metadata;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using Npgsql.EntityFrameworkCore.PostgreSQL.Utilities;

// ReSharper disable once CheckNamespace

namespace Microsoft.EntityFrameworkCore
{
public static class NpgsqlMetadataExtensions
Expand Down Expand Up @@ -44,5 +45,11 @@ public static INpgsqlPropertyAnnotations Npgsql([NotNull] this IProperty propert

public static NpgsqlPropertyAnnotations Npgsql([NotNull] this IMutableProperty property)
=> (NpgsqlPropertyAnnotations)Npgsql((IProperty)property);

public static NpgsqlAlterDatabaseOperationAnnotations Npgsql([NotNull] this AlterDatabaseOperation operation)
=> new NpgsqlAlterDatabaseOperationAnnotations(Check.NotNull(operation, nameof(operation)));

public static NpgsqlDatabaseModelAnnotations Npgsql([NotNull] this DatabaseModel model)
=> new NpgsqlDatabaseModelAnnotations(Check.NotNull(model, nameof(model)));
}
}
14 changes: 13 additions & 1 deletion src/EFCore.PG/Metadata/INpgsqlModelAnnotations.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Metadata;

namespace Npgsql.EntityFrameworkCore.PostgreSQL.Metadata
Expand All @@ -8,8 +9,19 @@ public interface INpgsqlModelAnnotations : IRelationalModelAnnotations
NpgsqlValueGenerationStrategy? ValueGenerationStrategy { get; }
string HiLoSequenceName { get; }
string HiLoSequenceSchema { get; }
IReadOnlyList<IPostgresExtension> PostgresExtensions { get; }
string DatabaseTemplate { get; }
string Tablespace { get; }

[NotNull]
[ItemNotNull]
IReadOnlyList<IPostgresExtension> PostgresExtensions { get; }

[NotNull]
[ItemNotNull]
IReadOnlyList<PostgresEnum> PostgresEnums { get; }

[NotNull]
[ItemNotNull]
IReadOnlyList<PostgresRange> PostgresRanges { get; }
}
}
52 changes: 52 additions & 0 deletions src/EFCore.PG/Metadata/NpgsqlAlterDatabaseOperationAnnotations.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations.Operations;

namespace Npgsql.EntityFrameworkCore.PostgreSQL.Metadata
{
/// <summary>
/// Provides relational-specific annotations specific to Npgsql.
/// </summary>
public class NpgsqlAlterDatabaseOperationAnnotations : RelationalAnnotations
{
[NotNull] readonly IAnnotatable _oldDatabase;

[NotNull]
[ItemNotNull]
public virtual IReadOnlyList<IPostgresExtension> PostgresExtensions
=> PostgresExtension.GetPostgresExtensions(Metadata).ToArray();

[NotNull]
[ItemNotNull]
public virtual IReadOnlyList<IPostgresExtension> OldPostgresExtensions
=> PostgresExtension.GetPostgresExtensions(_oldDatabase).ToArray();

[NotNull]
[ItemNotNull]
public virtual IReadOnlyList<PostgresEnum> PostgresEnums
=> PostgresEnum.GetPostgresEnums(Metadata).ToArray();

[NotNull]
[ItemNotNull]
public virtual IReadOnlyList<PostgresEnum> OldPostgresEnums
=> PostgresEnum.GetPostgresEnums(_oldDatabase).ToArray();

[NotNull]
[ItemNotNull]
public virtual IReadOnlyList<PostgresRange> PostgresRanges
=> PostgresRange.GetPostgresRanges(Metadata).ToArray();

[NotNull]
[ItemNotNull]
public virtual IReadOnlyList<PostgresRange> OldPostgresRanges
=> PostgresRange.GetPostgresRanges(_oldDatabase).ToArray();

/// <inheritdoc />
public NpgsqlAlterDatabaseOperationAnnotations([NotNull] AlterDatabaseOperation operation)
: base(operation)
=> _oldDatabase = operation.OldDatabase;
}
}
29 changes: 29 additions & 0 deletions src/EFCore.PG/Metadata/NpgsqlDatabaseModelAnnotations.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Scaffolding.Metadata;

namespace Npgsql.EntityFrameworkCore.PostgreSQL.Metadata
{
public class NpgsqlDatabaseModelAnnotations : RelationalAnnotations
{
[NotNull]
[ItemNotNull]
public virtual IReadOnlyList<IPostgresExtension> PostgresExtensions
=> PostgresExtension.GetPostgresExtensions(Metadata).ToArray();

[NotNull]
[ItemNotNull]
public virtual IReadOnlyList<PostgresEnum> PostgresEnums
=> PostgresEnum.GetPostgresEnums(Metadata).ToArray();

[NotNull]
[ItemNotNull]
public virtual IReadOnlyList<PostgresRange> PostgresRanges
=> PostgresRange.GetPostgresRanges(Metadata).ToArray();

/// <inheritdoc />
public NpgsqlDatabaseModelAnnotations([NotNull] DatabaseModel model) : base(model) {}
}
}
7 changes: 3 additions & 4 deletions src/EFCore.PG/Metadata/NpgsqlModelAnnotations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public virtual PostgresExtension GetOrAddPostgresExtension([NotNull] string name
=> PostgresExtension.GetOrAddPostgresExtension((IMutableModel)Model, name);

public virtual IReadOnlyList<IPostgresExtension> PostgresExtensions
=> PostgresExtension.GetPostgresExtensions(Model).ToList();
=> PostgresExtension.GetPostgresExtensions(Model).ToArray();

#endregion

Expand All @@ -86,7 +86,7 @@ public virtual PostgresEnum GetOrAddPostgresEnum(
=> GetOrAddPostgresEnum(null, name, labels);

public virtual IReadOnlyList<PostgresEnum> PostgresEnums
=> PostgresEnum.GetPostgresEnums(Model).ToList();
=> PostgresEnum.GetPostgresEnums(Model).ToArray();

#endregion Enum types

Expand Down Expand Up @@ -115,9 +115,8 @@ public virtual PostgresRange GetOrAddPostgresRange(
[NotNull] string subtype)
=> PostgresRange.GetOrAddPostgresRange((IMutableModel)Model, null, name, subtype);

[NotNull]
public virtual IReadOnlyList<PostgresRange> PostgresRanges
=> PostgresRange.GetPostgresRanges(Model).ToList();
=> PostgresRange.GetPostgresRanges(Model).ToArray();

#endregion Range types

Expand Down
28 changes: 14 additions & 14 deletions src/EFCore.PG/Migrations/NpgsqlMigrationsSqlGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,7 @@ protected override void Generate(
GenerateEnumStatements(operation, model, builder);
GenerateRangeStatements(operation, model, builder);

foreach (var extension in PostgresExtension.GetPostgresExtensions(operation))
foreach (var extension in operation.Npgsql().PostgresExtensions)
GenerateCreateExtension(extension, model, builder);

builder.EndCommand();
Expand Down Expand Up @@ -682,21 +682,21 @@ protected virtual void GenerateEnumStatements(
[NotNull] IModel model,
[NotNull] MigrationCommandListBuilder builder)
{
foreach (var enumTypeToCreate in PostgresEnum.GetPostgresEnums(operation)
.Where(ne => PostgresEnum.GetPostgresEnums(operation.OldDatabase).All(oe => oe.Name != ne.Name)))
foreach (var enumTypeToCreate in operation.Npgsql().PostgresEnums
.Where(ne => operation.Npgsql().OldPostgresEnums.All(oe => oe.Name != ne.Name)))
{
GenerateCreateEnum(enumTypeToCreate, model, builder);
}

foreach (var enumTypeToDrop in PostgresEnum.GetPostgresEnums(operation.OldDatabase)
.Where(oe => PostgresEnum.GetPostgresEnums(operation).All(ne => ne.Name != oe.Name)))
foreach (var enumTypeToDrop in operation.Npgsql().OldPostgresEnums
.Where(oe => operation.Npgsql().PostgresEnums.All(ne => ne.Name != oe.Name)))
{
GenerateDropEnum(enumTypeToDrop, operation.OldDatabase, builder);
}

// TODO: Some forms of enum alterations are actually supported...
if (PostgresEnum.GetPostgresEnums(operation).FirstOrDefault(nr =>
PostgresEnum.GetPostgresEnums(operation.OldDatabase).Any(or => or.Name == nr.Name)
if (operation.Npgsql().PostgresEnums.FirstOrDefault(nr =>
operation.Npgsql().OldPostgresEnums.Any(or => or.Name == nr.Name)
) is PostgresEnum enumTypeToAlter)
{
throw new NotSupportedException($"Altering enum type ${enumTypeToAlter} isn't supported.");
Expand Down Expand Up @@ -755,21 +755,21 @@ protected virtual void GenerateRangeStatements(
[NotNull] IModel model,
[NotNull] MigrationCommandListBuilder builder)
{
foreach (var rangeTypeToCreate in PostgresRange.GetPostgresRanges(operation)
.Where(ne => PostgresRange.GetPostgresRanges(operation.OldDatabase).All(oe => oe.Name != ne.Name)))
foreach (var rangeTypeToCreate in operation.Npgsql().PostgresRanges
.Where(ne => operation.Npgsql().OldPostgresRanges.All(oe => oe.Name != ne.Name)))
{
GenerateCreateRange(rangeTypeToCreate, model, builder);
}

foreach (var rangeTypeToDrop in PostgresRange.GetPostgresRanges(operation.OldDatabase)
.Where(oe => PostgresRange.GetPostgresRanges(operation).All(ne => ne.Name != oe.Name)))
foreach (var rangeTypeToDrop in operation.Npgsql().OldPostgresRanges
.Where(oe => operation.Npgsql().PostgresRanges.All(ne => ne.Name != oe.Name)))
{
GenerateDropRange(rangeTypeToDrop, builder);
}

if (PostgresRange.GetPostgresRanges(operation).FirstOrDefault(nr =>
PostgresRange.GetPostgresRanges(operation.OldDatabase).Any(or => or.Name == nr.Name)
) is PostgresRange rangeTypeToAlter)
if (operation.Npgsql().PostgresRanges.FirstOrDefault(nr =>
operation.Npgsql().OldPostgresRanges.Any(or => or.Name == nr.Name)
) is PostgresRange rangeTypeToAlter)
{
throw new NotSupportedException($"Altering range type ${rangeTypeToAlter} isn't supported.");
}
Expand Down
28 changes: 12 additions & 16 deletions src/EFCore.PG/Storage/Internal/NpgsqlDatabaseCreator.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Net.Sockets;
Expand All @@ -12,7 +11,6 @@
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Migrations.Operations;
using Microsoft.EntityFrameworkCore.Storage;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using Npgsql.EntityFrameworkCore.PostgreSQL.Migrations.Operations;

namespace Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal
Expand Down Expand Up @@ -293,13 +291,12 @@ public override void CreateTables()
var commands = Dependencies.MigrationsSqlGenerator.Generate(operations, Dependencies.Model);

// If a PostgreSQL extension, enum or range was added, we want Npgsql to reload all types at the ADO.NET level.
var reloadTypes = operations.Any(o =>
o is AlterDatabaseOperation && (
PostgresExtension.GetPostgresExtensions(o).Any() ||
PostgresEnum.GetPostgresEnums(o).Any() ||
PostgresRange.GetPostgresRanges(o).Any()
)
);
var reloadTypes =
operations.OfType<AlterDatabaseOperation>()
.Any(o =>
o.Npgsql().PostgresExtensions.Any() ||
o.Npgsql().PostgresEnums.Any() ||
o.Npgsql().PostgresRanges.Any());

try
{
Expand Down Expand Up @@ -333,13 +330,12 @@ public override async Task CreateTablesAsync(CancellationToken cancellationToken
var commands = Dependencies.MigrationsSqlGenerator.Generate(operations, Dependencies.Model);

// If a PostgreSQL extension, enum or range was added, we want Npgsql to reload all types at the ADO.NET level.
var reloadTypes = operations.Any(o =>
o is AlterDatabaseOperation && (
PostgresExtension.GetPostgresExtensions(o).Any() ||
PostgresEnum.GetPostgresEnums(o).Any() ||
PostgresRange.GetPostgresRanges(o).Any()
)
);
var reloadTypes =
operations.OfType<AlterDatabaseOperation>()
.Any(o =>
o.Npgsql().PostgresExtensions.Any() ||
o.Npgsql().PostgresEnums.Any() ||
o.Npgsql().PostgresRanges.Any());

try
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1656,7 +1656,7 @@ public void Postgres_extensions()
Enumerable.Empty<string>(),
dbModel =>
{
var extensions = PostgresExtension.GetPostgresExtensions(dbModel).ToList();
var extensions = dbModel.Npgsql().PostgresExtensions;
Assert.Equal(2, extensions.Count);
var hstore = extensions.Single(e => e.Name == "hstore");
var pgcrypto = extensions.Single(e => e.Name == "pgcrypto");
Expand All @@ -1676,7 +1676,7 @@ public void Enums()
Enumerable.Empty<string>(),
dbModel =>
{
var enums = PostgresEnum.GetPostgresEnums(dbModel).ToList();
var enums = dbModel.Npgsql().PostgresEnums;
Assert.Equal(2, enums.Count);

var mood = enums.Single(e => e.Schema == null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ protected override string BuildCustomSql(DatabaseModel databaseModel)
// Some extensions create tables (e.g. PostGIS), wo we must drop them first.
var sb = new StringBuilder();

foreach (var extension in PostgresExtension.GetPostgresExtensions(databaseModel))
foreach (var extension in databaseModel.Npgsql().PostgresExtensions)
sb
.Append("DROP EXTENSION ")
.Append(_sqlGenerationHelper.DelimitIdentifier(extension.Name, extension.Schema))
Expand All @@ -88,7 +88,7 @@ protected override string BuildCustomEndingSql(DatabaseModel databaseModel)
{
var sb = new StringBuilder();

foreach (var enumDef in PostgresEnum.GetPostgresEnums(databaseModel))
foreach (var enumDef in databaseModel.Npgsql().PostgresEnums)
sb
.Append("DROP TYPE ")
.Append(_sqlGenerationHelper.DelimitIdentifier(enumDef.Name, enumDef.Schema))
Expand Down