Beispiel #1
0
        protected virtual void GenerateEnumStatements(
            [NotNull] AlterDatabaseOperation operation,
            [NotNull] IModel model,
            [NotNull] MigrationCommandListBuilder builder)
        {
            foreach (var enumTypeToCreate in operation.Npgsql().PostgresEnums
                     .Where(ne => operation.Npgsql().OldPostgresEnums.All(oe => oe.Name != ne.Name)))
            {
                GenerateCreateEnum(enumTypeToCreate, model, builder);
            }

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

            // TODO: Some forms of enum alterations are actually supported...
            if (operation.Npgsql().PostgresEnums.FirstOrDefault(nr =>
                                                                operation.Npgsql().OldPostgresEnums.Any(or => or.Name == nr.Name)
                                                                ) is PostgresEnum enumTypeToAlter)
            {
                throw new NotSupportedException($"Altering enum type ${enumTypeToAlter} isn't supported.");
            }
        }
        protected virtual AlterDatabaseOperation PostFilterOperation(AlterDatabaseOperation operation)
        {
            HandleCharSetDelegation(operation, DelegationModes.ApplyToDatabases);

            ApplyCollationAnnotation(operation, (operation, collation) => operation.Collation ??= collation);
            ApplyCollationAnnotation(operation.OldDatabase, (operation, collation) => operation.Collation ??= collation);
            HandleCollationDelegation(operation, DelegationModes.ApplyToDatabases, o => o.Collation = null);

            // Ensure, that no properties have been added by the EF Core team in the meantime.
            // If they have, they need to be checked below.
            AssertMigrationOperationProperties(
                operation,
                new[]
            {
                nameof(AlterDatabaseOperation.OldDatabase),
                nameof(AlterDatabaseOperation.Collation),
            });

            // Ensure, that this hasn't become an empty operation.
            return(operation.Collation != operation.OldDatabase.Collation ||
                   operation.IsReadOnly != operation.OldDatabase.IsReadOnly ||
                   HasDifferences(operation.GetAnnotations(), operation.OldDatabase.GetAnnotations())
                ? operation
                : null);
        }
        protected override void Generate(
            AlterDatabaseOperation operation,
            IModel model,
            MigrationCommandListBuilder builder)
        {
            Check.NotNull(operation, nameof(operation));
            Check.NotNull(builder, nameof(builder));

            foreach (var extension in PostgresExtension.GetPostgresExtensions(operation))
            {
                GenerateCreateExtension(extension, model, builder);
            }

            foreach (var enumTypeToCreate in PostgresEnum.GetPostgresEnums(operation)
                     .Where(ne => PostgresEnum.GetPostgresEnums(operation.OldDatabase).All(oe => oe.Name != ne.Name)))
            {
                GenerateCreateEnum(enumTypeToCreate, model, builder);
            }

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

            foreach (var enumTypeToAlter in from newEnum in PostgresEnum.GetPostgresEnums(operation)
                     join oldEnum in PostgresEnum.GetPostgresEnums(operation.OldDatabase) on newEnum.Name equals oldEnum.Name
                     select new { newEnum.Name, OldLabels = oldEnum.Labels, newLabels = newEnum.Labels })
            {
                // TODO: Some forms of enum alterations are actually supported... At least log...
            }

            builder.EndCommand();
        }
        protected override void Generate(
            AlterDatabaseOperation operation,
            IModel model,
            MigrationCommandListBuilder builder)
        {
            Check.NotNull(operation, nameof(operation));
            Check.NotNull(builder, nameof(builder));

            foreach (var extension in PostgresExtension.GetPostgresExtensions(operation))
            {
                builder
                .Append("CREATE EXTENSION IF NOT EXISTS ")
                .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(extension.Name));

                if (extension.Schema != null)
                {
                    builder
                    .Append(" SCHEMA ")
                    .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(extension.Schema));
                }

                if (extension.Version != null)
                {
                    builder
                    .Append(" VERSION ")
                    .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(extension.Version));
                }

                builder.AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator);
                EndStatement(builder, suppressTransaction: true);
            }
        }
Beispiel #5
0
        public virtual AlterOperationBuilder <AlterDatabaseOperation> AlterDatabase()
        {
            var operation = new AlterDatabaseOperation();

            Operations.Add(operation);

            return(new AlterOperationBuilder <AlterDatabaseOperation>(operation));
        }
