コード例 #1
0
        internal override void ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement, DbInterceptionContext interceptionContext)
        {
            DebugCheck.NotNull(transaction);
            DebugCheck.NotNull(migrationStatement);

            if (string.IsNullOrWhiteSpace(migrationStatement.Sql))
            {
                return;
            }

            if (!migrationStatement.SuppressTransaction)
            {
                var dbCommand = DbInterception.Dispatch.Transaction.GetConnection(transaction, interceptionContext).CreateCommand();
                using (var command = ConfigureCommand(dbCommand, migrationStatement.Sql, interceptionContext))
                {
                    command.Transaction = transaction;

                    command.ExecuteNonQuery();
                }
            }
            else
            {
                using (var connection = CreateConnection())
                {
                    var dbCommand = connection.CreateCommand();
                    using (var command = ConfigureCommand(dbCommand, migrationStatement.Sql, interceptionContext))
                    {
                        DbInterception.Dispatch.Connection.Open(connection, interceptionContext);

                        command.ExecuteNonQuery();
                    }
                }
            }
        }
コード例 #2
0
ファイル: DbMigrator.cs プロジェクト: jwanagel/jjwtest
        internal override void ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement)
        {
            if (string.IsNullOrWhiteSpace(migrationStatement.Sql))
            {
                return;
            }

            //Console.WriteLine(migrationStatement.Sql);

            if (!migrationStatement.SuppressTransaction)
            {
                using (var command = transaction.Connection.CreateCommand())
                {
                    command.CommandText = migrationStatement.Sql;
                    command.Transaction = transaction;
                    ConfigureCommand(command);

                    command.ExecuteNonQuery();
                }
            }
            else
            {
                using (var connection = CreateConnection())
                {
                    using (var command = connection.CreateCommand())
                    {
                        command.CommandText = migrationStatement.Sql;
                        ConfigureCommand(command);

                        connection.Open();
                        command.ExecuteNonQuery();
                    }
                }
            }
        }
コード例 #3
0
        /// <summary>
        /// Generates a migration operation to add a column.
        /// </summary>
        /// <param name="op">The operation that represents a column being added to a table.</param>
        /// <returns>A migration operation to add a column.</returns>
        protected virtual MigrationStatement Generate(AddColumnOperation op)
        {
            if (op == null)
            {
                return(null);
            }

            _tableName = op.Table;

            MigrationStatement stmt = new MigrationStatement();
            //verify if there is any "AddPrimaryKeyOperation" related with the column that will be added and if it is defined as identity (auto_increment)
            bool uniqueAttr = (from pkOpe in _pkOperations
                               where (from col in pkOpe.Columns
                                      where col == op.Column.Name
                                      select col).Count() > 0
                               select pkOpe).Count() > 0 & op.Column.IsIdentity;

            // if the column to be added is PK as well as identity we need to specify the column as unique to avoid the error:
            // "Incorrect table definition there can be only one auto column and it must be defined as a key",
            // since unique and PK are almost equivalent we'll be able to add the new column and later add the PK related to it,
            // this because the "AddPrimaryKeyOperation" is executed after the column is added
            stmt.Sql = EndsWithSemicolon(string.Format("alter table `{0}` add column `{1}` {2} {3}", TrimSchemaPrefix(op.Table),
                                                       op.Column.Name, Generate(op.Column), (uniqueAttr ? " unique " : "")));

            return(stmt);
        }
コード例 #4
0
        internal override void ExecuteSql(
            MigrationStatement migrationStatement, DbConnection connection, DbTransaction transaction,
            DbInterceptionContext interceptionContext)
        {
            DebugCheck.NotNull(migrationStatement);
            DebugCheck.NotNull(connection);

            _logger.Verbose(migrationStatement.Sql);

            var providerServices = DbProviderServices.GetProviderServices(connection);

            if (providerServices != null)
            {
                providerServices.RegisterInfoMessageHandler(
                    connection,
                    message =>
                {
                    if (!string.Equals(message, _lastInfoMessage, StringComparison.OrdinalIgnoreCase))
                    {
                        _logger.Warning(message);

                        // simple duplicate filtering
                        _lastInfoMessage = message;
                    }
                });
            }

            base.ExecuteSql(migrationStatement, connection, transaction, interceptionContext);
        }
コード例 #5
0
        internal virtual void ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement, DbInterceptionContext interceptionContext)
        {
            DebugCheck.NotNull(transaction);
            DebugCheck.NotNull(migrationStatement);

            _this.ExecuteSql(transaction, migrationStatement, interceptionContext);
        }
