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
27 changes: 9 additions & 18 deletions src/EFCore.PG/Migrations/Internal/NpgsqlHistoryRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,17 @@ protected override string ExistsSql
{
get
{
var builder = new StringBuilder();

builder.Append("SELECT EXISTS (SELECT 1 FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid=c.relnamespace WHERE ");

var stringTypeMapping = Dependencies.TypeMappingSource.GetMapping(typeof(string));

if (TableSchema is not null)
{
builder
.Append("n.nspname=")
.Append(stringTypeMapping.GenerateSqlLiteral(TableSchema))
.Append(" AND ");
}

builder
.Append("c.relname=")
.Append(stringTypeMapping.GenerateSqlLiteral(TableName))
.Append(");");

return builder.ToString();
return
$"""
SELECT EXISTS (
SELECT 1 FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace n ON n.oid=c.relnamespace
WHERE n.nspname={stringTypeMapping.GenerateSqlLiteral(TableSchema ?? "public")} AND
c.relname={stringTypeMapping.GenerateSqlLiteral(TableName)}
)
""";
}
}

Expand Down
189 changes: 189 additions & 0 deletions test/EFCore.PG.Tests/Migrations/NpgsqlHistoryRepositoryTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
using Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities;

namespace Npgsql.EntityFrameworkCore.PostgreSQL.Migrations;

public class NpgsqlHistoryRepositoryTest
{
[ConditionalFact]
public void GetCreateScript_works()
{
var sql = CreateHistoryRepository().GetCreateScript();

Assert.Equal(
"""
CREATE TABLE "__EFMigrationsHistory" (
"MigrationId" character varying(150) NOT NULL,
"ProductVersion" character varying(32) NOT NULL,
CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY ("MigrationId")
);

""", sql, ignoreLineEndingDifferences: true);
}

[ConditionalFact]
public void GetCreateScript_works_with_schema()
{
var sql = CreateHistoryRepository("my").GetCreateScript();

Assert.Equal(
"""
DO $EF$
BEGIN
IF NOT EXISTS(SELECT 1 FROM pg_namespace WHERE nspname = 'my') THEN
CREATE SCHEMA my;
END IF;
END $EF$;
CREATE TABLE my."__EFMigrationsHistory" (
"MigrationId" character varying(150) NOT NULL,
"ProductVersion" character varying(32) NOT NULL,
CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY ("MigrationId")
);

""", sql, ignoreLineEndingDifferences: true);
}

[ConditionalFact]
public void GetCreateIfNotExistsScript_works()
{
var sql = CreateHistoryRepository().GetCreateIfNotExistsScript();

Assert.Equal(
"""
CREATE TABLE IF NOT EXISTS "__EFMigrationsHistory" (
"MigrationId" character varying(150) NOT NULL,
"ProductVersion" character varying(32) NOT NULL,
CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY ("MigrationId")
);

""", sql, ignoreLineEndingDifferences: true);
}

[ConditionalFact]
public void GetCreateIfNotExistsScript_works_with_schema()
{
var sql = CreateHistoryRepository("my").GetCreateIfNotExistsScript();

Assert.Equal(
"""
DO $EF$
BEGIN
IF NOT EXISTS(SELECT 1 FROM pg_namespace WHERE nspname = 'my') THEN
CREATE SCHEMA my;
END IF;
END $EF$;
CREATE TABLE IF NOT EXISTS my."__EFMigrationsHistory" (
"MigrationId" character varying(150) NOT NULL,
"ProductVersion" character varying(32) NOT NULL,
CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY ("MigrationId")
);

""", sql, ignoreLineEndingDifferences: true);
}

[ConditionalFact]
public void GetDeleteScript_works()
{
var sql = CreateHistoryRepository().GetDeleteScript("Migration1");

Assert.Equal(
"""
DELETE FROM "__EFMigrationsHistory"
WHERE "MigrationId" = 'Migration1';

""", sql, ignoreLineEndingDifferences: true);
}

[ConditionalFact]
public void GetInsertScript_works()
{
var sql = CreateHistoryRepository().GetInsertScript(
new HistoryRow("Migration1", "7.0.0"));

Assert.Equal(
"""
INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
VALUES ('Migration1', '7.0.0');

""", sql, ignoreLineEndingDifferences: true);
}

[ConditionalFact]
public void GetBeginIfNotExistsScript_works()
{
var sql = CreateHistoryRepository().GetBeginIfNotExistsScript("Migration1");

Assert.Equal(
"""

DO $EF$
BEGIN
IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = 'Migration1') THEN
""", sql, ignoreLineEndingDifferences: true);
}

[ConditionalFact]
public void GetBeginIfExistsScript_works()
{
var sql = CreateHistoryRepository().GetBeginIfExistsScript("Migration1");

Assert.Equal(
"""

DO $EF$
BEGIN
IF EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = 'Migration1') THEN
""", sql, ignoreLineEndingDifferences: true);
}

[ConditionalFact]
public void GetEndIfScript_works()
{
var sql = CreateHistoryRepository().GetEndIfScript();

Assert.Equal(
"""
END IF;
END $EF$;
""", sql, ignoreLineEndingDifferences: true);
}

private static IHistoryRepository CreateHistoryRepository(string schema = null)
=> new TestDbContext(
new DbContextOptionsBuilder()
.UseInternalServiceProvider(NpgsqlTestHelpers.Instance.CreateServiceProvider())
.UseNpgsql(
new NpgsqlConnection("Host=localhost;Database=DummyDatabase"),
b => b.MigrationsHistoryTable(HistoryRepository.DefaultTableName, schema))
.Options)
.GetService<IHistoryRepository>();

private class TestDbContext : DbContext
{
public TestDbContext(DbContextOptions options)
: base(options)
{
}

public DbSet<Blog> Blogs { get; set; }

[DbFunction("TableFunction")]
public IQueryable<TableFunction> TableFunction()
=> FromExpression(() => TableFunction());

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
}
}

private class Blog
{
public int Id { get; set; }
}

private class TableFunction
{
public int Id { get; set; }
public int BlogId { get; set; }
public Blog Blog { get; set; }
}
}