public static bool IsVersionChainMaintained(Database database, ReleaseChanges releaseChanges, int changeVersion, int lastExecutedCurrentChangeVersion) { if (releaseChanges.Sequence > 1) { // Check if last release changes are there var previousReleaseVersion = ChangeReader.AllReleaseChanges.FirstOrDefault(x => x.Sequence == releaseChanges.Sequence - 1); int lastExecutedPreviousChangeVersion = GetLastExecutedChangeVersion(database, previousReleaseVersion.Name); if (lastExecutedPreviousChangeVersion == 0) { Display.DisplayMessage(DisplayType.Warning, "Could not execute changes in {0} since previous release ({1}) changes were not executed in that database.", database.Name, previousReleaseVersion.Name); return(false); } if (lastExecutedPreviousChangeVersion < previousReleaseVersion.LastChangeVersion) { Display.DisplayMessage(DisplayType.Warning, "Could not execute changes in {0} since latest changes in previous release ({1}) were not executed in that database.", database.Name, previousReleaseVersion.Name); return(false); } } if (lastExecutedCurrentChangeVersion >= changeVersion) { Display.DisplayMessage(DisplayType.Info, "Change {0} in release {1} was already executed in database {2}.", changeVersion, releaseChanges.Name, database.Name); return(false); } return(true); }
public static void LogChanges(DatabaseGroup databaseGroup, string toReleaseVersion, int toChangeVersion) { ReleaseChanges toReleaseChanges = ChangeExecutor.AsserValidReleaseVersion(toReleaseVersion); if (!toReleaseChanges.Changes.Select(x => x.Version).Contains(toChangeVersion)) { throw new VersioningException("Change Version - " + toChangeVersion + " does not exist in Release version - " + toReleaseVersion + " in the change xml files."); } foreach (Database database in databaseGroup.Databases) { DatabaseVersion lastExecutedVersion = ChangeExecutor.GetLastExecutedVersion(database); if (lastExecutedVersion.ReleaseVersion != DatabaseVersion.NO_EXECUTED_RELEASE_VERSION) { Display.DisplayMessage(DisplayType.Error, "Can not insert logs in database - {0} since some logs were already inserted in this database by the tool.", database.Name); continue; } SqlDatabaseManager databaseManager = new SqlDatabaseManager(database, true); SqlTransaction tx = databaseManager.Connection.BeginTransaction(); try { for (int sequence = 1; sequence <= toReleaseChanges.Sequence; sequence++) { ReleaseChanges releaseChanges = ChangeReader.AllReleaseChanges.FirstOrDefault(x => x.Sequence == sequence); int toChangeVersionToExecute = releaseChanges.LastChangeVersion; if (releaseChanges.Sequence == toReleaseChanges.Sequence) { toChangeVersionToExecute = toChangeVersion; } for (int version = 1; version <= toChangeVersionToExecute; version++) { databaseManager.ExecuteNonQuery(@" INSERT INTO " + Constants.CHANGE_LOG_TABLE + @" (RELEASE_VERSION, CHANGE_VERSION, EXECUTION_TIME, EXECUTOR_NAME, EXECUTOR_IP, DESCRIPTION) VALUES ('" + releaseChanges.Name + "'," + version + " ,CURRENT_TIMESTAMP, SUSER_NAME(), CAST(CONNECTIONPROPERTY('client_net_address') AS VARCHAR(255)), '" + (releaseChanges.Changes.FirstOrDefault(x => x.Version == version).Description ?? "") + "');", tx); } } tx.Commit(); Display.DisplayMessage(DisplayType.Success, "Successfully inserted logs in database - {0}.", database.Name); } catch (Exception ex) { Display.DisplayMessage(DisplayType.Error, "Exception occured while inserting logs in database - {0}. Exception - {1}", database.Name, ex); tx.Rollback(); } finally { databaseManager.CloseConnection(); } } }
public static ReleaseChanges AsserValidReleaseVersion(string releaseVersion) { ReleaseChanges releaseChanges = ChangeReader.AllReleaseChanges.FirstOrDefault(x => x.Name == releaseVersion); if (releaseChanges == null) { throw new VersioningException("Release version - \"" + releaseVersion + "\" does not exist in the change xml files."); } return(releaseChanges); }
public static void ReadAllChanges() { AllReleaseChanges = new List <ReleaseChanges>(); if (!Directory.Exists(Constants.CHANGE_SCRIPT_DIRECTORY)) { Directory.CreateDirectory(Constants.CHANGE_SCRIPT_DIRECTORY); } string[] files = Directory.GetFiles(Constants.CHANGE_SCRIPT_DIRECTORY, "*.xml"); foreach (string filePath in files) { XmlSerializer serializer = new XmlSerializer(typeof(ReleaseChanges)); StreamReader reader = new StreamReader(filePath); ReleaseChanges releaseChanges = (ReleaseChanges)serializer.Deserialize(reader); reader.Close(); AllReleaseChanges.Add(releaseChanges); } if (AllReleaseChanges.Count < 1) { Display.DisplayMessage(DisplayType.Info, "There is no database change xml in {0}. If you want to start using the tool based on an existing database use the command -generatescript<space>{{database_group}} to generate the initial scripts for the current state of the database.", Constants.CHANGE_SCRIPT_DIRECTORY); return; } if (AllReleaseChanges.Count(x => string.IsNullOrEmpty(x.Name)) > 0) { throw new VersioningException("One or more change xml files is missing required attribute - releaseName"); } if (AllReleaseChanges.Count(x => x.Changes == null || x.Changes.Count == 0) > 0) { throw new VersioningException("There must be at least one \"Change\" element in the change xml file. One or more xml file is missing that."); } if (AllReleaseChanges.Count(x => x.Changes.Min(y => y.Version) != 1) > 0) { throw new VersioningException("Change versions must start with value 1. One or more xml file violates that constraint."); } if (AllReleaseChanges.Count(x => string.IsNullOrEmpty(x.PreviousReleaseName)) != 1) { throw new VersioningException("There must be exactly one XML with previousReleaseName attribute set to NULL."); } ReleaseChanges releaseChange = AllReleaseChanges.FirstOrDefault(x => string.IsNullOrEmpty(x.PreviousReleaseName)); releaseChange.Sequence = 1; releaseChange.LastChangeVersion = releaseChange.Changes.Max(x => x.Version); int releaseChangesToProcess = AllReleaseChanges.Count; while (releaseChangesToProcess > 1) { string prevReleaseName = releaseChange.Name; int prevReleaseSequence = releaseChange.Sequence; if (AllReleaseChanges.Count(x => x.PreviousReleaseName == prevReleaseName) != 1) { throw new VersioningException("There must be exactly one successor and one predecessor (except the first release) of a release version. Relese version \"" + prevReleaseName + "\" violates that constraint"); } releaseChange = AllReleaseChanges.FirstOrDefault(x => x.PreviousReleaseName == prevReleaseName); releaseChange.Sequence = prevReleaseSequence + 1; releaseChange.LastChangeVersion = releaseChange.Changes.Max(x => x.Version); releaseChangesToProcess--; } AllReleaseChanges.FirstOrDefault(x => x.Sequence == AllReleaseChanges.Count).IsLatestRelease = true; }
public static void ExecuteChanges(DatabaseGroup databaseGroup, string releaseVersion, int changeVersion, bool force) { ReleaseChanges releaseChanges = AsserValidReleaseVersion(releaseVersion); if (ChangeReader.AllReleaseChanges.First(x => x.Name == releaseVersion).Changes.Count(y => y.Version == changeVersion) == 0) { throw new VersioningException("Change version - \"" + changeVersion + "\" does not exist in the change xml file for Release version - \"" + releaseVersion + "\" ."); } foreach (Database database in databaseGroup.Databases) { int lastExecutedCurrentChangeVersion = GetLastExecutedChangeVersion(database, releaseVersion); if (force) { lastExecutedCurrentChangeVersion = changeVersion - 1; } else if (!IsVersionChainMaintained(database, releaseChanges, changeVersion, lastExecutedCurrentChangeVersion)) { continue; } SqlDatabaseManager databaseManager = new SqlDatabaseManager(database, true); SqlTransaction tx = databaseManager.Connection.BeginTransaction(); Change executingChange = null; string executingSql = null; try { List <int> executedVersions = new List <int>(); for (int version = lastExecutedCurrentChangeVersion + 1; version <= changeVersion; version++) { executingChange = releaseChanges.Changes.FirstOrDefault(x => x.Version == version); foreach (var sql in executingChange.ChangeSqls) { executingSql = string.Empty; if (!string.IsNullOrEmpty(sql.Path)) { executingSql = System.IO.File.ReadAllText(System.IO.Path.Combine(Constants.CHANGE_SCRIPT_DIRECTORY, sql.Path)); } else { executingSql = sql.Sql; } if (database.Replacements != null) { foreach (var replacement in database.Replacements) { executingSql = executingSql.Replace(replacement.Text, replacement.ReplacementText); } } databaseManager.ExecuteNonQuery(executingSql, tx); } if (!force) { databaseManager.ExecuteNonQuery(@" INSERT INTO " + Constants.CHANGE_LOG_TABLE + @" (RELEASE_VERSION, CHANGE_VERSION, EXECUTION_TIME, EXECUTOR_NAME, EXECUTOR_IP, DESCRIPTION) VALUES ('" + releaseVersion + "'," + version + " ,CURRENT_TIMESTAMP, SUSER_NAME(), CAST(CONNECTIONPROPERTY('client_net_address') AS VARCHAR(255)), '" + (releaseChanges.Changes.FirstOrDefault(x => x.Version == version).Description ?? "") + "');", tx); } executedVersions.Add(version); } tx.Commit(); Display.DisplayMessage(DisplayType.Success, "Successfulle executed change versions {0} in release {1} in database {2}", string.Join(", ", executedVersions), releaseVersion, database.Name); } catch (Exception ex) { string additionaMessage = string.Empty; string executingSqlText = string.Empty; if (executingChange != null) { additionaMessage += "\nException in Change \"" + executingChange.Version + "\" (" + (executingChange.Description ?? "") + ").\n"; } if (!string.IsNullOrEmpty(executingSql)) { executingSqlText = "\nException while executing SQL:\n" + executingSql; } Display.DisplayMessage(DisplayType.Error, "Exception occured while executing changes in release \"{0}\" in database \"{1}\".{2}\nException {3}{4}", releaseVersion, database.Name, additionaMessage, ex, executingSqlText); tx.Rollback(); } finally { databaseManager.CloseConnection(); } } }
public static void ExecuteChanges(DatabaseGroup databaseGroup, string releaseVersion) { ReleaseChanges releaseChanges = AsserValidReleaseVersion(releaseVersion); ExecuteChanges(databaseGroup, releaseVersion, releaseChanges.LastChangeVersion, false); }
public static void ExecuteChanges(DatabaseGroup databaseGroup) { ReleaseChanges latestReleaseChanges = ChangeReader.AllReleaseChanges.FirstOrDefault(x => x.IsLatestRelease); ExecuteChanges(databaseGroup, latestReleaseChanges.Name, latestReleaseChanges.LastChangeVersion, false); }