コード例 #6
0
        private MigrationMatch ProcessMigration(MigrationStatement statement)
        {
            var sql = statement.Sql;

            if (!sql.Contains(_contextName))
            {
                return(MigrationMatch.Miss);
            }

            // we are on the line where the migration is declared
            var migrationNameMatch = _matchingRegex.Match(sql);

            if (!migrationNameMatch.Success)
            {
                return(MigrationMatch.Miss);
            }

            var firstMatch    = migrationNameMatch.Groups[0].ToString();
            var migrationName = firstMatch.Substring(3, firstMatch.Length - 7);

            return(new MigrationMatch
            {
                Success = true,
                MigrationName = migrationName
            });
        }
コード例 #7
0
        internal override void ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement)
        {
            DebugCheck.NotNull(transaction);
            DebugCheck.NotNull(migrationStatement);

            if (string.IsNullOrWhiteSpace(migrationStatement.Sql))
            {
                return;
            }

            if (!migrationStatement.SuppressTransaction)
            {
                using (var command = ConfigureCommand(transaction.Connection.CreateCommand(), migrationStatement.Sql))
                {
                    command.Transaction = transaction;

                    command.ExecuteNonQuery();
                }
            }
            else
            {
                using (var connection = CreateConnection())
                {
                    using (var command = ConfigureCommand(connection.CreateCommand(), migrationStatement.Sql))
                    {
                        connection.Open();

                        command.ExecuteNonQuery();
                    }
                }
            }
        }
コード例 #8
0
        protected virtual MigrationStatement Generate(CreateProcedureOperation op)
        {
            MigrationStatement stmt = new MigrationStatement();

            stmt.Sql = GenerateProcedureCmd(op);
            return(stmt);
        }
コード例 #9
0
        private MigrationStatement GenerateStatement(MigrationOperation migrationOperation)
        {
            var migrationStatement = new MigrationStatement();

            migrationStatement.BatchTerminator = BATCHTERMINATOR;
            migrationStatement.Sql             = this.GenerateSqlStatement(migrationOperation);
            return(migrationStatement);
        }
コード例 #10
0
            protected override MigrationStatement Generate(AddForeignKeyOperation addForeignKeyOperation)
            {
                addForeignKeyOperation.PrincipalTable = addForeignKeyOperation.PrincipalTable.Replace("dbo.", "");
                addForeignKeyOperation.DependentTable = addForeignKeyOperation.DependentTable.Replace("dbo.", "");
                MigrationStatement ms = base.Generate(addForeignKeyOperation);

                return(ms);
            }
コード例 #11
0
 internal virtual void ExecuteSql(
     MigrationStatement migrationStatement,
     DbConnection connection,
     DbTransaction transaction,
     DbInterceptionContext interceptionContext)
 {
     this._this.ExecuteSql(migrationStatement, connection, transaction, interceptionContext);
 }
コード例 #12
0
        public void ExecuteSql_with_transactions_suppressed_dispatches_commands_to_interceptors()
        {
            var mockCommand = new Mock <DbCommand>();

            mockCommand.Setup(m => m.ExecuteNonQuery()).Returns(2013);

            var mockConnection = new Mock <DbConnection>();

            mockConnection.Protected().Setup <DbCommand>("CreateDbCommand").Returns(mockCommand.Object);

            var mockTransaction = new Mock <DbTransaction>();

            mockTransaction.Protected().Setup <DbConnection>("DbConnection").Returns(mockConnection.Object);

            var mockFactory = new Mock <DbProviderFactory>();

            mockFactory.Setup(m => m.CreateConnection()).Returns(mockConnection.Object);

            var objectContext       = new ObjectContext();
            var mockInternalContext = new Mock <InternalContextForMock>();

            mockInternalContext.Setup(m => m.ObjectContext).Returns(objectContext);
            var context = mockInternalContext.Object.Owner;

            objectContext.InterceptionContext = objectContext.InterceptionContext.WithDbContext(context);

            var migrator  = new DbMigrator(context, mockFactory.Object);
            var statement = new MigrationStatement
            {
                Sql = "Some Sql",
                SuppressTransaction = true
            };

            var mockInterceptor = new Mock <DbInterceptor> {
                CallBase = true
            };

            Interception.AddInterceptor(mockInterceptor.Object);

            try
            {
                migrator.ExecuteSql(mockTransaction.Object, statement);
            }
            finally
            {
                Interception.RemoveInterceptor(mockInterceptor.Object);
            }

            mockInterceptor.Verify(m => m.NonQueryExecuting(
                                       mockCommand.Object,
                                       It.Is <DbInterceptionContext>(c => c.DbContexts.Contains(context))));

            mockInterceptor.Verify(m => m.NonQueryExecuted(
                                       mockCommand.Object,
                                       2013,
                                       It.Is <DbInterceptionContext>(c => c.DbContexts.Contains(context))));
        }