Beispiel #6
0
 protected override void Generate(
     AlterDatabaseOperation operation,
     IModel model,
     MigrationCommandListBuilder builder)
 {
     Check.NotNull(operation, nameof(operation));
     Check.NotNull(builder, nameof(builder));
 }
        public void DropPostgresEnum()
        {
            var op = new AlterDatabaseOperation();

            PostgresEnum.GetOrAddPostgresEnum(op.OldDatabase, "public", "my_enum", new[] { "value1", "value2" });
            Generate(op);

            Assert.Equal(@"DROP TYPE public.my_enum;" + EOL, Sql);
        }
        public void CreatePostgresEnum()
        {
            var op = new AlterDatabaseOperation();

            PostgresEnum.GetOrAddPostgresEnum(op, "public", "my_enum", new[] { "value1", "value2" });
            Generate(op);

            Assert.Equal(@"CREATE TYPE public.my_enum AS ENUM ('value1', 'value2');" + EOL, Sql);
        }
Beispiel #9
0
        public void EnsurePostgresExtension()
        {
            var op = new AlterDatabaseOperation();

            PostgresExtension.GetOrAddPostgresExtension(op, "hstore");
            Generate(op);

            Assert.Equal(
                @"CREATE EXTENSION IF NOT EXISTS hstore;" + EOL,
                Sql);
        }
        public void EnsurePostgresExtension_with_schema()
        {
            var op = new AlterDatabaseOperation();

            op.Npgsql().GetOrAddPostgresExtension("myschema", "hstore", null);
            Generate(op);

            Assert.Equal(
                @"CREATE EXTENSION IF NOT EXISTS hstore SCHEMA myschema;" + EOL,
                Sql);
        }
Beispiel #11
0
        public void EnsurePostgresExtension_with_schema()
        {
            var op        = new AlterDatabaseOperation();
            var extension = PostgresExtension.GetOrAddPostgresExtension(op, "hstore");

            extension.Schema = "myschema";
            Generate(op);

            Assert.Equal(
                @"CREATE EXTENSION IF NOT EXISTS hstore SCHEMA myschema;" + EOL,
                Sql);
        }
        protected virtual void Generate([NotNull] AlterDatabaseOperation operation, [NotNull] IndentedStringBuilder builder)
        {
            Check.NotNull(operation, nameof(operation));
            Check.NotNull(builder, nameof(builder));

            builder.Append(".AlterDatabase()");

            using (builder.Indent())
            {
                Annotations(operation.GetAnnotations(), builder);
                OldAnnotations(operation.OldDatabase.GetAnnotations(), builder);
            }
        }
        /// <summary>
        ///     Builds commands for the given <see cref="AlterDatabaseOperation" /> by making calls on the given
        ///     <see cref="MigrationCommandListBuilder" />.
        /// </summary>
        /// <param name="operation"> The operation. </param>
        /// <param name="model"> The target model which may be <c>null</c> if the operations exist without a model. </param>
        /// <param name="builder"> The command builder to use to build the commands. </param>
        protected override void Generate(AlterDatabaseOperation operation, IModel model, MigrationCommandListBuilder builder)
        {
            if (operation[SqliteAnnotationNames.InitSpatialMetaData] as bool? != true ||
                operation.OldDatabase[SqliteAnnotationNames.InitSpatialMetaData] as bool? == true)
            {
                return;
            }

            builder
            .Append("SELECT InitSpatialMetaData()")
            .AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator);
            EndStatement(builder);
        }
        public void CreatePostgresEnumWithSchema()
        {
            var op = new AlterDatabaseOperation();

            PostgresEnum.GetOrAddPostgresEnum(op, "some_schema", "my_enum", new[] { "value1", "value2" });
            Generate(op);

            Assert.Equal(
                @"CREATE SCHEMA IF NOT EXISTS some_schema;" + EOL +
                @"GO" + EOL + EOL +
                @"CREATE TYPE some_schema.my_enum AS ENUM ('value1', 'value2');" + EOL,
                Sql);
        }
    public static MigrationBuilder EnsurePostgresExtension(
        this MigrationBuilder builder,
        string name,
        string?schema  = null,
        string?version = null)
    {
        Check.NotEmpty(name, nameof(name));
        Check.NullButNotEmpty(schema, nameof(schema));
        Check.NullButNotEmpty(version, nameof(schema));

        var op = new AlterDatabaseOperation();

        op.GetOrAddPostgresExtension(schema, name, version);
        builder.Operations.Add(op);

        return(builder);
    }
