You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
EntityFrameworkCore.Jet/test/EFCore.Jet.FunctionalTests/JetMigrationSqlGeneratorTes...

2064 lines
70 KiB
C#

// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using EntityFrameworkCore.Jet.FunctionalTests.TestUtilities;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Migrations.Operations;
using EntityFrameworkCore.Jet.Internal;
using EntityFrameworkCore.Jet.Metadata;
using EntityFrameworkCore.Jet.Metadata.Internal;
using EntityFrameworkCore.Jet.Migrations.Operations;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.TestUtilities;
using Xunit;
// ReSharper disable InconsistentNaming
namespace EntityFrameworkCore.Jet.FunctionalTests
{
public class JetMigrationSqlGeneratorTest : MigrationSqlGeneratorTestBase
{
public override void CreateTableOperation()
{
base.CreateTableOperation();
AssertSql(
$@"CREATE TABLE `People` (
`Id` int NOT NULL,
`EmployerId` int NULL,
`SSN` char(11) NULL,
PRIMARY KEY (`Id`),
UNIQUE (`SSN`),
CHECK (SSN > 0),
FOREIGN KEY (`EmployerId`) REFERENCES `Companies` (`Id`)
);
EXEC sp_addextendedproperty 'MS_Description', 'Table comment', 'SCHEMA', 'dbo', 'TABLE', 'People';
EXEC sp_addextendedproperty 'MS_Description', 'Employer ID comment', 'SCHEMA', 'dbo', 'TABLE', 'People', 'COLUMN', 'EmployerId';
");
}
[ConditionalFact]
public void CreateTableOperation_default_schema_with_comments()
{
Generate(
new CreateTableOperation
{
Name = "People",
Columns =
{
new AddColumnOperation
{
Name = "Id",
Table = "People",
ClrType = typeof(int),
IsNullable = false,
Comment = "ID comment"
},
new AddColumnOperation
{
Name = "Name",
Table = "People",
ClrType = typeof(string),
IsNullable = false,
Comment = "Name comment"
}
},
Comment = "Table comment"
});
AssertSql(
$@"CREATE TABLE `People` (
`Id` int NOT NULL,
`Name` nvarchar(max) NOT NULL
);
DECLARE @defaultSchema AS sysname;
SET @defaultSchema = SCHEMA_NAME();
EXEC sp_addextendedproperty 'MS_Description', 'Table comment', 'SCHEMA', @defaultSchema, 'TABLE', 'People';
EXEC sp_addextendedproperty 'MS_Description', 'ID comment', 'SCHEMA', @defaultSchema, 'TABLE', 'People', 'COLUMN', 'Id';
EXEC sp_addextendedproperty 'MS_Description', 'Name comment', 'SCHEMA', @defaultSchema, 'TABLE', 'People', 'COLUMN', 'Name';
");
}
[ConditionalFact]
public void CreateTableOperation_default_schema_with_column_comments()
{
Generate(
new CreateTableOperation
{
Name = "People",
Columns =
{
new AddColumnOperation
{
Name = "Id",
Table = "People",
ClrType = typeof(int),
IsNullable = false,
Comment = "ID comment"
},
new AddColumnOperation
{
Name = "Name",
Table = "People",
ClrType = typeof(string),
IsNullable = false,
Comment = "Name comment"
}
}
});
AssertSql(
$@"CREATE TABLE `People` (
`Id` int NOT NULL,
`Name` nvarchar(max) NOT NULL
);
DECLARE @defaultSchema AS sysname;
SET @defaultSchema = SCHEMA_NAME();
EXEC sp_addextendedproperty 'MS_Description', 'ID comment', 'SCHEMA', @defaultSchema, 'TABLE', 'People', 'COLUMN', 'Id';
EXEC sp_addextendedproperty 'MS_Description', 'Name comment', 'SCHEMA', @defaultSchema, 'TABLE', 'People', 'COLUMN', 'Name';
");
}
public override void CreateTableOperation_no_key()
{
base.CreateTableOperation_no_key();
AssertSql(
$@"CREATE TABLE `Anonymous` (
`Value` int NOT NULL
);
");
}
public override void CreateIndexOperation_with_filter_where_clause()
{
base.CreateIndexOperation_with_filter_where_clause();
AssertSql(
$@"CREATE INDEX `IX_People_Name` ON `People` (`Name`) WHERE `Name` IS NOT NULL;
");
}
public override void CreateIndexOperation_with_filter_where_clause_and_is_unique()
{
base.CreateIndexOperation_with_filter_where_clause_and_is_unique();
AssertSql(
$@"CREATE UNIQUE INDEX `IX_People_Name` ON `People` (`Name`) WHERE `Name` IS NOT NULL AND <> '';
");
}
[ConditionalFact]
public void AlterTableOperation_with_new_comment()
{
Generate(
new AlterTableOperation
{
Name = "People",
Schema = null,
Comment = "My Comment"
});
AssertSql(
$@"EXEC sp_addextendedproperty 'MS_Description', 'My Comment', 'SCHEMA', 'dbo', 'TABLE', 'People';
");
}
[ConditionalFact]
public void AlterTableOperation_with_different_comment_to_existing()
{
Generate(
modelBuilder => modelBuilder
.HasAnnotation(CoreAnnotationNames.ProductVersion, "1.1.0")
.Entity(
"Person", x =>
{
x.HasComment("My Comment");
}),
new AlterTableOperation
{
Schema = null,
Name = "People",
Comment = "My Comment 2",
OldTable = new TableOperation { Comment = "My Comment" }
});
AssertSql(
$@"EXEC sp_dropextendedproperty 'MS_Description', 'SCHEMA', 'dbo', 'TABLE', 'People';
EXEC sp_addextendedproperty 'MS_Description', 'My Comment 2', 'SCHEMA', 'dbo', 'TABLE', 'People';
");
}
[ConditionalFact]
public void AlterTableOperation_removing_comment()
{
Generate(
modelBuilder => modelBuilder
.HasAnnotation(CoreAnnotationNames.ProductVersion, "1.1.0")
.Entity(
"Person", x =>
{
x.HasComment("My Comment");
}),
new AlterTableOperation
{
Schema = null,
Name = "People",
OldTable = new TableOperation { Comment = "My Comment" }
});
AssertSql(
$@"EXEC sp_dropextendedproperty 'MS_Description', 'SCHEMA', 'dbo', 'TABLE', 'People';
");
}
[ConditionalFact]
public virtual void AddColumnOperation_with_computedSql()
{
Generate(
new AddColumnOperation
{
Table = "People",
Name = "FullName",
ClrType = typeof(string),
ComputedColumnSql = "FirstName + ' ' + LastName"
});
AssertSql(
$@"ALTER TABLE `People` ADD `FullName` AS FirstName + ' ' + LastName;
");
}
[ConditionalFact]
public void AddColumnOperation_with_computed_column_SQL()
{
Generate(
new AddColumnOperation
{
Table = "People",
Name = "Birthday",
ClrType = typeof(DateTime),
ColumnType = "date",
IsNullable = true,
ComputedColumnSql = "CURRENT_TIMESTAMP"
});
AssertSql(
$@"ALTER TABLE `People` ADD `Birthday` AS CURRENT_TIMESTAMP;
");
}
[ConditionalFact]
public virtual void AddColumnOperation_identity()
{
Generate(
new AddColumnOperation
{
Table = "People",
Name = "Id",
ClrType = typeof(int),
ColumnType = "int",
DefaultValue = 0,
IsNullable = false,
[JetAnnotationNames.Identity] = "1, 1"
});
AssertSql(
$@"ALTER TABLE `People` ADD `Id` int NOT NULL IDENTITY;
");
}
[ConditionalFact]
public virtual void AddColumnOperation_identity_legacy()
{
Generate(
new AddColumnOperation
{
Table = "People",
Name = "Id",
ClrType = typeof(int),
ColumnType = "int",
DefaultValue = 0,
IsNullable = false,
[JetAnnotationNames.ValueGenerationStrategy] =
JetValueGenerationStrategy.IdentityColumn
});
AssertSql(
$@"ALTER TABLE `People` ADD `Id` int NOT NULL IDENTITY;
");
}
[ConditionalFact]
public virtual void AddColumnOperation_identity_seed_increment()
{
Generate(
new AddColumnOperation
{
Table = "People",
Name = "Id",
ClrType = typeof(int),
ColumnType = "int",
DefaultValue = 0,
IsNullable = false,
[JetAnnotationNames.Identity] = "100,5"
});
AssertSql(
$@"ALTER TABLE `People` ADD `Id` int NOT NULL IDENTITY(100,5);
");
}
public override void AddColumnOperation_without_column_type()
{
base.AddColumnOperation_without_column_type();
AssertSql(
$@"ALTER TABLE `People` ADD `Alias` nvarchar(max) NOT NULL;
");
}
public override void AddColumnOperation_with_unicode_no_model()
{
base.AddColumnOperation_with_unicode_no_model();
AssertSql(
$@"ALTER TABLE `Person` ADD `Name` varchar(max) NULL;
");
}
public override void AddColumnOperation_with_maxLength()
{
base.AddColumnOperation_with_maxLength();
AssertSql(
$@"ALTER TABLE `Person` ADD `Name` nvarchar(30) NULL;
");
}
[ConditionalFact]
public virtual void AddColumnOperation_datetime_with_defaultValue()
{
Generate(
new AddColumnOperation
{
Table = "People",
Schema = null,
Name = "Birthday",
ClrType = typeof(DateTime),
ColumnType = "datetime",
IsNullable = false,
DefaultValue = new DateTime(2019, 1, 1)
});
AssertSql(
$@"ALTER TABLE `People` ADD `Birthday` datetime NOT NULL DEFAULT #01/01/2019 00:00:00#;
");
}
[ConditionalFact]
public virtual void AddColumnOperation_smalldatetime_with_defaultValue()
{
Generate(
new AddColumnOperation
{
Table = "People",
Schema = null,
Name = "Birthday",
ClrType = typeof(DateTime),
ColumnType = "smalldatetime",
IsNullable = false,
DefaultValue = new DateTime(2019, 1, 1)
});
AssertSql(
$@"ALTER TABLE `People` ADD `Birthday` smalldatetime NOT NULL DEFAULT '2019-01-01T00:00:00';
");
}
public override void AddColumnOperation_with_maxLength_overridden()
{
base.AddColumnOperation_with_maxLength_overridden();
AssertSql(
$@"ALTER TABLE `Person` ADD `Name` nvarchar(32) NULL;
");
}
public override void AddColumnOperation_with_maxLength_on_derived()
{
base.AddColumnOperation_with_maxLength_on_derived();
AssertSql(
$@"ALTER TABLE `Person` ADD `Name` nvarchar(30) NULL;
");
}
public override void AddColumnOperation_with_ansi()
{
base.AddColumnOperation_with_ansi();
AssertSql(
$@"ALTER TABLE `Person` ADD `Name` varchar(max) NULL;
");
}
public override void AddColumnOperation_with_unicode_overridden()
{
base.AddColumnOperation_with_unicode_overridden();
AssertSql(
$@"ALTER TABLE `Person` ADD `Name` nvarchar(max) NULL;
");
}
public override void AddColumnOperation_with_shared_column()
{
base.AddColumnOperation_with_shared_column();
AssertSql(
$@"ALTER TABLE `Base` ADD `Foo` nvarchar(max) NULL;
");
}
[ConditionalFact]
public virtual void AddColumnOperation_with_rowversion_overridden()
{
Generate(
modelBuilder => modelBuilder.Entity("Person").Property<byte[]>("RowVersion"),
new AddColumnOperation
{
Table = "Person",
Name = "RowVersion",
ClrType = typeof(byte[]),
IsRowVersion = true,
IsNullable = true
});
AssertSql(
$@"ALTER TABLE `Person` ADD `RowVersion` rowversion NULL;
");
}
[ConditionalFact]
public virtual void AddColumnOperation_with_rowversion_no_model()
{
Generate(
new AddColumnOperation
{
Table = "Person",
Name = "RowVersion",
ClrType = typeof(byte[]),
IsRowVersion = true,
IsNullable = true
});
AssertSql(
$@"ALTER TABLE `Person` ADD `RowVersion` rowversion NULL;
");
}
[ConditionalFact]
public virtual void AddColumnOperation_with_comment()
{
Generate(
new AddColumnOperation
{
Table = "People",
Name = "FullName",
ClrType = typeof(string),
Comment = "My comment"
});
AssertSql(
$@"ALTER TABLE `People` ADD `FullName` nvarchar(max) NOT NULL;
DECLARE @defaultSchema AS sysname;
SET @defaultSchema = SCHEMA_NAME();
EXEC sp_addextendedproperty 'MS_Description', 'My comment', 'SCHEMA', @defaultSchema, 'TABLE', 'People', 'COLUMN', 'FullName';
");
}
[ConditionalFact]
public virtual void AddColumnOperation_with_comment_non_default_schema()
{
Generate(
new AddColumnOperation
{
Schema = "my",
Table = "People",
Name = "FullName",
ClrType = typeof(string),
Comment = "My comment"
});
AssertSql(
$@"ALTER TABLE `my`.`People` ADD `FullName` nvarchar(max) NOT NULL;
EXEC sp_addextendedproperty 'MS_Description', 'My comment', 'SCHEMA', 'my', 'TABLE', 'People', 'COLUMN', 'FullName';
");
}
[ConditionalFact]
public virtual void AddPrimaryKeyOperation_nonclustered()
{
Generate(
new AddPrimaryKeyOperation
{
Table = "People",
Columns = new[] { "Id" },
});
AssertSql(
$@"ALTER TABLE `People` ADD PRIMARY KEY NONCLUSTERED (`Id`);
");
}
public override void AlterColumnOperation()
{
base.AlterColumnOperation();
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('`People`') AND `c`.`name` = 'LuckyNumber');
IF @var0 IS NOT NULL EXEC('ALTER TABLE `People` DROP CONSTRAINT [' + @var0 + '];');
ALTER TABLE `People` ALTER COLUMN `LuckyNumber` int NOT NULL;
ALTER TABLE `People` ADD DEFAULT 7 FOR `LuckyNumber`;
");
}
public override void AlterColumnOperation_without_column_type()
{
base.AlterColumnOperation_without_column_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('`People`') AND `c`.`name` = 'LuckyNumber');
IF @var0 IS NOT NULL EXEC('ALTER TABLE `People` DROP CONSTRAINT [' + @var0 + '];');
ALTER TABLE `People` ALTER COLUMN `LuckyNumber` int NOT NULL;
");
}
[ConditionalFact]
public virtual void AlterColumnOperation_with_identity()
{
Generate(
new AlterColumnOperation
{
Table = "People",
Name = "Id",
ClrType = typeof(int),
[JetAnnotationNames.Identity] = "1, 1"
});
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('`People`') AND `c`.`name` = 'Id');
IF @var0 IS NOT NULL EXEC('ALTER TABLE `People` DROP CONSTRAINT [' + @var0 + '];');
ALTER TABLE `People` ALTER COLUMN `Id` int NOT NULL;
");
}
[ConditionalFact]
public virtual void AlterColumnOperation_with_identity_legacy()
{
Generate(
new AlterColumnOperation
{
Table = "People",
Name = "Id",
ClrType = typeof(int),
[JetAnnotationNames.ValueGenerationStrategy] =
JetValueGenerationStrategy.IdentityColumn
});
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('`People`') AND `c`.`name` = 'Id');
IF @var0 IS NOT NULL EXEC('ALTER TABLE `People` DROP CONSTRAINT [' + @var0 + '];');
ALTER TABLE `People` ALTER COLUMN `Id` int NOT NULL;
");
}
[ConditionalFact]
public void AlterColumnOperation_computed()
{
Generate(
new AlterColumnOperation
{
Table = "People",
Name = "FullName",
ClrType = typeof(string),
ComputedColumnSql = "`FirstName` + ' ' + `LastName`"
});
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('`People`') AND `c`.`name` = 'FullName');
IF @var0 IS NOT NULL EXEC('ALTER TABLE `People` DROP CONSTRAINT [' + @var0 + '];');
ALTER TABLE `People` DROP COLUMN `FullName`;
ALTER TABLE `People` ADD `FullName` AS `FirstName` + ' ' + `LastName`;
");
}
[ConditionalFact]
public virtual void AlterColumnOperation_computed_with_index()
{
Generate(
modelBuilder => modelBuilder
.HasAnnotation(CoreAnnotationNames.ProductVersion, "1.1.0")
.Entity(
"Person", x =>
{
x.Property<string>("FullName").HasComputedColumnSql("`FirstName` + ' ' + `LastName`");
x.HasKey("FullName");
x.HasIndex("FullName");
}),
new AlterColumnOperation
{
Table = "Person",
Name = "FullName",
ClrType = typeof(string),
ComputedColumnSql = "`FirstName` + ' ' + `LastName`",
OldColumn = new ColumnOperation { ClrType = typeof(string), ComputedColumnSql = "`LastName` + ', ' + `FirstName`" }
});
AssertSql(
$@"DROP INDEX `IX_Person_FullName` ON `Person`;
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('`Person`') AND `c`.`name` = 'FullName');
IF @var0 IS NOT NULL EXEC('ALTER TABLE `Person` DROP CONSTRAINT [' + @var0 + '];');
ALTER TABLE `Person` DROP COLUMN `FullName`;
ALTER TABLE `Person` ADD `FullName` AS `FirstName` + ' ' + `LastName`;
CREATE INDEX `IX_Person_FullName` ON `Person` (`FullName`);
");
}
[ConditionalFact]
public virtual void AlterColumnOperation_memoryOptimized_with_index()
{
Generate(
modelBuilder => modelBuilder
.HasAnnotation(CoreAnnotationNames.ProductVersion, "1.1.0")
.Entity(
"Person", x =>
{
x.Property<string>("Name");
x.HasKey("Name");
x.HasIndex("Name");
}),
new AlterColumnOperation
{
Table = "Person",
Name = "Name",
ClrType = typeof(string),
MaxLength = 30,
OldColumn = new ColumnOperation { ClrType = typeof(string) }
});
AssertSql(
$@"ALTER TABLE `Person` DROP INDEX `IX_Person_Name`;
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('`Person`') AND `c`.`name` = 'Name');
IF @var0 IS NOT NULL EXEC('ALTER TABLE `Person` DROP CONSTRAINT [' + @var0 + '];');
ALTER TABLE `Person` ALTER COLUMN `Name` nvarchar(30) NOT NULL;
ALTER TABLE `Person` ADD INDEX `IX_Person_Name` NONCLUSTERED (`Name`);
");
}
[ConditionalFact]
public virtual void AlterColumnOperation_with_index_no_narrowing()
{
Generate(
modelBuilder => modelBuilder
.HasAnnotation(CoreAnnotationNames.ProductVersion, "1.1.0")
.Entity(
"Person", x =>
{
x.Property<string>("Name");
x.HasKey("Name");
x.HasIndex("Name");
}),
new AlterColumnOperation
{
Table = "Person",
Name = "Name",
ClrType = typeof(string),
IsNullable = true,
OldColumn = new ColumnOperation { ClrType = typeof(string), IsNullable = false }
});
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('`Person`') AND `c`.`name` = 'Name');
IF @var0 IS NOT NULL EXEC('ALTER TABLE `Person` DROP CONSTRAINT [' + @var0 + '];');
ALTER TABLE `Person` ALTER COLUMN `Name` nvarchar(450) NULL;
");
}
[ConditionalFact]
public virtual void AlterColumnOperation_with_index()
{
Generate(
modelBuilder => modelBuilder
.HasAnnotation(CoreAnnotationNames.ProductVersion, "1.1.0")
.Entity(
"Person", x =>
{
x.Property<string>("Name").HasMaxLength(30);
x.HasKey("Name");
x.HasIndex("Name");
}),
new AlterColumnOperation
{
Table = "Person",
Name = "Name",
ClrType = typeof(string),
MaxLength = 30,
IsNullable = true,
OldColumn = new ColumnOperation { ClrType = typeof(string), IsNullable = true }
});
AssertSql(
$@"DROP INDEX `IX_Person_Name` ON `Person`;
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('`Person`') AND `c`.`name` = 'Name');
IF @var0 IS NOT NULL EXEC('ALTER TABLE `Person` DROP CONSTRAINT [' + @var0 + '];');
ALTER TABLE `Person` ALTER COLUMN `Name` nvarchar(30) NULL;
CREATE INDEX `IX_Person_Name` ON `Person` (`Name`);
");
}
[ConditionalFact]
public virtual void AlterColumnOperation_with_index_included_column()
{
Generate(
modelBuilder => modelBuilder
.HasAnnotation(CoreAnnotationNames.ProductVersion, "1.1.0")
.Entity(
"Person", x =>
{
x.Property<string>("Name").HasMaxLength(30);
x.Property<string>("FirstName");
x.Property<string>("LastName");
x.HasKey("Name");
}),
new AlterColumnOperation
{
Table = "Person",
Name = "Name",
ClrType = typeof(string),
MaxLength = 30,
IsNullable = true,
OldColumn = new ColumnOperation { ClrType = typeof(string), IsNullable = true }
});
AssertSql(
$@"DROP INDEX `IX_Person_FirstName_LastName` ON `Person`;
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('`Person`') AND `c`.`name` = 'Name');
IF @var0 IS NOT NULL EXEC('ALTER TABLE `Person` DROP CONSTRAINT [' + @var0 + '];');
ALTER TABLE `Person` ALTER COLUMN `Name` nvarchar(30) NULL;
CREATE INDEX `IX_Person_FirstName_LastName` ON `Person` (`FirstName`, `LastName`) INCLUDE (`Name`);
");
}
[ConditionalFact]
public virtual void AlterColumnOperation_with_index_no_included()
{
Generate(
modelBuilder => modelBuilder
.HasAnnotation(CoreAnnotationNames.ProductVersion, "1.1.0")
.Entity(
"Person", x =>
{
x.Property<string>("Name").HasMaxLength(30);
x.Property<string>("FirstName");
x.Property<string>("LastName");
x.HasIndex("FirstName", "LastName");
}),
new AlterColumnOperation
{
Table = "Person",
Name = "Name",
ClrType = typeof(string),
MaxLength = 30,
IsNullable = true,
OldColumn = new ColumnOperation { ClrType = typeof(string), IsNullable = true }
});
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('`Person`') AND `c`.`name` = 'Name');
IF @var0 IS NOT NULL EXEC('ALTER TABLE `Person` DROP CONSTRAINT [' + @var0 + '];');
ALTER TABLE `Person` ALTER COLUMN `Name` nvarchar(30) NULL;
");
}
[ConditionalFact]
public virtual void AlterColumnOperation_with_index_no_oldColumn()
{
Generate(
modelBuilder => modelBuilder
.HasAnnotation(CoreAnnotationNames.ProductVersion, "1.0.0-rtm")
.Entity(
"Person", x =>
{
x.Property<string>("Name").HasMaxLength(30);
x.HasIndex("Name");
}),
new AlterColumnOperation
{
Table = "Person",
Name = "Name",
ClrType = typeof(string),
MaxLength = 30,
IsNullable = true,
OldColumn = new ColumnOperation()
});
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('`Person`') AND `c`.`name` = 'Name');
IF @var0 IS NOT NULL EXEC('ALTER TABLE `Person` DROP CONSTRAINT [' + @var0 + '];');
ALTER TABLE `Person` ALTER COLUMN `Name` nvarchar(30) NULL;
");
}
[ConditionalFact]
public virtual void AlterColumnOperation_with_composite_index()
{
Generate(
modelBuilder => modelBuilder
.HasAnnotation(CoreAnnotationNames.ProductVersion, "1.1.0")
.Entity(
"Person", x =>
{
x.Property<string>("FirstName").IsRequired();
x.Property<string>("LastName");
x.HasKey("LastName");
x.HasIndex("FirstName", "LastName");
}),
new AlterColumnOperation
{
Table = "Person",
Name = "FirstName",
ClrType = typeof(string),
IsNullable = false,
OldColumn = new ColumnOperation { ClrType = typeof(string), IsNullable = true }
});
AssertSql(
$@"DROP INDEX `IX_Person_FirstName_LastName` ON `Person`;
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('`Person`') AND `c`.`name` = 'FirstName');
IF @var0 IS NOT NULL EXEC('ALTER TABLE `Person` DROP CONSTRAINT [' + @var0 + '];');
ALTER TABLE `Person` ALTER COLUMN `FirstName` nvarchar(450) NOT NULL;
CREATE INDEX `IX_Person_FirstName_LastName` ON `Person` (`FirstName`, `LastName`);
");
}
[ConditionalFact]
public virtual void AlterColumnOperation_with_added_index()
{
Generate(
modelBuilder => modelBuilder
.HasAnnotation(CoreAnnotationNames.ProductVersion, "1.1.0")
.Entity(
"Person", x =>
{
x.Property<string>("Name").HasMaxLength(30);
x.HasIndex("Name");
}),
new AlterColumnOperation
{
Table = "Person",
Name = "Name",
ClrType = typeof(string),
MaxLength = 30,
IsNullable = true,
OldColumn = new ColumnOperation { ClrType = typeof(string), IsNullable = true }
},
new CreateIndexOperation
{
Name = "IX_Person_Name",
Table = "Person",
Columns = new[] { "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('`Person`') AND `c`.`name` = 'Name');
IF @var0 IS NOT NULL EXEC('ALTER TABLE `Person` DROP CONSTRAINT [' + @var0 + '];');
ALTER TABLE `Person` ALTER COLUMN `Name` nvarchar(30) NULL;
GO
CREATE INDEX `IX_Person_Name` ON `Person` (`Name`);
");
}
[ConditionalFact]
public virtual void AlterColumnOperation_with_added_online_index()
{
Generate(
modelBuilder => modelBuilder
.HasAnnotation(CoreAnnotationNames.ProductVersion, "1.1.0")
.Entity(
"Person", x =>
{
x.Property<string>("Name").HasMaxLength(30);
}),
new AlterColumnOperation
{
Table = "Person",
Name = "Name",
ClrType = typeof(string),
MaxLength = 30,
IsNullable = true,
OldColumn = new ColumnOperation { ClrType = typeof(string), IsNullable = true }
},
new CreateIndexOperation
{
Name = "IX_Person_Name",
Table = "Person",
Columns = new[] { "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('`Person`') AND `c`.`name` = 'Name');
IF @var0 IS NOT NULL EXEC('ALTER TABLE `Person` DROP CONSTRAINT [' + @var0 + '];');
ALTER TABLE `Person` ALTER COLUMN `Name` nvarchar(30) NULL;
GO
CREATE INDEX `IX_Person_Name` ON `Person` (`Name`) WITH (ONLINE = ON);
");
}
[ConditionalFact]
public virtual void AlterColumnOperation_identity()
{
Generate(
modelBuilder => modelBuilder.HasAnnotation(CoreAnnotationNames.ProductVersion, "1.1.0"),
new AlterColumnOperation
{
Table = "Person",
Name = "Id",
ClrType = typeof(long),
[JetAnnotationNames.Identity] = "1, 1",
OldColumn = new ColumnOperation { ClrType = typeof(int), [JetAnnotationNames.Identity] = "1, 1" }
});
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('`Person`') AND `c`.`name` = 'Id');
IF @var0 IS NOT NULL EXEC('ALTER TABLE `Person` DROP CONSTRAINT [' + @var0 + '];');
ALTER TABLE `Person` ALTER COLUMN `Id` bigint NOT NULL;
");
}
[ConditionalFact]
public virtual void AlterColumnOperation_identity_legacy()
{
Generate(
modelBuilder => modelBuilder.HasAnnotation(CoreAnnotationNames.ProductVersion, "1.1.0"),
new AlterColumnOperation
{
Table = "Person",
Name = "Id",
ClrType = typeof(long),
[JetAnnotationNames.ValueGenerationStrategy] = JetValueGenerationStrategy.IdentityColumn,
OldColumn = new ColumnOperation
{
ClrType = typeof(int),
[JetAnnotationNames.ValueGenerationStrategy] = JetValueGenerationStrategy.IdentityColumn
}
});
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('`Person`') AND `c`.`name` = 'Id');
IF @var0 IS NOT NULL EXEC('ALTER TABLE `Person` DROP CONSTRAINT [' + @var0 + '];');
ALTER TABLE `Person` ALTER COLUMN `Id` bigint NOT NULL;
");
}
[ConditionalFact]
public virtual void AlterColumnOperation_add_identity()
{
var ex = Assert.Throws<InvalidOperationException>(
() => Generate(
modelBuilder => modelBuilder.HasAnnotation(CoreAnnotationNames.ProductVersion, "1.1.0"),
new AlterColumnOperation
{
Table = "Person",
Name = "Id",
ClrType = typeof(int),
[JetAnnotationNames.Identity] = "1, 1",
OldColumn = new ColumnOperation { ClrType = typeof(int) }
}));
Assert.Equal(JetStrings.AlterIdentityColumn, ex.Message);
}
[ConditionalFact]
public virtual void AlterColumnOperation_add_identity_legacy()
{
var ex = Assert.Throws<InvalidOperationException>(
() => Generate(
modelBuilder => modelBuilder.HasAnnotation(CoreAnnotationNames.ProductVersion, "1.1.0"),
new AlterColumnOperation
{
Table = "Person",
Name = "Id",
ClrType = typeof(int),
[JetAnnotationNames.ValueGenerationStrategy] = JetValueGenerationStrategy.IdentityColumn,
OldColumn = new ColumnOperation { ClrType = typeof(int) }
}));
Assert.Equal(JetStrings.AlterIdentityColumn, ex.Message);
}
[ConditionalFact]
public virtual void AlterColumnOperation_remove_identity()
{
var ex = Assert.Throws<InvalidOperationException>(
() => Generate(
modelBuilder => modelBuilder.HasAnnotation(CoreAnnotationNames.ProductVersion, "1.1.0"),
new AlterColumnOperation
{
Table = "Person",
Name = "Id",
ClrType = typeof(int),
OldColumn = new ColumnOperation { ClrType = typeof(int), [JetAnnotationNames.Identity] = "1, 1" }
}));
Assert.Equal(JetStrings.AlterIdentityColumn, ex.Message);
}
[ConditionalFact]
public virtual void AlterColumnOperation_remove_identity_legacy()
{
var ex = Assert.Throws<InvalidOperationException>(
() => Generate(
modelBuilder => modelBuilder.HasAnnotation(CoreAnnotationNames.ProductVersion, "1.1.0"),
new AlterColumnOperation
{
Table = "Person",
Name = "Id",
ClrType = typeof(int),
OldColumn = new ColumnOperation
{
ClrType = typeof(int),
[JetAnnotationNames.ValueGenerationStrategy] = JetValueGenerationStrategy.IdentityColumn
}
}));
Assert.Equal(JetStrings.AlterIdentityColumn, ex.Message);
}
[ConditionalFact]
public void AlterColumnOperation_with_new_comment()
{
Generate(
new AlterColumnOperation
{
Table = "People",
Schema = null,
Name = "LuckyNumber",
ClrType = typeof(int),
ColumnType = "int",
IsNullable = false,
Comment = "My Comment"
});
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('`People`') AND `c`.`name` = 'LuckyNumber');
IF @var0 IS NOT NULL EXEC('ALTER TABLE `People` DROP CONSTRAINT [' + @var0 + '];');
ALTER TABLE `People` ALTER COLUMN `LuckyNumber` int NOT NULL;
EXEC sp_addextendedproperty 'MS_Description', 'My Comment', 'SCHEMA', 'dbo', 'TABLE', 'People', 'COLUMN', 'LuckyNumber';
");
}
[ConditionalFact]
public void AlterColumnOperation_with_different_comment_to_existing()
{
Generate(
modelBuilder => modelBuilder
.HasAnnotation(CoreAnnotationNames.ProductVersion, "1.1.0")
.Entity(
"Person", x =>
{
x.Property<string>("Name").HasComment("My Comment");
}),
new AlterColumnOperation
{
Table = "People",
Schema = null,
Name = "Name",
ClrType = typeof(string),
IsNullable = false,
Comment = "My Comment 2",
OldColumn = new ColumnOperation
{
ClrType = typeof(string),
IsNullable = true,
Comment = "My Comment"
}
});
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('`People`') AND `c`.`name` = 'Name');
IF @var0 IS NOT NULL EXEC('ALTER TABLE `People` DROP CONSTRAINT [' + @var0 + '];');
ALTER TABLE `People` ALTER COLUMN `Name` nvarchar(max) NOT NULL;
EXEC sp_dropextendedproperty 'MS_Description', 'SCHEMA', 'dbo', 'TABLE', 'People', 'COLUMN', 'Name';
EXEC sp_addextendedproperty 'MS_Description', 'My Comment 2', 'SCHEMA', 'dbo', 'TABLE', 'People', 'COLUMN', 'Name';
");
}
[ConditionalFact]
public void AlterColumnOperation_removing_comment()
{
Generate(
modelBuilder => modelBuilder
.HasAnnotation(CoreAnnotationNames.ProductVersion, "1.1.0")
.Entity(
"Person", x =>
{
x.Property<string>("Name").HasComment("My Comment");
}),
new AlterColumnOperation
{
Table = "People",
Schema = null,
Name = "Name",
ClrType = typeof(string),
IsNullable = false,
OldColumn = new ColumnOperation
{
ClrType = typeof(string),
IsNullable = true,
Comment = "My Comment"
}
});
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('`People`') AND `c`.`name` = 'Name');
IF @var0 IS NOT NULL EXEC('ALTER TABLE `People` DROP CONSTRAINT [' + @var0 + '];');
ALTER TABLE `People` ALTER COLUMN `Name` nvarchar(max) NOT NULL;
EXEC sp_dropextendedproperty 'MS_Description', 'SCHEMA', 'dbo', 'TABLE', 'People', 'COLUMN', 'Name';
");
}
[ConditionalFact]
public virtual void CreateDatabaseOperation()
{
Generate(
new JetCreateDatabaseOperation { Name = "Northwind" });
AssertSql(
$@"CREATE DATABASE `Northwind`;
GO
IF SERVERPROPERTY('EngineEdition') <> 5
BEGIN
ALTER DATABASE `Northwind` SET READ_COMMITTED_SNAPSHOT ON;
END;
");
}
[ConditionalFact]
public virtual void CreateDatabaseOperation_with_filename()
{
Generate(
new JetCreateDatabaseOperation { Name = "Narf.mdf" });
var expectedFile = Path.GetFullPath("Narf.mdf");
var expectedLog = Path.GetFullPath("Narf_log.ldf");
AssertSql(
$@"CREATE DATABASE `Northwind`
ON (NAME = 'Narf', FILENAME = '{expectedFile}')
LOG ON (NAME = 'Narf_log', FILENAME = '{expectedLog}');
GO
IF SERVERPROPERTY('EngineEdition') <> 5
BEGIN
ALTER DATABASE `Northwind` SET READ_COMMITTED_SNAPSHOT ON;
END;
");
}
[ConditionalFact]
public virtual void CreateDatabaseOperation_with_filename_and_datadirectory()
{
var baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
Generate(
new JetCreateDatabaseOperation { Name = "|DataDirectory|Narf.mdf" });
var expectedFile = Path.Combine(baseDirectory, "Narf.mdf");
var expectedLog = Path.Combine(baseDirectory, "Narf_log.ldf");
AssertSql(
$@"CREATE DATABASE `Northwind`
ON (NAME = 'Narf', FILENAME = '{expectedFile}')
LOG ON (NAME = 'Narf_log', FILENAME = '{expectedLog}');
GO
IF SERVERPROPERTY('EngineEdition') <> 5
BEGIN
ALTER DATABASE `Northwind` SET READ_COMMITTED_SNAPSHOT ON;
END;
");
}
[ConditionalFact]
public virtual void CreateDatabaseOperation_with_filename_and_custom_datadirectory()
{
var dataDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Data");
AppDomain.CurrentDomain.SetData("DataDirectory", dataDirectory);
Generate(
new JetCreateDatabaseOperation { Name = "|DataDirectory|Narf.mdf" });
AppDomain.CurrentDomain.SetData("DataDirectory", null);
var expectedFile = Path.Combine(dataDirectory, "Narf.mdf");
var expectedLog = Path.Combine(dataDirectory, "Narf_log.ldf");
AssertSql(
$@"CREATE DATABASE `Northwind`
ON (NAME = 'Narf', FILENAME = '{expectedFile}')
LOG ON (NAME = 'Narf_log', FILENAME = '{expectedLog}');
GO
IF SERVERPROPERTY('EngineEdition') <> 5
BEGIN
ALTER DATABASE `Northwind` SET READ_COMMITTED_SNAPSHOT ON;
END;
");
}
[ConditionalFact]
public virtual void AlterDatabaseOperation_memory_optimized()
{
Generate(
new AlterDatabaseOperation());
Assert.Contains(
"CONTAINS MEMORY_OPTIMIZED_DATA;",
Sql);
}
public override void CreateIndexOperation_nonunique()
{
base.CreateIndexOperation_nonunique();
AssertSql(
$@"CREATE INDEX `IX_People_Name` ON `People` (`Name`);
");
}
public override void CreateIndexOperation_unique()
{
base.CreateIndexOperation_unique();
AssertSql(
$@"CREATE UNIQUE INDEX `IX_People_Name` ON `People` (`FirstName`, `LastName`) WHERE `FirstName` IS NOT NULL AND `LastName` IS NOT NULL;
");
}
[ConditionalFact]
public virtual void CreateIndexOperation_unique_non_legacy()
{
Generate(
modelBuilder => modelBuilder.HasAnnotation(CoreAnnotationNames.ProductVersion, "2.0.0"),
new CreateIndexOperation
{
Name = "IX_People_Name",
Table = "People",
Schema = null,
Columns = new[] { "FirstName", "LastName" },
IsUnique = true
});
AssertSql(
$@"CREATE UNIQUE INDEX `IX_People_Name` ON `People` (`FirstName`, `LastName`);
");
}
[ConditionalFact]
public virtual void CreateIndexOperation_clustered()
{
Generate(
new CreateIndexOperation
{
Name = "IX_People_Name",
Table = "People",
Columns = new[] { "Name" },
});
AssertSql(
$@"CREATE CLUSTERED INDEX `IX_People_Name` ON `People` (`Name`);
");
}
[ConditionalFact]
public virtual void CreateIndexOperation_unique_clustered()
{
Generate(
new CreateIndexOperation
{
Name = "IX_People_Name",
Table = "People",
Columns = new[] { "Name" },
IsUnique = true,
});
AssertSql(
$@"CREATE UNIQUE CLUSTERED INDEX `IX_People_Name` ON `People` (`Name`);
");
}
[ConditionalFact]
public virtual void CreateIndexOperation_with_include()
{
Generate(
new CreateIndexOperation
{
Name = "IX_People_Name",
Table = "People",
Columns = new[] { "Name" },
[JetAnnotationNames.Include] = new[] { "FirstName", "LastName" }
});
AssertSql(
$@"CREATE INDEX `IX_People_Name` ON `People` (`Name`) INCLUDE (`FirstName`, `LastName`);
");
}
[ConditionalFact]
public virtual void CreateIndexOperation_with_include_and_filter()
{
Generate(
new CreateIndexOperation
{
Name = "IX_People_Name",
Table = "People",
Columns = new[] { "Name" },
Filter = "`Name` IS NOT NULL AND <> ''",
[JetAnnotationNames.Include] = new[] { "FirstName", "LastName" }
});
AssertSql(
$@"CREATE INDEX `IX_People_Name` ON `People` (`Name`) INCLUDE (`FirstName`, `LastName`) WHERE `Name` IS NOT NULL AND <> '';
");
}
[ConditionalFact]
public virtual void CreateIndexOperation_unique_with_include()
{
Generate(
new CreateIndexOperation
{
Name = "IX_People_Name",
Table = "People",
Columns = new[] { "Name" },
IsUnique = true,
[JetAnnotationNames.Include] = new[] { "FirstName", "LastName" }
});
AssertSql(
$@"CREATE UNIQUE INDEX `IX_People_Name` ON `People` (`Name`) INCLUDE (`FirstName`, `LastName`) WHERE `Name` IS NOT NULL;
");
}
[ConditionalFact]
public virtual void CreateIndexOperation_unique_with_include_and_filter()
{
Generate(
new CreateIndexOperation
{
Name = "IX_People_Name",
Table = "People",
Columns = new[] { "Name" },
IsUnique = true,
Filter = "`Name` IS NOT NULL AND <> ''",
[JetAnnotationNames.Include] = new[] { "FirstName", "LastName" }
});
AssertSql(
$@"CREATE UNIQUE INDEX `IX_People_Name` ON `People` (`Name`) INCLUDE (`FirstName`, `LastName`) WHERE `Name` IS NOT NULL AND <> '';
");
}
[ConditionalFact]
public virtual void CreateIndexOperation_unique_with_include_and_filter_online()
{
Generate(
new CreateIndexOperation
{
Name = "IX_People_Name",
Table = "People",
Columns = new[] { "Name" },
IsUnique = true,
Filter = "`Name` IS NOT NULL AND <> ''",
[JetAnnotationNames.Include] = new[] { "FirstName", "LastName" },
});
AssertSql(
$@"CREATE UNIQUE INDEX `IX_People_Name` ON `People` (`Name`) INCLUDE (`FirstName`, `LastName`) WHERE `Name` IS NOT NULL AND <> '' WITH (ONLINE = ON);
");
}
[ConditionalFact]
public virtual void CreateIndexOperation_unique_with_include_non_legacy()
{
Generate(
modelBuilder => modelBuilder.HasAnnotation(CoreAnnotationNames.ProductVersion, "2.0.0"),
new CreateIndexOperation
{
Name = "IX_People_Name",
Table = "People",
Columns = new[] { "Name" },
IsUnique = true,
[JetAnnotationNames.Include] = new[] { "FirstName", "LastName" }
});
AssertSql(
$@"CREATE UNIQUE INDEX `IX_People_Name` ON `People` (`Name`) INCLUDE (`FirstName`, `LastName`);
");
}
[ConditionalFact]
public virtual void CreateIndexOperation_unique_bound_null()
{
Generate(
modelBuilder => modelBuilder.Entity("People").Property<string>("Name"),
new CreateIndexOperation
{
Name = "IX_People_Name",
Table = "People",
Columns = new[] { "Name" },
IsUnique = true
});
AssertSql(
$@"CREATE UNIQUE INDEX `IX_People_Name` ON `People` (`Name`) WHERE `Name` IS NOT NULL;
");
}
[ConditionalFact]
public virtual void CreateIndexOperation_unique_bound_not_null()
{
Generate(
modelBuilder => modelBuilder.Entity(
"People", x =>
{
x.Property<string>("Name").IsRequired();
x.HasKey("Name");
}),
new CreateIndexOperation
{
Name = "IX_People_Name",
Table = "People",
Columns = new[] { "Name" },
IsUnique = true
});
AssertSql(
$@"CREATE UNIQUE INDEX `IX_People_Name` ON `People` (`Name`);
");
}
[ConditionalFact]
public virtual void CreateIndexOperation_memoryOptimized_unique_nullable()
{
Generate(
modelBuilder => modelBuilder.Entity(
"People", x =>
{
x.Property<int>("Id");
x.HasKey("Id");
}),
new CreateIndexOperation
{
Name = "IX_People_Name",
Schema = null,
Table = "People",
Columns = new[] { "Name" },
IsUnique = true
});
AssertSql(
$@"ALTER TABLE `People` ADD INDEX `IX_People_Name` (`Name`);
");
}
[ConditionalFact]
public virtual void CreateIndexOperation_memoryOptimized_unique_nullable_with_filter()
{
Generate(
modelBuilder => modelBuilder.Entity(
"People", x =>
{
x.Property<int>("Id");
x.HasKey("Id");
}),
new CreateIndexOperation
{
Name = "IX_People_Name",
Table = "People",
Columns = new[] { "Name" },
IsUnique = true,
Filter = "`Name` IS NOT NULL AND <> ''"
});
AssertSql(
$@"ALTER TABLE `People` ADD INDEX `IX_People_Name` (`Name`);
");
}
[ConditionalFact]
public virtual void CreateIndexOperation_memoryOptimized_unique_nonclustered_not_nullable()
{
Generate(
modelBuilder => modelBuilder.Entity(
"People", x =>
{
x.HasKey("Name");
}),
new CreateIndexOperation
{
Name = "IX_People_Name",
Table = "People",
Columns = new[] { "Name" },
IsUnique = true,
});
AssertSql(
$@"ALTER TABLE `People` ADD INDEX `IX_People_Name` UNIQUE NONCLUSTERED (`Name`);
");
}
[ConditionalFact]
public virtual void CreateSchemaOperation()
{
Generate(
new EnsureSchemaOperation { Name = "my" });
AssertSql(
$@"IF SCHEMA_ID('my') IS NULL EXEC('CREATE SCHEMA `my`;');
");
}
[ConditionalFact]
public virtual void CreateSchemaOperation_dbo()
{
Generate(
new EnsureSchemaOperation { Name = null });
AssertSql($@"");
}
public override void DropColumnOperation()
{
base.DropColumnOperation();
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('`People`') AND `c`.`name` = 'LuckyNumber');
IF @var0 IS NOT NULL EXEC('ALTER TABLE `People` DROP CONSTRAINT [' + @var0 + '];');
ALTER TABLE `People` DROP COLUMN `LuckyNumber`;
");
}
[ConditionalFact]
public virtual void DropDatabaseOperation()
{
Generate(
new JetDropDatabaseOperation { Name = "Northwind" });
AssertSql(
$@"IF SERVERPROPERTY('EngineEdition') <> 5
BEGIN
ALTER DATABASE `Northwind` SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
END;
GO
DROP DATABASE `Northwind`;
");
}
public override void DropIndexOperation()
{
base.DropIndexOperation();
AssertSql(
$@"DROP INDEX `IX_People_Name` ON `People`;
");
}
[ConditionalFact]
public virtual void DropIndexOperation_memoryOptimized()
{
Generate(
modelBuilder => modelBuilder.Entity(
"People", x =>
{
x.Property<int>("Id");
x.HasKey("Id");
}),
new DropIndexOperation { Name = "IX_People_Name", Table = "People" });
AssertSql(
$@"ALTER TABLE `People` DROP INDEX `IX_People_Name`;
");
}
[ConditionalFact]
public virtual void MoveSequenceOperation_legacy()
{
Generate(
new RenameSequenceOperation
{
Name = "EntityFrameworkHiLoSequence",
Schema = null,
NewSchema = "my"
});
AssertSql(
$@"ALTER SCHEMA `my` TRANSFER `EntityFrameworkHiLoSequence`;
");
}
[ConditionalFact]
public virtual void MoveSequenceOperation()
{
Generate(
modelBuilder => modelBuilder.HasAnnotation(CoreAnnotationNames.ProductVersion, "2.1.0"),
new RenameSequenceOperation
{
Name = "EntityFrameworkHiLoSequence",
Schema = null,
NewName = "EntityFrameworkHiLoSequence",
NewSchema = "my"
});
AssertSql(
$@"ALTER SCHEMA `my` TRANSFER `EntityFrameworkHiLoSequence`;
");
}
[ConditionalFact]
public virtual void MoveSequenceOperation_into_default()
{
Generate(
modelBuilder => modelBuilder.HasAnnotation(CoreAnnotationNames.ProductVersion, "2.1.0"),
new RenameSequenceOperation
{
Name = "EntityFrameworkHiLoSequence",
Schema = null,
NewName = "EntityFrameworkHiLoSequence"
});
AssertSql(
$@"DECLARE @defaultSchema sysname = SCHEMA_NAME();
EXEC('ALTER SCHEMA [' + @defaultSchema + '] TRANSFER `EntityFrameworkHiLoSequence`;');
");
}
[ConditionalFact]
public virtual void MoveTableOperation_legacy()
{
Generate(
new RenameTableOperation
{
Name = "People",
Schema = null,
NewSchema = "hr"
});
AssertSql(
$@"ALTER SCHEMA `hr` TRANSFER `People`;
");
}
[ConditionalFact]
public virtual void MoveTableOperation()
{
Generate(
modelBuilder => modelBuilder.HasAnnotation(CoreAnnotationNames.ProductVersion, "2.1.0"),
new RenameTableOperation
{
Name = "People",
Schema = null,
NewName = "People",
NewSchema = "hr"
});
AssertSql(
$@"ALTER SCHEMA `hr` TRANSFER `People`;
");
}
[ConditionalFact]
public virtual void MoveTableOperation_into_default()
{
Generate(
modelBuilder => modelBuilder.HasAnnotation(CoreAnnotationNames.ProductVersion, "2.1.0"),
new RenameTableOperation
{
Name = "People",
Schema = null,
NewName = "People"
});
AssertSql(
$@"DECLARE @defaultSchema sysname = SCHEMA_NAME();
EXEC('ALTER SCHEMA [' + @defaultSchema + '] TRANSFER `People`;');
");
}
[ConditionalFact]
public virtual void RenameColumnOperation()
{
Generate(
new RenameColumnOperation
{
Table = "People",
Schema = null,
Name = "Name",
NewName = "FullName"
});
AssertSql(
$@"EXEC sp_rename '`People`.`Name`', 'FullName', 'COLUMN';
");
}
[ConditionalFact]
public virtual void RenameIndexOperation()
{
Generate(
new RenameIndexOperation
{
Table = "People",
Schema = null,
Name = "IX_People_Name",
NewName = "IX_People_FullName"
});
AssertSql(
$@"EXEC sp_rename '`People`.`IX_People_Name`', 'IX_People_FullName', 'INDEX';
");
}
[ConditionalFact]
public virtual void RenameIndexOperations_throws_when_no_table()
{
var migrationBuilder = new MigrationBuilder("Jet");
migrationBuilder.RenameIndex(
name: "IX_OldIndex",
newName: "IX_NewIndex");
var ex = Assert.Throws<InvalidOperationException>(
() => Generate(migrationBuilder.Operations.ToArray()));
Assert.Equal(JetStrings.IndexTableRequired, ex.Message);
}
[ConditionalFact]
public virtual void RenameSequenceOperation_legacy()
{
Generate(
new RenameSequenceOperation
{
Name = "EntityFrameworkHiLoSequence",
Schema = null,
NewName = "MySequence"
});
AssertSql(
$@"EXEC sp_rename '`EntityFrameworkHiLoSequence`', 'MySequence';
");
}
[ConditionalFact]
public virtual void RenameSequenceOperation()
{
Generate(
modelBuilder => modelBuilder.HasAnnotation(CoreAnnotationNames.ProductVersion, "2.1.0"),
new RenameSequenceOperation
{
Name = "EntityFrameworkHiLoSequence",
Schema = null,
NewName = "MySequence",
NewSchema = null
});
AssertSql(
$@"EXEC sp_rename '`EntityFrameworkHiLoSequence`', 'MySequence';
");
}
[ConditionalFact]
public override void RenameTableOperation_legacy()
{
base.RenameTableOperation_legacy();
AssertSql(
$@"EXEC sp_rename '`People`', 'Person';
");
}
[ConditionalFact]
public override void RenameTableOperation()
{
base.RenameTableOperation();
AssertSql(
$@"EXEC sp_rename '`People`', 'Person';
");
}
[ConditionalFact]
public virtual void SqlOperation_handles_backslash()
{
Generate(
new SqlOperation { Sql = @"-- Multiline \" + EOL + "comment" });
AssertSql(
$@"-- Multiline comment
");
}
[ConditionalFact]
public virtual void SqlOperation_ignores_sequential_gos()
{
Generate(
new SqlOperation { Sql = "-- Ready set" + EOL + "GO" + EOL + "GO" });
AssertSql(
$@"-- Ready set
");
}
[ConditionalFact]
public virtual void SqlOperation_handles_go()
{
Generate(
new SqlOperation { Sql = "-- I" + EOL + "go" + EOL + "-- Too" });
AssertSql(
$@"-- I
GO
-- Too
");
}
[ConditionalFact]
public virtual void SqlOperation_handles_go_with_count()
{
Generate(
new SqlOperation { Sql = "-- I" + EOL + "GO 2" });
AssertSql(
$@"-- I
GO
-- I
");
}
[ConditionalFact]
public virtual void SqlOperation_ignores_non_go()
{
Generate(
new SqlOperation { Sql = "-- I GO 2" });
AssertSql(
$@"-- I GO 2
");
}
public override void InsertDataOperation()
{
base.InsertDataOperation();
AssertSql(
$@"IF EXISTS (SELECT * FROM `sys`.`identity_columns` WHERE `name` IN ('Id', 'Full Name') AND `object_id` = OBJECT_ID('`People`'))
SET IDENTITY_INSERT `People` ON;
INSERT INTO `People` (`Id`, `Full Name`)
VALUES (0, NULL),
(1, 'Daenerys Targaryen'),
(2, 'John Snow'),
(3, 'Arya Stark'),
(4, 'Harry Strickland');
IF EXISTS (SELECT * FROM `sys`.`identity_columns` WHERE `name` IN ('Id', 'Full Name') AND `object_id` = OBJECT_ID('`People`'))
SET IDENTITY_INSERT `People` OFF;
");
}
public override void DeleteDataOperation_simple_key()
{
base.DeleteDataOperation_simple_key();
// TODO remove rowcount
AssertSql(
$@"DELETE FROM `People`
WHERE `Id` = 2;
SELECT @@ROWCOUNT;
DELETE FROM `People`
WHERE `Id` = 4;
SELECT @@ROWCOUNT;
");
}
public override void DeleteDataOperation_composite_key()
{
base.DeleteDataOperation_composite_key();
// TODO remove rowcount
AssertSql(
$@"DELETE FROM `People`
WHERE `First Name` = 'Hodor' AND `Last Name` IS NULL;
SELECT @@ROWCOUNT;
DELETE FROM `People`
WHERE `First Name` = 'Daenerys' AND `Last Name` = 'Targaryen';
SELECT @@ROWCOUNT;
");
}
public override void UpdateDataOperation_simple_key()
{
base.UpdateDataOperation_simple_key();
// TODO remove rowcount
AssertSql(
$@"UPDATE `People` SET `Full Name` = 'Daenerys Stormborn'
WHERE `Id` = 1;
SELECT @@ROWCOUNT;
UPDATE `People` SET `Full Name` = 'Homeless Harry Strickland'
WHERE `Id` = 4;
SELECT @@ROWCOUNT;
");
}
public override void UpdateDataOperation_composite_key()
{
base.UpdateDataOperation_composite_key();
// TODO remove rowcount
AssertSql(
$@"UPDATE `People` SET `First Name` = 'Hodor'
WHERE `Id` = 0 AND `Last Name` IS NULL;
SELECT @@ROWCOUNT;
UPDATE `People` SET `First Name` = 'Harry'
WHERE `Id` = 4 AND `Last Name` = 'Strickland';
SELECT @@ROWCOUNT;
");
}
public override void UpdateDataOperation_multiple_columns()
{
base.UpdateDataOperation_multiple_columns();
// TODO remove rowcount
AssertSql(
$@"UPDATE `People` SET `First Name` = 'Daenerys', `Nickname` = 'Dany'
WHERE `Id` = 1;
SELECT @@ROWCOUNT;
UPDATE `People` SET `First Name` = 'Harry', `Nickname` = 'Homeless'
WHERE `Id` = 4;
SELECT @@ROWCOUNT;
");
}
public JetMigrationSqlGeneratorTest()
: base(JetTestHelpers.Instance)
{
}
}
}