コード例 #13
0
        public void ExecuteSql_dispatches_to_interceptors()
        {
            var mockCommand = new Mock <DbCommand>();

            mockCommand.Setup(m => m.ExecuteNonQuery()).Returns(2013);

            var mockConnection = new Mock <DbConnection>();

            mockConnection.Protected().Setup <DbCommand>("CreateDbCommand").Returns(mockCommand.Object);

            var mockTransaction = new Mock <DbTransaction>(MockBehavior.Strict);

            mockTransaction.Protected().Setup <DbConnection>("DbConnection").Returns(mockConnection.Object);

            var migrator  = new DbMigrator();
            var statement = new MigrationStatement
            {
                Sql = "Some Sql"
            };

            var providerFactoryServiceMock = new Mock <IDbProviderFactoryResolver>();

            providerFactoryServiceMock.Setup(m => m.ResolveProviderFactory(It.IsAny <DbConnection>()))
            .Returns(FakeSqlProviderFactory.Instance);
            MutableResolver.AddResolver <IDbProviderFactoryResolver>(k => providerFactoryServiceMock.Object);
            var mockInterceptor = new Mock <DbCommandInterceptor> {
                CallBase = true
            };

            DbInterception.Add(mockInterceptor.Object);
            var transactionInterceptorMock = new Mock <IDbTransactionInterceptor>();

            DbInterception.Add(transactionInterceptorMock.Object);
            try
            {
                new MigratorLoggingDecorator(migrator, new Mock <MigrationsLogger>().Object)
                .ExecuteSql(mockTransaction.Object, statement, new DbInterceptionContext());
            }
            finally
            {
                MutableResolver.ClearResolvers();
                DbInterception.Remove(mockInterceptor.Object);
                DbInterception.Remove(transactionInterceptorMock.Object);
            }

            mockInterceptor.Verify(m => m.NonQueryExecuting(mockCommand.Object, It.IsAny <DbCommandInterceptionContext <int> >()), Times.Once());
            mockInterceptor.Verify(m => m.NonQueryExecuted(mockCommand.Object, It.IsAny <DbCommandInterceptionContext <int> >()), Times.Once());

            transactionInterceptorMock.Verify(
                m => m.ConnectionGetting(It.IsAny <DbTransaction>(), It.IsAny <DbTransactionInterceptionContext <DbConnection> >()),
                Times.Exactly(2));
            transactionInterceptorMock.Verify(
                m => m.ConnectionGot(It.IsAny <DbTransaction>(), It.IsAny <DbTransactionInterceptionContext <DbConnection> >()),
                Times.Exactly(2));
            mockTransaction.Protected().Verify <DbConnection>("DbConnection", Times.Exactly(2));
        }
コード例 #14
0
        /// <summary>
        /// 创建表对象迁移SQL代码生成。
        /// </summary>
        /// <param name="column">创建表操作对象。</param>
        /// <returns>生成的SQL。</returns>
        protected override MigrationStatement Generate(CreateTableOperation op)
        {
            MigrationStatement s = null;

            op.Annotations.WriteComment(() => { s = base.Generate(op); }, o =>
            {
                s.Sql += $" COMMENT '{o}'";
            });
            return(s);
        }
コード例 #15
0
        protected override MigrationStatement Generate(CreateIndexOperation op)
        {
            var    u = new MigrationStatement();
            string unique = (op.IsUnique ? "UNIQUE" : ""), columns = "";

            foreach (var col in op.Columns)
            {
                columns += ($"`{col}` DESC{(op.Columns.IndexOf(col) < op.Columns.Count - 1 ? ", " : "")}");
            }
            u.Sql = $"CREATE {unique} INDEX `{op.Name}` ON `{TrimSchemaPrefix(op.Table)}` ({columns}) USING BTREE";
            return(u);
        }
