|
|
|
|
|
|
|
|
|
// Licensed to the .NET Foundation under one or more agreements.
|
|
|
|
|
// The .NET Foundation licenses this file to you under the MIT license.
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Globalization;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using EntityFrameworkCore.Jet.FunctionalTests.TestUtilities;
|
|
|
|
|
using EntityFrameworkCore.Jet.Internal;
|
|
|
|
|
using EntityFrameworkCore.Jet.Metadata.Internal;
|
|
|
|
|
using EntityFrameworkCore.Jet.Scaffolding.Internal;
|
|
|
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
|
using Microsoft.EntityFrameworkCore.Metadata;
|
|
|
|
|
using Microsoft.EntityFrameworkCore.Migrations;
|
|
|
|
|
using Microsoft.EntityFrameworkCore.Scaffolding;
|
|
|
|
|
using Microsoft.EntityFrameworkCore.Scaffolding.Metadata.Internal;
|
|
|
|
|
using Microsoft.EntityFrameworkCore.TestUtilities;
|
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
|
using Xunit;
|
|
|
|
|
using Xunit.Abstractions;
|
|
|
|
|
|
|
|
|
|
// ReSharper disable StringLiteralTypo
|
|
|
|
|
// ReSharper disable UnusedParameter.Local
|
|
|
|
|
// ReSharper disable ParameterOnlyUsedForPreconditionCheck.Local
|
|
|
|
|
|
|
|
|
|
#nullable enable
|
|
|
|
|
|
|
|
|
|
namespace EntityFrameworkCore.Jet.FunctionalTests.Migrations;
|
|
|
|
|
|
|
|
|
|
public class MigrationsJetTest : MigrationsTestBase<MigrationsJetTest.MigrationsJetFixture>
|
|
|
|
|
{
|
|
|
|
|
protected static string EOL
|
|
|
|
|
=> Environment.NewLine;
|
|
|
|
|
|
|
|
|
|
public MigrationsJetTest(MigrationsJetFixture fixture, ITestOutputHelper testOutputHelper)
|
|
|
|
|
: base(fixture)
|
|
|
|
|
{
|
|
|
|
|
Fixture.TestSqlLoggerFactory.Clear();
|
|
|
|
|
Fixture.TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Create_table()
|
|
|
|
|
{
|
|
|
|
|
await base.Create_table();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
CREATE TABLE [People] (
|
|
|
|
|
[Id] int NOT NULL IDENTITY,
|
|
|
|
|
[Name] nvarchar(max) NULL,
|
|
|
|
|
CONSTRAINT [PK_People] PRIMARY KEY ([Id])
|
|
|
|
|
);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Create_table_all_settings()
|
|
|
|
|
{
|
|
|
|
|
await base.Create_table_all_settings();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
IF SCHEMA_ID(N'dbo2') IS NULL EXEC(N'CREATE SCHEMA [dbo2];');
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
CREATE TABLE [dbo2].[People] (
|
|
|
|
|
[CustomId] int NOT NULL IDENTITY,
|
|
|
|
|
[EmployerId] int NOT NULL,
|
|
|
|
|
[SSN] nvarchar(11) COLLATE German_PhoneBook_CI_AS NOT NULL,
|
|
|
|
|
CONSTRAINT [PK_People] PRIMARY KEY ([CustomId]),
|
|
|
|
|
CONSTRAINT [AK_People_SSN] UNIQUE ([SSN]),
|
|
|
|
|
CONSTRAINT [CK_People_EmployerId] CHECK ([EmployerId] > 0),
|
|
|
|
|
CONSTRAINT [FK_People_Employers_EmployerId] FOREIGN KEY ([EmployerId]) REFERENCES [Employers] ([Id]) ON DELETE CASCADE
|
|
|
|
|
);
|
|
|
|
|
DECLARE @description AS sql_variant;
|
|
|
|
|
SET @description = N'Table comment';
|
|
|
|
|
EXEC sp_addextendedproperty 'MS_Description', @description, 'SCHEMA', N'dbo2', 'TABLE', N'People';
|
|
|
|
|
SET @description = N'Employer ID comment';
|
|
|
|
|
EXEC sp_addextendedproperty 'MS_Description', @description, 'SCHEMA', N'dbo2', 'TABLE', N'People', 'COLUMN', N'EmployerId';
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
CREATE INDEX [IX_People_EmployerId] ON [dbo2].[People] ([EmployerId]);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Create_table_no_key()
|
|
|
|
|
{
|
|
|
|
|
await base.Create_table_no_key();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
CREATE TABLE [Anonymous] (
|
|
|
|
|
[SomeColumn] int NOT NULL
|
|
|
|
|
);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Create_table_with_comments()
|
|
|
|
|
{
|
|
|
|
|
await base.Create_table_with_comments();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
CREATE TABLE [People] (
|
|
|
|
|
[Id] int NOT NULL IDENTITY,
|
|
|
|
|
[Name] nvarchar(max) NULL,
|
|
|
|
|
CONSTRAINT [PK_People] PRIMARY KEY ([Id])
|
|
|
|
|
);
|
|
|
|
|
DECLARE @defaultSchema AS sysname;
|
|
|
|
|
SET @defaultSchema = SCHEMA_NAME();
|
|
|
|
|
DECLARE @description AS sql_variant;
|
|
|
|
|
SET @description = N'Table comment';
|
|
|
|
|
EXEC sp_addextendedproperty 'MS_Description', @description, 'SCHEMA', @defaultSchema, 'TABLE', N'People';
|
|
|
|
|
SET @description = N'Column comment';
|
|
|
|
|
EXEC sp_addextendedproperty 'MS_Description', @description, 'SCHEMA', @defaultSchema, 'TABLE', N'People', 'COLUMN', N'Name';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Create_table_with_multiline_comments()
|
|
|
|
|
{
|
|
|
|
|
await base.Create_table_with_multiline_comments();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
CREATE TABLE [People] (
|
|
|
|
|
[Id] int NOT NULL IDENTITY,
|
|
|
|
|
[Name] nvarchar(max) NULL,
|
|
|
|
|
CONSTRAINT [PK_People] PRIMARY KEY ([Id])
|
|
|
|
|
);
|
|
|
|
|
DECLARE @defaultSchema AS sysname;
|
|
|
|
|
SET @defaultSchema = SCHEMA_NAME();
|
|
|
|
|
DECLARE @description AS sql_variant;
|
|
|
|
|
SET @description = CONCAT(N'This is a multi-line', NCHAR(13), NCHAR(10), N'table comment.', NCHAR(13), NCHAR(10), N'More information can', NCHAR(13), NCHAR(10), N'be found in the docs.');
|
|
|
|
|
EXEC sp_addextendedproperty 'MS_Description', @description, 'SCHEMA', @defaultSchema, 'TABLE', N'People';
|
|
|
|
|
SET @description = CONCAT(N'This is a multi-line', NCHAR(10), N'column comment.', NCHAR(10), N'More information can', NCHAR(10), N'be found in the docs.');
|
|
|
|
|
EXEC sp_addextendedproperty 'MS_Description', @description, 'SCHEMA', @defaultSchema, 'TABLE', N'People', 'COLUMN', N'Name';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Create_table_with_computed_column(bool? stored)
|
|
|
|
|
{
|
|
|
|
|
await base.Create_table_with_computed_column(stored);
|
|
|
|
|
|
|
|
|
|
var storedSql = stored == true ? " PERSISTED" : "";
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
$"""
|
|
|
|
|
CREATE TABLE [People] (
|
|
|
|
|
[Id] int NOT NULL IDENTITY,
|
|
|
|
|
[Sum] AS [X] + [Y]{storedSql},
|
|
|
|
|
[X] int NOT NULL,
|
|
|
|
|
[Y] int NOT NULL,
|
|
|
|
|
CONSTRAINT [PK_People] PRIMARY KEY ([Id])
|
|
|
|
|
);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Create_table_with_json_column()
|
|
|
|
|
{
|
|
|
|
|
await base.Create_table_with_json_column();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
CREATE TABLE [Entity] (
|
|
|
|
|
[Id] int NOT NULL IDENTITY,
|
|
|
|
|
[Name] nvarchar(max) NULL,
|
|
|
|
|
[OwnedCollection] nvarchar(max) NULL,
|
|
|
|
|
[OwnedReference] nvarchar(max) NULL,
|
|
|
|
|
[OwnedRequiredReference] nvarchar(max) NOT NULL,
|
|
|
|
|
CONSTRAINT [PK_Entity] PRIMARY KEY ([Id])
|
|
|
|
|
);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Create_table_with_json_column_explicit_json_column_names()
|
|
|
|
|
{
|
|
|
|
|
await base.Create_table_with_json_column_explicit_json_column_names();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
CREATE TABLE [Entity] (
|
|
|
|
|
[Id] int NOT NULL IDENTITY,
|
|
|
|
|
[Name] nvarchar(max) NULL,
|
|
|
|
|
[json_collection] nvarchar(max) NULL,
|
|
|
|
|
[json_reference] nvarchar(max) NULL,
|
|
|
|
|
CONSTRAINT [PK_Entity] PRIMARY KEY ([Id])
|
|
|
|
|
);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task Create_table_with_identity_column_value_converter()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
_ => { },
|
|
|
|
|
builder => builder.UseJetIdentityColumns()
|
|
|
|
|
.Entity("People").Property<int>("IdentityColumn").HasConversion<short>().ValueGeneratedOnAdd(),
|
|
|
|
|
model =>
|
|
|
|
|
{
|
|
|
|
|
var table = Assert.Single(model.Tables);
|
|
|
|
|
var column = Assert.Single(table.Columns, c => c.Name == "IdentityColumn");
|
|
|
|
|
Assert.Equal(ValueGenerated.OnAdd, column.ValueGenerated);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
CREATE TABLE [People] (
|
|
|
|
|
[IdentityColumn] smallint NOT NULL IDENTITY
|
|
|
|
|
);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Drop_table()
|
|
|
|
|
{
|
|
|
|
|
await base.Drop_table();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DROP TABLE [People];
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Alter_table_add_comment()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_table_add_comment();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @defaultSchema AS sysname;
|
|
|
|
|
SET @defaultSchema = SCHEMA_NAME();
|
|
|
|
|
DECLARE @description AS sql_variant;
|
|
|
|
|
SET @description = N'Table comment';
|
|
|
|
|
EXEC sp_addextendedproperty 'MS_Description', @description, 'SCHEMA', @defaultSchema, 'TABLE', N'People';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Alter_table_add_comment_non_default_schema()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_table_add_comment_non_default_schema();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @description AS sql_variant;
|
|
|
|
|
SET @description = N'Table comment';
|
|
|
|
|
EXEC sp_addextendedproperty 'MS_Description', @description, 'SCHEMA', N'SomeOtherSchema', 'TABLE', N'People';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Alter_table_change_comment()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_table_change_comment();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @defaultSchema AS sysname;
|
|
|
|
|
SET @defaultSchema = SCHEMA_NAME();
|
|
|
|
|
DECLARE @description AS sql_variant;
|
|
|
|
|
EXEC sp_dropextendedproperty 'MS_Description', 'SCHEMA', @defaultSchema, 'TABLE', N'People';
|
|
|
|
|
SET @description = N'Table comment2';
|
|
|
|
|
EXEC sp_addextendedproperty 'MS_Description', @description, 'SCHEMA', @defaultSchema, 'TABLE', N'People';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Alter_table_remove_comment()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_table_remove_comment();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @defaultSchema AS sysname;
|
|
|
|
|
SET @defaultSchema = SCHEMA_NAME();
|
|
|
|
|
DECLARE @description AS sql_variant;
|
|
|
|
|
EXEC sp_dropextendedproperty 'MS_Description', 'SCHEMA', @defaultSchema, 'TABLE', N'People';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Rename_table()
|
|
|
|
|
{
|
|
|
|
|
await base.Rename_table();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] DROP CONSTRAINT [PK_People];
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
EXEC sp_rename '[People]', 'Persons', 'OBJECT';
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Persons] ADD CONSTRAINT [PK_Persons] PRIMARY KEY ([Id]);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Rename_table_with_primary_key()
|
|
|
|
|
{
|
|
|
|
|
await base.Rename_table_with_primary_key();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] DROP CONSTRAINT [PK_People];
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
EXEC sp_rename '[People]', N'Persons', 'OBJECT';
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Persons] ADD CONSTRAINT [PK_Persons] PRIMARY KEY ([Id]);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Rename_table_with_json_column()
|
|
|
|
|
{
|
|
|
|
|
await base.Rename_table_with_json_column();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Entities] DROP CONSTRAINT [PK_Entities];
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
EXEC sp_rename N'[Entities]', N'NewEntities', 'OBJECT';
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [NewEntities] ADD CONSTRAINT [PK_NewEntities] PRIMARY KEY ([Id]);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Move_table()
|
|
|
|
|
{
|
|
|
|
|
await base.Move_table();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
IF SCHEMA_ID(N'TestTableSchema') IS NULL EXEC(N'CREATE SCHEMA [TestTableSchema];');
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
ALTER SCHEMA [TestTableSchema] TRANSFER [TestTable];
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Create_schema()
|
|
|
|
|
{
|
|
|
|
|
await base.Create_schema();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
IF SCHEMA_ID(N'SomeOtherSchema') IS NULL EXEC(N'CREATE SCHEMA [SomeOtherSchema];');
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
CREATE TABLE [SomeOtherSchema].[People] (
|
|
|
|
|
[Id] int NOT NULL IDENTITY,
|
|
|
|
|
CONSTRAINT [PK_People] PRIMARY KEY ([Id])
|
|
|
|
|
);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task Create_schema_dbo_is_ignored()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => { },
|
|
|
|
|
builder => builder.Entity("People")
|
|
|
|
|
.ToTable("People", "dbo")
|
|
|
|
|
.Property<int>("Id"),
|
|
|
|
|
model => Assert.Equal("dbo", Assert.Single(model.Tables).Schema));
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
CREATE TABLE [dbo].[People] (
|
|
|
|
|
[Id] int NOT NULL IDENTITY,
|
|
|
|
|
CONSTRAINT [PK_People] PRIMARY KEY ([Id])
|
|
|
|
|
);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_column_with_defaultValue_string()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_column_with_defaultValue_string();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD [Name] nvarchar(max) NOT NULL DEFAULT N'John Doe';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_column_with_defaultValue_datetime()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_column_with_defaultValue_datetime();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD [Birthday] datetime2 NOT NULL DEFAULT '2015-04-12T17:05:00.0000000';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalTheory]
|
|
|
|
|
[InlineData(0, "", 1234567)]
|
|
|
|
|
[InlineData(1, ".1", 1234567)]
|
|
|
|
|
[InlineData(2, ".12", 1234567)]
|
|
|
|
|
[InlineData(3, ".123", 1234567)]
|
|
|
|
|
[InlineData(4, ".1234", 1234567)]
|
|
|
|
|
[InlineData(5, ".12345", 1234567)]
|
|
|
|
|
[InlineData(6, ".123456", 1234567)]
|
|
|
|
|
[InlineData(7, ".1234567", 1234567)]
|
|
|
|
|
[InlineData(7, ".1200000", 1200000)] //should this really output trailing zeros?
|
|
|
|
|
public async Task Add_column_with_defaultValue_datetime_with_explicit_precision(int precision, string fractionalSeconds, int ticksToAdd)
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.Entity("People").Property<int>("Id"),
|
|
|
|
|
builder => { },
|
|
|
|
|
builder => builder.Entity("People").Property<DateTime>("Birthday").HasPrecision(precision)
|
|
|
|
|
.HasDefaultValue(new DateTime(2015, 4, 12, 17, 5, 0).AddTicks(ticksToAdd)),
|
|
|
|
|
model =>
|
|
|
|
|
{
|
|
|
|
|
var table = Assert.Single(model.Tables);
|
|
|
|
|
Assert.Equal(2, table.Columns.Count);
|
|
|
|
|
var birthdayColumn = Assert.Single(table.Columns, c => c.Name == "Birthday");
|
|
|
|
|
Assert.False(birthdayColumn.IsNullable);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
$"""
|
|
|
|
|
ALTER TABLE [People] ADD [Birthday] datetime2({precision}) NOT NULL DEFAULT '2015-04-12T17:05:00{fractionalSeconds}';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalTheory]
|
|
|
|
|
[InlineData(0, "", 1234567)]
|
|
|
|
|
[InlineData(1, ".1", 1234567)]
|
|
|
|
|
[InlineData(2, ".12", 1234567)]
|
|
|
|
|
[InlineData(3, ".123", 1234567)]
|
|
|
|
|
[InlineData(4, ".1234", 1234567)]
|
|
|
|
|
[InlineData(5, ".12345", 1234567)]
|
|
|
|
|
[InlineData(6, ".123456", 1234567)]
|
|
|
|
|
[InlineData(7, ".1234567", 1234567)]
|
|
|
|
|
[InlineData(7, ".1200000", 1200000)] //should this really output trailing zeros?
|
|
|
|
|
public async Task Add_column_with_defaultValue_datetimeoffset_with_explicit_precision(
|
|
|
|
|
int precision,
|
|
|
|
|
string fractionalSeconds,
|
|
|
|
|
int ticksToAdd)
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.Entity("People").Property<int>("Id"),
|
|
|
|
|
builder => { },
|
|
|
|
|
builder => builder.Entity("People").Property<DateTimeOffset>("Birthday").HasPrecision(precision)
|
|
|
|
|
.HasDefaultValue(new DateTimeOffset(new DateTime(2015, 4, 12, 17, 5, 0).AddTicks(ticksToAdd), TimeSpan.FromHours(10))),
|
|
|
|
|
model =>
|
|
|
|
|
{
|
|
|
|
|
var table = Assert.Single(model.Tables);
|
|
|
|
|
Assert.Equal(2, table.Columns.Count);
|
|
|
|
|
var birthdayColumn = Assert.Single(table.Columns, c => c.Name == "Birthday");
|
|
|
|
|
Assert.False(birthdayColumn.IsNullable);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
$"""
|
|
|
|
|
ALTER TABLE [People] ADD [Birthday] datetimeoffset({precision}) NOT NULL DEFAULT '2015-04-12T17:05:00{fractionalSeconds}+10:00';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalTheory]
|
|
|
|
|
[InlineData(0, "", 1234567)]
|
|
|
|
|
[InlineData(1, ".1", 1234567)]
|
|
|
|
|
[InlineData(2, ".12", 1234567)]
|
|
|
|
|
[InlineData(3, ".123", 1234567)]
|
|
|
|
|
[InlineData(4, ".1234", 1234567)]
|
|
|
|
|
[InlineData(5, ".12345", 1234567)]
|
|
|
|
|
[InlineData(6, ".123456", 1234567)]
|
|
|
|
|
[InlineData(7, ".1234567", 1234567)]
|
|
|
|
|
[InlineData(7, ".12", 1200000)]
|
|
|
|
|
public async Task Add_column_with_defaultValue_time_with_explicit_precision(int precision, string fractionalSeconds, int ticksToAdd)
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.Entity("People").Property<int>("Id"),
|
|
|
|
|
builder => { },
|
|
|
|
|
builder => builder.Entity("People").Property<TimeSpan>("Age").HasPrecision(precision)
|
|
|
|
|
.HasDefaultValue(
|
|
|
|
|
TimeSpan.Parse("12:34:56", CultureInfo.InvariantCulture).Add(TimeSpan.FromTicks(ticksToAdd))),
|
|
|
|
|
model =>
|
|
|
|
|
{
|
|
|
|
|
var table = Assert.Single(model.Tables);
|
|
|
|
|
Assert.Equal(2, table.Columns.Count);
|
|
|
|
|
var birthdayColumn = Assert.Single(table.Columns, c => c.Name == "Age");
|
|
|
|
|
Assert.False(birthdayColumn.IsNullable);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
$"""
|
|
|
|
|
ALTER TABLE [People] ADD [Age] time({precision}) NOT NULL DEFAULT '12:34:56{fractionalSeconds}';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task Add_column_with_defaultValue_datetime_store_type()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.Entity("People").Property<string>("Id"),
|
|
|
|
|
builder => { },
|
|
|
|
|
builder => builder.Entity("People").Property<DateTime>("Birthday")
|
|
|
|
|
.HasColumnType("datetime")
|
|
|
|
|
.HasDefaultValue(new DateTime(2019, 1, 1)),
|
|
|
|
|
model =>
|
|
|
|
|
{
|
|
|
|
|
var table = Assert.Single(model.Tables);
|
|
|
|
|
var column = Assert.Single(table.Columns, c => c.Name == "Birthday");
|
|
|
|
|
Assert.Contains("2019", column.DefaultValueSql);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD [Birthday] datetime NOT NULL DEFAULT '2019-01-01T00:00:00.000';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task Add_column_with_defaultValue_smalldatetime_store_type()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.Entity("People").Property<string>("Id"),
|
|
|
|
|
builder => { },
|
|
|
|
|
builder => builder.Entity("People").Property<DateTime>("Birthday")
|
|
|
|
|
.HasColumnType("smalldatetime")
|
|
|
|
|
.HasDefaultValue(new DateTime(2019, 1, 1)),
|
|
|
|
|
model =>
|
|
|
|
|
{
|
|
|
|
|
var table = Assert.Single(model.Tables);
|
|
|
|
|
var column = Assert.Single(table.Columns, c => c.Name == "Birthday");
|
|
|
|
|
Assert.Contains("2019", column.DefaultValueSql);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD [Birthday] smalldatetime NOT NULL DEFAULT '2019-01-01T00:00:00';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task Add_column_with_rowversion()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.Entity("People").Property<int>("Id"),
|
|
|
|
|
builder => { },
|
|
|
|
|
builder => builder.Entity("People").Property<byte[]>("RowVersion").IsRowVersion(),
|
|
|
|
|
model =>
|
|
|
|
|
{
|
|
|
|
|
var table = Assert.Single(model.Tables);
|
|
|
|
|
var column = Assert.Single(table.Columns, c => c.Name == "RowVersion");
|
|
|
|
|
Assert.Equal("rowversion", column.StoreType);
|
|
|
|
|
Assert.True(column.IsRowVersion());
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD [RowVersion] rowversion NULL;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task Add_column_with_rowversion_and_value_conversion()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.Entity("People").Property<int>("Id"),
|
|
|
|
|
builder => { },
|
|
|
|
|
builder => builder.Entity("People").Property<ulong>("RowVersion")
|
|
|
|
|
.IsRowVersion()
|
|
|
|
|
.HasConversion<byte[]>(),
|
|
|
|
|
model =>
|
|
|
|
|
{
|
|
|
|
|
var table = Assert.Single(model.Tables);
|
|
|
|
|
var column = Assert.Single(table.Columns, c => c.Name == "RowVersion");
|
|
|
|
|
Assert.Equal("rowversion", column.StoreType);
|
|
|
|
|
Assert.True(column.IsRowVersion());
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD [RowVersion] rowversion NOT NULL;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_column_with_defaultValueSql()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_column_with_defaultValueSql();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD [Sum] int NOT NULL DEFAULT (1 + 2);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_json_columns_to_existing_table()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_json_columns_to_existing_table();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Entity] ADD [OwnedCollection] nvarchar(max) NULL;
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Entity] ADD [OwnedReference] nvarchar(max) NULL;
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Entity] ADD [OwnedRequiredReference] nvarchar(max) NOT NULL DEFAULT N'{}';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_column_with_computedSql(bool? stored)
|
|
|
|
|
{
|
|
|
|
|
await base.Add_column_with_computedSql(stored);
|
|
|
|
|
|
|
|
|
|
var computedColumnTypeSql = stored == true ? " PERSISTED" : "";
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
$"""
|
|
|
|
|
ALTER TABLE [People] ADD [Sum] AS [X] + [Y]{computedColumnTypeSql};
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task Add_column_generates_exec_when_computed_and_idempotent()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.Entity("People").Property<int>("Id"),
|
|
|
|
|
builder => { },
|
|
|
|
|
builder => builder.Entity("People").Property<int>("IdPlusOne").HasComputedColumnSql("[Id] + 1"),
|
|
|
|
|
model =>
|
|
|
|
|
{
|
|
|
|
|
var table = Assert.Single(model.Tables);
|
|
|
|
|
Assert.Equal(2, table.Columns.Count);
|
|
|
|
|
var column = Assert.Single(table.Columns, c => c.Name == "IdPlusOne");
|
|
|
|
|
Assert.Equal("([Id]+(1))", column.ComputedColumnSql);
|
|
|
|
|
},
|
|
|
|
|
migrationsSqlGenerationOptions: MigrationsSqlGenerationOptions.Idempotent);
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
EXEC(N'ALTER TABLE [People] ADD [IdPlusOne] AS [Id] + 1');
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_column_with_required()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_column_with_required();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD [Name] nvarchar(max) NOT NULL DEFAULT N'';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_column_with_ansi()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_column_with_ansi();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD [Name] varchar(max) NULL;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_column_with_max_length()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_column_with_max_length();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD [Name] nvarchar(30) NULL;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_column_with_max_length_on_derived()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_column_with_max_length_on_derived();
|
|
|
|
|
|
|
|
|
|
Assert.Empty(Fixture.TestSqlLoggerFactory.SqlStatements);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_column_with_fixed_length()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_column_with_fixed_length();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD [Name] nchar(100) NULL;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_column_with_comment()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_column_with_comment();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD [FullName] nvarchar(max) NULL;
|
|
|
|
|
DECLARE @defaultSchema AS sysname;
|
|
|
|
|
SET @defaultSchema = SCHEMA_NAME();
|
|
|
|
|
DECLARE @description AS sql_variant;
|
|
|
|
|
SET @description = N'My comment';
|
|
|
|
|
EXEC sp_addextendedproperty 'MS_Description', @description, 'SCHEMA', @defaultSchema, 'TABLE', N'People', 'COLUMN', N'FullName';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_column_with_collation()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_column_with_collation();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD [Name] nvarchar(max) COLLATE German_PhoneBook_CI_AS NULL;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_column_computed_with_collation(bool stored)
|
|
|
|
|
{
|
|
|
|
|
await base.Add_column_computed_with_collation(stored);
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
stored
|
|
|
|
|
? """ALTER TABLE [People] ADD [Name] AS 'hello' COLLATE German_PhoneBook_CI_AS PERSISTED;"""
|
|
|
|
|
: """ALTER TABLE [People] ADD [Name] AS 'hello' COLLATE German_PhoneBook_CI_AS;""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_column_shared()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_column_shared();
|
|
|
|
|
|
|
|
|
|
AssertSql();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_column_with_check_constraint()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_column_with_check_constraint();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD [DriverLicense] int NOT NULL DEFAULT 0;
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD CONSTRAINT [CK_People_Foo] CHECK ([DriverLicense] > 0);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task Add_column_identity()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.Entity("People").Property<string>("Id"),
|
|
|
|
|
builder => { },
|
|
|
|
|
builder => builder.Entity("People").Property<int>("IdentityColumn").UseJetIdentityColumn(),
|
|
|
|
|
model =>
|
|
|
|
|
{
|
|
|
|
|
var table = Assert.Single(model.Tables);
|
|
|
|
|
var column = Assert.Single(table.Columns, c => c.Name == "IdentityColumn");
|
|
|
|
|
Assert.Equal(ValueGenerated.OnAdd, column.ValueGenerated);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD [IdentityColumn] int NOT NULL IDENTITY;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task Add_column_identity_seed_increment()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.Entity("People").Property<string>("Id"),
|
|
|
|
|
builder => { },
|
|
|
|
|
builder => builder.Entity("People").Property<int>("IdentityColumn").UseJetIdentityColumn(100, 5),
|
|
|
|
|
model =>
|
|
|
|
|
{
|
|
|
|
|
var table = Assert.Single(model.Tables);
|
|
|
|
|
var column = Assert.Single(table.Columns, c => c.Name == "IdentityColumn");
|
|
|
|
|
Assert.Equal(ValueGenerated.OnAdd, column.ValueGenerated);
|
|
|
|
|
// TODO: Do we not reverse-engineer identity facets?
|
|
|
|
|
// Assert.Equal(100, column[SqlServerAnnotationNames.IdentitySeed]);
|
|
|
|
|
// Assert.Equal(5, column[SqlServerAnnotationNames.IdentityIncrement]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD [IdentityColumn] int NOT NULL IDENTITY(100, 5);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task Add_column_identity_seed_increment_for_TPC()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
buildCommonAction: builder =>
|
|
|
|
|
{
|
|
|
|
|
builder.Entity("Animal").UseTpcMappingStrategy().Property<string>("Id");
|
|
|
|
|
builder.Entity("Cat").HasBaseType("Animal").ToTable("Cats");
|
|
|
|
|
builder.Entity("Dog").HasBaseType("Animal").ToTable("Dogs");
|
|
|
|
|
},
|
|
|
|
|
buildSourceAction:builder => { },
|
|
|
|
|
buildTargetAction:builder =>
|
|
|
|
|
{
|
|
|
|
|
builder.Entity("Animal")
|
|
|
|
|
.Property<int>("IdentityColumn");
|
|
|
|
|
builder.Entity("Cat").ToTable("Cats", tb => tb.Property("IdentityColumn").UseJetIdentityColumn(1, 2));
|
|
|
|
|
builder.Entity("Dog").ToTable("Dogs", tb => tb.Property("IdentityColumn").UseJetIdentityColumn(2, 2));
|
|
|
|
|
},
|
|
|
|
|
asserter:model =>
|
|
|
|
|
{
|
|
|
|
|
Assert.Collection(
|
|
|
|
|
model.Tables,
|
|
|
|
|
t =>
|
|
|
|
|
{
|
|
|
|
|
Assert.Equal("Animal", t.Name);
|
|
|
|
|
var column = Assert.Single(t.Columns, c => c.Name == "IdentityColumn");
|
|
|
|
|
Assert.Null(column.ValueGenerated);
|
|
|
|
|
},
|
|
|
|
|
t =>
|
|
|
|
|
{
|
|
|
|
|
Assert.Equal("Cats", t.Name);
|
|
|
|
|
var column = Assert.Single(t.Columns, c => c.Name == "IdentityColumn");
|
|
|
|
|
Assert.Equal(ValueGenerated.OnAdd, column.ValueGenerated);
|
|
|
|
|
// TODO: Do we not reverse-engineer identity facets?
|
|
|
|
|
// Assert.Equal(100, column[SqlServerAnnotationNames.IdentitySeed]);
|
|
|
|
|
// Assert.Equal(5, column[SqlServerAnnotationNames.IdentityIncrement]);
|
|
|
|
|
},
|
|
|
|
|
t =>
|
|
|
|
|
{
|
|
|
|
|
Assert.Equal("Dogs", t.Name);
|
|
|
|
|
var column = Assert.Single(t.Columns, c => c.Name == "IdentityColumn");
|
|
|
|
|
Assert.Equal(ValueGenerated.OnAdd, column.ValueGenerated);
|
|
|
|
|
// TODO: Do we not reverse-engineer identity facets?
|
|
|
|
|
// Assert.Equal(100, column[SqlServerAnnotationNames.IdentitySeed]);
|
|
|
|
|
// Assert.Equal(5, column[SqlServerAnnotationNames.IdentityIncrement]);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Dogs] ADD [IdentityColumn] int NOT NULL IDENTITY(2, 2);
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Cats] ADD [IdentityColumn] int NOT NULL IDENTITY(1, 2);
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Animal] ADD [IdentityColumn] int NOT NULL DEFAULT 0;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Alter_column_change_type()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_column_change_type();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'SomeColumn');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [People] ALTER COLUMN [SomeColumn] bigint NOT NULL;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Alter_column_make_required()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_column_make_required();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'SomeColumn');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
UPDATE [People] SET [SomeColumn] = N'' WHERE [SomeColumn] IS NULL;
|
|
|
|
|
ALTER TABLE [People] ALTER COLUMN [SomeColumn] nvarchar(max) NOT NULL;
|
|
|
|
|
ALTER TABLE [People] ADD DEFAULT N'' FOR [SomeColumn];
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Alter_column_make_required_with_null_data()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_column_make_required_with_null_data();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'SomeColumn');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
UPDATE [People] SET [SomeColumn] = N'' WHERE [SomeColumn] IS NULL;
|
|
|
|
|
ALTER TABLE [People] ALTER COLUMN [SomeColumn] nvarchar(max) NOT NULL;
|
|
|
|
|
ALTER TABLE [People] ADD DEFAULT N'' FOR [SomeColumn];
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public override async Task Alter_column_make_required_with_index()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_column_make_required_with_index();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DROP INDEX [IX_People_SomeColumn] ON [People];
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'SomeColumn');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
UPDATE [People] SET [SomeColumn] = N'' WHERE [SomeColumn] IS NULL;
|
|
|
|
|
ALTER TABLE [People] ALTER COLUMN [SomeColumn] nvarchar(450) NOT NULL;
|
|
|
|
|
ALTER TABLE [People] ADD DEFAULT N'' FOR [SomeColumn];
|
|
|
|
|
CREATE INDEX [IX_People_SomeColumn] ON [People] ([SomeColumn]);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public override async Task Alter_column_make_required_with_composite_index()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_column_make_required_with_composite_index();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DROP INDEX [IX_People_FirstName_LastName] ON [People];
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'FirstName');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
UPDATE [People] SET [FirstName] = N'' WHERE [FirstName] IS NULL;
|
|
|
|
|
ALTER TABLE [People] ALTER COLUMN [FirstName] nvarchar(450) NOT NULL;
|
|
|
|
|
ALTER TABLE [People] ADD DEFAULT N'' FOR [FirstName];
|
|
|
|
|
CREATE INDEX [IX_People_FirstName_LastName] ON [People] ([FirstName], [LastName]);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Alter_column_make_computed(bool? stored)
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_column_make_computed(stored);
|
|
|
|
|
|
|
|
|
|
var computedColumnTypeSql = stored == true ? " PERSISTED" : "";
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
$"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'Sum');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [People] DROP COLUMN [Sum];
|
|
|
|
|
ALTER TABLE [People] ADD [Sum] AS [X] + [Y]{computedColumnTypeSql};
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Alter_column_change_computed()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_column_change_computed();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'Sum');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [People] DROP COLUMN [Sum];
|
|
|
|
|
ALTER TABLE [People] ADD [Sum] AS [X] - [Y];
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Alter_column_change_computed_recreates_indexes()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_column_change_computed_recreates_indexes();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DROP INDEX [IX_People_Sum] ON [People];
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'Sum');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [People] DROP COLUMN [Sum];
|
|
|
|
|
ALTER TABLE [People] ADD [Sum] AS [X] - [Y];
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
CREATE INDEX [IX_People_Sum] ON [People] ([Sum]);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Alter_column_change_computed_type()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_column_change_computed_type();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'Sum');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [People] DROP COLUMN [Sum];
|
|
|
|
|
ALTER TABLE [People] ADD [Sum] AS [X] + [Y] PERSISTED;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Alter_column_make_non_computed()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_column_make_non_computed();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'Sum');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [People] DROP COLUMN [Sum];
|
|
|
|
|
ALTER TABLE [People] ADD [Sum] int NOT NULL;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public override async Task Alter_column_add_comment()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_column_add_comment();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @defaultSchema AS sysname;
|
|
|
|
|
SET @defaultSchema = SCHEMA_NAME();
|
|
|
|
|
DECLARE @description AS sql_variant;
|
|
|
|
|
SET @description = N'Some comment';
|
|
|
|
|
EXEC sp_addextendedproperty 'MS_Description', @description, 'SCHEMA', @defaultSchema, 'TABLE', N'People', 'COLUMN', N'Id';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public override async Task Alter_computed_column_add_comment()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_computed_column_add_comment();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @defaultSchema AS sysname;
|
|
|
|
|
SET @defaultSchema = SCHEMA_NAME();
|
|
|
|
|
DECLARE @description AS sql_variant;
|
|
|
|
|
SET @description = N'Some comment';
|
|
|
|
|
EXEC sp_addextendedproperty 'MS_Description', @description, 'SCHEMA', @defaultSchema, 'TABLE', N'People', 'COLUMN', N'SomeColumn';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public override async Task Alter_column_change_comment()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_column_change_comment();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @defaultSchema AS sysname;
|
|
|
|
|
SET @defaultSchema = SCHEMA_NAME();
|
|
|
|
|
DECLARE @description AS sql_variant;
|
|
|
|
|
EXEC sp_dropextendedproperty 'MS_Description', 'SCHEMA', @defaultSchema, 'TABLE', N'People', 'COLUMN', N'Id';
|
|
|
|
|
SET @description = N'Some comment2';
|
|
|
|
|
EXEC sp_addextendedproperty 'MS_Description', @description, 'SCHEMA', @defaultSchema, 'TABLE', N'People', 'COLUMN', N'Id';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public override async Task Alter_column_remove_comment()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_column_remove_comment();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @defaultSchema AS sysname;
|
|
|
|
|
SET @defaultSchema = SCHEMA_NAME();
|
|
|
|
|
DECLARE @description AS sql_variant;
|
|
|
|
|
EXEC sp_dropextendedproperty 'MS_Description', 'SCHEMA', @defaultSchema, 'TABLE', N'People', 'COLUMN', N'Id';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public override async Task Alter_column_set_collation()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_column_set_collation();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'Name');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [People] ALTER COLUMN [Name] nvarchar(max) COLLATE German_PhoneBook_CI_AS NULL;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task Alter_column_set_collation_with_index()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.Entity(
|
|
|
|
|
"People", e =>
|
|
|
|
|
{
|
|
|
|
|
e.Property<string>("Name");
|
|
|
|
|
e.HasIndex("Name");
|
|
|
|
|
}),
|
|
|
|
|
builder => { },
|
|
|
|
|
builder => builder.Entity("People").Property<string>("Name")
|
|
|
|
|
.UseCollation(NonDefaultCollation),
|
|
|
|
|
model =>
|
|
|
|
|
{
|
|
|
|
|
var nameColumn = Assert.Single(Assert.Single(model.Tables).Columns);
|
|
|
|
|
Assert.Equal(NonDefaultCollation, nameColumn.Collation);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DROP INDEX [IX_People_Name] ON [People];
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'Name');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [People] ALTER COLUMN [Name] nvarchar(450) COLLATE German_PhoneBook_CI_AS NULL;
|
|
|
|
|
CREATE INDEX [IX_People_Name] ON [People] ([Name]);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public override async Task Alter_column_reset_collation()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_column_reset_collation();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'Name');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [People] ALTER COLUMN [Name] nvarchar(max) NULL;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Convert_json_entities_to_regular_owned()
|
|
|
|
|
{
|
|
|
|
|
await base.Convert_json_entities_to_regular_owned();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[Entity]') AND [c].[name] = N'OwnedCollection');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [Entity] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [Entity] DROP COLUMN [OwnedCollection];
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var1 sysname;
|
|
|
|
|
SELECT @var1 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[Entity]') AND [c].[name] = N'OwnedReference');
|
|
|
|
|
IF @var1 IS NOT NULL EXEC(N'ALTER TABLE [Entity] DROP CONSTRAINT [' + @var1 + '];');
|
|
|
|
|
ALTER TABLE [Entity] DROP COLUMN [OwnedReference];
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Entity] ADD [OwnedReference_Date] datetime2 NULL;
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Entity] ADD [OwnedReference_NestedReference_Number] int NULL;
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
CREATE TABLE [Entity_NestedCollection] (
|
|
|
|
|
[OwnedEntityId] int NOT NULL,
|
|
|
|
|
[Id] int NOT NULL IDENTITY,
|
|
|
|
|
[Number2] int NOT NULL,
|
|
|
|
|
CONSTRAINT [PK_Entity_NestedCollection] PRIMARY KEY ([OwnedEntityId], [Id]),
|
|
|
|
|
CONSTRAINT [FK_Entity_NestedCollection_Entity_OwnedEntityId] FOREIGN KEY ([OwnedEntityId]) REFERENCES [Entity] ([Id]) ON DELETE CASCADE
|
|
|
|
|
);
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
CREATE TABLE [Entity_OwnedCollection] (
|
|
|
|
|
[EntityId] int NOT NULL,
|
|
|
|
|
[Id] int NOT NULL IDENTITY,
|
|
|
|
|
[Date2] datetime2 NOT NULL,
|
|
|
|
|
[NestedReference2_Number3] int NULL,
|
|
|
|
|
CONSTRAINT [PK_Entity_OwnedCollection] PRIMARY KEY ([EntityId], [Id]),
|
|
|
|
|
CONSTRAINT [FK_Entity_OwnedCollection_Entity_EntityId] FOREIGN KEY ([EntityId]) REFERENCES [Entity] ([Id]) ON DELETE CASCADE
|
|
|
|
|
);
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
CREATE TABLE [Entity_OwnedCollection_NestedCollection2] (
|
|
|
|
|
[Owned2EntityId] int NOT NULL,
|
|
|
|
|
[Owned2Id] int NOT NULL,
|
|
|
|
|
[Id] int NOT NULL IDENTITY,
|
|
|
|
|
[Number4] int NOT NULL,
|
|
|
|
|
CONSTRAINT [PK_Entity_OwnedCollection_NestedCollection2] PRIMARY KEY ([Owned2EntityId], [Owned2Id], [Id]),
|
|
|
|
|
CONSTRAINT [FK_Entity_OwnedCollection_NestedCollection2_Entity_OwnedCollection_Owned2EntityId_Owned2Id] FOREIGN KEY ([Owned2EntityId], [Owned2Id]) REFERENCES [Entity_OwnedCollection] ([EntityId], [Id]) ON DELETE CASCADE
|
|
|
|
|
);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Convert_regular_owned_entities_to_json()
|
|
|
|
|
{
|
|
|
|
|
await base.Convert_regular_owned_entities_to_json();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DROP TABLE [Entity_NestedCollection];
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
DROP TABLE [Entity_OwnedCollection_NestedCollection2];
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
DROP TABLE [Entity_OwnedCollection];
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[Entity]') AND [c].[name] = N'OwnedReference_Date');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [Entity] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [Entity] DROP COLUMN [OwnedReference_Date];
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var1 sysname;
|
|
|
|
|
SELECT @var1 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[Entity]') AND [c].[name] = N'OwnedReference_NestedReference_Number');
|
|
|
|
|
IF @var1 IS NOT NULL EXEC(N'ALTER TABLE [Entity] DROP CONSTRAINT [' + @var1 + '];');
|
|
|
|
|
ALTER TABLE [Entity] DROP COLUMN [OwnedReference_NestedReference_Number];
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Entity] ADD [OwnedCollection] nvarchar(max) NULL;
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Entity] ADD [OwnedReference] nvarchar(max) NULL;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Convert_string_column_to_a_json_column_containing_reference()
|
|
|
|
|
{
|
|
|
|
|
await base.Convert_string_column_to_a_json_column_containing_reference();
|
|
|
|
|
|
|
|
|
|
AssertSql();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Convert_string_column_to_a_json_column_containing_required_reference()
|
|
|
|
|
{
|
|
|
|
|
await base.Convert_string_column_to_a_json_column_containing_required_reference();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[Entity]') AND [c].[name] = N'Name');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [Entity] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
UPDATE [Entity] SET [Name] = N'{}' WHERE [Name] IS NULL;
|
|
|
|
|
ALTER TABLE [Entity] ALTER COLUMN [Name] nvarchar(max) NOT NULL;
|
|
|
|
|
ALTER TABLE [Entity] ADD DEFAULT N'{}' FOR [Name];
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Convert_string_column_to_a_json_column_containing_collection()
|
|
|
|
|
{
|
|
|
|
|
await base.Convert_string_column_to_a_json_column_containing_collection();
|
|
|
|
|
|
|
|
|
|
AssertSql();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task Alter_column_with_index_no_narrowing()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.Entity(
|
|
|
|
|
"People", e =>
|
|
|
|
|
{
|
|
|
|
|
e.Property<int>("Id");
|
|
|
|
|
e.Property<string>("Name");
|
|
|
|
|
e.HasIndex("Name");
|
|
|
|
|
}),
|
|
|
|
|
builder => builder.Entity("People").Property<string>("Name").IsRequired(),
|
|
|
|
|
builder => builder.Entity("People").Property<string>("Name").IsRequired(false),
|
|
|
|
|
model =>
|
|
|
|
|
{
|
|
|
|
|
var table = Assert.Single(model.Tables);
|
|
|
|
|
var column = Assert.Single(table.Columns, c => c.Name == "Name");
|
|
|
|
|
Assert.True(column.IsNullable);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'Name');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [People] ALTER COLUMN [Name] nvarchar(450) NULL;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task Alter_column_add_identity()
|
|
|
|
|
{
|
|
|
|
|
var ex = await TestThrows<InvalidOperationException>(
|
|
|
|
|
builder => builder.Entity("People").Property<int>("SomeColumn"),
|
|
|
|
|
builder => builder.Entity("People").Property<int>("SomeColumn").UseJetIdentityColumn());
|
|
|
|
|
|
|
|
|
|
Assert.Equal(JetStrings.AlterIdentityColumn, ex.Message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task Alter_column_remove_identity()
|
|
|
|
|
{
|
|
|
|
|
var ex = await TestThrows<InvalidOperationException>(
|
|
|
|
|
builder => builder.Entity("People").Property<int>("SomeColumn").UseJetIdentityColumn(),
|
|
|
|
|
builder => builder.Entity("People").Property<int>("SomeColumn"));
|
|
|
|
|
|
|
|
|
|
Assert.Equal(JetStrings.AlterIdentityColumn, ex.Message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task Alter_column_change_type_with_identity()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.Entity(
|
|
|
|
|
"People", e =>
|
|
|
|
|
{
|
|
|
|
|
e.Property<string>("Id");
|
|
|
|
|
e.Property<int>("IdentityColumn").UseJetIdentityColumn();
|
|
|
|
|
}),
|
|
|
|
|
builder => builder.Entity(
|
|
|
|
|
"People", e =>
|
|
|
|
|
{
|
|
|
|
|
e.Property<string>("Id");
|
|
|
|
|
e.Property<long>("IdentityColumn").UseJetIdentityColumn();
|
|
|
|
|
}),
|
|
|
|
|
model =>
|
|
|
|
|
{
|
|
|
|
|
var table = Assert.Single(model.Tables);
|
|
|
|
|
var column = Assert.Single(table.Columns, c => c.Name == "IdentityColumn");
|
|
|
|
|
Assert.Equal("bigint", column.StoreType);
|
|
|
|
|
Assert.Equal(ValueGenerated.OnAdd, column.ValueGenerated);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'IdentityColumn');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [People] ALTER COLUMN [IdentityColumn] bigint NOT NULL;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task Alter_column_change_identity_seed()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.Entity("People", e => e.Property<int>("Id").UseJetIdentityColumn(seed: 10)),
|
|
|
|
|
builder => builder.Entity("People", e => e.Property<int>("Id").UseJetIdentityColumn(seed: 100)),
|
|
|
|
|
model =>
|
|
|
|
|
{
|
|
|
|
|
// DBCC CHECKIDENT RESEED doesn't actually change the table definition, it only resets the current identity value.
|
|
|
|
|
// For example, if the table is truncated, the identity is reset back to its original value (with the RESEED lost).
|
|
|
|
|
// Therefore we cannot check the value via scaffolding.
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DBCC CHECKIDENT(N'[People]', RESEED, 100);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task Alter_column_change_default()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.Entity("People").Property<string>("Name"),
|
|
|
|
|
builder => { },
|
|
|
|
|
builder => builder.Entity("People").Property<string>("Name")
|
|
|
|
|
.HasDefaultValue("Doe"),
|
|
|
|
|
model =>
|
|
|
|
|
{
|
|
|
|
|
var nameColumn = Assert.Single(Assert.Single(model.Tables).Columns);
|
|
|
|
|
Assert.Equal("(N'Doe')", nameColumn.DefaultValueSql);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'Name');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [People] ADD DEFAULT N'Doe' FOR [Name];
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task Alter_column_change_comment_with_default()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.Entity("People").Property<string>("Name").HasDefaultValue("Doe"),
|
|
|
|
|
builder => { },
|
|
|
|
|
builder => builder.Entity("People").Property<string>("Name")
|
|
|
|
|
.HasComment("Some comment"),
|
|
|
|
|
model =>
|
|
|
|
|
{
|
|
|
|
|
var nameColumn = Assert.Single(Assert.Single(model.Tables).Columns);
|
|
|
|
|
Assert.Equal("(N'Doe')", nameColumn.DefaultValueSql);
|
|
|
|
|
Assert.Equal("Some comment", nameColumn.Comment);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @defaultSchema AS sysname;
|
|
|
|
|
SET @defaultSchema = SCHEMA_NAME();
|
|
|
|
|
DECLARE @description AS sql_variant;
|
|
|
|
|
SET @description = N'Some comment';
|
|
|
|
|
EXEC sp_addextendedproperty 'MS_Description', @description, 'SCHEMA', @defaultSchema, 'TABLE', N'People', 'COLUMN', N'Name';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Drop_column()
|
|
|
|
|
{
|
|
|
|
|
await base.Drop_column();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'SomeColumn');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [People] DROP COLUMN [SomeColumn];
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Drop_column_primary_key()
|
|
|
|
|
{
|
|
|
|
|
await base.Drop_column_primary_key();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] DROP CONSTRAINT [PK_People];
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'Id');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [People] DROP COLUMN [Id];
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Drop_column_computed_and_non_computed_with_dependency()
|
|
|
|
|
{
|
|
|
|
|
await base.Drop_column_computed_and_non_computed_with_dependency();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'Y');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [People] DROP COLUMN [Y];
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var1 sysname;
|
|
|
|
|
SELECT @var1 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'X');
|
|
|
|
|
IF @var1 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var1 + '];');
|
|
|
|
|
ALTER TABLE [People] DROP COLUMN [X];
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Drop_json_columns_from_existing_table()
|
|
|
|
|
{
|
|
|
|
|
await base.Drop_json_columns_from_existing_table();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[Entity]') AND [c].[name] = N'OwnedCollection');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [Entity] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [Entity] DROP COLUMN [OwnedCollection];
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var1 sysname;
|
|
|
|
|
SELECT @var1 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[Entity]') AND [c].[name] = N'OwnedReference');
|
|
|
|
|
IF @var1 IS NOT NULL EXEC(N'ALTER TABLE [Entity] DROP CONSTRAINT [' + @var1 + '];');
|
|
|
|
|
ALTER TABLE [Entity] DROP COLUMN [OwnedReference];
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Rename_column()
|
|
|
|
|
{
|
|
|
|
|
await base.Rename_column();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
EXEC sp_rename N'[People].[SomeColumn]', N'SomeOtherColumn', 'COLUMN';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Rename_json_column()
|
|
|
|
|
{
|
|
|
|
|
await base.Rename_json_column();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
EXEC sp_rename N'[Entity].[json_reference]', N'new_json_reference', 'COLUMN';
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
EXEC sp_rename N'[Entity].[json_collection]', N'new_json_collection', 'COLUMN';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Create_index()
|
|
|
|
|
{
|
|
|
|
|
await base.Create_index();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'FirstName');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [People] ALTER COLUMN [FirstName] nvarchar(450) NULL;
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
CREATE INDEX [IX_People_FirstName] ON [People] ([FirstName]);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Create_index_unique()
|
|
|
|
|
{
|
|
|
|
|
await base.Create_index_unique();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'LastName');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [People] ALTER COLUMN [LastName] nvarchar(450) NULL;
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var1 sysname;
|
|
|
|
|
SELECT @var1 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'FirstName');
|
|
|
|
|
IF @var1 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var1 + '];');
|
|
|
|
|
ALTER TABLE [People] ALTER COLUMN [FirstName] nvarchar(450) NULL;
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
CREATE UNIQUE INDEX [IX_People_FirstName_LastName] ON [People] ([FirstName], [LastName]) WHERE [FirstName] IS NOT NULL AND [LastName] IS NOT NULL;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Create_index_descending()
|
|
|
|
|
{
|
|
|
|
|
await base.Create_index_descending();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
CREATE INDEX [IX_People_X] ON [People] ([X] DESC);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Create_index_descending_mixed()
|
|
|
|
|
{
|
|
|
|
|
await base.Create_index_descending_mixed();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
CREATE INDEX [IX_People_X_Y_Z] ON [People] ([X], [Y] DESC, [Z]);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Alter_index_make_unique()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_index_make_unique();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DROP INDEX [IX_People_X] ON [People];
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
CREATE UNIQUE INDEX [IX_People_X] ON [People] ([X]);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Alter_index_change_sort_order()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_index_change_sort_order();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DROP INDEX [IX_People_X_Y_Z] ON [People];
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
CREATE INDEX [IX_People_X_Y_Z] ON [People] ([X], [Y] DESC, [Z]);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Create_index_with_filter()
|
|
|
|
|
{
|
|
|
|
|
await base.Create_index_with_filter();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'Name');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [People] ALTER COLUMN [Name] nvarchar(450) NULL;
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
CREATE INDEX [IX_People_Name] ON [People] ([Name]) WHERE [Name] IS NOT NULL;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task CreateIndex_generates_exec_when_filter_and_idempotent()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.Entity(
|
|
|
|
|
"People", e =>
|
|
|
|
|
{
|
|
|
|
|
e.Property<int>("Id");
|
|
|
|
|
e.Property<string>("Name");
|
|
|
|
|
}),
|
|
|
|
|
builder => { },
|
|
|
|
|
builder => builder.Entity("People").HasIndex("Name").HasFilter("[Name] IS NOT NULL"),
|
|
|
|
|
model =>
|
|
|
|
|
{
|
|
|
|
|
var table = Assert.Single(model.Tables);
|
|
|
|
|
var index = Assert.Single(table.Indexes);
|
|
|
|
|
Assert.Same(table.Columns.Single(c => c.Name == "Name"), Assert.Single(index.Columns));
|
|
|
|
|
Assert.Contains("Name", index.Filter);
|
|
|
|
|
},
|
|
|
|
|
migrationsSqlGenerationOptions: MigrationsSqlGenerationOptions.Idempotent);
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'Name');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [People] ALTER COLUMN [Name] nvarchar(450) NULL;
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
EXEC(N'CREATE INDEX [IX_People_Name] ON [People] ([Name]) WHERE [Name] IS NOT NULL');
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Create_unique_index_with_filter()
|
|
|
|
|
{
|
|
|
|
|
await base.Create_unique_index_with_filter();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'Name');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [People] ALTER COLUMN [Name] nvarchar(450) NULL;
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
CREATE UNIQUE INDEX [IX_People_Name] ON [People] ([Name]) WHERE [Name] IS NOT NULL AND [Name] <> '';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Drop_index()
|
|
|
|
|
{
|
|
|
|
|
await base.Drop_index();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DROP INDEX [IX_People_SomeField] ON [People];
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Rename_index()
|
|
|
|
|
{
|
|
|
|
|
await base.Rename_index();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
EXEC sp_rename N'[People].[Foo]', N'foo', 'INDEX';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_primary_key_int()
|
|
|
|
|
{
|
|
|
|
|
var exception = await Assert.ThrowsAsync<InvalidOperationException>(() => base.Add_primary_key_int());
|
|
|
|
|
|
|
|
|
|
Assert.Equal(JetStrings.AlterIdentityColumn, exception.Message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_primary_key_string()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_primary_key_string();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'SomeField');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [People] ALTER COLUMN [SomeField] nvarchar(450) NOT NULL;
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD CONSTRAINT [PK_People] PRIMARY KEY ([SomeField]);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_primary_key_with_name()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_primary_key_with_name();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'SomeField');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
UPDATE [People] SET [SomeField] = N'' WHERE [SomeField] IS NULL;
|
|
|
|
|
ALTER TABLE [People] ALTER COLUMN [SomeField] nvarchar(450) NOT NULL;
|
|
|
|
|
ALTER TABLE [People] ADD DEFAULT N'' FOR [SomeField];
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD CONSTRAINT [PK_Foo] PRIMARY KEY ([SomeField]);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_primary_key_composite_with_name()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_primary_key_composite_with_name();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD CONSTRAINT [PK_Foo] PRIMARY KEY ([SomeField1], [SomeField2]);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Drop_primary_key_int()
|
|
|
|
|
{
|
|
|
|
|
var exception = await Assert.ThrowsAsync<InvalidOperationException>(() => base.Drop_primary_key_int());
|
|
|
|
|
|
|
|
|
|
Assert.Equal(JetStrings.AlterIdentityColumn, exception.Message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Drop_primary_key_string()
|
|
|
|
|
{
|
|
|
|
|
await base.Drop_primary_key_string();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] DROP CONSTRAINT [PK_People];
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'SomeField');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [People] ALTER COLUMN [SomeField] nvarchar(max) NOT NULL;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_foreign_key()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_foreign_key();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
CREATE INDEX [IX_Orders_CustomerId] ON [Orders] ([CustomerId]);
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Orders] ADD CONSTRAINT [FK_Orders_Customers_CustomerId] FOREIGN KEY ([CustomerId]) REFERENCES [Customers] ([Id]) ON DELETE CASCADE;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_foreign_key_with_name()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_foreign_key_with_name();
|
|
|
|
|
|
|
|
|
|
// AssertSql(
|
|
|
|
|
// @"ALTER TABLE [Orders] DROP CONSTRAINT [FK_Orders_Customers_CustomerId];",
|
|
|
|
|
// //
|
|
|
|
|
// @"DROP INDEX [IX_Orders_CustomerId] ON [Orders];");
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
CREATE INDEX [IX_Orders_CustomerId] ON [Orders] ([CustomerId]);
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Orders] ADD CONSTRAINT [FK_Foo] FOREIGN KEY ([CustomerId]) REFERENCES [Customers] ([Id]) ON DELETE CASCADE;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Drop_foreign_key()
|
|
|
|
|
{
|
|
|
|
|
await base.Drop_foreign_key();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Orders] DROP CONSTRAINT [FK_Orders_Customers_CustomerId];
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
DROP INDEX [IX_Orders_CustomerId] ON [Orders];
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_unique_constraint()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_unique_constraint();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD CONSTRAINT [AK_People_AlternateKeyColumn] UNIQUE ([AlternateKeyColumn]);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_unique_constraint_composite_with_name()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_unique_constraint_composite_with_name();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD CONSTRAINT [AK_Foo] UNIQUE ([AlternateKeyColumn1], [AlternateKeyColumn2]);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Drop_unique_constraint()
|
|
|
|
|
{
|
|
|
|
|
await base.Drop_unique_constraint();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] DROP CONSTRAINT [AK_People_AlternateKeyColumn];
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Add_check_constraint_with_name()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_check_constraint_with_name();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD CONSTRAINT [CK_People_Foo] CHECK ([DriverLicense] > 0);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task Add_check_constraint_generates_exec_when_idempotent()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.Entity(
|
|
|
|
|
"People", e =>
|
|
|
|
|
{
|
|
|
|
|
e.Property<int>("Id");
|
|
|
|
|
e.Property<int>("DriverLicense");
|
|
|
|
|
}),
|
|
|
|
|
builder => { },
|
|
|
|
|
builder => builder.Entity("People").ToTable(tb => tb.HasCheckConstraint("CK_People_Foo", "[DriverLicense] > 0")),
|
|
|
|
|
model =>
|
|
|
|
|
{
|
|
|
|
|
// TODO: no scaffolding support for check constraints, https://github.com/aspnet/EntityFrameworkCore/issues/15408
|
|
|
|
|
},
|
|
|
|
|
migrationsSqlGenerationOptions: MigrationsSqlGenerationOptions.Idempotent);
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
EXEC(N'ALTER TABLE [People] ADD CONSTRAINT [CK_People_Foo] CHECK ([DriverLicense] > 0)');
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Alter_check_constraint()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_check_constraint();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] DROP CONSTRAINT [CK_People_Foo];
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD CONSTRAINT [CK_People_Foo] CHECK ([DriverLicense] > 1);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Drop_check_constraint()
|
|
|
|
|
{
|
|
|
|
|
await base.Drop_check_constraint();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] DROP CONSTRAINT [CK_People_Foo];
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Create_sequence()
|
|
|
|
|
{
|
|
|
|
|
await base.Create_sequence();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
CREATE SEQUENCE [TestSequence] AS int START WITH 1 INCREMENT BY 1 NO CYCLE;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Create_sequence_long()
|
|
|
|
|
{
|
|
|
|
|
await base.Create_sequence_long();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
CREATE SEQUENCE [TestSequence] START WITH 1 INCREMENT BY 1 NO CYCLE;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Create_sequence_short()
|
|
|
|
|
{
|
|
|
|
|
await base.Create_sequence_short();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
CREATE SEQUENCE [TestSequence] AS smallint START WITH 1 INCREMENT BY 1 NO CYCLE;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Create_sequence_all_settings()
|
|
|
|
|
{
|
|
|
|
|
await base.Create_sequence_all_settings();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
IF SCHEMA_ID(N'dbo2') IS NULL EXEC(N'CREATE SCHEMA [dbo2];');
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
CREATE SEQUENCE [dbo2].[TestSequence] START WITH 3 INCREMENT BY 2 MINVALUE 2 MAXVALUE 916 CYCLE;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Alter_sequence_all_settings()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_sequence_all_settings();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER SEQUENCE [foo] INCREMENT BY 2 MINVALUE -5 MAXVALUE 10 CYCLE;
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
ALTER SEQUENCE [foo] RESTART WITH -3;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Alter_sequence_increment_by()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_sequence_increment_by();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER SEQUENCE [foo] INCREMENT BY 2 NO MINVALUE NO MAXVALUE NO CYCLE;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Alter_sequence_restart_with()
|
|
|
|
|
{
|
|
|
|
|
await base.Alter_sequence_restart_with();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
@"ALTER SEQUENCE [foo] RESTART WITH 3;");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Drop_sequence()
|
|
|
|
|
{
|
|
|
|
|
await base.Drop_sequence();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DROP SEQUENCE [TestSequence];
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Rename_sequence()
|
|
|
|
|
{
|
|
|
|
|
await base.Rename_sequence();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
EXEC sp_rename N'[TestSequence]', N'testsequence', 'OBJECT';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task Move_sequence()
|
|
|
|
|
{
|
|
|
|
|
await base.Move_sequence();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
IF SCHEMA_ID(N'TestSequenceSchema') IS NULL EXEC(N'CREATE SCHEMA [TestSequenceSchema];');
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
ALTER SCHEMA [TestSequenceSchema] TRANSFER [TestSequence];
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task Move_sequence_into_default_schema()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.HasSequence<int>("TestSequence", "TestSequenceSchema"),
|
|
|
|
|
builder => builder.HasSequence<int>("TestSequence"),
|
|
|
|
|
model =>
|
|
|
|
|
{
|
|
|
|
|
var sequence = Assert.Single(model.Sequences);
|
|
|
|
|
Assert.Equal("dbo", sequence.Schema);
|
|
|
|
|
Assert.Equal("TestSequence", sequence.Name);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @defaultSchema sysname = SCHEMA_NAME();
|
|
|
|
|
EXEC(N'ALTER SCHEMA [' + @defaultSchema + N'] TRANSFER [TestSequenceSchema].[TestSequence];');
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public async Task Create_sequence_and_dependent_column()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.Entity("People").Property<int>("Id"),
|
|
|
|
|
builder => { },
|
|
|
|
|
builder =>
|
|
|
|
|
{
|
|
|
|
|
builder.HasSequence<int>("TestSequence");
|
|
|
|
|
builder.Entity("People").Property<int>("SeqProp").HasDefaultValueSql("NEXT VALUE FOR TestSequence");
|
|
|
|
|
},
|
|
|
|
|
model =>
|
|
|
|
|
{
|
|
|
|
|
var sequence = Assert.Single(model.Sequences);
|
|
|
|
|
Assert.Equal("TestSequence", sequence.Name);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
CREATE SEQUENCE [TestSequence] AS int START WITH 1 INCREMENT BY 1 NO CYCLE;
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [People] ADD [SeqProp] int NOT NULL DEFAULT (NEXT VALUE FOR TestSequence);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public async Task Drop_sequence_and_dependent_column()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.Entity("People").Property<int>("Id"),
|
|
|
|
|
builder =>
|
|
|
|
|
{
|
|
|
|
|
builder.HasSequence<int>("TestSequence");
|
|
|
|
|
builder.Entity("People").Property<int>("SeqProp").HasDefaultValueSql("NEXT VALUE FOR TestSequence");
|
|
|
|
|
},
|
|
|
|
|
builder => { },
|
|
|
|
|
model => Assert.Empty(model.Sequences));
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DECLARE @var0 sysname;
|
|
|
|
|
SELECT @var0 = [d].[name]
|
|
|
|
|
FROM [sys].[default_constraints] [d]
|
|
|
|
|
INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id]
|
|
|
|
|
WHERE ([d].[parent_object_id] = OBJECT_ID(N'[People]') AND [c].[name] = N'SeqProp');
|
|
|
|
|
IF @var0 IS NOT NULL EXEC(N'ALTER TABLE [People] DROP CONSTRAINT [' + @var0 + '];');
|
|
|
|
|
ALTER TABLE [People] DROP COLUMN [SeqProp];
|
|
|
|
|
""",
|
|
|
|
|
//
|
|
|
|
|
"""
|
|
|
|
|
DROP SEQUENCE [TestSequence];
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task InsertDataOperation()
|
|
|
|
|
{
|
|
|
|
|
await base.InsertDataOperation();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
IF EXISTS (SELECT * FROM [sys].[identity_columns] WHERE [name] IN (N'Id', N'Name') AND [object_id] = OBJECT_ID(N'[Person]'))
|
|
|
|
|
SET IDENTITY_INSERT [Person] ON;
|
|
|
|
|
INSERT INTO [Person] ([Id], [Name])
|
|
|
|
|
VALUES (1, N'Daenerys Targaryen'),
|
|
|
|
|
(2, N'John Snow'),
|
|
|
|
|
(3, N'Arya Stark'),
|
|
|
|
|
(4, N'Harry Strickland'),
|
|
|
|
|
(5, NULL);
|
|
|
|
|
IF EXISTS (SELECT * FROM [sys].[identity_columns] WHERE [name] IN (N'Id', N'Name') AND [object_id] = OBJECT_ID(N'[Person]'))
|
|
|
|
|
SET IDENTITY_INSERT [Person] OFF;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task DeleteDataOperation_simple_key()
|
|
|
|
|
{
|
|
|
|
|
await base.DeleteDataOperation_simple_key();
|
|
|
|
|
|
|
|
|
|
// TODO remove rowcount
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DELETE FROM [Person]
|
|
|
|
|
WHERE [Id] = 2;
|
|
|
|
|
SELECT @@ROWCOUNT;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task DeleteDataOperation_composite_key()
|
|
|
|
|
{
|
|
|
|
|
await base.DeleteDataOperation_composite_key();
|
|
|
|
|
|
|
|
|
|
// TODO remove rowcount
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
DELETE FROM [Person]
|
|
|
|
|
WHERE [AnotherId] = 12 AND [Id] = 2;
|
|
|
|
|
SELECT @@ROWCOUNT;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task UpdateDataOperation_simple_key()
|
|
|
|
|
{
|
|
|
|
|
await base.UpdateDataOperation_simple_key();
|
|
|
|
|
|
|
|
|
|
// TODO remove rowcount
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
UPDATE [Person] SET [Name] = N'Another John Snow'
|
|
|
|
|
WHERE [Id] = 2;
|
|
|
|
|
SELECT @@ROWCOUNT;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task UpdateDataOperation_composite_key()
|
|
|
|
|
{
|
|
|
|
|
await base.UpdateDataOperation_composite_key();
|
|
|
|
|
|
|
|
|
|
// TODO remove rowcount
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
UPDATE [Person] SET [Name] = N'Another John Snow'
|
|
|
|
|
WHERE [AnotherId] = 11 AND [Id] = 2;
|
|
|
|
|
SELECT @@ROWCOUNT;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task UpdateDataOperation_multiple_columns()
|
|
|
|
|
{
|
|
|
|
|
await base.UpdateDataOperation_multiple_columns();
|
|
|
|
|
|
|
|
|
|
// TODO remove rowcount
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
UPDATE [Person] SET [Age] = 21, [Name] = N'Another John Snow'
|
|
|
|
|
WHERE [Id] = 2;
|
|
|
|
|
SELECT @@ROWCOUNT;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task InsertDataOperation_generates_exec_when_idempotent()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.Entity(
|
|
|
|
|
"Person", e =>
|
|
|
|
|
{
|
|
|
|
|
e.Property<int>("Id");
|
|
|
|
|
e.Property<string>("Name");
|
|
|
|
|
e.HasKey("Id");
|
|
|
|
|
}),
|
|
|
|
|
builder => { },
|
|
|
|
|
builder => builder.Entity("Person")
|
|
|
|
|
.HasData(
|
|
|
|
|
new Person { Id = 1, Name = "Daenerys Targaryen" },
|
|
|
|
|
new Person { Id = 2, Name = "John Snow" },
|
|
|
|
|
new Person { Id = 3, Name = "Arya Stark" },
|
|
|
|
|
new Person { Id = 4, Name = "Harry Strickland" },
|
|
|
|
|
new Person { Id = 5, Name = null }),
|
|
|
|
|
model => { },
|
|
|
|
|
migrationsSqlGenerationOptions: MigrationsSqlGenerationOptions.Idempotent);
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
IF EXISTS (SELECT * FROM [sys].[identity_columns] WHERE [name] IN (N'Id', N'Name') AND [object_id] = OBJECT_ID(N'[Person]'))
|
|
|
|
|
SET IDENTITY_INSERT [Person] ON;
|
|
|
|
|
EXEC(N'INSERT INTO [Person] ([Id], [Name])
|
|
|
|
|
VALUES (1, N''Daenerys Targaryen''),
|
|
|
|
|
(2, N''John Snow''),
|
|
|
|
|
(3, N''Arya Stark''),
|
|
|
|
|
(4, N''Harry Strickland''),
|
|
|
|
|
(5, NULL)');
|
|
|
|
|
IF EXISTS (SELECT * FROM [sys].[identity_columns] WHERE [name] IN (N'Id', N'Name') AND [object_id] = OBJECT_ID(N'[Person]'))
|
|
|
|
|
SET IDENTITY_INSERT [Person] OFF;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task DeleteDataOperation_generates_exec_when_idempotent()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.Entity(
|
|
|
|
|
"Person", e =>
|
|
|
|
|
{
|
|
|
|
|
e.Property<int>("Id");
|
|
|
|
|
e.Property<string>("Name");
|
|
|
|
|
e.HasKey("Id");
|
|
|
|
|
e.HasData(new Person { Id = 1, Name = "Daenerys Targaryen" });
|
|
|
|
|
}),
|
|
|
|
|
builder => builder.Entity("Person").HasData(new Person { Id = 2, Name = "John Snow" }),
|
|
|
|
|
builder => { },
|
|
|
|
|
model => { },
|
|
|
|
|
migrationsSqlGenerationOptions: MigrationsSqlGenerationOptions.Idempotent);
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
EXEC(N'DELETE FROM [Person]
|
|
|
|
|
WHERE [Id] = 2;
|
|
|
|
|
SELECT @@ROWCOUNT');
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public virtual async Task UpdateDataOperation_generates_exec_when_idempotent()
|
|
|
|
|
{
|
|
|
|
|
await Test(
|
|
|
|
|
builder => builder.Entity(
|
|
|
|
|
"Person", e =>
|
|
|
|
|
{
|
|
|
|
|
e.Property<int>("Id");
|
|
|
|
|
e.Property<string>("Name");
|
|
|
|
|
e.HasKey("Id");
|
|
|
|
|
e.HasData(new Person { Id = 1, Name = "Daenerys Targaryen" });
|
|
|
|
|
}),
|
|
|
|
|
builder => builder.Entity("Person").HasData(new Person { Id = 2, Name = "John Snow" }),
|
|
|
|
|
builder => builder.Entity("Person").HasData(new Person { Id = 2, Name = "Another John Snow" }),
|
|
|
|
|
model => { },
|
|
|
|
|
migrationsSqlGenerationOptions: MigrationsSqlGenerationOptions.Idempotent);
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
EXEC(N'UPDATE [Person] SET [Name] = N''Another John Snow''
|
|
|
|
|
WHERE [Id] = 2;
|
|
|
|
|
SELECT @@ROWCOUNT');
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public override async Task Add_required_primitive_collection_to_existing_table()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_required_primitive_collection_to_existing_table();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Customers] ADD [Numbers] nvarchar(max) NOT NULL DEFAULT N'[]';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public override async Task Add_required_primitive_collection_with_custom_default_value_to_existing_table()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_required_primitive_collection_with_custom_default_value_to_existing_table();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Customers] ADD [Numbers] nvarchar(max) NOT NULL DEFAULT N'[1,2,3]';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public override async Task Add_required_primitive_collection_with_custom_default_value_sql_to_existing_table()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_required_primitive_collection_with_custom_default_value_sql_to_existing_table_core("N'[3, 2, 1]'");
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Customers] ADD [Numbers] nvarchar(max) NOT NULL DEFAULT (N'[3, 2, 1]');
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact(Skip = "issue #33038")]
|
|
|
|
|
public override async Task Add_required_primitive_collection_with_custom_converter_to_existing_table()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_required_primitive_collection_with_custom_converter_to_existing_table();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Customers] ADD [Numbers] nvarchar(max) NOT NULL DEFAULT N'nothing';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public override async Task Add_required_primitive_collection_with_custom_converter_and_custom_default_value_to_existing_table()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_required_primitive_collection_with_custom_converter_and_custom_default_value_to_existing_table();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Customers] ADD [Numbers] nvarchar(max) NOT NULL DEFAULT N'some numbers';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public override async Task Add_optional_primitive_collection_to_existing_table()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_optional_primitive_collection_to_existing_table();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Customers] ADD [Numbers] nvarchar(max) NULL;
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public override async Task Create_table_with_required_primitive_collection()
|
|
|
|
|
{
|
|
|
|
|
await base.Create_table_with_required_primitive_collection();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
CREATE TABLE [Customers] (
|
|
|
|
|
[Id] int NOT NULL IDENTITY,
|
|
|
|
|
[Name] nvarchar(max) NULL,
|
|
|
|
|
[Numbers] nvarchar(max) NOT NULL,
|
|
|
|
|
CONSTRAINT [PK_Customers] PRIMARY KEY ([Id])
|
|
|
|
|
);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public override async Task Create_table_with_optional_primitive_collection()
|
|
|
|
|
{
|
|
|
|
|
await base.Create_table_with_optional_primitive_collection();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
CREATE TABLE [Customers] (
|
|
|
|
|
[Id] int NOT NULL IDENTITY,
|
|
|
|
|
[Name] nvarchar(max) NULL,
|
|
|
|
|
[Numbers] nvarchar(max) NULL,
|
|
|
|
|
CONSTRAINT [PK_Customers] PRIMARY KEY ([Id])
|
|
|
|
|
);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public override async Task Create_table_with_complex_type_with_required_properties_on_derived_entity_in_TPH()
|
|
|
|
|
{
|
|
|
|
|
await base.Create_table_with_complex_type_with_required_properties_on_derived_entity_in_TPH();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
CREATE TABLE [Contacts] (
|
|
|
|
|
[Id] int NOT NULL IDENTITY,
|
|
|
|
|
[Discriminator] nvarchar(8) NOT NULL,
|
|
|
|
|
[Name] nvarchar(max) NULL,
|
|
|
|
|
[Number] int NULL,
|
|
|
|
|
[MyComplex_Prop] nvarchar(max) NULL,
|
|
|
|
|
[MyComplex_MyNestedComplex_Bar] datetime2 NULL,
|
|
|
|
|
[MyComplex_MyNestedComplex_Foo] int NULL,
|
|
|
|
|
CONSTRAINT [PK_Contacts] PRIMARY KEY ([Id])
|
|
|
|
|
);
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public override async Task Add_required_primitve_collection_to_existing_table()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_required_primitve_collection_to_existing_table();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Customers] ADD [Numbers] nvarchar(max) NOT NULL DEFAULT N'[]';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public override async Task Add_required_primitve_collection_with_custom_default_value_to_existing_table()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_required_primitve_collection_with_custom_default_value_to_existing_table();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Customers] ADD [Numbers] nvarchar(max) NOT NULL DEFAULT N'[1,2,3]';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public override async Task Add_required_primitve_collection_with_custom_default_value_sql_to_existing_table()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_required_primitve_collection_with_custom_default_value_sql_to_existing_table_core("N'[3, 2, 1]'");
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Customers] ADD [Numbers] nvarchar(max) NOT NULL DEFAULT (N'[3, 2, 1]');
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact(Skip = "issue #33038")]
|
|
|
|
|
public override async Task Add_required_primitve_collection_with_custom_converter_to_existing_table()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_required_primitve_collection_with_custom_converter_to_existing_table();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Customers] ADD [Numbers] nvarchar(max) NOT NULL DEFAULT N'nothing';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConditionalFact]
|
|
|
|
|
public override async Task Add_required_primitve_collection_with_custom_converter_and_custom_default_value_to_existing_table()
|
|
|
|
|
{
|
|
|
|
|
await base.Add_required_primitve_collection_with_custom_converter_and_custom_default_value_to_existing_table();
|
|
|
|
|
|
|
|
|
|
AssertSql(
|
|
|
|
|
"""
|
|
|
|
|
ALTER TABLE [Customers] ADD [Numbers] nvarchar(max) NOT NULL DEFAULT N'some numbers';
|
|
|
|
|
""");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override string NonDefaultCollation
|
|
|
|
|
=> _nonDefaultCollation ??= GetDatabaseCollation() == "German_PhoneBook_CI_AS"
|
|
|
|
|
? "French_CI_AS"
|
|
|
|
|
: "German_PhoneBook_CI_AS";
|
|
|
|
|
|
|
|
|
|
private string? _nonDefaultCollation;
|
|
|
|
|
|
|
|
|
|
private string? GetDatabaseCollation()
|
|
|
|
|
{
|
|
|
|
|
using var ctx = CreateContext();
|
|
|
|
|
var connection = ctx.Database.GetDbConnection();
|
|
|
|
|
using var command = connection.CreateCommand();
|
|
|
|
|
|
|
|
|
|
command.CommandText = $@"
|
|
|
|
|
SELECT collation_name
|
|
|
|
|
FROM sys.databases
|
|
|
|
|
WHERE name = '{connection.Database}';";
|
|
|
|
|
|
|
|
|
|
return command.ExecuteScalar() is string collation
|
|
|
|
|
? collation
|
|
|
|
|
: null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class MigrationsJetFixture : MigrationsFixtureBase
|
|
|
|
|
{
|
|
|
|
|
protected override string StoreName
|
|
|
|
|
=> nameof(MigrationsJetTest);
|
|
|
|
|
|
|
|
|
|
protected override ITestStoreFactory TestStoreFactory
|
|
|
|
|
=> JetTestStoreFactory.Instance;
|
|
|
|
|
|
|
|
|
|
public override RelationalTestHelpers TestHelpers
|
|
|
|
|
=> JetTestHelpers.Instance;
|
|
|
|
|
|
|
|
|
|
protected override IServiceCollection AddServices(IServiceCollection serviceCollection)
|
|
|
|
|
=> base.AddServices(serviceCollection)
|
|
|
|
|
.AddScoped<IDatabaseModelFactory, JetDatabaseModelFactory>();
|
|
|
|
|
}
|
|
|
|
|
}
|