/// <summary> /// Script out the target database /// </summary> public void ScriptTarget() { try { //make sure we can run string error = null; if (RunOptions.Current.Connections.Targets.Count == 0) { error = "Missing a valid target database"; } if (error != null) { Exit(error, false); } //Load the target database ScriptParser targetParser = LoadTargetDatabase(null); //generate new scripts RunOptions.Current.Logger.Log("Generating Scripts", OutputLevel.Reads); DifferenceSet differences = null; ScriptSet scripts = targetParser.Database.CreateScripts(); //store the scripts ScriptManager.WriteScripts(scripts, differences); } catch (Exception ex) { Exit("Error: " + ex.Message, false); } Exit("Update Successful", true); }
/// <summary> /// Gets the differences between two sets. /// </summary> /// <param name="other">The other set of permissions to compare against.</param> /// <param name="differences">The set of differences to fill.</param> public void GetDifferences(PermissionSet other, DifferenceSet differences) { foreach (Name name in permissions.Keys) { if (IsDifferent(other, differences, name)) { differences.Add(new Difference(DifferenceType.CreatedPermission, name), null); } } }
private bool IsDifferent(PermissionSet other, DifferenceSet differences, Name name) { if (!other.permissions.ContainsKey(name)) { return(true); } foreach (SmallName account in permissions[name].Keys) { if (!other.permissions[name].ContainsKey(account)) { return(true); } foreach (SmallName grantType in permissions[name][account].Keys) { SmallName permission = permissions[name][account][grantType]; SmallName otherPermission = null; bool granted = other.permissions[name][account].ContainsKey(grantType); if (!granted && grantType == "exec" && other.permissions[name][account].ContainsKey("execute")) { granted = true; otherPermission = other.permissions[name][account]["execute"]; } if (!granted && grantType == "execute" && other.permissions[name][account].ContainsKey("exec")) { granted = true; otherPermission = other.permissions[name][account]["exec"]; } if (!granted) { return(true); } if (otherPermission == null) { otherPermission = other.permissions[name][account][grantType]; } if (permission != otherPermission) { return(true); } } } return(false); }
/// <summary> /// Gets the differences between this collection of items and another. /// </summary> /// <param name="other">The set of items to compare against.</param> /// <param name="dependencies">The dependencies for this collection.</param> /// <param name="otherDependencies">The dependencies for the other collection.</param> /// <param name="differences">The set of differences to fill.</param> public void GetDifferences(HashArray <T> other, DependencyCollection dependencies, DependencyCollection otherDependencies, DifferenceSet differences) { foreach (Item item in this) { Item otherItem = other == null ? null : other[item.Name]; Difference difference = item.GetDifferences(otherItem, true); if (difference != null) { differences.Add(difference, dependencies, otherDependencies); } } if (RunOptions.Current.FullyScripted && other != null) { foreach (Item otherItem in other) { if (this[otherItem.Name] == null) { differences.Add(new Difference(DifferenceType.Removed, otherItem.Name), otherDependencies); } } } }
/// <summary> /// The main functionality of the tool /// </summary> public void DoUpdate() { try { //make sure we can run string error = null; if (RunOptions.Current.Connections.Targets.Count == 0) { error = "Missing a valid target database"; } if (error != null) { Exit(error, false); } //Load any reference database ScriptSet referenceScripts = new ScriptSet(); ScriptParser referenceParser = new ScriptParser(); foreach (ConnectionInfo connection in RunOptions.Current.Connections.References) { switch (connection.Type) { case ConnectionType.Database: ScriptManager.ParseDatabase(referenceParser, connection.Path); ScriptManager.GetData(referenceParser.Database, RunOptions.Current.LoadData, connection.Path); break; case ConnectionType.Directory: referenceScripts.Add(ScriptManager.LoadScripts(connection.Path)); referenceParser.RetrieveParsableObjects(referenceScripts); break; case ConnectionType.File: referenceScripts.Add(ScriptManager.LoadScript(connection.Path)); referenceParser.RetrieveParsableObjects(referenceScripts); break; default: throw new Exception(connection.Type.ToString()); } } //Load the target database ScriptParser targetParser = LoadTargetDatabase(referenceParser); //generate new scripts RunOptions.Current.Logger.Log("Calculating Differences", OutputLevel.Reads); DifferenceSet differences = null; if (referenceParser.Database.IsEmpty) { referenceScripts = targetParser.Database.CreateDiffScripts(new Database()); } else { differences = referenceParser.Database.GetDifferences(targetParser.Database); if (targetParser.Database.IsEmpty && differences.Count > 0) { Console.WriteLine("Creating database schema"); } else { differences.Write(Console.Out); } referenceScripts.Add(referenceParser.Database.CreateDiffScripts(targetParser.Database, differences)); } //Make sure everything runs in the right order referenceScripts.Sort(); //store scripts if requested if (RunOptions.Current.ScriptOutputDirectory != "") { ScriptManager.WriteScripts(referenceScripts, differences); } if (!string.IsNullOrEmpty(RunOptions.Current.DiffFile)) { ScriptManager.WriteDifferenceSummary(referenceParser.Database, targetParser.Database, differences); } //run the scripts if (!RunOptions.Current.Test && RunOptions.Current.Connections.References.Count > 0) { if (RunOptions.Current.Connections.Targets.Count > 1) { throw new ApplicationException("Updating multiple targets is not supported"); } ScriptManager.ExecuteScripts(referenceScripts, RunOptions.Current.Connections.Targets[0].Path); } } catch (Exception ex) { Exit("Error: " + ex.Message, false); } Exit("Update Successful", true); }
/// <summary> /// Gets the differences between this database and another. /// </summary> /// <param name="other">The other database.</param> /// <returns></returns> public DifferenceSet GetDifferences(Database other) { CalculateDependencies(); other.CalculateDependencies(); DifferenceSet differences = new DifferenceSet(); //check table differences Tables.GetDifferences(other.Tables, dependencies, other.dependencies, differences); foreach (Table table in Tables) { Table otherTable = (Table)other.Tables[table.Name]; table.Indexes.GetDifferences(otherTable == null ? null : otherTable.Indexes, dependencies, other.dependencies, differences); if (!table.Data.AreEqual(otherTable == null ? null : otherTable.Data)) { differences.Add(new Difference(DifferenceType.TableData, table.Data.Name, table.Name), otherTable == null ? null : dependencies); } } foreach (Table otherTable in other.Tables) { Table table = (Table)Tables[otherTable.Name]; if (table == null) { foreach (Index index in otherTable.Indexes) { differences.Add(new Difference(DifferenceType.Removed, index.Name, otherTable.Name), other.dependencies); } } } //check constraint differences Constraints.GetDifferences(other.Constraints, dependencies, other.dependencies, differences); //deal with changing names... foreach (Constraint constraint in Constraints) { Table constrainedTable = other.Tables[constraint.ConstrainedTable]; if (constrainedTable == null) { continue; } if (constraint.Type == ConstraintType.Default) { foreach (Name dependency in other.dependencies[constrainedTable.Name]) { Constraint otherConstraint = other[dependency] as Constraint; if (otherConstraint != null && otherConstraint.Type == ConstraintType.Default && constraint.ConstrainedTable == otherConstraint.ConstrainedTable && constraint.ColumnsEqual(otherConstraint) && constraint != otherConstraint ) { differences.Add(new Difference(DifferenceType.Removed, otherConstraint.Name), other.dependencies); break; } } } else if (constraint.Type == ConstraintType.ForeignKey && other.Tables[constraint.ConstrainedTable] != null) { foreach (Name dependency in other.dependencies[constrainedTable.Name]) { Constraint otherConstraint = other[dependency] as Constraint; if (otherConstraint != null && otherConstraint.Type == ConstraintType.ForeignKey && constraint.ConstrainedTable == otherConstraint.ConstrainedTable && constraint.ReferencedTable == otherConstraint.ReferencedTable && constraint.ColumnsEqual(otherConstraint) && constraint != otherConstraint ) { differences.Add(new Difference(DifferenceType.Removed, otherConstraint.Name), other.dependencies); break; } } } else if (constraint.Type == ConstraintType.PrimaryKey && other.Tables[constraint.ConstrainedTable] != null) { foreach (Name dependency in other.dependencies[constrainedTable.Name]) { Constraint otherConstraint = other[dependency] as Constraint; if (otherConstraint != null && otherConstraint.Type == ConstraintType.PrimaryKey && constraint.ConstrainedTable == otherConstraint.ConstrainedTable && constraint != otherConstraint ) { differences.Add(new Difference(DifferenceType.Removed, otherConstraint.Name), other.dependencies); break; } } } } //check function differences Functions.GetDifferences(other.Functions, dependencies, other.dependencies, differences); //check fulltext catalog differences FulltextCatalogs.GetDifferences(other.FulltextCatalogs, dependencies, other.dependencies, differences); //check fulltext index differences FulltextIndexes.GetDifferences(other.FulltextIndexes, dependencies, other.dependencies, differences); //check procedure differences Procedures.GetDifferences(other.Procedures, dependencies, other.dependencies, differences); //check trigger differences Triggers.GetDifferences(other.Triggers, dependencies, other.dependencies, differences); //check trigger order differences TriggerOrder.GetDifferences(other.TriggerOrder, dependencies, other.dependencies, differences); //check view differences Views.GetDifferences(other.Views, dependencies, other.dependencies, differences); foreach (View view in Views) { View otherView = (View)other.Views[view.Name]; view.Indexes.GetDifferences(otherView == null ? null : otherView.Indexes, dependencies, other.dependencies, differences); } foreach (View view in Views) { View otherView = (View)other.Views[view.Name]; if (otherView != null) { view.Indexes.GetDifferences(otherView.Indexes, dependencies, other.dependencies, differences); } } //check for new permissions Permissions.GetDifferences(other.Permissions, differences); return(differences); }
/// <summary> /// Generates the scripts required to turn another <see cref="Database"/> into a copy of this one. /// </summary> /// <param name="other">Another <see cref="Database"/>.</param> /// <param name="differences">The differences between these databases.</param> /// <returns></returns> public ScriptSet CreateDiffScripts(Database other, DifferenceSet differences) { ScriptSet scripts = new ScriptSet(); foreach (Difference difference in differences) { Item adding = null; Item removing = null; switch (difference.DifferenceType) { case DifferenceType.Created: adding = this[difference.Item]; scripts.Add(adding.GenerateCreateScript()); scripts.Add(Permissions.GenerateCreateScript(adding)); break; case DifferenceType.CreatedPermission: adding = this[difference.Item]; scripts.Add(Permissions.GenerateCreateScript(adding == null ? other[difference.Item] : adding)); break; case DifferenceType.Dependency: case DifferenceType.Modified: adding = this[difference.Item]; removing = other[difference.Item]; if (adding is Table && !((Table)adding).IsType) { scripts.Add(((Table)removing).GenerateSaveScript()); scripts.Add(((Table)adding).GenerateCreateScript()); scripts.Add(((Table)adding).GenerateRestoreScript(((Table)removing))); } else { scripts.Add(removing.GenerateDropScript()); if (adding != null) { scripts.Add(adding.GenerateCreateScript()); } } if (adding != null) { scripts.Add(Permissions.GenerateCreateScript(adding)); } break; case DifferenceType.Removed: removing = other[difference.Item]; if (removing is Table) { if (RunOptions.Current.FullyScripted) { scripts.Add(removing.GenerateDropScript()); } } else { scripts.Add(removing.GenerateDropScript()); } break; case DifferenceType.TableData: TableData newData = Tables[difference.ParentItem].Data; Table oldTable = other.Tables[difference.ParentItem]; TableData oldData = oldTable == null ? null : oldTable.Data; scripts.Add(newData.GetDifferenceScript(oldData, difference.ParentItem)); break; default: throw new ApplicationException(difference.DifferenceType.ToString()); } } return(scripts); }