コード例 #16
0
    protected override MigrationStatement Generate(CreateTableOperation op)
    {
        MigrationStatement statement = base.Generate(op);

        foreach (ColumnModel column in op.Columns)
        {
            if (column.MaxLength.HasValue)
            {
                statement.Sql = statement.Sql.Replace("binary", $"binary({column.MaxLength.Value})");
            }
        }
        return(statement);
    }
コード例 #17
0
        /// <summary>
        /// Generates a migration operation to drop a column.
        /// </summary>
        /// <param name="op">The operation that represents a column being dropped from a table.</param>
        /// <returns>The migration operation to drop a column.</returns>
        protected virtual MigrationStatement Generate(DropColumnOperation op)
        {
            if (op == null)
            {
                return(null);
            }

            MigrationStatement stmt = new MigrationStatement();

            stmt.Sql = EndsWithSemicolon(string.Format("alter table `{0}` drop column `{1}`",
                                                       TrimSchemaPrefix(op.Table), op.Name));
            return(stmt);
        }
コード例 #18
0
        protected virtual MigrationStatement Generate(DropColumnOperation op)
        {
            if (op == null)
            {
                return(null);
            }

            MigrationStatement stmt = new MigrationStatement();
            StringBuilder      sb   = new StringBuilder();

            stmt.Sql = string.Format("alter table `{0}` drop column `{1}`",
                                     op.Table, op.Name);
            return(stmt);
        }
コード例 #19
0
    /// <summary>
    /// we want BTREE because HASH is not correct for normal Keys on MySQL 8
    /// </summary>
    /// <param name="op"></param>
    /// <returns></returns>
    protected override MigrationStatement Generate(CreateIndexOperation op)
    {
        MigrationStatement migrationStatement = base.Generate(op);

        System.Diagnostics.Trace.WriteLine(migrationStatement.Sql);
        string fubarSql = migrationStatement.Sql.TrimEnd();

        if (fubarSql.EndsWith("using HASH", StringComparison.OrdinalIgnoreCase))
        {
            string modSql = fubarSql.Replace("using HASH", " using BTREE");
            migrationStatement.Sql = modSql;
        }
        return(migrationStatement);
    }
コード例 #20
0
        public void ExecuteSql_dispatches_to_interceptors()
        {
            var mockCommand = new Mock <DbCommand>();

            mockCommand.Setup(m => m.ExecuteNonQuery()).Returns(2013);

            var mockConnection = new Mock <DbConnection>();

            mockConnection.Protected().Setup <DbCommand>("CreateDbCommand").Returns(mockCommand.Object);

            var mockTransaction = new Mock <DbTransaction>(MockBehavior.Strict);

            mockTransaction.Protected().Setup <DbConnection>("DbConnection").Returns(mockConnection.Object);

            var migrator  = new DbMigrator();
            var statement = new MigrationStatement
            {
                Sql = "Some Sql"
            };

            var mockInterceptor = new Mock <DbCommandInterceptor> {
                CallBase = true
            };

            DbInterception.Add(mockInterceptor.Object);
            var transactionInterceptorMock = new Mock <IDbTransactionInterceptor>();

            DbInterception.Add(transactionInterceptorMock.Object);
            try
            {
                migrator.ExecuteSql(statement, mockConnection.Object, mockTransaction.Object, new DbInterceptionContext());
            }
            finally
            {
                DbInterception.Remove(mockInterceptor.Object);
                DbInterception.Remove(transactionInterceptorMock.Object);
            }

            mockInterceptor.Verify(m => m.NonQueryExecuting(mockCommand.Object, It.IsAny <DbCommandInterceptionContext <int> >()), Times.Once());
            mockInterceptor.Verify(m => m.NonQueryExecuted(mockCommand.Object, It.IsAny <DbCommandInterceptionContext <int> >()), Times.Once());

            transactionInterceptorMock.Verify(
                m => m.ConnectionGetting(It.IsAny <DbTransaction>(), It.IsAny <DbTransactionInterceptionContext <DbConnection> >()),
                Times.Never());
            transactionInterceptorMock.Verify(
                m => m.ConnectionGot(It.IsAny <DbTransaction>(), It.IsAny <DbTransactionInterceptionContext <DbConnection> >()),
                Times.Never());
            mockTransaction.Protected().Verify <DbConnection>("DbConnection", Times.Never());
        }
コード例 #21
0
        protected virtual MigrationStatement Generate(AddColumnOperation op)
        {
            if (op == null)
            {
                return(null);
            }

            _tableName = op.Table;

            MigrationStatement stmt = new MigrationStatement();

            stmt.Sql = string.Format("alter table `{0}` add column `{1}`",
                                     TrimSchemaPrefix(op.Table), op.Column.Name) + " " + Generate(op.Column);
            return(stmt);
        }