Beispiel #16
0
        protected override void Generate(
            AlterDatabaseOperation operation,
            IModel model,
            MigrationCommandListBuilder builder)
        {
            Check.NotNull(operation, nameof(operation));
            Check.NotNull(model, nameof(model));
            Check.NotNull(builder, nameof(builder));

            GenerateEnumStatements(operation, model, builder);
            GenerateRangeStatements(operation, model, builder);

            foreach (var extension in operation.Npgsql().PostgresExtensions)
            {
                GenerateCreateExtension(extension, model, builder);
            }

            builder.EndCommand();
        }
        protected override void Generate(AlterDatabaseOperation operation, IModel model, MigrationCommandListBuilder builder)
        {
            var changeTrackingEnabled    = operation.IsChangeTrackingEnabled();
            var changeTrackingWasEnabled = operation.OldDatabase.FindAnnotation(SqlChangeTrackingAnnotationNames.Enabled)?.Value as bool? ?? false;

            if (!changeTrackingEnabled && !changeTrackingWasEnabled)
            {
                base.Generate(operation, model, builder);
                return;
            }

            var sqlHelper = Dependencies.SqlGenerationHelper;
            var database  = Dependencies.CurrentContext.Context.Database.GetDbConnection().Database;

            if (changeTrackingEnabled)
            {
                Generate(new EnableChangeTrackingForDatabaseOperation(operation.ChangeTrackingRetentionDays(), operation.ChangeTrackingAutoCleanUp()), model, builder);
            }
            else
            {
                Generate(new DisableChangeTrackingForDatabaseOperation(), model, builder);
            }

            //if (serviceBrokerEnabled)
            //{
            //    builder
            //        .Append("ALTER DATABASE ")
            //        .Append(sqlHelper.DelimitIdentifier(database))
            //        .Append(" SET ALLOW_SNAPSHOT_ISOLATION ON ")
            //        .AppendLine(sqlHelper.StatementTerminator)
            //        .EndCommand();
            //}
            //else
            //{
            //    builder
            //        .Append("ALTER DATABASE ")
            //        .Append(sqlHelper.DelimitIdentifier(database))
            //        .Append(" SET ALLOW_SNAPSHOT_ISOLATION OFF ")
            //        .AppendLine(sqlHelper.StatementTerminator)
            //        .EndCommand();
            //}
        }
Beispiel #18
0
        public static MigrationBuilder EnsurePostgresExtension(
            this MigrationBuilder builder,
            [NotNull] string name,
            string schema  = null,
            string version = null
            )
        {
            Check.NotEmpty(name, nameof(name));
            Check.NullButNotEmpty(schema, nameof(schema));
            Check.NullButNotEmpty(version, nameof(schema));

            var op        = new AlterDatabaseOperation();
            var extension = PostgresExtension.GetOrAddPostgresExtension(op, name);

            extension.Schema  = schema;
            extension.Version = version;
            builder.Operations.Add(op);

            return(builder);
        }
Beispiel #19
0
        protected virtual IEnumerable <MigrationOperation> PostFilterOperations(IEnumerable <MigrationOperation> migrationOperations)
        {
            foreach (var migrationOperation in migrationOperations)
            {
                var resultOperation = migrationOperation switch
                {
                    AlterDatabaseOperation operation => PostFilterOperation(operation),
                    CreateTableOperation operation => PostFilterOperation(operation),
                    AlterTableOperation operation => PostFilterOperation(operation),
                    AddColumnOperation operation => PostFilterOperation(operation),
                    AlterColumnOperation operation => PostFilterOperation(operation),
                    _ => migrationOperation
                };

                if (resultOperation != null)
                {
                    yield return(resultOperation);
                }
            }
        }
