// 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("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("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("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("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("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("Name").HasMaxLength(30); x.Property("FirstName"); x.Property("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("Name").HasMaxLength(30); x.Property("FirstName"); x.Property("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("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("FirstName").IsRequired(); x.Property("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("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("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( () => 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( () => 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( () => 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( () => 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("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("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("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("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("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("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("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( () => 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) { } } }