コード例 #22
0
        protected virtual MigrationStatement Generate(HistoryOperation op)
        {
            if (op == null)
            {
                return(null);
            }

            MigrationStatement stmt = new MigrationStatement();

            var          cmdStr    = "";
            SqlGenerator generator = new SelectGenerator();

            foreach (var commandTree in op.CommandTrees)
            {
                switch (commandTree.CommandTreeKind)
                {
                case DbCommandTreeKind.Insert:
                    generator = new InsertGenerator();
                    break;

                case DbCommandTreeKind.Delete:
                    generator = new DeleteGenerator();
                    break;

                case DbCommandTreeKind.Update:
                    generator = new UpdateGenerator();
                    break;

                case DbCommandTreeKind.Query:
                    generator = new SelectGenerator();
                    break;

                case DbCommandTreeKind.Function:
                    generator = new FunctionGenerator();
                    break;

                default:
                    throw new NotImplementedException(commandTree.CommandTreeKind.ToString());
                }
                cmdStr = generator.GenerateSQL(commandTree);

                ReplaceParemeters(ref cmdStr, generator.Parameters);
                stmt.Sql += cmdStr.Replace("dbo", "") + ";";
            }
            return(stmt);
        }
コード例 #23
0
 internal override void ExecuteSql(
     MigrationStatement migrationStatement,
     DbConnection connection,
     DbTransaction transaction,
     DbInterceptionContext interceptionContext)
 {
     this._logger.Verbose(migrationStatement.Sql);
     DbProviderServices.GetProviderServices(connection)?.RegisterInfoMessageHandler(connection, (Action <string>)(message =>
     {
         if (string.Equals(message, this._lastInfoMessage, StringComparison.OrdinalIgnoreCase))
         {
             return;
         }
         this._logger.Warning(message);
         this._lastInfoMessage = message;
     }));
     base.ExecuteSql(migrationStatement, connection, transaction, interceptionContext);
 }
コード例 #24
0
 internal override void ExecuteSql(
     MigrationStatement migrationStatement,
     DbConnection connection,
     DbTransaction transaction,
     DbInterceptionContext interceptionContext)
 {
     if (string.IsNullOrWhiteSpace(migrationStatement.Sql))
     {
         return;
     }
     using (InterceptableDbCommand interceptableDbCommand = this.ConfigureCommand(connection.CreateCommand(), migrationStatement.Sql, interceptionContext))
     {
         if (transaction != null)
         {
             interceptableDbCommand.Transaction = transaction;
         }
         interceptableDbCommand.ExecuteNonQuery();
     }
 }
コード例 #25
0
        public override string GenerateProcedureBody(ICollection <DbModificationCommandTree> commandTrees, string rowsAffectedParameter, string providerManifestToken)
        {
            MySqlConnection    con  = new MySqlConnection();
            MigrationStatement stmt = new MigrationStatement();

            _providerManifest = DbProviderServices.GetProviderServices(con).GetProviderManifest(providerManifestToken);

            var          cmdStr    = "";
            SqlGenerator generator = new SelectGenerator();

            foreach (var commandTree in commandTrees)
            {
                switch (commandTree.CommandTreeKind)
                {
                case DbCommandTreeKind.Insert:
                    generator = new InsertGenerator();
                    cmdStr    = generator.GenerateSQL(commandTree);
                    break;

                case DbCommandTreeKind.Delete:
                    generator = new DeleteGenerator();
                    cmdStr    = generator.GenerateSQL(commandTree);
                    break;

                case DbCommandTreeKind.Update:
                    generator = new UpdateGenerator();
                    cmdStr    = generator.GenerateSQL(commandTree);
                    break;

                case DbCommandTreeKind.Query:
                    generator = new SelectGenerator();
                    cmdStr    = generator.GenerateSQL(commandTree);
                    break;

                case DbCommandTreeKind.Function:
                    generator = new FunctionGenerator();
                    cmdStr    = generator.GenerateSQL(commandTree);
                    break;
                }
                stmt.Sql += cmdStr.Replace("dbo.", "") + ";";
            }
            return(stmt.Sql);
        }