Beispiel #20
0
        private IEnumerable <MigrationOperation> DiffAnnotations(
            IModel source,
            IModel target)
        {
            var sourceMigrationsAnnotations = source == null ? null : MigrationsAnnotations.For(source).ToList();
            var targetMigrationsAnnotations = target == null ? null : MigrationsAnnotations.For(target).ToList();

            if (source == null)
            {
                if (targetMigrationsAnnotations?.Count > 0)
                {
                    var alterDatabaseOperation = new AlterDatabaseOperation();
                    alterDatabaseOperation.AddAnnotations(targetMigrationsAnnotations);
                    yield return(alterDatabaseOperation);
                }

                yield break;
            }

            if (target == null)
            {
                sourceMigrationsAnnotations = MigrationsAnnotations.ForRemove(source).ToList();
                if (sourceMigrationsAnnotations.Count > 0)
                {
                    var alterDatabaseOperation = new AlterDatabaseOperation();
                    alterDatabaseOperation.OldDatabase.AddAnnotations(MigrationsAnnotations.ForRemove(source));
                    yield return(alterDatabaseOperation);
                }

                yield break;
            }

            if (HasDifferences(sourceMigrationsAnnotations, targetMigrationsAnnotations))
            {
                var alterDatabaseOperation = new AlterDatabaseOperation();
                alterDatabaseOperation.AddAnnotations(targetMigrationsAnnotations);
                alterDatabaseOperation.OldDatabase.AddAnnotations(sourceMigrationsAnnotations);
                yield return(alterDatabaseOperation);
            }
        }
Beispiel #21
0
        protected override void Generate(
            AlterDatabaseOperation operation,
            IModel model,
            MigrationCommandListBuilder builder)
        {
            Check.NotNull(operation, nameof(operation));
            Check.NotNull(builder, nameof(builder));

            foreach (var extension in PostgresExtension.GetPostgresExtensions(operation))
            {
                GenerateCreateExtension(extension, model, builder);
            }

            foreach (var enumType in PostgresEnum.GetPostgresEnums(operation))
            {
                GenerateCreateEnum(enumType, model, builder);
            }
            // TODO: Some forms of enum alterations are actually supported...
            foreach (var enumType in PostgresEnum.GetPostgresEnums(operation.OldDatabase))
            {
                GenerateDropEnum(enumType, builder);
            }
            builder.EndCommand();
        }
Beispiel #22
0
        protected virtual void GenerateRangeStatements(
            [NotNull] AlterDatabaseOperation operation,
            [NotNull] IModel model,
            [NotNull] MigrationCommandListBuilder builder)
        {
            foreach (var rangeTypeToCreate in operation.Npgsql().PostgresRanges
                     .Where(ne => operation.Npgsql().OldPostgresRanges.All(oe => oe.Name != ne.Name)))
            {
                GenerateCreateRange(rangeTypeToCreate, model, builder);
            }

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

            if (operation.Npgsql().PostgresRanges.FirstOrDefault(nr =>
                                                                 operation.Npgsql().OldPostgresRanges.Any(or => or.Name == nr.Name)
                                                                 ) is PostgresRange rangeTypeToAlter)
            {
                throw new NotSupportedException($"Altering range type ${rangeTypeToAlter} isn't supported.");
            }
        }
 protected virtual void Generate(
     [NotNull] AlterDatabaseOperation operation,
     [CanBeNull] IModel model,
     [NotNull] MigrationCommandListBuilder builder)
 {
 }
 public static IReadOnlyList <PostgresEnum> GetPostgresEnums([NotNull] this AlterDatabaseOperation operation)
 => PostgresEnum.GetPostgresEnums(operation).ToArray();
Beispiel #25
0
 public static PostgresExtension GetOrAddPostgresExtension(
     this AlterDatabaseOperation operation,
     string?schema,
     string name,
     string?version)
 => PostgresExtension.GetOrAddPostgresExtension(operation, schema, name, version);
 public static IReadOnlyList <PostgresRange> GetOldPostgresRanges([NotNull] this AlterDatabaseOperation operation)
 => PostgresRange.GetPostgresRanges(operation.OldDatabase).ToArray();
 public static PostgresExtension GetOrAddPostgresExtension(
     [NotNull] this AlterDatabaseOperation operation,
     [CanBeNull] string schema,
     [NotNull] string name,
     [CanBeNull] string version)
 => PostgresExtension.GetOrAddPostgresExtension(operation, schema, name, version);
        protected override void Generate(
            AlterDatabaseOperation operation,
            IModel model,
            MigrationCommandListBuilder builder)
        {
            Check.NotNull(operation, nameof(operation));
            Check.NotNull(builder, nameof(builder));

            builder.AppendLine("IF SERVERPROPERTY('IsXTPSupported') = 1 AND SERVERPROPERTY('EngineEdition') <> 5");
            using (builder.Indent())
            {
                builder
                .AppendLine("BEGIN")
                .AppendLine("IF NOT EXISTS (");
                using (builder.Indent())
                {
                    builder
                    .Append("SELECT 1 FROM [sys].[filegroups] [FG] ")
                    .Append("JOIN [sys].[database_files] [F] ON [FG].[data_space_id] = [F].[data_space_id] ")
                    .AppendLine("WHERE [FG].[type] = N'FX' AND [F].[type] = 2)");
                }

                using (builder.Indent())
                {
                    builder
                    .AppendLine("BEGIN")
                    .AppendLine("DECLARE @db_name NVARCHAR(MAX) = DB_NAME();")
                    .AppendLine("DECLARE @fg_name NVARCHAR(MAX);")
                    .AppendLine("SELECT TOP(1) @fg_name = [name] FROM [sys].[filegroups] WHERE [type] = N'FX';")
                    .AppendLine()
                    .AppendLine("IF @fg_name IS NULL");

                    using (builder.Indent())
                    {
                        builder
                        .AppendLine("BEGIN")
                        .AppendLine("SET @fg_name = @db_name + N'_MODFG';")
                        .AppendLine("EXEC(N'ALTER DATABASE CURRENT ADD FILEGROUP [' + @fg_name + '] CONTAINS MEMORY_OPTIMIZED_DATA;');")
                        .AppendLine("END");
                    }

                    builder
                    .AppendLine()
                    .AppendLine("DECLARE @path NVARCHAR(MAX);")
                    .Append("SELECT TOP(1) @path = [physical_name] FROM [sys].[database_files] ")
                    .AppendLine("WHERE charindex('\\', [physical_name]) > 0 ORDER BY [file_id];")
                    .AppendLine("IF (@path IS NULL)")
                    .IncrementIndent().AppendLine("SET @path = '\\' + @db_name;").DecrementIndent()
                    .AppendLine()
                    .AppendLine("DECLARE @filename NVARCHAR(MAX) = right(@path, charindex('\\', reverse(@path)) - 1);")
                    .AppendLine("SET @filename = REPLACE(left(@filename, len(@filename) - charindex('.', reverse(@filename))), '''', '''''') + N'_MOD';")
                    .AppendLine("DECLARE @new_path NVARCHAR(MAX) = REPLACE(CAST(SERVERPROPERTY('InstanceDefaultDataPath') AS NVARCHAR(MAX)), '''', '''''') + @filename;")
                    .AppendLine()
                    .AppendLine("EXEC(N'");

                    using (builder.Indent())
                    {
                        builder
                        .AppendLine("ALTER DATABASE CURRENT")
                        .AppendLine("ADD FILE (NAME=''' + @filename + ''', filename=''' + @new_path + ''')")
                        .AppendLine("TO FILEGROUP [' + @fg_name + '];')");
                    }

                    builder.AppendLine("END");
                }
                builder.AppendLine("END");
            }

            builder.AppendLine()
            .AppendLine("IF SERVERPROPERTY('IsXTPSupported') = 1")
            .AppendLine("EXEC(N'");
            using (builder.Indent())
            {
                builder
                .AppendLine("ALTER DATABASE CURRENT")
                .AppendLine("SET MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT ON;')");
            }

            builder.EndCommand(suppressTransaction: true);
        }
 protected override void Generate(AlterDatabaseOperation operation, IModel model, MigrationCommandListBuilder builder)
 => base.Generate(operation, model, builder);
Beispiel #30
0
 /// <summary>
 /// 修数据库。
 /// </summary>
 /// <param name="operation">操作实例。</param>
 /// <param name="builder"><see cref="MigrationCommandListBuilder"/>实例对象。</param>
 protected virtual void Generate(
     AlterDatabaseOperation operation,
     MigrationCommandListBuilder builder)
 {
 }