コード例 #26
0
        public void ExecuteSql_dispatches_commands_to_interceptors()
        {
            var mockCommand = new Mock <DbCommand>();

            mockCommand.Setup(m => m.ExecuteNonQuery()).Returns(2013);

            var mockConnection = new Mock <DbConnection>();

            mockConnection.Protected().Setup <DbCommand>("CreateDbCommand").Returns(mockCommand.Object);

            var mockTransaction = new Mock <DbTransaction>();

            mockTransaction.Protected().Setup <DbConnection>("DbConnection").Returns(mockConnection.Object);

            var migrator  = new DbMigrator();
            var statement = new MigrationStatement
            {
                Sql = "Some Sql"
            };

            var mockInterceptor = new Mock <DbCommandInterceptor> {
                CallBase = true
            };

            DbInterception.Add(mockInterceptor.Object);

            try
            {
                migrator.ExecuteSql(mockTransaction.Object, statement, new DbInterceptionContext());
            }
            finally
            {
                DbInterception.Remove(mockInterceptor.Object);
            }

            mockInterceptor.Verify(m => m.NonQueryExecuting(mockCommand.Object, It.IsAny <DbCommandInterceptionContext <int> >()));
            mockInterceptor.Verify(m => m.NonQueryExecuted(mockCommand.Object, It.IsAny <DbCommandInterceptionContext <int> >()));
        }
コード例 #27
0
        internal override void ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement)
        {
            _logger.Verbose(migrationStatement.Sql);

            base.ExecuteSql(transaction, migrationStatement);
        }
コード例 #28
0
        private MigrationStatement Generate(UpdateDatabaseOperation updateDatabaseOperation)
        {
            if (updateDatabaseOperation == null)
            {
                throw new ArgumentNullException("UpdateDatabaseOperation");
            }

            MigrationStatement statement            = new MigrationStatement();
            StringBuilder      sql                  = new StringBuilder();
            const string       idempotentScriptName = "_idempotent_script";
            SelectGenerator    generator            = new SelectGenerator();

            if (!updateDatabaseOperation.Migrations.Any())
            {
                return(statement);
            }

            sql.AppendFormat("DROP PROCEDURE IF EXISTS `{0}`;", idempotentScriptName);
            sql.AppendLine();
            sql.AppendLine();

            sql.AppendLine("DELIMITER //");
            sql.AppendLine();

            sql.AppendFormat("CREATE PROCEDURE `{0}`()", idempotentScriptName);
            sql.AppendLine();
            sql.AppendLine("BEGIN");
            sql.AppendLine("  DECLARE CurrentMigration TEXT;");
            sql.AppendLine();
            sql.AppendLine("  IF EXISTS(SELECT 1 FROM information_schema.tables ");
            sql.AppendLine("  WHERE table_name = '__MigrationHistory' ");
            sql.AppendLine("  AND table_schema = DATABASE()) THEN ");

            foreach (var historyQueryTree in updateDatabaseOperation.HistoryQueryTrees)
            {
                string historyQuery = generator.GenerateSQL(historyQueryTree);
                ReplaceParemeters(ref historyQuery, generator.Parameters);
                sql.AppendLine(@"    SET CurrentMigration = (" + historyQuery + ");");
                sql.AppendLine("  END IF;");
                sql.AppendLine();
            }

            sql.AppendLine("  IF CurrentMigration IS NULL THEN");
            sql.AppendLine("    SET CurrentMigration = '0';");
            sql.AppendLine("  END IF;");
            sql.AppendLine();

            // Migrations
            foreach (var migration in updateDatabaseOperation.Migrations)
            {
                if (migration.Operations.Count == 0)
                {
                    continue;
                }

                sql.AppendLine("  IF CurrentMigration < '" + migration.MigrationId + "' THEN ");
                var statements = Generate(migration.Operations, _providerManifestToken);
                foreach (var migrationStatement in statements)
                {
                    string sqlStatement = migrationStatement.Sql;
                    if (!sqlStatement.EndsWith(";"))
                    {
                        sqlStatement += ";";
                    }
                    sql.AppendLine(sqlStatement);
                }
                sql.AppendLine("  END IF;");
                sql.AppendLine();
            }

            sql.AppendLine("END //");
            sql.AppendLine();
            sql.AppendLine("DELIMITER ;");
            sql.AppendLine();
            sql.AppendFormat("CALL `{0}`();", idempotentScriptName);
            sql.AppendLine();
            sql.AppendLine();
            sql.AppendFormat("DROP PROCEDURE IF EXISTS `{0}`;", idempotentScriptName);
            sql.AppendLine();

            statement.Sql = sql.ToString();

            return(statement);
        }