Initial commit
This commit is contained in:
126
OpenDBDiff.Schema.SQLServer.Generates/Model/Assembly.cs
Normal file
126
OpenDBDiff.Schema.SQLServer.Generates/Model/Assembly.cs
Normal file
@@ -0,0 +1,126 @@
|
||||
using System;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class Assembly : Code
|
||||
{
|
||||
public Assembly(ISchemaBase parent)
|
||||
: base(parent, ObjectType.Assembly, ScriptAction.AddAssembly, ScriptAction.DropAssembly)
|
||||
{
|
||||
Files = new SchemaList<AssemblyFile, Assembly>(this);
|
||||
}
|
||||
|
||||
public override ISchemaBase Clone(ISchemaBase parent)
|
||||
{
|
||||
Assembly item = new Assembly(parent)
|
||||
{
|
||||
Id = this.Id,
|
||||
Name = this.Name,
|
||||
Owner = this.Owner,
|
||||
Visible = this.Visible,
|
||||
Text = this.Text,
|
||||
PermissionSet = this.PermissionSet,
|
||||
CLRName = this.CLRName,
|
||||
Guid = this.Guid,
|
||||
Files = this.Files
|
||||
};
|
||||
this.DependenciesOut.ForEach(dep => item.DependenciesOut.Add(dep));
|
||||
this.ExtendedProperties.ForEach(ep => item.ExtendedProperties.Add(ep));
|
||||
return item;
|
||||
}
|
||||
|
||||
public SchemaList<AssemblyFile, Assembly> Files { get; set; }
|
||||
|
||||
public override string FullName
|
||||
{
|
||||
get { return "[" + Name + "]"; }
|
||||
}
|
||||
|
||||
public string CLRName { get; set; }
|
||||
|
||||
public bool Visible { get; set; }
|
||||
|
||||
public string PermissionSet { get; set; }
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
string access = PermissionSet;
|
||||
if (PermissionSet.Equals("UNSAFE_ACCESS")) access = "UNSAFE";
|
||||
if (PermissionSet.Equals("SAFE_ACCESS")) access = "SAFE";
|
||||
string toSql = "CREATE ASSEMBLY ";
|
||||
toSql += FullName + "\r\n";
|
||||
toSql += "AUTHORIZATION " + Owner + "\r\n";
|
||||
toSql += "FROM " + Text + "\r\n";
|
||||
toSql += "WITH PERMISSION_SET = " + access + "\r\n";
|
||||
toSql += "GO\r\n";
|
||||
toSql += Files.ToSql();
|
||||
toSql += this.ExtendedProperties.ToSql();
|
||||
return toSql;
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
return "DROP ASSEMBLY " + FullName + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
return ToSql();
|
||||
}
|
||||
|
||||
private string ToSQLAlter()
|
||||
{
|
||||
string access = PermissionSet;
|
||||
if (PermissionSet.Equals("UNSAFE_ACCESS")) access = "UNSAFE";
|
||||
if (PermissionSet.Equals("SAFE_ACCESS")) access = "SAFE";
|
||||
return "ALTER ASSEMBLY " + FullName + " WITH PERMISSION_SET = " + access + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
private string ToSQLAlterOwner()
|
||||
{
|
||||
return "ALTER AUTHORIZATION ON ASSEMBLY::" + FullName + " TO " + Owner + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
|
||||
if (this.Status == ObjectStatus.Drop)
|
||||
{
|
||||
list.AddRange(RebuildDependencies());
|
||||
list.Add(Drop());
|
||||
}
|
||||
if (this.Status == ObjectStatus.Create)
|
||||
list.Add(Create());
|
||||
if (this.HasState(ObjectStatus.Rebuild))
|
||||
list.AddRange(Rebuild());
|
||||
if (this.HasState(ObjectStatus.ChangeOwner))
|
||||
list.Add(ToSQLAlterOwner(), 0, ScriptAction.AlterAssembly);
|
||||
if (this.HasState(ObjectStatus.PermissionSet))
|
||||
list.Add(ToSQLAlter(), 0, ScriptAction.AlterAssembly);
|
||||
if (this.HasState(ObjectStatus.Alter))
|
||||
list.AddRange(Files.ToSqlDiff());
|
||||
list.AddRange(this.ExtendedProperties.ToSqlDiff());
|
||||
return list;
|
||||
}
|
||||
|
||||
public bool Compare(Assembly obj)
|
||||
{
|
||||
if (obj == null) throw new ArgumentNullException("obj");
|
||||
if (!this.CLRName.Equals(obj.CLRName)) return false;
|
||||
if (!this.PermissionSet.Equals(obj.PermissionSet)) return false;
|
||||
if (!this.Owner.Equals(obj.Owner)) return false;
|
||||
if (!this.Text.Equals(obj.Text)) return false;
|
||||
if (this.Files.Count != obj.Files.Count) return false;
|
||||
for (int j = 0; j < this.Files.Count; j++)
|
||||
if (!this.Files[j].Content.Equals(obj.Files[j].Content)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override Boolean IsCodeType
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
}
|
||||
}
|
||||
67
OpenDBDiff.Schema.SQLServer.Generates/Model/AssemblyFile.cs
Normal file
67
OpenDBDiff.Schema.SQLServer.Generates/Model/AssemblyFile.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class AssemblyFile : SQLServerSchemaBase
|
||||
{
|
||||
public AssemblyFile(ISchemaBase parent, AssemblyFile assemblyFile, ObjectStatus status)
|
||||
: base(parent, ObjectType.AssemblyFile)
|
||||
{
|
||||
this.Name = assemblyFile.Name;
|
||||
this.Content = assemblyFile.Content;
|
||||
this.Status = status;
|
||||
}
|
||||
|
||||
public AssemblyFile(ISchemaBase parent, string name, string content)
|
||||
: base(parent, ObjectType.AssemblyFile)
|
||||
{
|
||||
this.Name = name;
|
||||
this.Content = content;
|
||||
}
|
||||
|
||||
public override string FullName
|
||||
{
|
||||
get { return "[" + Name + "]"; }
|
||||
}
|
||||
|
||||
public string Content { get; set; }
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
string sql = "ALTER ASSEMBLY ";
|
||||
sql += this.Parent.FullName + "\r\n";
|
||||
sql += "ADD FILE FROM " + this.Content + "\r\n";
|
||||
sql += "AS N'" + this.Name + "'\r\n";
|
||||
return sql + "GO\r\n";
|
||||
}
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
return ToSqlAdd();
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
string sql = "ALTER ASSEMBLY ";
|
||||
sql += this.Parent.FullName + "\r\n";
|
||||
sql += "DROP FILE N'" + this.Name + "'\r\n";
|
||||
return sql + "GO\r\n";
|
||||
}
|
||||
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList listDiff = new SQLScriptList();
|
||||
|
||||
if (this.Status == ObjectStatus.Drop)
|
||||
listDiff.Add(ToSqlDrop(), 0, ScriptAction.DropAssemblyFile);
|
||||
if (this.Status == ObjectStatus.Create)
|
||||
listDiff.Add(ToSqlAdd(), 0, ScriptAction.AddAssemblyFile);
|
||||
if (this.HasState(ObjectStatus.Alter))
|
||||
{
|
||||
listDiff.Add(ToSqlDrop(), 0, ScriptAction.DropAssemblyFile);
|
||||
listDiff.Add(ToSqlAdd(), 0, ScriptAction.AddAssemblyFile);
|
||||
}
|
||||
return listDiff;
|
||||
}
|
||||
}
|
||||
}
|
||||
30
OpenDBDiff.Schema.SQLServer.Generates/Model/CLRCode.cs
Normal file
30
OpenDBDiff.Schema.SQLServer.Generates/Model/CLRCode.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public abstract class CLRCode : Code
|
||||
{
|
||||
public CLRCode(ISchemaBase parent, ObjectType type, ScriptAction addAction, ScriptAction dropAction)
|
||||
: base(parent, type, addAction, dropAction)
|
||||
{
|
||||
}
|
||||
|
||||
public string AssemblyMethod { get; set; }
|
||||
|
||||
public string AssemblyExecuteAs { get; set; }
|
||||
|
||||
public string AssemblyName { get; set; }
|
||||
|
||||
public Boolean IsAssembly { get; set; }
|
||||
|
||||
public string AssemblyClass { get; set; }
|
||||
|
||||
public int AssemblyId { get; set; }
|
||||
|
||||
public override Boolean IsCodeType
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
}
|
||||
}
|
||||
56
OpenDBDiff.Schema.SQLServer.Generates/Model/CLRFunction.cs
Normal file
56
OpenDBDiff.Schema.SQLServer.Generates/Model/CLRFunction.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class CLRFunction : CLRCode
|
||||
{
|
||||
public CLRFunction(ISchemaBase parent)
|
||||
: base(parent, ObjectType.CLRFunction, ScriptAction.AddFunction, ScriptAction.DropFunction)
|
||||
{
|
||||
Parameters = new List<Parameter>();
|
||||
ReturnType = new Parameter();
|
||||
}
|
||||
|
||||
public List<Parameter> Parameters { get; set; }
|
||||
|
||||
public Parameter ReturnType { get; private set; }
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
string sql = "CREATE FUNCTION " + FullName + "";
|
||||
string param = "";
|
||||
Parameters.ForEach(item => param += item.ToSql() + ",");
|
||||
if (!String.IsNullOrEmpty(param))
|
||||
{
|
||||
param = param.Substring(0, param.Length - 1);
|
||||
sql += " (" + param + ")\r\n";
|
||||
}
|
||||
else
|
||||
sql += "()\r\n";
|
||||
sql += "RETURNS " + ReturnType.ToSql() + " ";
|
||||
sql += "WITH EXECUTE AS " + AssemblyExecuteAs + "\r\n";
|
||||
sql += "AS\r\n";
|
||||
sql += "EXTERNAL NAME [" + AssemblyName + "].[" + AssemblyClass + "].[" + AssemblyMethod + "]\r\n";
|
||||
sql += "GO\r\n";
|
||||
return sql;
|
||||
}
|
||||
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
|
||||
if (this.HasState(ObjectStatus.Drop))
|
||||
list.Add(Drop());
|
||||
if (this.HasState(ObjectStatus.Create))
|
||||
list.Add(Create());
|
||||
if (this.Status == ObjectStatus.Alter)
|
||||
{
|
||||
list.AddRange(Rebuild());
|
||||
}
|
||||
list.AddRange(this.ExtendedProperties.ToSqlDiff());
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class CLRStoredProcedure : CLRCode
|
||||
{
|
||||
public CLRStoredProcedure(ISchemaBase parent)
|
||||
: base(parent, ObjectType.CLRStoredProcedure, ScriptAction.AddStoredProcedure, ScriptAction.DropStoredProcedure)
|
||||
{
|
||||
Parameters = new List<Parameter>();
|
||||
}
|
||||
|
||||
public List<Parameter> Parameters { get; set; }
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
string sql = "CREATE PROCEDURE " + FullName + "\r\n";
|
||||
string param = "";
|
||||
Parameters.ForEach(item => param += "\t" + item.ToSql() + ",\r\n");
|
||||
if (!String.IsNullOrEmpty(param)) param = param.Substring(0, param.Length - 3) + "\r\n";
|
||||
sql += param;
|
||||
sql += "WITH EXECUTE AS " + AssemblyExecuteAs + "\r\n";
|
||||
sql += "AS\r\n";
|
||||
sql += "EXTERNAL NAME [" + AssemblyName + "].[" + AssemblyClass + "].[" + AssemblyMethod + "]\r\n";
|
||||
sql += "GO\r\n";
|
||||
return sql;
|
||||
}
|
||||
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
|
||||
if (this.HasState(ObjectStatus.Drop))
|
||||
list.Add(Drop());
|
||||
if (this.HasState(ObjectStatus.Create))
|
||||
list.Add(Create());
|
||||
if (this.Status == ObjectStatus.Alter)
|
||||
{
|
||||
list.AddRange(Rebuild());
|
||||
}
|
||||
list.AddRange(this.ExtendedProperties.ToSqlDiff());
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
48
OpenDBDiff.Schema.SQLServer.Generates/Model/CLRTrigger.cs
Normal file
48
OpenDBDiff.Schema.SQLServer.Generates/Model/CLRTrigger.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class CLRTrigger : CLRCode
|
||||
{
|
||||
public CLRTrigger(ISchemaBase parent)
|
||||
: base(parent, ObjectType.CLRTrigger, ScriptAction.AddTrigger, ScriptAction.DropTrigger)
|
||||
{
|
||||
}
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
string sql = "CREATE TRIGGER " + FullName + " ON " + Parent.FullName;
|
||||
sql += " AFTER ";
|
||||
if (IsInsert) sql += "INSERT,";
|
||||
if (IsUpdate) sql += "UPDATE,";
|
||||
if (IsDelete) sql += "DELETE,";
|
||||
sql = sql.Substring(0, sql.Length - 1) + " ";
|
||||
sql += "AS\r\n";
|
||||
sql += "EXTERNAL NAME [" + AssemblyName + "].[" + AssemblyClass + "].[" + AssemblyMethod + "]\r\n";
|
||||
sql += "GO\r\n";
|
||||
return sql;
|
||||
}
|
||||
|
||||
public bool IsUpdate { get; set; }
|
||||
|
||||
public bool IsInsert { get; set; }
|
||||
|
||||
public bool IsDelete { get; set; }
|
||||
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
|
||||
if (this.HasState(ObjectStatus.Drop))
|
||||
list.Add(Drop());
|
||||
if (this.HasState(ObjectStatus.Create))
|
||||
list.Add(Create());
|
||||
if (this.Status == ObjectStatus.Alter)
|
||||
{
|
||||
list.AddRange(Rebuild());
|
||||
}
|
||||
list.AddRange(this.ExtendedProperties.ToSqlDiff());
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
256
OpenDBDiff.Schema.SQLServer.Generates/Model/Code.cs
Normal file
256
OpenDBDiff.Schema.SQLServer.Generates/Model/Code.cs
Normal file
@@ -0,0 +1,256 @@
|
||||
using OpenDBDiff.Schema.Model;
|
||||
using OpenDBDiff.Schema.SQLServer.Generates.Model.Util;
|
||||
using OpenDBDiff.Schema.SQLServer.Generates.Options;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public abstract class Code : SQLServerSchemaBase, ICode
|
||||
{
|
||||
protected string sql = null;
|
||||
protected string typeName = "";
|
||||
private int deepMax = 0;
|
||||
private int deepMin = 0;
|
||||
private ScriptAction addAction;
|
||||
private ScriptAction dropAction;
|
||||
|
||||
public Code(ISchemaBase parent, ObjectType type, ScriptAction addAction, ScriptAction dropAction)
|
||||
: base(parent, type)
|
||||
{
|
||||
DependenciesIn = new List<String>();
|
||||
DependenciesOut = new List<String>();
|
||||
typeName = GetObjectTypeName(ObjectType);
|
||||
/*Por el momento, solo los Assemblys manejan deep de dependencias*/
|
||||
if (this.ObjectType == ObjectType.Assembly)
|
||||
{
|
||||
deepMax = 501;
|
||||
deepMin = 500;
|
||||
}
|
||||
this.addAction = addAction;
|
||||
this.dropAction = dropAction;
|
||||
}
|
||||
|
||||
public override SQLScript Create()
|
||||
{
|
||||
int iCount = DependenciesCount;
|
||||
if (iCount > 0) iCount = iCount * -1;
|
||||
if (!GetWasInsertInDiffList(addAction))
|
||||
{
|
||||
SetWasInsertInDiffList(addAction);
|
||||
return new SQLScript(this.ToSqlAdd(), iCount, addAction);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public override SQLScript Drop()
|
||||
{
|
||||
int iCount = DependenciesCount;
|
||||
if (!GetWasInsertInDiffList(dropAction))
|
||||
{
|
||||
SetWasInsertInDiffList(dropAction);
|
||||
return new SQLScript(this.ToSqlDrop(), iCount, dropAction);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetObjectTypeName(ObjectType type)
|
||||
{
|
||||
if (type == ObjectType.Rule) return "RULE";
|
||||
if (type == ObjectType.Trigger) return "TRIGGER";
|
||||
if (type == ObjectType.View) return "VIEW";
|
||||
if (type == ObjectType.Function) return "FUNCTION";
|
||||
if (type == ObjectType.StoredProcedure) return "PROCEDURE";
|
||||
if (type == ObjectType.CLRStoredProcedure) return "PROCEDURE";
|
||||
if (type == ObjectType.CLRTrigger) return "TRIGGER";
|
||||
if (type == ObjectType.CLRFunction) return "FUNCTION";
|
||||
if (type == ObjectType.Assembly) return "ASSEMBLY";
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Names collection of dependant objects of the object
|
||||
/// </summary>
|
||||
public List<String> DependenciesOut { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Names collection of objects which the object depends on
|
||||
/// </summary>
|
||||
public List<String> DependenciesIn { get; set; }
|
||||
|
||||
public Boolean IsSchemaBinding { get; set; }
|
||||
|
||||
public string Text { get; set; }
|
||||
|
||||
public override int DependenciesCount
|
||||
{
|
||||
get
|
||||
{
|
||||
int iCount = 0;
|
||||
if (this.DependenciesOut.Any())
|
||||
{
|
||||
Dictionary<string, bool> depencyTracker = new Dictionary<string, bool>();
|
||||
iCount = DependenciesCountFilter(this.FullName, depencyTracker);
|
||||
}
|
||||
return iCount;
|
||||
}
|
||||
}
|
||||
|
||||
private int DependenciesCountFilter(string FullName, Dictionary<string, bool> depencyTracker)
|
||||
{
|
||||
int count = 0;
|
||||
ICode item;
|
||||
try
|
||||
{
|
||||
item = (ICode)((Database)Parent).Find(FullName);
|
||||
if (item != null)
|
||||
{
|
||||
for (int j = 0; j < item.DependenciesOut.Count; j++)
|
||||
{
|
||||
if (!depencyTracker.ContainsKey(FullName.ToUpper()))
|
||||
{
|
||||
depencyTracker.Add(FullName.ToUpper(), true);
|
||||
}
|
||||
count += 1 + DependenciesCountFilter(item.DependenciesOut[j], depencyTracker);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if there are dependant tables on the object which must be rebuild
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Boolean HasToRebuild
|
||||
{
|
||||
get
|
||||
{
|
||||
for (int j = 0; j < DependenciesIn.Count; j++)
|
||||
{
|
||||
ISchemaBase item = ((Database)Parent).Find(DependenciesIn[j]);
|
||||
if (item != null)
|
||||
{
|
||||
if ((item.Status == ObjectStatus.Rebuild) || (item.Status == ObjectStatus.RebuildDependencies))
|
||||
return true;
|
||||
}
|
||||
};
|
||||
return IsSchemaBinding;
|
||||
}
|
||||
}
|
||||
|
||||
private SQLScriptList RebuildDependencies(List<string> depends, int deepMin, int deepMax)
|
||||
{
|
||||
int newDeepMax = (deepMax != 0) ? deepMax + 1 : 0;
|
||||
int newDeepMin = (deepMin != 0) ? deepMin - 1 : 0;
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
for (int j = 0; j < depends.Count; j++)
|
||||
{
|
||||
ISchemaBase item = ((Database)Parent).Find(depends[j]);
|
||||
if (item != null)
|
||||
{
|
||||
if ((item.Status != ObjectStatus.Create) && (item.Status != ObjectStatus.Drop))
|
||||
{
|
||||
if ((item.ObjectType != ObjectType.CLRStoredProcedure) && (item.ObjectType != ObjectType.Assembly) && (item.ObjectType != ObjectType.UserDataType) && (item.ObjectType != ObjectType.View) && (item.ObjectType != ObjectType.Function))
|
||||
{
|
||||
newDeepMin = 0;
|
||||
newDeepMax = 0;
|
||||
}
|
||||
if (item.Status != ObjectStatus.Drop)
|
||||
{
|
||||
if (!((item.Parent.HasState(ObjectStatus.Rebuild)) && (item.ObjectType == ObjectType.Trigger)))
|
||||
list.Add(item.Drop(), newDeepMin);
|
||||
}
|
||||
if ((this.Status != ObjectStatus.Drop) && (item.Status != ObjectStatus.Create))
|
||||
list.Add(item.Create(), newDeepMax);
|
||||
if (item.IsCodeType)
|
||||
list.AddRange(RebuildDependencies(((ICode)item).DependenciesOut, newDeepMin, newDeepMax));
|
||||
}
|
||||
}
|
||||
};
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rebuilds the object and all its dependant objects.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public SQLScriptList Rebuild()
|
||||
{
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
list.AddRange(RebuildDependencies());
|
||||
if (this.Status != ObjectStatus.Create) list.Add(Drop(), deepMin);
|
||||
if (this.Status != ObjectStatus.Drop) list.Add(Create(), deepMax);
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rebuilds the dependant objects.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public SQLScriptList RebuildDependencies()
|
||||
{
|
||||
return RebuildDependencies(this.DependenciesOut, deepMin, deepMax);
|
||||
}
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
if (String.IsNullOrEmpty(sql))
|
||||
sql = FormatCode.FormatCreate(typeName, Text, this);
|
||||
return sql;
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
string sql = ToSql();
|
||||
sql += this.ExtendedProperties.ToSql();
|
||||
return sql;
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
return String.Format("DROP {0} {1}\r\nGO\r\n", typeName, FullName);
|
||||
}
|
||||
|
||||
public virtual bool CompareExceptWhitespace(ICode obj)
|
||||
{
|
||||
if (obj == null) throw new ArgumentNullException("obj");
|
||||
string sql1 = this.ToSql();
|
||||
string sql2 = obj.ToSql();
|
||||
|
||||
Regex whitespace = new Regex(@"\s");
|
||||
sql1 = whitespace.Replace(this.ToSql(), "");
|
||||
sql2 = whitespace.Replace(obj.ToSql(), "");
|
||||
|
||||
if (((Database)RootParent).Options.Comparison.CaseSensityInCode == Options.SqlOptionComparison.CaseSensityOptions.CaseInsensity)
|
||||
return (sql1.Equals(sql2, StringComparison.InvariantCultureIgnoreCase));
|
||||
|
||||
return (sql1.Equals(sql2, StringComparison.InvariantCulture));
|
||||
}
|
||||
|
||||
public virtual bool Compare(ICode obj)
|
||||
{
|
||||
if (obj == null) throw new ArgumentNullException("obj");
|
||||
string sql1 = this.ToSql();
|
||||
string sql2 = obj.ToSql();
|
||||
if (((Database)RootParent).Options.Comparison.IgnoreWhiteSpacesInCode)
|
||||
{
|
||||
Regex whitespace = new Regex(@"\s");
|
||||
sql1 = whitespace.Replace(this.ToSql(), "");
|
||||
sql2 = whitespace.Replace(obj.ToSql(), "");
|
||||
}
|
||||
if (((Database)RootParent).Options.Comparison.CaseSensityInCode == SqlOptionComparison.CaseSensityOptions.CaseInsensity)
|
||||
return (sql1.Equals(sql2, StringComparison.InvariantCultureIgnoreCase));
|
||||
|
||||
return (sql1.Equals(sql2, StringComparison.InvariantCulture));
|
||||
}
|
||||
}
|
||||
}
|
||||
641
OpenDBDiff.Schema.SQLServer.Generates/Model/Column.cs
Normal file
641
OpenDBDiff.Schema.SQLServer.Generates/Model/Column.cs
Normal file
@@ -0,0 +1,641 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Xml.Serialization;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class Column : SQLServerSchemaBase, IComparable<Column>
|
||||
{
|
||||
public Column(ISchemaBase parent)
|
||||
: base(parent, ObjectType.Column)
|
||||
{
|
||||
ComputedFormula = "";
|
||||
Collation = "";
|
||||
this.Default = new Default(this);
|
||||
this.Rule = new Rule(this);
|
||||
this.DefaultConstraint = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clona el objeto Column en una nueva instancia.
|
||||
/// </summary>
|
||||
public new Column Clone(ISchemaBase parent)
|
||||
{
|
||||
Column col;
|
||||
if (parent == null)
|
||||
col = new Column(this.Parent);
|
||||
else
|
||||
col = new Column(parent);
|
||||
col.ComputedFormula = this.ComputedFormula;
|
||||
col.DataUserTypeId = this.DataUserTypeId;
|
||||
col.Id = this.Id;
|
||||
col.Guid = this.Guid;
|
||||
col.Owner = this.Owner;
|
||||
col.IdentityIncrement = this.IdentityIncrement;
|
||||
col.IdentitySeed = this.IdentitySeed;
|
||||
col.IsIdentity = this.IsIdentity;
|
||||
col.IsIdentityForReplication = this.IsIdentityForReplication;
|
||||
col.IsComputed = this.IsComputed;
|
||||
col.IsRowGuid = this.IsRowGuid;
|
||||
col.IsPersisted = this.IsPersisted;
|
||||
col.IsFileStream = this.IsFileStream;
|
||||
col.IsSparse = this.IsSparse;
|
||||
col.IsXmlDocument = this.IsXmlDocument;
|
||||
col.IsUserDefinedType = this.IsUserDefinedType;
|
||||
col.HasComputedDependencies = this.HasComputedDependencies;
|
||||
col.HasIndexDependencies = this.HasIndexDependencies;
|
||||
col.Name = this.Name;
|
||||
col.IsNullable = this.IsNullable;
|
||||
col.Position = this.Position;
|
||||
col.Precision = this.Precision;
|
||||
col.Scale = this.Scale;
|
||||
col.Collation = this.Collation;
|
||||
col.Size = this.Size;
|
||||
col.Status = this.Status;
|
||||
col.Type = this.Type;
|
||||
col.XmlSchema = this.XmlSchema;
|
||||
col.Default = this.Default.Clone(this);
|
||||
col.Rule = this.Rule.Clone(this);
|
||||
if (this.DefaultConstraint != null)
|
||||
col.DefaultConstraint = this.DefaultConstraint.Clone(this);
|
||||
return col;
|
||||
}
|
||||
|
||||
public ColumnConstraint DefaultConstraint { get; set; }
|
||||
|
||||
public Rule Rule { get; set; }
|
||||
|
||||
public Default Default { get; set; }
|
||||
|
||||
public Boolean IsFileStream { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is XML document.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance is XML document; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public Boolean IsXmlDocument { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the XML schema.
|
||||
/// </summary>
|
||||
/// <value>The XML schema.</value>
|
||||
public string XmlSchema { get; set; }
|
||||
|
||||
public Boolean IsSparse { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is user defined type.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance is user defined type; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public Boolean IsUserDefinedType { get; set; }
|
||||
|
||||
public int DataUserTypeId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the column position.
|
||||
/// </summary>
|
||||
/// <value>The position.</value>
|
||||
public int Position { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the scale (only in numeric or decimal datatypes).
|
||||
/// </summary>
|
||||
/// <value>The scale.</value>
|
||||
public int Scale { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the precision (only in numeric or decimal datatypes).
|
||||
/// </summary>
|
||||
/// <value>The precision.</value>
|
||||
public int Precision { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the collation (only in text datatypes).
|
||||
/// </summary>
|
||||
/// <value>The collation.</value>
|
||||
public string Collation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="Column"/> is nullable.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if nullable; otherwise, <c>false</c>.</value>
|
||||
public Boolean IsNullable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the size.
|
||||
/// </summary>
|
||||
/// <value>The size.</value>
|
||||
public int Size { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type.
|
||||
/// </summary>
|
||||
/// <value>The type.</value>
|
||||
public string Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is persisted (only in Computed columns).
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance is persisted; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public Boolean IsPersisted { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance has index dependencies.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance has index dependencies; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public Boolean HasIndexDependencies { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance has computed dependencies.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance has computed dependencies; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public Boolean HasComputedDependencies { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance has to rebuild only constraint.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance has to rebuild only constraint; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public Boolean HasToRebuildOnlyConstraint
|
||||
{
|
||||
get
|
||||
{
|
||||
return (HasIndexDependencies && !HasComputedDependencies && !IsComputed);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance has to rebuild.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance has to rebuild; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public Boolean HasToRebuild(int newPosition, string newType, bool isFileStream)
|
||||
{
|
||||
if (newType.Equals("text") && (!this.IsText)) return true;
|
||||
if (newType.Equals("ntext") && (!this.IsText)) return true;
|
||||
if (newType.Equals("image") && (!this.IsBinary)) return true;
|
||||
if (isFileStream != this.IsFileStream) return true;
|
||||
return ((Position != newPosition) || HasComputedDependencies || HasIndexDependencies || IsComputed || Type.ToLower().Equals("timestamp"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the computed formula (only in Computed columns).
|
||||
/// </summary>
|
||||
/// <value>The computed formula.</value>
|
||||
public string ComputedFormula { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is computed.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance is computed; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public Boolean IsComputed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this column is BLOB.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this column is BLOB; otherwise, <c>false</c>.</value>
|
||||
public Boolean IsBLOB
|
||||
{
|
||||
get
|
||||
{
|
||||
return Type.Equals("varchar(MAX)") || Type.Equals("nvarchar(MAX)") || Type.Equals("varbinary(MAX)") || Type.Equals("text") || Type.Equals("image") || Type.Equals("ntext") || Type.Equals("xml");
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean IsText
|
||||
{
|
||||
get
|
||||
{
|
||||
return Type.Equals("varchar(MAX)") || Type.Equals("nvarchar(MAX)") || Type.Equals("ntext") || Type.Equals("text") || Type.Equals("nvarchar") || Type.Equals("varchar") || Type.Equals("xml") || Type.Equals("char") || Type.Equals("nchar");
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean IsBinary
|
||||
{
|
||||
get
|
||||
{
|
||||
return Type.Equals("varbinary") || Type.Equals("varbinary(MAX)") || Type.Equals("image") || Type.Equals("binary");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this field is identity for replication.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this field is identity for replication; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public Boolean IsIdentityForReplication { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this field is identity.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this field is identity; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public Boolean IsIdentity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the identity increment (only if the field is Identity).
|
||||
/// </summary>
|
||||
/// <value>The identity increment.</value>
|
||||
public int IdentityIncrement { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the identity seed (only if the field is Identity).
|
||||
/// </summary>
|
||||
/// <value>The identity seed.</value>
|
||||
public long IdentitySeed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indica si el campo es Row Guid
|
||||
/// </summary>
|
||||
public Boolean IsRowGuid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Nombre completo del objeto, incluyendo el owner.
|
||||
/// </summary>
|
||||
public override string FullName
|
||||
{
|
||||
get
|
||||
{
|
||||
return Parent.FullName + ".[" + Name + "]";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convierte el schema de la tabla en XML.
|
||||
/// </summary>
|
||||
public string ToXML()
|
||||
{
|
||||
/*string xml = "";
|
||||
xml += "<COLUMN name=\"" + Name + "\" HasIndexDependencies=\"" + (hasIndexDependencies ? "1" : "0") + "\" HasComputedDependencies=\"" + (hasComputedDependencies ? "1" : "0") + "\" IsRowGuid=\"" + (isRowGuid ? "1" : "0") + "\" IsComputed=\"" + (isComputed ? "1" : "0") + "\" computedFormula=\"" + computedFormula + "\">\n";
|
||||
xml += "<TYPE>" + type + "</TYPE>";
|
||||
xml += "<ORIGINALTYPE>" + OriginalType + "</ORIGINALTYPE>";
|
||||
xml += "<SIZE>" + size.ToString() + "</SIZE>";
|
||||
xml += "<NULLABLE>" + (nullable ? "1":"0") + "</NULLABLE>";
|
||||
xml += "<PREC>" + precision.ToString() + "</PREC>";
|
||||
xml += "<SCALE>" + scale.ToString() + "</SCALE>";
|
||||
if (this.identity)
|
||||
xml += "<IDENTITY seed=\"" + identitySeed.ToString() + "\",increment=\"" + identityIncrement.ToString() + "\"/>";
|
||||
if (this.identityForReplication)
|
||||
xml += "<IDENTITYNOTFORREPLICATION seed=\"" + identitySeed.ToString() + "\",increment=\"" + identityIncrement.ToString() + "\"/>";
|
||||
xml += constraints.ToXML();
|
||||
xml += "</COLUMN>\n";
|
||||
return xml;*/
|
||||
XmlSerializer serial = new XmlSerializer(this.GetType());
|
||||
return serial.ToString();
|
||||
}
|
||||
|
||||
public Boolean HasToForceValue
|
||||
{
|
||||
get
|
||||
{
|
||||
return (this.HasState(ObjectStatus.Update)) || ((!this.IsNullable) && (this.Status == ObjectStatus.Create));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default force value.
|
||||
/// </summary>
|
||||
/// <value>The default force value.</value>
|
||||
public string DefaultForceValue
|
||||
{
|
||||
get
|
||||
{
|
||||
string tl = this.Type;
|
||||
if (this.IsUserDefinedType)
|
||||
tl = ((Database)this.Parent.Parent).UserTypes[Type].Type.ToLower();
|
||||
|
||||
if ((((Database)Parent.Parent).Options.Defaults.UseDefaultValueIfExists) && (this.DefaultConstraint != null))
|
||||
{
|
||||
return this.DefaultConstraint.Definition;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tl.Equals("time")) return ((Database)Parent.Parent).Options.Defaults.DefaultTime;
|
||||
if (tl.Equals("int") || tl.Equals("bit") || tl.Equals("smallint") || tl.Equals("bigint") || tl.Equals("tinyint")) return ((Database)Parent.Parent).Options.Defaults.DefaultIntegerValue;
|
||||
if (tl.Equals("text") || tl.Equals("char") || tl.Equals("varchar") || tl.Equals("varchar(max)")) return ((Database)Parent.Parent).Options.Defaults.DefaultTextValue;
|
||||
if (tl.Equals("ntext") || tl.Equals("nchar") || tl.Equals("nvarchar") || tl.Equals("nvarchar(max)")) return ((Database)Parent.Parent).Options.Defaults.DefaultNTextValue;
|
||||
if (tl.Equals("date") || tl.Equals("datetimeoffset") || tl.Equals("datetime2") || tl.Equals("datetime") || tl.Equals("smalldatetime")) return ((Database)Parent.Parent).Options.Defaults.DefaultDateValue;
|
||||
if (tl.Equals("numeric") || tl.Equals("decimal") || tl.Equals("float") || tl.Equals("money") || tl.Equals("smallmoney") || tl.Equals("real")) return ((Database)Parent.Parent).Options.Defaults.DefaultRealValue;
|
||||
if (tl.Equals("sql_variant")) return ((Database)Parent.Parent).Options.Defaults.DefaultVariantValue;
|
||||
if (tl.Equals("uniqueidentifier")) return ((Database)Parent.Parent).Options.Defaults.DefaultUniqueValue;
|
||||
if (tl.Equals("image") || tl.Equals("binary") || tl.Equals("varbinary")) return ((Database)Parent.Parent).Options.Defaults.DefaultBlobValue;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Toes the SQL drop.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
string sql = "ALTER TABLE " + Parent.FullName + " DROP COLUMN [" + Name + "]\r\nGO\r\n";
|
||||
return sql;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toes the SQL add.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
return "ALTER TABLE " + Parent.FullName + " ADD " + ToSql(false) + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
return ToSql(true);
|
||||
}
|
||||
|
||||
public string ToSQLRedefine(string type, int size, string xmlSchema)
|
||||
{
|
||||
string originalType = "";
|
||||
int originalSize = 0;
|
||||
string originalXMLSchema = "";
|
||||
|
||||
string sql;
|
||||
|
||||
if (type != null)
|
||||
{
|
||||
originalType = this.Type;
|
||||
this.Type = type;
|
||||
}
|
||||
if (size != 0)
|
||||
{
|
||||
originalSize = this.Size;
|
||||
this.Size = size;
|
||||
}
|
||||
if (xmlSchema != null)
|
||||
{
|
||||
originalXMLSchema = this.XmlSchema;
|
||||
this.XmlSchema = xmlSchema;
|
||||
|
||||
}
|
||||
sql = this.ToSql(false);
|
||||
|
||||
if (type != null)
|
||||
this.Type = originalType;
|
||||
if (size != 0)
|
||||
this.Size = originalSize;
|
||||
if (xmlSchema != null)
|
||||
this.XmlSchema = originalXMLSchema;
|
||||
return sql;
|
||||
}
|
||||
/// <summary>
|
||||
/// Devuelve el schema de la columna en formato SQL.
|
||||
/// </summary>
|
||||
public string ToSql(Boolean sqlConstraint)
|
||||
{
|
||||
string sql = "";
|
||||
sql += "[" + Name + "] ";
|
||||
if (!IsComputed)
|
||||
{
|
||||
if (this.IsUserDefinedType)
|
||||
sql += Type;
|
||||
else
|
||||
sql += "[" + Type + "]";
|
||||
if (Type.Equals("binary") || Type.Equals("varbinary") || Type.Equals("varchar") || Type.Equals("char") || Type.Equals("nchar") || Type.Equals("nvarchar"))
|
||||
{
|
||||
if (Size == -1)
|
||||
sql += " (max)";
|
||||
else
|
||||
{
|
||||
if (Type.Equals("nchar") || Type.Equals("nvarchar"))
|
||||
sql += " (" + (Size / 2).ToString(CultureInfo.InvariantCulture) + ")";
|
||||
else
|
||||
sql += " (" + Size.ToString(CultureInfo.InvariantCulture) + ")";
|
||||
}
|
||||
}
|
||||
if (Type.Equals("xml"))
|
||||
{
|
||||
if (!String.IsNullOrEmpty(XmlSchema))
|
||||
{
|
||||
if (IsXmlDocument)
|
||||
sql += "(DOCUMENT " + XmlSchema + ")";
|
||||
else
|
||||
sql += "(CONTENT " + XmlSchema + ")";
|
||||
}
|
||||
}
|
||||
if (Type.Equals("numeric") || Type.Equals("decimal")) sql += " (" + Precision.ToString(CultureInfo.InvariantCulture) + "," + Scale.ToString(CultureInfo.InvariantCulture) + ")";
|
||||
if (((Database)Parent.Parent).Info.Version >= DatabaseInfo.SQLServerVersion.SQLServer2008)
|
||||
{
|
||||
if (Type.Equals("datetime2") || Type.Equals("datetimeoffset") || Type.Equals("time")) sql += "(" + Scale.ToString(CultureInfo.InvariantCulture) + ")";
|
||||
}
|
||||
if ((!String.IsNullOrEmpty(Collation)) && (!IsUserDefinedType)) sql += " COLLATE " + Collation;
|
||||
if (IsIdentity) sql += " IDENTITY (" + IdentitySeed.ToString(CultureInfo.InvariantCulture) + "," + IdentityIncrement.ToString(CultureInfo.InvariantCulture) + ")";
|
||||
if (IsIdentityForReplication) sql += " NOT FOR REPLICATION";
|
||||
if (IsSparse) sql += " SPARSE";
|
||||
if (IsFileStream) sql += " FILESTREAM";
|
||||
if (IsNullable)
|
||||
sql += " NULL";
|
||||
else
|
||||
sql += " NOT NULL";
|
||||
if (IsRowGuid) sql += " ROWGUIDCOL";
|
||||
}
|
||||
else
|
||||
{
|
||||
sql += "AS " + ComputedFormula;
|
||||
if (IsPersisted) sql += " PERSISTED";
|
||||
}
|
||||
if ((sqlConstraint) && (DefaultConstraint != null))
|
||||
{
|
||||
if (DefaultConstraint.Status != ObjectStatus.Drop)
|
||||
sql += " " + DefaultConstraint.ToSql().Replace("\t", "").Trim();
|
||||
}
|
||||
return sql;
|
||||
}
|
||||
|
||||
public SQLScriptList RebuildDependencies()
|
||||
{
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
list.AddRange(RebuildConstraint());
|
||||
list.AddRange(RebuildIndex());
|
||||
list.AddRange(RebuildFullTextIndex());
|
||||
return list;
|
||||
}
|
||||
|
||||
private SQLScriptList RebuildFullTextIndex()
|
||||
{
|
||||
return RebuildFullTextIndex(null);
|
||||
}
|
||||
|
||||
private SQLScriptList RebuildFullTextIndex(string index)
|
||||
{
|
||||
bool it;
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
((Table)Parent).FullTextIndex.ForEach(item =>
|
||||
{
|
||||
if (index == null)
|
||||
it = item.Columns.Exists(col => { return col.ColumnName.Equals(this.Name); });
|
||||
else
|
||||
it = item.Index.Equals(index);
|
||||
if (it)
|
||||
{
|
||||
if (item.Status != ObjectStatus.Create) list.Add(item.Drop());
|
||||
if (item.Status != ObjectStatus.Drop) list.Add(item.Create());
|
||||
}
|
||||
}
|
||||
);
|
||||
return list;
|
||||
}
|
||||
|
||||
private SQLScriptList RebuildConstraint()
|
||||
{
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
((Table)Parent).Constraints.ForEach(item =>
|
||||
{
|
||||
ConstraintColumn ic = item.Columns.Find(this.Id);
|
||||
if (ic != null)
|
||||
{
|
||||
if (item.Status != ObjectStatus.Create) list.Add(item.Drop());
|
||||
if (item.Status != ObjectStatus.Drop) list.Add(item.Create());
|
||||
list.AddRange(RebuildFullTextIndex(item.Name));
|
||||
}
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
private SQLScriptList RebuildIndex()
|
||||
{
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
if (HasIndexDependencies)
|
||||
{
|
||||
((Table)Parent).Indexes.ForEach(item =>
|
||||
{
|
||||
IndexColumn ic = item.Columns.Find(this.Id);
|
||||
if (ic != null)
|
||||
{
|
||||
if (item.Status != ObjectStatus.Create) list.Add(item.Drop());
|
||||
if (item.Status != ObjectStatus.Drop) list.Add(item.Create());
|
||||
list.AddRange(RebuildFullTextIndex(item.Name));
|
||||
}
|
||||
});
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public SQLScriptList RebuildConstraint(Boolean Check)
|
||||
{
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
if (DefaultConstraint != null)
|
||||
{
|
||||
if ((!Check) || (DefaultConstraint.CanCreate)) list.Add(DefaultConstraint.Create());
|
||||
list.Add(DefaultConstraint.Drop());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public SQLScriptList RebuildSchemaBindingDependencies()
|
||||
{
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
List<ISchemaBase> items = ((Database)this.Parent.Parent).Dependencies.Find(this.Parent.Id, this.Id, 0);
|
||||
items.ForEach(item =>
|
||||
{
|
||||
if ((item.ObjectType == ObjectType.Function) || (item.ObjectType == ObjectType.View))
|
||||
{
|
||||
if (item.Status != ObjectStatus.Create)
|
||||
list.Add(item.Drop());
|
||||
if (item.Status != ObjectStatus.Drop)
|
||||
list.Add(item.Create());
|
||||
}
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
public SQLScriptList Alter(ScriptAction typeStatus)
|
||||
{
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
string sql = "ALTER TABLE " + Parent.FullName + " ALTER COLUMN " + this.ToSql(false) + "\r\nGO\r\n";
|
||||
list.Add(sql, 0, typeStatus);
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compara solo las propiedades de dos campos relacionadas con los Identity. Si existen
|
||||
/// diferencias, devuelve falso, caso contrario, true.
|
||||
/// </summary>
|
||||
public static Boolean CompareIdentity(Column origin, Column destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (origin == null) throw new ArgumentNullException("origin");
|
||||
if (origin.IsIdentity != destination.IsIdentity) return false;
|
||||
if (origin.IsIdentityForReplication != destination.IsIdentityForReplication) return false;
|
||||
if (origin.IdentityIncrement != destination.IdentityIncrement) return false;
|
||||
if (origin.IdentitySeed != destination.IdentitySeed) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Boolean CompareRule(Column origin, Column destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (origin == null) throw new ArgumentNullException("origin");
|
||||
if ((origin.Rule.Name != null) && (destination.Rule.Name == null)) return false;
|
||||
if ((origin.Rule.Name == null) && (destination.Rule.Name != null)) return false;
|
||||
if (origin.Rule.Name != null)
|
||||
if (!origin.Rule.Name.Equals(destination.Rule.Name)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compara dos campos y devuelve true si son iguales, caso contrario, devuelve false.
|
||||
/// </summary>
|
||||
public static Boolean Compare(Column origin, Column destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (origin == null) throw new ArgumentNullException("origin");
|
||||
if (!origin.ComputedFormula.Equals(destination.ComputedFormula)) return false;
|
||||
if (origin.IsComputed != destination.IsComputed) return false;
|
||||
//if (origin.Position != destination.Position) return false;
|
||||
if (!origin.IsComputed)
|
||||
{
|
||||
if (origin.IsXmlDocument != destination.IsXmlDocument) return false;
|
||||
if ((origin.XmlSchema == null) && (destination.XmlSchema != null)) return false;
|
||||
if (origin.XmlSchema != null)
|
||||
if (!origin.XmlSchema.Equals(destination.XmlSchema)) return false;
|
||||
if (origin.IsNullable != destination.IsNullable) return false;
|
||||
if (origin.IsFileStream != destination.IsFileStream) return false;
|
||||
if (origin.IsSparse != destination.IsSparse) return false;
|
||||
if (!origin.Collation.Equals(destination.Collation)) return false;
|
||||
if (!origin.Type.Equals(destination.Type, StringComparison.CurrentCultureIgnoreCase)) return false;
|
||||
//Si el tipo de campo es custom, no compara size del campo.
|
||||
if (!origin.IsUserDefinedType)
|
||||
{
|
||||
if (origin.Precision != destination.Precision) return false;
|
||||
if (origin.Scale != destination.Scale) return false;
|
||||
//Si el tamaño de un campo Text cambia, entonces por la opcion TextInRowLimit.
|
||||
if ((origin.Size != destination.Size) && (origin.Type.Equals(destination.Type, StringComparison.CurrentCultureIgnoreCase)) && (!origin.Type.Equals("text", StringComparison.CurrentCultureIgnoreCase))) return false;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (origin.IsPersisted != destination.IsPersisted) return false;
|
||||
}
|
||||
if (!CompareIdentity(origin, destination)) return false;
|
||||
return CompareRule(origin, destination);
|
||||
}
|
||||
|
||||
public int CompareTo(Column other)
|
||||
{
|
||||
return this.Id.CompareTo(other.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
171
OpenDBDiff.Schema.SQLServer.Generates/Model/ColumnConstraint.cs
Normal file
171
OpenDBDiff.Schema.SQLServer.Generates/Model/ColumnConstraint.cs
Normal file
@@ -0,0 +1,171 @@
|
||||
using System;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// Clase de constraints de Columnas (Default Constraint y Check Constraint)
|
||||
/// </summary>
|
||||
public class ColumnConstraint : SQLServerSchemaBase
|
||||
{
|
||||
public ColumnConstraint(Column parent)
|
||||
: base(parent, ObjectType.Constraint)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clona el objeto ColumnConstraint en una nueva instancia.
|
||||
/// </summary>
|
||||
public ColumnConstraint Clone(Column parent)
|
||||
{
|
||||
ColumnConstraint ccons = new ColumnConstraint(parent);
|
||||
ccons.Name = this.Name;
|
||||
ccons.Type = this.Type;
|
||||
ccons.Definition = this.Definition;
|
||||
ccons.Status = this.Status;
|
||||
ccons.Disabled = this.Disabled;
|
||||
ccons.Owner = this.Owner;
|
||||
return ccons;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indica si la constraint esta deshabilitada.
|
||||
/// </summary>
|
||||
public Boolean Disabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indica si la constraint va a ser usada en replicacion.
|
||||
/// </summary>
|
||||
public Boolean NotForReplication { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [with no check].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [with no check]; otherwise, <c>false</c>.</value>
|
||||
public Boolean WithNoCheck { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Valor de la constraint.
|
||||
/// </summary>
|
||||
public string Definition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indica el tipo de constraint (Default o Check constraint).
|
||||
/// </summary>
|
||||
public Constraint.ConstraintType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Convierte el schema de la constraint en XML.
|
||||
/// </summary>
|
||||
public string ToXML()
|
||||
{
|
||||
string xml = "";
|
||||
if (this.Type == Constraint.ConstraintType.Default)
|
||||
{
|
||||
xml += "<COLUMNCONSTRAINT name=\"" + Name + "\" type=\"DF\" value=\"" + Definition + "\"/>\n";
|
||||
}
|
||||
if (this.Type == Constraint.ConstraintType.Check)
|
||||
{
|
||||
xml += "<COLUMNCONSTRAINT name=\"" + Name + "\" type=\"C\" value=\"" + Definition + "\" notForReplication=\"" + (NotForReplication ? "1" : "0") + "\"/>\n";
|
||||
}
|
||||
return xml;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compara dos campos y devuelve true si son iguales, caso contrario, devuelve false.
|
||||
/// </summary>
|
||||
public static Boolean Compare(ColumnConstraint origin, ColumnConstraint destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (origin == null) throw new ArgumentNullException("origin");
|
||||
if (origin.NotForReplication != destination.NotForReplication) return false;
|
||||
if (origin.Disabled != destination.Disabled) return false;
|
||||
if ((!origin.Definition.Equals(destination.Definition)) && (!origin.Definition.Equals("(" + destination.Definition + ")"))) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override SQLScript Create()
|
||||
{
|
||||
ScriptAction action = ScriptAction.AddConstraint;
|
||||
if (!GetWasInsertInDiffList(action))
|
||||
{
|
||||
SetWasInsertInDiffList(action);
|
||||
return new SQLScript(this.ToSqlAdd(), 0, action);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
public override SQLScript Drop()
|
||||
{
|
||||
ScriptAction action = ScriptAction.DropConstraint;
|
||||
if (!GetWasInsertInDiffList(action))
|
||||
{
|
||||
SetWasInsertInDiffList(action);
|
||||
return new SQLScript(this.ToSqlDrop(), 0, action);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public Boolean CanCreate
|
||||
{
|
||||
get
|
||||
{
|
||||
ObjectStatus tableStatus = this.Parent.Parent.Status;
|
||||
ObjectStatus columnStatus = this.Parent.Status;
|
||||
return ((columnStatus != ObjectStatus.Drop) && (((tableStatus == ObjectStatus.Alter) || (tableStatus == ObjectStatus.Original) || (tableStatus == ObjectStatus.RebuildDependencies)) && (this.Status == ObjectStatus.Original)));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Devuelve el schema de la constraint en formato SQL.
|
||||
/// </summary>
|
||||
public override string ToSql()
|
||||
{
|
||||
string sql = "";
|
||||
if (this.Type == Constraint.ConstraintType.Default)
|
||||
sql = " CONSTRAINT [" + Name + "] DEFAULT " + Definition;
|
||||
return sql;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toes the SQL add.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
if (this.Type == Constraint.ConstraintType.Default)
|
||||
return "ALTER TABLE " + ((Table)Parent.Parent).FullName + " ADD" + ToSql() + " FOR [" + Parent.Name + "]\r\nGO\r\n";
|
||||
if (this.Type == Constraint.ConstraintType.Check)
|
||||
return "ALTER TABLE " + ((Table)Parent.Parent).FullName + " ADD" + ToSql() + "\r\nGO\r\n";
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toes the SQL drop.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
return "ALTER TABLE " + ((Table)Parent.Parent).FullName + " DROP CONSTRAINT [" + Name + "]\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<OpenDBDiff.Schema.Model.ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
if (this.HasState(ObjectStatus.Drop))
|
||||
list.Add(Drop());
|
||||
if (this.HasState(ObjectStatus.Create))
|
||||
list.Add(Create());
|
||||
|
||||
if (this.Status == ObjectStatus.Alter)
|
||||
{
|
||||
list.Add(Drop());
|
||||
list.Add(Create());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
114
OpenDBDiff.Schema.SQLServer.Generates/Model/Columns.cs
Normal file
114
OpenDBDiff.Schema.SQLServer.Generates/Model/Columns.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
using OpenDBDiff.Schema.Model;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class Columns<T> : SchemaList<Column, T> where T : ISchemaBase
|
||||
{
|
||||
public Columns(T parent) : base(parent)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clona el objeto Columns en una nueva instancia.
|
||||
/// </summary>
|
||||
public new Columns<T> Clone(T parentObject)
|
||||
{
|
||||
Columns<T> columns = new Columns<T>(parentObject);
|
||||
for (int index = 0; index < this.Count; index++)
|
||||
{
|
||||
columns.Add(this[index].Clone(parentObject));
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
return string.Join
|
||||
(
|
||||
",\r\n",
|
||||
this
|
||||
.Where(c => !c.HasState(ObjectStatus.Drop))
|
||||
.Select(c => "\t" + c.ToSql(true))
|
||||
);
|
||||
}
|
||||
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
string sqlDrop = "";
|
||||
string sqlAdd = "";
|
||||
string sqlCons = "";
|
||||
string sqlBinds = "";
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
if (Parent.Status != ObjectStatus.Rebuild)
|
||||
{
|
||||
this.ForEach(item =>
|
||||
{
|
||||
bool isIncluded = schemas.Count == 0;
|
||||
if (!isIncluded)
|
||||
{
|
||||
foreach (var selectedSchema in schemas)
|
||||
{
|
||||
if (selectedSchema.Id == item.Id)
|
||||
{
|
||||
isIncluded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isIncluded)
|
||||
{
|
||||
if (item.HasState(ObjectStatus.Drop))
|
||||
{
|
||||
if (item.DefaultConstraint != null)
|
||||
list.Add(item.DefaultConstraint.Drop());
|
||||
/*Si la columna formula debe ser eliminada y ya fue efectuada la operacion en otro momento, no
|
||||
* se borra nuevamente*/
|
||||
if (!item.GetWasInsertInDiffList(ScriptAction.AlterColumnFormula))
|
||||
sqlDrop += "[" + item.Name + "],";
|
||||
}
|
||||
if (item.HasState(ObjectStatus.Create))
|
||||
sqlAdd += "\r\n" + item.ToSql(true) + ",";
|
||||
if ((item.HasState(ObjectStatus.Alter) || (item.HasState(ObjectStatus.RebuildDependencies))))
|
||||
{
|
||||
if ((!item.Parent.HasState(ObjectStatus.RebuildDependencies) || (!item.Parent.HasState(ObjectStatus.Rebuild))))
|
||||
list.AddRange(item.RebuildSchemaBindingDependencies());
|
||||
list.AddRange(item.RebuildConstraint(false));
|
||||
list.AddRange(item.RebuildDependencies());
|
||||
list.AddRange(item.Alter(ScriptAction.AlterTable));
|
||||
}
|
||||
if (item.HasState(ObjectStatus.Update))
|
||||
list.Add("UPDATE " + Parent.FullName + " SET [" + item.Name + "] = " + item.DefaultForceValue + " WHERE [" + item.Name + "] IS NULL\r\nGO\r\n", 0, ScriptAction.UpdateTable);
|
||||
if (item.HasState(ObjectStatus.Bind))
|
||||
{
|
||||
if (item.Rule.Id != 0)
|
||||
sqlBinds += item.Rule.ToSQLAddBind();
|
||||
if (item.Rule.Id == 0)
|
||||
sqlBinds += item.Rule.ToSQLAddUnBind();
|
||||
}
|
||||
if (item.DefaultConstraint != null)
|
||||
list.AddRange(item.DefaultConstraint.ToSqlDiff(schemas));
|
||||
}
|
||||
});
|
||||
if (!String.IsNullOrEmpty(sqlDrop))
|
||||
sqlDrop = "ALTER TABLE " + Parent.FullName + " DROP COLUMN " + sqlDrop.Substring(0, sqlDrop.Length - 1) + "\r\nGO\r\n";
|
||||
if (!String.IsNullOrEmpty(sqlAdd))
|
||||
sqlAdd = "ALTER TABLE " + Parent.FullName + " ADD " + sqlAdd.Substring(0, sqlAdd.Length - 1) + "\r\nGO\r\n";
|
||||
|
||||
if (!String.IsNullOrEmpty(sqlDrop + sqlAdd + sqlCons + sqlBinds))
|
||||
list.Add(sqlDrop + sqlAdd + sqlBinds, 0, ScriptAction.AlterTable);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ForEach(item =>
|
||||
{
|
||||
if (item.Status != ObjectStatus.Original)
|
||||
item.RootParent.ActionMessage[item.Parent.FullName].Add(item);
|
||||
});
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
359
OpenDBDiff.Schema.SQLServer.Generates/Model/Constraint.cs
Normal file
359
OpenDBDiff.Schema.SQLServer.Generates/Model/Constraint.cs
Normal file
@@ -0,0 +1,359 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class Constraint : SQLServerSchemaBase
|
||||
{
|
||||
public enum ConstraintType
|
||||
{
|
||||
None = 0,
|
||||
PrimaryKey = 1,
|
||||
ForeignKey = 2,
|
||||
Default = 3,
|
||||
Unique = 4,
|
||||
Check = 5
|
||||
}
|
||||
|
||||
public Constraint(ISchemaBase parent)
|
||||
: base(parent, ObjectType.Constraint)
|
||||
{
|
||||
this.Columns = new ConstraintColumns(this);
|
||||
this.Index = new Index(parent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clona el objeto Column en una nueva instancia.
|
||||
/// </summary>
|
||||
public override ISchemaBase Clone(ISchemaBase parent)
|
||||
{
|
||||
Constraint col = new Constraint(parent);
|
||||
col.Id = this.Id;
|
||||
col.Name = this.Name;
|
||||
col.NotForReplication = this.NotForReplication;
|
||||
col.RelationalTableFullName = this.RelationalTableFullName;
|
||||
col.Status = this.Status;
|
||||
col.Type = this.Type;
|
||||
col.WithNoCheck = this.WithNoCheck;
|
||||
col.OnDeleteCascade = this.OnDeleteCascade;
|
||||
col.OnUpdateCascade = this.OnUpdateCascade;
|
||||
col.Owner = this.Owner;
|
||||
col.Columns = this.Columns.Clone();
|
||||
col.Index = (Index)this.Index.Clone(parent);
|
||||
col.IsDisabled = this.IsDisabled;
|
||||
col.Definition = this.Definition;
|
||||
col.Guid = this.Guid;
|
||||
return col;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Informacion sobre le indice asociado al Constraint.
|
||||
/// </summary>
|
||||
public Index Index { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Coleccion de columnas de la constraint.
|
||||
/// </summary>
|
||||
public ConstraintColumns Columns { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indica si la constraint tiene asociada un indice Clustered.
|
||||
/// </summary>
|
||||
public Boolean HasClusteredIndex
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Index != null)
|
||||
return (Index.Type == Index.IndexTypeEnum.Clustered);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this constraint is disabled.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this constraint is disabled; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public Boolean IsDisabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the on delete cascade (only for FK).
|
||||
/// </summary>
|
||||
/// <value>The on delete cascade.</value>
|
||||
public int OnDeleteCascade { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the on update cascade (only for FK).
|
||||
/// </summary>
|
||||
/// <value>The on update cascade.</value>
|
||||
public int OnUpdateCascade { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Valor de la constraint (se usa para los Check Constraint).
|
||||
/// </summary>
|
||||
public string Definition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indica si la constraint va a ser usada en replicacion.
|
||||
/// </summary>
|
||||
public Boolean NotForReplication { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [with no check].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [with no check]; otherwise, <c>false</c>.</value>
|
||||
public Boolean WithNoCheck { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indica el tipo de constraint (PrimaryKey, ForeignKey, Unique o Default).
|
||||
/// </summary>
|
||||
public ConstraintType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ID de la tabla relacionada a la que hace referencia (solo aplica a FK)
|
||||
/// </summary>
|
||||
public int RelationalTableId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Nombre de la tabla relacionada a la que hace referencia (solo aplica a FK)
|
||||
/// </summary>
|
||||
public string RelationalTableFullName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Compara dos campos y devuelve true si son iguales, caso contrario, devuelve false.
|
||||
/// </summary>
|
||||
public static Boolean Compare(Constraint origin, Constraint destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (origin == null) throw new ArgumentNullException("origin");
|
||||
if (origin.NotForReplication != destination.NotForReplication) return false;
|
||||
if ((origin.RelationalTableFullName == null) && (destination.RelationalTableFullName != null)) return false;
|
||||
if (origin.RelationalTableFullName != null)
|
||||
if (!origin.RelationalTableFullName.Equals(destination.RelationalTableFullName, StringComparison.CurrentCultureIgnoreCase)) return false;
|
||||
if ((origin.Definition == null) && (destination.Definition != null)) return false;
|
||||
if (origin.Definition != null)
|
||||
if ((!origin.Definition.Equals(destination.Definition)) && (!origin.Definition.Equals("(" + destination.Definition + ")"))) return false;
|
||||
/*Solo si la constraint esta habilitada, se chequea el is_trusted*/
|
||||
if (!destination.IsDisabled)
|
||||
if (origin.WithNoCheck != destination.WithNoCheck) return false;
|
||||
if (origin.OnUpdateCascade != destination.OnUpdateCascade) return false;
|
||||
if (origin.OnDeleteCascade != destination.OnDeleteCascade) return false;
|
||||
if (!ConstraintColumns.Compare(origin.Columns, destination.Columns)) return false;
|
||||
if ((origin.Index != null) && (destination.Index != null))
|
||||
return Index.Compare(origin.Index, destination.Index);
|
||||
return true;
|
||||
}
|
||||
|
||||
private string ToSQLGeneric(ConstraintType consType)
|
||||
{
|
||||
Database database = null;
|
||||
ISchemaBase current = this;
|
||||
while (database == null && current.Parent != null)
|
||||
{
|
||||
database = current.Parent as Database;
|
||||
current = current.Parent;
|
||||
}
|
||||
var isAzure10 = database.Info.Version == DatabaseInfo.SQLServerVersion.SQLServerAzure10;
|
||||
string typeConstraint = "";
|
||||
StringBuilder sql = new StringBuilder();
|
||||
if (Index.Type == Index.IndexTypeEnum.Clustered) typeConstraint = "CLUSTERED";
|
||||
if (Index.Type == Index.IndexTypeEnum.Nonclustered) typeConstraint = "NONCLUSTERED";
|
||||
if (Index.Type == Index.IndexTypeEnum.XML) typeConstraint = "XML";
|
||||
if (Index.Type == Index.IndexTypeEnum.Heap) typeConstraint = "HEAP";
|
||||
if (Parent.ObjectType != ObjectType.TableType)
|
||||
sql.Append("CONSTRAINT [" + Name + "] ");
|
||||
else
|
||||
sql.Append("\t");
|
||||
if (consType == ConstraintType.PrimaryKey)
|
||||
sql.Append("PRIMARY KEY " + typeConstraint + "\r\n\t(\r\n");
|
||||
else
|
||||
sql.Append("UNIQUE " + typeConstraint + "\r\n\t(\r\n");
|
||||
|
||||
this.Columns.Sort();
|
||||
|
||||
for (int j = 0; j < this.Columns.Count; j++)
|
||||
{
|
||||
sql.Append("\t\t[" + this.Columns[j].Name + "]");
|
||||
if (this.Columns[j].Order) sql.Append(" DESC"); else sql.Append(" ASC");
|
||||
if (j != this.Columns.Count - 1) sql.Append(",");
|
||||
sql.Append("\r\n");
|
||||
}
|
||||
sql.Append("\t)");
|
||||
sql.Append(" WITH (");
|
||||
if (Parent.ObjectType == ObjectType.TableType)
|
||||
if (Index.IgnoreDupKey) sql.Append("IGNORE_DUP_KEY = ON"); else sql.Append("IGNORE_DUP_KEY = OFF");
|
||||
else
|
||||
{
|
||||
if (!isAzure10)
|
||||
{
|
||||
if (Index.IsPadded) sql.Append("PAD_INDEX = ON, "); else sql.Append("PAD_INDEX = OFF, ");
|
||||
}
|
||||
if (Index.IsAutoStatistics) sql.Append("STATISTICS_NORECOMPUTE = ON"); else sql.Append("STATISTICS_NORECOMPUTE = OFF");
|
||||
if (Index.IgnoreDupKey) sql.Append(", IGNORE_DUP_KEY = ON"); else sql.Append(", IGNORE_DUP_KEY = OFF");
|
||||
if (!isAzure10)
|
||||
{
|
||||
if (Index.AllowRowLocks) sql.Append(", ALLOW_ROW_LOCKS = ON"); else sql.Append(", ALLOW_ROW_LOCKS = OFF");
|
||||
if (Index.AllowPageLocks) sql.Append(", ALLOW_PAGE_LOCKS = ON"); else sql.Append(", ALLOW_PAGE_LOCKS = OFF");
|
||||
if (Index.FillFactor != 0) sql.Append(", FILLFACTOR = " + Index.FillFactor.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
}
|
||||
sql.Append(")");
|
||||
if (!isAzure10)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(Index.FileGroup)) sql.Append(" ON [" + Index.FileGroup + "]");
|
||||
}
|
||||
return sql.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Devuelve el schema de la tabla en formato SQL.
|
||||
/// </summary>
|
||||
public override string ToSql()
|
||||
{
|
||||
if (this.Type == ConstraintType.PrimaryKey)
|
||||
{
|
||||
return ToSQLGeneric(ConstraintType.PrimaryKey);
|
||||
}
|
||||
if (this.Type == ConstraintType.ForeignKey)
|
||||
{
|
||||
StringBuilder sql = new StringBuilder();
|
||||
StringBuilder sqlReference = new StringBuilder();
|
||||
int indexc = 0;
|
||||
|
||||
this.Columns.Sort();
|
||||
sql.Append("CONSTRAINT [" + Name + "] FOREIGN KEY\r\n\t(\r\n");
|
||||
foreach (ConstraintColumn column in this.Columns)
|
||||
{
|
||||
sql.Append("\t\t[" + column.Name + "]");
|
||||
sqlReference.Append("\t\t[" + column.ColumnRelationalName + "]");
|
||||
if (indexc != this.Columns.Count - 1)
|
||||
{
|
||||
sql.Append(",");
|
||||
sqlReference.Append(",");
|
||||
}
|
||||
sql.Append("\r\n");
|
||||
sqlReference.Append("\r\n");
|
||||
indexc++;
|
||||
}
|
||||
sql.Append("\t)\r\n");
|
||||
sql.Append("\tREFERENCES " + this.RelationalTableFullName + "\r\n\t(\r\n");
|
||||
sql.Append(sqlReference + "\t)");
|
||||
if (OnUpdateCascade == 1) sql.Append(" ON UPDATE CASCADE");
|
||||
if (OnDeleteCascade == 1) sql.Append(" ON DELETE CASCADE");
|
||||
if (OnUpdateCascade == 2) sql.Append(" ON UPDATE SET NULL");
|
||||
if (OnDeleteCascade == 2) sql.Append(" ON DELETE SET NULL");
|
||||
if (OnUpdateCascade == 3) sql.Append(" ON UPDATE SET DEFAULT");
|
||||
if (OnDeleteCascade == 3) sql.Append(" ON DELETE SET DEFAULT");
|
||||
sql.Append((NotForReplication ? " NOT FOR REPLICATION" : ""));
|
||||
return sql.ToString();
|
||||
}
|
||||
if (this.Type == ConstraintType.Unique)
|
||||
{
|
||||
return ToSQLGeneric(ConstraintType.Unique);
|
||||
}
|
||||
if (this.Type == ConstraintType.Check)
|
||||
{
|
||||
string sqlcheck = "";
|
||||
if (Parent.ObjectType != ObjectType.TableType)
|
||||
sqlcheck = "CONSTRAINT [" + Name + "] ";
|
||||
|
||||
return sqlcheck + "CHECK " + (NotForReplication ? "NOT FOR REPLICATION" : "") + " (" + Definition + ")";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
return "ALTER TABLE " + Parent.FullName + (WithNoCheck ? " WITH NOCHECK" : "") + " ADD " + ToSql() + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
return ToSqlDrop(null);
|
||||
}
|
||||
|
||||
public override SQLScript Create()
|
||||
{
|
||||
ScriptAction action = ScriptAction.AddConstraint;
|
||||
if (this.Type == ConstraintType.ForeignKey)
|
||||
action = ScriptAction.AddConstraintFK;
|
||||
if (this.Type == ConstraintType.PrimaryKey)
|
||||
action = ScriptAction.AddConstraintPK;
|
||||
if (!GetWasInsertInDiffList(action))
|
||||
{
|
||||
SetWasInsertInDiffList(action);
|
||||
return new SQLScript(this.ToSqlAdd(), ((Table)Parent).DependenciesCount, action);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public override SQLScript Drop()
|
||||
{
|
||||
ScriptAction action = ScriptAction.DropConstraint;
|
||||
if (this.Type == ConstraintType.ForeignKey)
|
||||
action = ScriptAction.DropConstraintFK;
|
||||
if (this.Type == ConstraintType.PrimaryKey)
|
||||
action = ScriptAction.DropConstraintPK;
|
||||
if (!GetWasInsertInDiffList(action))
|
||||
{
|
||||
SetWasInsertInDiffList(action);
|
||||
return new SQLScript(this.ToSqlDrop(), ((Table)Parent).DependenciesCount, action);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public string ToSqlDrop(string FileGroupName)
|
||||
{
|
||||
string sql = "ALTER TABLE " + ((Table)Parent).FullName + " DROP CONSTRAINT [" + Name + "]";
|
||||
if (!String.IsNullOrEmpty(FileGroupName)) sql += " WITH (MOVE TO [" + FileGroupName + "])";
|
||||
sql += "\r\nGO\r\n";
|
||||
return sql;
|
||||
}
|
||||
|
||||
public string ToSQLEnabledDisabled()
|
||||
{
|
||||
StringBuilder sql = new StringBuilder();
|
||||
if (this.IsDisabled)
|
||||
return "ALTER TABLE " + Parent.FullName + " NOCHECK CONSTRAINT [" + Name + "]\r\nGO\r\n";
|
||||
else
|
||||
{
|
||||
return "ALTER TABLE " + Parent.FullName + " CHECK CONSTRAINT [" + Name + "]\r\nGO\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
if (this.Status != ObjectStatus.Original)
|
||||
RootParent.ActionMessage[Parent.FullName].Add(this);
|
||||
|
||||
if (this.HasState(ObjectStatus.Drop))
|
||||
{
|
||||
if (this.Parent.Status != ObjectStatus.Rebuild)
|
||||
list.Add(Drop());
|
||||
}
|
||||
if (this.HasState(ObjectStatus.Create))
|
||||
list.Add(Create());
|
||||
if (this.HasState(ObjectStatus.Alter))
|
||||
{
|
||||
list.Add(Drop());
|
||||
list.Add(Create());
|
||||
}
|
||||
if (this.HasState(ObjectStatus.Disabled))
|
||||
{
|
||||
list.Add(this.ToSQLEnabledDisabled(), ((Table)Parent).DependenciesCount, ScriptAction.AlterConstraint);
|
||||
}
|
||||
/*if (this.Status == StatusEnum.ObjectStatusType.ChangeFileGroup)
|
||||
{
|
||||
list.Add(this.ToSQLDrop(this.Index.FileGroup), ((Table)Parent).DependenciesCount, actionDrop);
|
||||
list.Add(this.ToSQLAdd(), ((Table)Parent).DependenciesCount, actionAdd);
|
||||
}*/
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class ConstraintColumn : SQLServerSchemaBase, IComparable<ConstraintColumn>
|
||||
{
|
||||
public ConstraintColumn(Constraint parentObject)
|
||||
: base(parentObject, ObjectType.ConstraintColumn)
|
||||
{
|
||||
}
|
||||
|
||||
public ConstraintColumn Clone()
|
||||
{
|
||||
ConstraintColumn ccol = new ConstraintColumn((Constraint)this.Parent);
|
||||
ccol.ColumnRelationalName = this.ColumnRelationalName;
|
||||
ccol.ColumnRelationalId = this.ColumnRelationalId;
|
||||
ccol.Name = this.Name;
|
||||
ccol.IsIncluded = this.IsIncluded;
|
||||
ccol.Order = this.Order;
|
||||
ccol.KeyOrder = this.KeyOrder;
|
||||
ccol.Id = this.Id;
|
||||
ccol.DataTypeId = this.DataTypeId;
|
||||
ccol.ColumnRelationalDataTypeId = this.ColumnRelationalDataTypeId;
|
||||
return ccol;
|
||||
}
|
||||
|
||||
public int DataTypeId { get; set; }
|
||||
|
||||
public int ColumnRelationalDataTypeId { get; set; }
|
||||
|
||||
public int ColumnRelationalId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the column key order in the index.
|
||||
/// </summary>
|
||||
/// <value>The key order.</value>
|
||||
public int KeyOrder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this column is included in the index leaf page.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this column is included; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public Boolean IsIncluded { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Orden de la columna (Ascendente o Descendente). Se usa solo en Primary Keys.
|
||||
/// </summary>
|
||||
public Boolean Order { get; set; }
|
||||
|
||||
public string ColumnRelationalName { get; set; }
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
public static Boolean Compare(ConstraintColumn origin, ConstraintColumn destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (origin == null) throw new ArgumentNullException("origin");
|
||||
if ((origin.ColumnRelationalName == null) && (destination.ColumnRelationalName != null)) return false;
|
||||
if (origin.ColumnRelationalName != null)
|
||||
{
|
||||
if (!origin.ColumnRelationalName.Equals(destination.ColumnRelationalName, StringComparison.CurrentCultureIgnoreCase)) return false;
|
||||
}
|
||||
if (origin.IsIncluded != destination.IsIncluded) return false;
|
||||
if (origin.Order != destination.Order) return false;
|
||||
if (origin.KeyOrder != destination.KeyOrder) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public int CompareTo(ConstraintColumn other)
|
||||
{
|
||||
return this.ColumnRelationalId.CompareTo(other.ColumnRelationalId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class ConstraintColumns : SchemaList<ConstraintColumn, Constraint>
|
||||
{
|
||||
public ConstraintColumns(Constraint parent)
|
||||
: base(parent)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clona el objeto ColumnConstraints en una nueva instancia.
|
||||
/// </summary>
|
||||
public ConstraintColumns Clone()
|
||||
{
|
||||
ConstraintColumns columns = new ConstraintColumns(this.Parent);
|
||||
for (int index = 0; index < this.Count; index++)
|
||||
{
|
||||
columns.Add(this[index].Clone());
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compara dos campos y devuelve true si son iguales, caso contrario, devuelve false.
|
||||
/// </summary>
|
||||
public static Boolean Compare(ConstraintColumns origin, ConstraintColumns destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (origin == null) throw new ArgumentNullException("origin");
|
||||
if (origin.Count != destination.Count) return false;
|
||||
for (int j = 0; j < origin.Count; j++)
|
||||
{
|
||||
ConstraintColumn item = destination[origin[j].FullName];
|
||||
if (item == null)
|
||||
return false;
|
||||
else
|
||||
if (!ConstraintColumn.Compare(origin[j], item)) return false;
|
||||
}
|
||||
for (int j = 0; j < destination.Count; j++)
|
||||
{
|
||||
ConstraintColumn item = origin[destination[j].FullName];
|
||||
if (item == null)
|
||||
return false;
|
||||
else
|
||||
if (!ConstraintColumn.Compare(destination[j], item)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
446
OpenDBDiff.Schema.SQLServer.Generates/Model/Database.cs
Normal file
446
OpenDBDiff.Schema.SQLServer.Generates/Model/Database.cs
Normal file
@@ -0,0 +1,446 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using OpenDBDiff.Schema.Attributes;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
using OpenDBDiff.Schema.SQLServer.Generates.Options;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class Database : SQLServerSchemaBase, IDatabase
|
||||
{
|
||||
private readonly List<DatabaseChangeStatus> _changesOptions;
|
||||
|
||||
public Database() : base(null, ObjectType.Database)
|
||||
{
|
||||
AllObjects = new SearchSchemaBase();
|
||||
_changesOptions = new List<DatabaseChangeStatus>();
|
||||
Dependencies = new Dependencies();
|
||||
TablesTypes = new SchemaList<TableType, Database>(this, AllObjects);
|
||||
UserTypes = new SchemaList<UserDataType, Database>(this, AllObjects);
|
||||
XmlSchemas = new SchemaList<XMLSchema, Database>(this, AllObjects);
|
||||
Schemas = new SchemaList<Schema, Database>(this, AllObjects);
|
||||
Procedures = new SchemaList<StoredProcedure, Database>(this, AllObjects);
|
||||
CLRProcedures = new SchemaList<CLRStoredProcedure, Database>(this, AllObjects);
|
||||
CLRFunctions = new SchemaList<CLRFunction, Database>(this, AllObjects);
|
||||
FileGroups = new SchemaList<FileGroup, Database>(this);
|
||||
Rules = new SchemaList<Rule, Database>(this, AllObjects);
|
||||
DDLTriggers = new SchemaList<Trigger, Database>(this, AllObjects);
|
||||
Synonyms = new SchemaList<Synonym, Database>(this, AllObjects);
|
||||
Assemblies = new SchemaList<Assembly, Database>(this, AllObjects);
|
||||
Views = new SchemaList<View, Database>(this, AllObjects);
|
||||
Users = new SchemaList<User, Database>(this, AllObjects);
|
||||
FullText = new SchemaList<FullText, Database>(this, AllObjects);
|
||||
Functions = new SchemaList<Function, Database>(this, AllObjects);
|
||||
PartitionFunctions = new SchemaList<PartitionFunction, Database>(this, AllObjects);
|
||||
PartitionSchemes = new SchemaList<PartitionScheme, Database>(this, AllObjects);
|
||||
Roles = new SchemaList<Role, Database>(this);
|
||||
Tables = new SchemaList<Table, Database>(this, AllObjects);
|
||||
Defaults = new SchemaList<Default, Database>(this, AllObjects);
|
||||
ActionMessage = new SqlAction(this);
|
||||
}
|
||||
|
||||
internal SearchSchemaBase AllObjects { get; private set; }
|
||||
|
||||
[SchemaNode("Full Text Catalog", "FullText")]
|
||||
public SchemaList<FullText, Database> FullText { get; private set; }
|
||||
|
||||
[SchemaNode("Table Type", "Table")]
|
||||
public SchemaList<TableType, Database> TablesTypes { get; private set; }
|
||||
|
||||
[SchemaNode("Partition Scheme", "PartitionScheme")]
|
||||
public SchemaList<PartitionScheme, Database> PartitionSchemes { get; private set; }
|
||||
|
||||
[SchemaNode("Partition Functions", "PartitionFunction")]
|
||||
public SchemaList<PartitionFunction, Database> PartitionFunctions { get; private set; }
|
||||
|
||||
[SchemaNode("Defaults")]
|
||||
public SchemaList<Default, Database> Defaults { get; private set; }
|
||||
|
||||
[SchemaNode("Roles", "Rol")]
|
||||
public SchemaList<Role, Database> Roles { get; private set; }
|
||||
|
||||
[SchemaNode("Functions", "Function", true)]
|
||||
public SchemaList<Function, Database> Functions { get; private set; }
|
||||
|
||||
[SchemaNode("Users", "User")]
|
||||
public SchemaList<User, Database> Users { get; private set; }
|
||||
|
||||
[SchemaNode("Views", "View", true)]
|
||||
public SchemaList<View, Database> Views { get; private set; }
|
||||
|
||||
[SchemaNode("Assemblies", "Assembly")]
|
||||
public SchemaList<Assembly, Database> Assemblies { get; private set; }
|
||||
|
||||
[SchemaNode("Synonyms", "Assembly")] // We don't have an icon for synonyms at the moment.
|
||||
public SchemaList<Synonym, Database> Synonyms { get; private set; }
|
||||
|
||||
[SchemaNode("DLL Triggers")]
|
||||
public SchemaList<Trigger, Database> DDLTriggers { get; private set; }
|
||||
|
||||
[SchemaNode("File Groups")]
|
||||
public SchemaList<FileGroup, Database> FileGroups { get; private set; }
|
||||
|
||||
[SchemaNode("Rules")]
|
||||
public SchemaList<Rule, Database> Rules { get; private set; }
|
||||
|
||||
[SchemaNode("Stored Procedures", "Procedure", true)]
|
||||
public SchemaList<StoredProcedure, Database> Procedures { get; private set; }
|
||||
|
||||
[SchemaNode("CLR Stored Procedures", "CLRProcedure", true)]
|
||||
public SchemaList<CLRStoredProcedure, Database> CLRProcedures { get; private set; }
|
||||
|
||||
[SchemaNode("CLR Functions", "CLRFunction", true)]
|
||||
public SchemaList<CLRFunction, Database> CLRFunctions { get; private set; }
|
||||
|
||||
[SchemaNode("Schemas", "Schema")]
|
||||
public SchemaList<Schema, Database> Schemas { get; private set; }
|
||||
|
||||
[SchemaNode("XML Schemas", "XMLSchema")]
|
||||
public SchemaList<XMLSchema, Database> XmlSchemas { get; private set; }
|
||||
|
||||
[SchemaNode("Tables", "Table", true)]
|
||||
public SchemaList<Table, Database> Tables { get; private set; }
|
||||
|
||||
[SchemaNode("User Types", "UDT")]
|
||||
public SchemaList<UserDataType, Database> UserTypes { get; private set; }
|
||||
|
||||
public SqlOption Options { get; set; }
|
||||
IOption IDatabase.Options { get { return Options; } }
|
||||
|
||||
public DatabaseInfo Info { get; set; }
|
||||
|
||||
public DatabaseInfo SourceInfo
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coleccion de dependencias de constraints.
|
||||
/// </summary>
|
||||
internal Dependencies Dependencies { get; set; }
|
||||
|
||||
private List<DatabaseChangeStatus> ChangesOptions
|
||||
{
|
||||
get { return _changesOptions; }
|
||||
}
|
||||
|
||||
#region IDatabase Members
|
||||
|
||||
public override ISchemaBase Clone(ISchemaBase parent)
|
||||
{
|
||||
//Get a list of all of the objects that are SchemaLists, so that we can clone them all.
|
||||
var item = new Database() { AllObjects = this.AllObjects };
|
||||
|
||||
var explicitProperties = (from properties in this.GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public)
|
||||
where properties.PropertyType.GetInterface(typeof(ISchemaList<Code, Database>).Name) != null
|
||||
select properties).ToList();
|
||||
|
||||
foreach (var property in explicitProperties)
|
||||
{
|
||||
object value = property.GetValue(this, null);
|
||||
|
||||
//Clone the value
|
||||
value = value.GetType().GetMethod("Clone").Invoke(value, new object[] { this });
|
||||
|
||||
//Set the value to the cloned object
|
||||
property.SetValue(item, value, null);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
public SqlAction ActionMessage { get; private set; }
|
||||
|
||||
public Boolean IsCaseSensitive
|
||||
{
|
||||
get
|
||||
{
|
||||
bool isCS = false;
|
||||
if (!String.IsNullOrEmpty(Info.Collation))
|
||||
isCS = Info.Collation.IndexOf("_CS_") != -1;
|
||||
|
||||
if (Options.Comparison.CaseSensityType == SqlOptionComparison.CaseSensityOptions.Automatic)
|
||||
return isCS;
|
||||
if (Options.Comparison.CaseSensityType == SqlOptionComparison.CaseSensityOptions.CaseSensity)
|
||||
return true;
|
||||
if (Options.Comparison.CaseSensityType == SqlOptionComparison.CaseSensityOptions.CaseInsensity)
|
||||
return false;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
string sql = "";
|
||||
sql += FileGroups.ToSql();
|
||||
sql += Schemas.ToSql();
|
||||
sql += XmlSchemas.ToSql();
|
||||
sql += Rules.ToSql();
|
||||
sql += UserTypes.ToSql();
|
||||
sql += Assemblies.ToSql();
|
||||
sql += Tables.ToSql();
|
||||
sql += Functions.ToSql();
|
||||
sql += Procedures.ToSql();
|
||||
sql += CLRProcedures.ToSql();
|
||||
sql += CLRFunctions.ToSql();
|
||||
sql += DDLTriggers.ToSql();
|
||||
sql += Synonyms.ToSql();
|
||||
sql += Views.ToSql();
|
||||
sql += Users.ToSql();
|
||||
sql += PartitionFunctions.ToSql();
|
||||
sql += FullText.ToSql();
|
||||
return sql;
|
||||
}
|
||||
|
||||
public override SQLScriptList ToSqlDiff(ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
var isAzure10 = this.Info.Version == DatabaseInfo.SQLServerVersion.SQLServerAzure10;
|
||||
|
||||
var listDiff = new SQLScriptList();
|
||||
|
||||
var header = $@"/*
|
||||
|
||||
OpenDBDiff {System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString()}
|
||||
https://github.com/OpenDBDiff/OpenDBDiff
|
||||
|
||||
Script created by {Environment.UserDomainName}\{Environment.UserName} on {DateTime.Now.ToShortDateString()} at {DateTime.Now.ToLongTimeString()}.
|
||||
|
||||
Created on: {Environment.MachineName}
|
||||
Source: {SourceInfo?.Database ?? "Unknown"} on {SourceInfo?.Server ?? "Unknown"}
|
||||
Destination: {Info?.Database ?? "Unknown"} on {Info?.Server ?? "Unknown"}
|
||||
|
||||
### This script performs actions to change the Destination schema to the Source schema. ###
|
||||
|
||||
*/
|
||||
|
||||
";
|
||||
|
||||
listDiff.Add(new SQLScript(header, 0, ScriptAction.None));
|
||||
|
||||
if (!isAzure10)
|
||||
{
|
||||
listDiff.Add("USE [" + Name + "]\r\nGO\r\n\r\n", 0, ScriptAction.UseDatabase);
|
||||
listDiff.AddRange(Assemblies.ToSqlDiff(schemas));
|
||||
listDiff.AddRange(UserTypes.ToSqlDiff(schemas));
|
||||
}
|
||||
listDiff.AddRange(TablesTypes.ToSqlDiff(schemas));
|
||||
listDiff.AddRange(Tables.ToSqlDiff(schemas));
|
||||
listDiff.AddRange(Rules.ToSqlDiff(schemas));
|
||||
listDiff.AddRange(Schemas.ToSqlDiff(schemas));
|
||||
listDiff.AddRange(XmlSchemas.ToSqlDiff(schemas));
|
||||
listDiff.AddRange(Procedures.ToSqlDiff(schemas));
|
||||
if (!isAzure10)
|
||||
{
|
||||
listDiff.AddRange(CLRProcedures.ToSqlDiff(schemas));
|
||||
listDiff.AddRange(CLRFunctions.ToSqlDiff(schemas));
|
||||
listDiff.AddRange(FileGroups.ToSqlDiff(schemas));
|
||||
}
|
||||
listDiff.AddRange(DDLTriggers.ToSqlDiff(schemas));
|
||||
listDiff.AddRange(Synonyms.ToSqlDiff(schemas));
|
||||
listDiff.AddRange(Views.ToSqlDiff(schemas));
|
||||
listDiff.AddRange(Users.ToSqlDiff(schemas));
|
||||
listDiff.AddRange(Functions.ToSqlDiff(schemas));
|
||||
listDiff.AddRange(Roles.ToSqlDiff(schemas));
|
||||
listDiff.AddRange(PartitionFunctions.ToSqlDiff(schemas));
|
||||
listDiff.AddRange(PartitionSchemes.ToSqlDiff(schemas));
|
||||
if (!isAzure10)
|
||||
{
|
||||
listDiff.AddRange(FullText.ToSqlDiff(schemas));
|
||||
}
|
||||
return listDiff;
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public ISchemaBase Find(int id)
|
||||
{
|
||||
try
|
||||
{
|
||||
string full = AllObjects.GetFullName(id);
|
||||
return Find(full);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ISchemaBase Find(String _FullName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var typeVal = AllObjects.GetType(_FullName);
|
||||
if (!typeVal.HasValue)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
ObjectType type = typeVal.Value;
|
||||
|
||||
|
||||
string parentName = "";
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ObjectType.Table:
|
||||
return Tables[_FullName];
|
||||
case ObjectType.StoredProcedure:
|
||||
return Procedures[_FullName];
|
||||
case ObjectType.Function:
|
||||
return Functions[_FullName];
|
||||
case ObjectType.View:
|
||||
return Views[_FullName];
|
||||
case ObjectType.Assembly:
|
||||
return Assemblies[_FullName];
|
||||
case ObjectType.UserDataType:
|
||||
return UserTypes[_FullName];
|
||||
case ObjectType.TableType:
|
||||
return TablesTypes[_FullName];
|
||||
case ObjectType.XMLSchema:
|
||||
return XmlSchemas[_FullName];
|
||||
case ObjectType.CLRStoredProcedure:
|
||||
return CLRProcedures[_FullName];
|
||||
case ObjectType.CLRFunction:
|
||||
return CLRFunctions[_FullName];
|
||||
case ObjectType.Synonym:
|
||||
return Synonyms[_FullName];
|
||||
case ObjectType.FullText:
|
||||
return FullText[_FullName];
|
||||
case ObjectType.Rule:
|
||||
return Rules[_FullName];
|
||||
case ObjectType.PartitionFunction:
|
||||
return PartitionFunctions[_FullName];
|
||||
case ObjectType.PartitionScheme:
|
||||
return PartitionSchemes[_FullName];
|
||||
case ObjectType.Role:
|
||||
return Roles[_FullName];
|
||||
case ObjectType.Schema:
|
||||
return Schemas[_FullName];
|
||||
case ObjectType.Constraint:
|
||||
parentName = AllObjects.GetParentName(_FullName);
|
||||
return Tables[parentName].Constraints[_FullName];
|
||||
case ObjectType.Index:
|
||||
parentName = AllObjects.GetParentName(_FullName);
|
||||
|
||||
var typeName = AllObjects.GetType(parentName);
|
||||
if (!typeName.HasValue)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
type = typeName.Value;
|
||||
if (type == ObjectType.Table)
|
||||
return Tables[parentName].Indexes[_FullName];
|
||||
return Views[parentName].Indexes[_FullName];
|
||||
case ObjectType.Trigger:
|
||||
parentName = AllObjects.GetParentName(_FullName);
|
||||
var typeNameB = AllObjects.GetType(parentName);
|
||||
if (!typeNameB.HasValue)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
type = typeNameB.Value;
|
||||
if (type == ObjectType.Table)
|
||||
return Tables[parentName].Triggers[_FullName];
|
||||
return Views[parentName].Triggers[_FullName];
|
||||
case ObjectType.CLRTrigger:
|
||||
parentName = AllObjects.GetParentName(_FullName);
|
||||
var typeNameC = AllObjects.GetType(parentName);
|
||||
if (!typeNameC.HasValue)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
type = typeNameC.Value;
|
||||
if (type == ObjectType.Table)
|
||||
return Tables[parentName].CLRTriggers[_FullName];
|
||||
return Views[parentName].CLRTriggers[_FullName];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/*private SQLScriptList CleanScripts(SQLScriptList listDiff)
|
||||
{
|
||||
SQLScriptList alters = listDiff.FindAlter();
|
||||
for (int j = 0; j < alters.Count; j++)
|
||||
{
|
||||
//alters[j].
|
||||
}
|
||||
return null;
|
||||
}*/
|
||||
|
||||
public void BuildDependency()
|
||||
{
|
||||
ISchemaBase schema;
|
||||
var indexes = new List<Index>();
|
||||
var constraints = new List<Constraint>();
|
||||
|
||||
Tables.ForEach(item => indexes.AddRange(item.Indexes));
|
||||
Views.ForEach(item => indexes.AddRange(item.Indexes));
|
||||
Tables.ForEach(item => constraints.AddRange(item.Constraints));
|
||||
|
||||
foreach (Index index in indexes)
|
||||
{
|
||||
schema = index.Parent;
|
||||
foreach (IndexColumn icolumn in index.Columns)
|
||||
{
|
||||
Dependencies.Add(this, schema.Id, icolumn.Id, schema.Id, icolumn.DataTypeId, index);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Constraint con in constraints)
|
||||
{
|
||||
schema = con.Parent;
|
||||
if (con.Type != Constraint.ConstraintType.Check)
|
||||
{
|
||||
foreach (ConstraintColumn ccolumn in con.Columns)
|
||||
{
|
||||
Dependencies.Add(this, schema.Id, ccolumn.Id, schema.Id, ccolumn.DataTypeId, con);
|
||||
if (con.Type == Constraint.ConstraintType.ForeignKey)
|
||||
{
|
||||
Dependencies.Add(this, con.RelationalTableId, ccolumn.ColumnRelationalId, schema.Id,
|
||||
ccolumn.ColumnRelationalDataTypeId, con);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (
|
||||
((Table)schema).FullTextIndex.Exists(
|
||||
item => { return item.Index.Equals(con.Name); }))
|
||||
{
|
||||
Dependencies.Add(this, schema.Id, 0, schema.Id, 0, con);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
Dependencies.Add(this, schema.Id, 0, schema.Id, 0, con);
|
||||
}
|
||||
}
|
||||
|
||||
#region Nested type: DatabaseChangeStatus
|
||||
|
||||
private enum DatabaseChangeStatus
|
||||
{
|
||||
AlterChangeTracking = 1,
|
||||
AlterCollation = 2
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
94
OpenDBDiff.Schema.SQLServer.Generates/Model/DatabaseInfo.cs
Normal file
94
OpenDBDiff.Schema.SQLServer.Generates/Model/DatabaseInfo.cs
Normal file
@@ -0,0 +1,94 @@
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class DatabaseInfo
|
||||
{
|
||||
public enum SQLServerVersion
|
||||
{
|
||||
SQLServer2000,
|
||||
SQLServer2005,
|
||||
SQLServer2008,
|
||||
SQLServer2008R2,
|
||||
|
||||
// Azure will be reporting v11 instead of v10.25 soon...
|
||||
// http://social.msdn.microsoft.com/Forums/en-US/ssdsgetstarted/thread/ad7aae98-26ac-4979-848d-517a86c3fa5c/
|
||||
SQLServerAzure10, /*Azure*/
|
||||
|
||||
SQLServer2012,
|
||||
SQLServer2014,
|
||||
SQLServer2016,
|
||||
SQLServer2017,
|
||||
}
|
||||
|
||||
public enum SQLServerEdition
|
||||
{
|
||||
Personal = 1,
|
||||
Standard = 2,
|
||||
Enterprise = 3,
|
||||
Express = 4,
|
||||
Azure = 5
|
||||
}
|
||||
|
||||
private float versionNumber;
|
||||
|
||||
public DatabaseInfo()
|
||||
{
|
||||
Version = SQLServerVersion.SQLServer2005;
|
||||
}
|
||||
|
||||
public string Server { get; set; }
|
||||
|
||||
public string Database { get; set; }
|
||||
|
||||
public SQLServerVersion Version { get; private set; }
|
||||
|
||||
public SQLServerEdition Edition { get; private set; }
|
||||
|
||||
public string Collation { get; set; }
|
||||
|
||||
public bool HasFullTextEnabled { get; set; }
|
||||
|
||||
public string ChangeTrackingPeriodUnitsDesc { get; set; }
|
||||
|
||||
public int ChangeTrackingPeriodUnits { get; set; }
|
||||
|
||||
public int ChangeTrackingRetentionPeriod { get; set; }
|
||||
|
||||
public bool IsChangeTrackingAutoCleanup { get; set; }
|
||||
|
||||
public bool HasChangeTracking { get; set; }
|
||||
|
||||
public float VersionNumber
|
||||
{
|
||||
get { return versionNumber; }
|
||||
set
|
||||
{
|
||||
versionNumber = value;
|
||||
|
||||
SQLServerVersion version = this.Version;
|
||||
|
||||
// https://buildnumbers.wordpress.com/sqlserver/
|
||||
if (versionNumber >= 8) version = SQLServerVersion.SQLServer2000;
|
||||
if (versionNumber >= 9) version = SQLServerVersion.SQLServer2005;
|
||||
if (versionNumber >= 10) version = SQLServerVersion.SQLServer2008;
|
||||
if (versionNumber >= 10.25) version = SQLServerVersion.SQLServerAzure10;
|
||||
if (versionNumber >= 10.5) version = SQLServerVersion.SQLServer2008R2;
|
||||
if (versionNumber >= 11.0) version = SQLServerVersion.SQLServer2012;
|
||||
if (versionNumber >= 12.0) version = SQLServerVersion.SQLServer2014;
|
||||
if (versionNumber >= 13.0) version = SQLServerVersion.SQLServer2016;
|
||||
if (versionNumber >= 14.0) version = SQLServerVersion.SQLServer2017;
|
||||
|
||||
this.Version = version;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetEdition(SQLServerEdition edition)
|
||||
{
|
||||
this.Edition = edition;
|
||||
|
||||
if (edition == SQLServerEdition.Azure)
|
||||
{
|
||||
this.Version = SQLServerVersion.SQLServerAzure10;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
76
OpenDBDiff.Schema.SQLServer.Generates/Model/Default.cs
Normal file
76
OpenDBDiff.Schema.SQLServer.Generates/Model/Default.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class Default : SQLServerSchemaBase
|
||||
{
|
||||
public Default(ISchemaBase parent)
|
||||
: base(parent, ObjectType.Default)
|
||||
{
|
||||
}
|
||||
|
||||
public new Default Clone(ISchemaBase parent)
|
||||
{
|
||||
Default item = new Default(parent);
|
||||
item.Id = this.Id;
|
||||
item.Name = this.Name;
|
||||
item.Owner = this.Owner;
|
||||
item.Value = this.Value;
|
||||
return item;
|
||||
}
|
||||
|
||||
public string Value { get; set; }
|
||||
|
||||
public string ToSQLAddBind()
|
||||
{
|
||||
string sql = "";
|
||||
sql += "EXEC sp_bindefault N'" + Name + "', N'" + this.Parent.Name + "'\r\nGO\r\n";
|
||||
return sql;
|
||||
}
|
||||
|
||||
public string ToSQLAddUnBind()
|
||||
{
|
||||
string sql = "";
|
||||
sql += "EXEC sp_unbindefault @objname=N'" + this.Parent.Name + "'\r\nGO\r\n";
|
||||
return sql;
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
return ToSql();
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
return "DROP DEFAULT " + FullName + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Devuelve el schema de diferencias del Schema en formato SQL.
|
||||
/// </summary>
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList listDiff = new SQLScriptList();
|
||||
|
||||
if (this.Status == ObjectStatus.Drop)
|
||||
{
|
||||
listDiff.Add(ToSqlDrop(), 0, ScriptAction.DropRule);
|
||||
}
|
||||
if (this.Status == ObjectStatus.Create)
|
||||
{
|
||||
listDiff.Add(ToSql(), 0, ScriptAction.AddRule);
|
||||
}
|
||||
if (this.Status == ObjectStatus.Alter)
|
||||
{
|
||||
listDiff.Add(ToSqlDrop(), 0, ScriptAction.DropRule);
|
||||
listDiff.Add(ToSql(), 0, ScriptAction.AddRule);
|
||||
}
|
||||
return listDiff;
|
||||
}
|
||||
}
|
||||
}
|
||||
151
OpenDBDiff.Schema.SQLServer.Generates/Model/Dependencies.cs
Normal file
151
OpenDBDiff.Schema.SQLServer.Generates/Model/Dependencies.cs
Normal file
@@ -0,0 +1,151 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
internal class Dependencies : List<Dependency>
|
||||
{
|
||||
public Database Database { get; private set; }
|
||||
|
||||
public void Add(Database database, int tableId, int columnId, int ownerTableId, int typeId, ISchemaBase constraint)
|
||||
{
|
||||
Dependency dependency = new Dependency();
|
||||
dependency.SubObjectId = columnId;
|
||||
dependency.ObjectId = tableId;
|
||||
dependency.OwnerTableId = ownerTableId;
|
||||
|
||||
dependency.FullName = constraint.FullName;
|
||||
dependency.Type = constraint.ObjectType;
|
||||
dependency.DataTypeId = typeId;
|
||||
this.Database = database;
|
||||
base.Add(dependency);
|
||||
}
|
||||
|
||||
public void Add(Database database, int objectId, ISchemaBase objectSchema)
|
||||
{
|
||||
Dependency dependency = new Dependency();
|
||||
dependency.ObjectId = objectId;
|
||||
dependency.FullName = objectSchema.FullName;
|
||||
dependency.Type = objectSchema.ObjectType;
|
||||
this.Database = database;
|
||||
base.Add(dependency);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Devuelve todos las constraints dependientes de una tabla.
|
||||
/// </summary>
|
||||
public List<ISchemaBase> FindNotOwner(int tableId, ObjectType type)
|
||||
{
|
||||
try
|
||||
{
|
||||
List<ISchemaBase> cons = new List<ISchemaBase>();
|
||||
this.ForEach(dependency =>
|
||||
{
|
||||
if (dependency.Type == type)
|
||||
{
|
||||
ISchemaBase item = (ISchemaBase)Database.Find(dependency.FullName);
|
||||
if (dependency.Type == ObjectType.Constraint)
|
||||
{
|
||||
if ((dependency.ObjectId == tableId) && (((Constraint)item).Type == Constraint.ConstraintType.ForeignKey))
|
||||
cons.Add(item);
|
||||
}
|
||||
else
|
||||
if (dependency.ObjectId == tableId)
|
||||
cons.Add(item);
|
||||
}
|
||||
|
||||
});
|
||||
return cons;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Devuelve todos las constraints dependientes de una tabla.
|
||||
/// </summary>
|
||||
/*public void Set(int tableId, Constraint constraint)
|
||||
{
|
||||
this.ForEach(item =>
|
||||
{
|
||||
if (item.Type == ObjectType.Constraint)
|
||||
if ((item.ObjectId == tableId) && (item.ObjectSchema.Name.Equals(constraint.Name)))
|
||||
item.ObjectSchema = constraint;
|
||||
});
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// Devuelve todos las constraints dependientes de una tabla.
|
||||
/// </summary>
|
||||
public List<ISchemaBase> Find(int tableId)
|
||||
{
|
||||
return Find(tableId, 0, 0);
|
||||
}
|
||||
|
||||
public int DependenciesCount(int objectId, ObjectType type)
|
||||
{
|
||||
Dictionary<int, bool> depencyTracker = new Dictionary<int, bool>();
|
||||
return DependenciesCount(objectId, type, depencyTracker);
|
||||
}
|
||||
|
||||
private int DependenciesCount(int tableId, ObjectType type, Dictionary<int, bool> depencyTracker)
|
||||
{
|
||||
int count = 0;
|
||||
bool putItem = false;
|
||||
int relationalTableId;
|
||||
List<ISchemaBase> constraints = this.FindNotOwner(tableId, type);
|
||||
for (int index = 0; index < constraints.Count; index++)
|
||||
{
|
||||
ISchemaBase cons = constraints[index];
|
||||
if (cons.ObjectType == type)
|
||||
{
|
||||
if (type == ObjectType.Constraint)
|
||||
{
|
||||
relationalTableId = ((Constraint)cons).RelationalTableId;
|
||||
putItem = (relationalTableId == tableId);
|
||||
}
|
||||
}
|
||||
if (putItem)
|
||||
{
|
||||
if (!depencyTracker.ContainsKey(tableId))
|
||||
{
|
||||
depencyTracker.Add(tableId, true);
|
||||
count += 1 + DependenciesCount(cons.Parent.Id, type, depencyTracker);
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Devuelve todos las constraints dependientes de una tabla y una columna.
|
||||
/// </summary>
|
||||
public List<ISchemaBase> Find(int tableId, int columnId, int dataTypeId)
|
||||
{
|
||||
List<string> cons = new List<string>();
|
||||
List<ISchemaBase> real = new List<ISchemaBase>();
|
||||
|
||||
cons = (from depends in this
|
||||
where (depends.Type == ObjectType.Constraint || depends.Type == ObjectType.Index) &&
|
||||
((depends.DataTypeId == dataTypeId || dataTypeId == 0) && (depends.SubObjectId == columnId || columnId == 0) && (depends.ObjectId == tableId))
|
||||
select depends.FullName)
|
||||
.Concat(from depends in this
|
||||
where (depends.Type == ObjectType.View || depends.Type == ObjectType.Function) &&
|
||||
(depends.ObjectId == tableId)
|
||||
select depends.FullName).ToList();
|
||||
|
||||
cons.ForEach(item =>
|
||||
{
|
||||
ISchemaBase schema = Database.Find(item);
|
||||
if (schema != null) real.Add(schema);
|
||||
}
|
||||
);
|
||||
return real;
|
||||
}
|
||||
}
|
||||
}
|
||||
23
OpenDBDiff.Schema.SQLServer.Generates/Model/Dependency.cs
Normal file
23
OpenDBDiff.Schema.SQLServer.Generates/Model/Dependency.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
internal class Dependency
|
||||
{
|
||||
public string FullName { get; set; }
|
||||
|
||||
public int DataTypeId { get; set; }
|
||||
|
||||
public ObjectType Type { get; set; }
|
||||
|
||||
public int SubObjectId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ID de la tabla a la que hace referencia la constraint.
|
||||
/// </summary>
|
||||
public int ObjectId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ID de la tabla a la que pertenece la constraint.
|
||||
/// </summary>
|
||||
public int OwnerTableId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
using System;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class ExtendedProperty : SQLServerSchemaBase, ISchemaBase
|
||||
{
|
||||
public ExtendedProperty(ISchemaBase parent)
|
||||
: base(parent, ObjectType.ExtendedProperty)
|
||||
{
|
||||
}
|
||||
|
||||
public override string FullName
|
||||
{
|
||||
get
|
||||
{
|
||||
string normal = "[" + Level0name + "]" + (String.IsNullOrEmpty(Level1name) ? "" : ".[" + Level1name + "]") + (String.IsNullOrEmpty(Level2name) ? "" : ".[" + Level2name + "]");
|
||||
if ((String.IsNullOrEmpty(Level1type)) || (String.IsNullOrEmpty(Level2type)))
|
||||
return normal;
|
||||
if (!Level2type.Equals("TRIGGER"))
|
||||
return normal;
|
||||
else
|
||||
return "[" + Level0name + "].[" + Level2name + "]";
|
||||
}
|
||||
}
|
||||
|
||||
public string Level2name { get; set; }
|
||||
|
||||
public string Level2type { get; set; }
|
||||
|
||||
public string Level1name { get; set; }
|
||||
|
||||
public string Level1type { get; set; }
|
||||
|
||||
public string Level0name { get; set; }
|
||||
|
||||
public string Level0type { get; set; }
|
||||
|
||||
public string Value { get; set; }
|
||||
|
||||
public override SQLScript Create()
|
||||
{
|
||||
ScriptAction action = ScriptAction.AddExtendedProperty;
|
||||
return new SQLScript(this.ToSqlAdd(), 0, action);
|
||||
}
|
||||
|
||||
public override SQLScript Drop()
|
||||
{
|
||||
ScriptAction action = ScriptAction.DropExtendedProperty;
|
||||
return new SQLScript(this.ToSqlDrop(), 0, action);
|
||||
}
|
||||
|
||||
public override ObjectStatus Status { get; set; }
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
string sql = "EXEC sys.sp_addextendedproperty @name=N'" + Name + "', @value=N'" + Value + "' ,";
|
||||
sql += "@level0type=N'" + Level0type + "',@level0name=N'" + Level0name + "'";
|
||||
if (!String.IsNullOrEmpty(Level1name))
|
||||
sql += ", @level1type=N'" + Level1type + "',@level1name=N'" + Level1name + "'";
|
||||
if (!String.IsNullOrEmpty(Level2name))
|
||||
sql += ", @level2type=N'" + Level2type + "',@level2name=N'" + Level2name + "'";
|
||||
|
||||
return sql + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
string sql = "EXEC sys.sp_dropextendedproperty @name=N'" + Name + "', @value=N'" + Value + "' ,";
|
||||
sql += "@level0type=N'" + Level0type + "',@level0name=N'" + Level0name + "'";
|
||||
if (!String.IsNullOrEmpty(Level1name))
|
||||
sql += ", @level1type=N'" + Level1type + "',@level1name=N'" + Level1name + "'";
|
||||
|
||||
if (!String.IsNullOrEmpty(Level2name))
|
||||
sql += ", @level2type=N'" + Level2type + "',@level2name=N'" + Level2name + "'";
|
||||
return sql + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
return ToSqlAdd();
|
||||
}
|
||||
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
if (this.Parent.Status != ObjectStatus.Create)
|
||||
{
|
||||
if (this.Status == ObjectStatus.Create)
|
||||
list.Add(this.Create());
|
||||
if (this.Status == ObjectStatus.Drop)
|
||||
list.Add(this.Drop());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
106
OpenDBDiff.Schema.SQLServer.Generates/Model/FileGroup.cs
Normal file
106
OpenDBDiff.Schema.SQLServer.Generates/Model/FileGroup.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class FileGroup : SQLServerSchemaBase
|
||||
{
|
||||
public FileGroup(ISchemaBase parent)
|
||||
: base(parent, ObjectType.FileGroup)
|
||||
{
|
||||
Files = new FileGroupFiles(this);
|
||||
}
|
||||
|
||||
public override ISchemaBase Clone(ISchemaBase parent)
|
||||
{
|
||||
FileGroup file = new FileGroup(parent);
|
||||
file.IsDefaultFileGroup = this.IsDefaultFileGroup;
|
||||
file.IsReadOnly = this.IsReadOnly;
|
||||
file.Name = this.Name;
|
||||
file.Id = this.Id;
|
||||
file.Files = this.Files.Clone(file);
|
||||
file.Guid = this.Guid;
|
||||
file.IsFileStream = this.IsFileStream;
|
||||
return file;
|
||||
}
|
||||
|
||||
public FileGroupFiles Files { get; set; }
|
||||
|
||||
public Boolean IsFileStream { get; set; }
|
||||
|
||||
public Boolean IsDefaultFileGroup { get; set; }
|
||||
|
||||
public Boolean IsReadOnly { get; set; }
|
||||
|
||||
public static Boolean Compare(FileGroup origin, FileGroup destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (origin == null) throw new ArgumentNullException("origin");
|
||||
if (origin.IsReadOnly != destination.IsReadOnly) return false;
|
||||
if (origin.IsDefaultFileGroup != destination.IsDefaultFileGroup) return false;
|
||||
if (origin.IsFileStream != destination.IsFileStream) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private string ToSQL(string action)
|
||||
{
|
||||
string sql = "ALTER DATABASE [" + Parent.Name + "] " + action + " ";
|
||||
sql += "FILEGROUP [" + Name + "]";
|
||||
if (action.Equals("MODIFY"))
|
||||
{
|
||||
if (IsDefaultFileGroup) sql += " DEFAULT";
|
||||
}
|
||||
else
|
||||
if (IsFileStream) sql += " CONTAINS FILESTREAM";
|
||||
if (IsReadOnly) sql += " READONLY";
|
||||
sql += "\r\nGO\r\n";
|
||||
return sql;
|
||||
}
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
string sql = ToSQL("ADD");
|
||||
foreach (FileGroupFile file in this.Files)
|
||||
sql += file.ToSql();
|
||||
if (IsDefaultFileGroup)
|
||||
sql += ToSQL("MODIFY");
|
||||
return sql;
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
string sql = ToSQL("ADD");
|
||||
foreach (FileGroupFile file in this.Files)
|
||||
sql += file.ToSqlAdd();
|
||||
if (IsDefaultFileGroup)
|
||||
sql += ToSQL("MODIFY");
|
||||
return sql;
|
||||
}
|
||||
|
||||
public string ToSQLAlter()
|
||||
{
|
||||
return ToSQL("MODIFY");
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
string sql = "";
|
||||
sql = Files.ToSQLDrop();
|
||||
return sql + "ALTER DATABASE [" + Parent.Name + "] REMOVE FILEGROUP [" + Name + "]\r\nGO\r\n\r\n";
|
||||
}
|
||||
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList listDiff = new SQLScriptList();
|
||||
|
||||
if (this.Status == ObjectStatus.Drop)
|
||||
listDiff.Add(this.ToSqlDrop(), 1, ScriptAction.DropFileGroup);
|
||||
if (this.Status == ObjectStatus.Create)
|
||||
listDiff.Add(this.ToSqlAdd(), 1, ScriptAction.AddFileGroup);
|
||||
if (this.Status == ObjectStatus.Alter)
|
||||
listDiff.Add(this.ToSQLAlter(), 1, ScriptAction.AlterFileGroup);
|
||||
|
||||
return listDiff;
|
||||
}
|
||||
}
|
||||
}
|
||||
111
OpenDBDiff.Schema.SQLServer.Generates/Model/FileGroupFile.cs
Normal file
111
OpenDBDiff.Schema.SQLServer.Generates/Model/FileGroupFile.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
using System;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class FileGroupFile : SQLServerSchemaBase
|
||||
{
|
||||
public FileGroupFile(ISchemaBase parent)
|
||||
: base(parent, ObjectType.File)
|
||||
{
|
||||
}
|
||||
|
||||
public override ISchemaBase Clone(ISchemaBase parent)
|
||||
{
|
||||
FileGroupFile file = new FileGroupFile(parent);
|
||||
file.Growth = this.Growth;
|
||||
file.Id = this.Id;
|
||||
file.IsPercentGrowth = this.IsPercentGrowth;
|
||||
file.IsSparse = this.IsSparse;
|
||||
file.MaxSize = this.MaxSize;
|
||||
file.Name = this.Name;
|
||||
file.PhysicalName = this.PhysicalName;
|
||||
file.Size = this.Size;
|
||||
file.Type = this.Type;
|
||||
return file;
|
||||
}
|
||||
|
||||
public int Size { get; set; }
|
||||
|
||||
public Boolean IsSparse { get; set; }
|
||||
|
||||
public Boolean IsPercentGrowth { get; set; }
|
||||
|
||||
private string TypeGrowth
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Growth == 0)
|
||||
return "";
|
||||
else
|
||||
if (IsPercentGrowth)
|
||||
return "%";
|
||||
else
|
||||
return "KB";
|
||||
}
|
||||
}
|
||||
|
||||
public int Growth { get; set; }
|
||||
|
||||
public int MaxSize { get; set; }
|
||||
|
||||
public string PhysicalName { get; set; }
|
||||
|
||||
public int Type { get; set; }
|
||||
|
||||
private string GetNameNewFileGroup(string path)
|
||||
{
|
||||
string result = "";
|
||||
string[] flies = path.Split('\\');
|
||||
for (int index = 0; index < flies.Length - 1; index++)
|
||||
if (!String.IsNullOrEmpty(flies[index]))
|
||||
result += flies[index] + "\\";
|
||||
result += Parent.Parent.Name + "_" + Name + "_DB.ndf";
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compara dos triggers y devuelve true si son iguales, caso contrario, devuelve false.
|
||||
/// </summary>
|
||||
public static Boolean Compare(FileGroupFile origin, FileGroupFile destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (origin == null) throw new ArgumentNullException("origin");
|
||||
if (origin.Growth != destination.Growth) return false;
|
||||
if (origin.IsPercentGrowth != destination.IsPercentGrowth) return false;
|
||||
if (origin.IsSparse != destination.IsSparse) return false;
|
||||
if (origin.MaxSize != destination.MaxSize) return false;
|
||||
if (!origin.PhysicalName.Equals(destination.PhysicalName)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
if (Type != 2)
|
||||
return "ALTER DATABASE " + Parent.Parent.FullName + "\r\nADD" + ((Type != 1) ? "" : " LOG") + " FILE ( NAME = N'" + Name + "', FILENAME = N'" + PhysicalName + "' , SIZE = " + Size * 1000 + "KB , FILEGROWTH = " + Growth * 1000 + TypeGrowth + ") TO FILEGROUP " + Parent.FullName + "\r\nGO\r\n";
|
||||
else
|
||||
return "ALTER DATABASE " + Parent.Parent.FullName + "\r\nADD" + ((Type != 1) ? "" : " LOG") + " FILE ( NAME = N'" + Name + "', FILENAME = N'" + PhysicalName + "') TO FILEGROUP " + Parent.FullName + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
if (Type != 2)
|
||||
return "ALTER DATABASE " + Parent.Parent.FullName + "\r\nADD" + ((Type != 1) ? "" : " LOG") + " FILE ( NAME = N'" + Name + "', FILENAME = N'" + GetNameNewFileGroup(PhysicalName) + "' , SIZE = " + Size * 1000 + "KB , FILEGROWTH = " + Growth * 1000 + TypeGrowth + ") TO FILEGROUP " + Parent.FullName + "\r\nGO\r\n";
|
||||
else
|
||||
return "ALTER DATABASE " + Parent.Parent.FullName + "\r\nADD" + ((Type != 1) ? "" : " LOG") + " FILE ( NAME = N'" + Name + "', FILENAME = N'" + GetNameNewFileGroup(PhysicalName) + "') TO FILEGROUP " + Parent.FullName + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public string ToSQLAlter()
|
||||
{
|
||||
if (Type != 2)
|
||||
return "ALTER DATABASE " + Parent.Parent.FullName + " MODIFY FILE ( NAME = N'" + Name + "', FILENAME = N'" + PhysicalName + "' , SIZE = " + Size * 1000 + "KB , FILEGROWTH = " + Growth * 1000 + TypeGrowth + ")";
|
||||
else
|
||||
return "ALTER DATABASE " + Parent.Parent.FullName + " MODIFY FILE ( NAME = N'" + Name + "', FILENAME = N'" + PhysicalName + "')";
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
return "ALTER DATABASE " + Parent.Parent.FullName + " REMOVE FILE " + this.FullName + "\r\nGO\r\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
104
OpenDBDiff.Schema.SQLServer.Generates/Model/FileGroupFiles.cs
Normal file
104
OpenDBDiff.Schema.SQLServer.Generates/Model/FileGroupFiles.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class FileGroupFiles : List<FileGroupFile>
|
||||
{
|
||||
private Hashtable hash = new Hashtable();
|
||||
|
||||
/// <summary>
|
||||
/// Constructor de la clase.
|
||||
/// </summary>
|
||||
/// <param name="parent">
|
||||
/// Objeto Database padre.
|
||||
/// </param>
|
||||
public FileGroupFiles(FileGroup parent)
|
||||
{
|
||||
this.Parent = parent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clona el objeto FileGroups en una nueva instancia.
|
||||
/// </summary>
|
||||
public FileGroupFiles Clone(FileGroup parentObject)
|
||||
{
|
||||
FileGroupFiles columns = new FileGroupFiles(parentObject);
|
||||
for (int index = 0; index < this.Count; index++)
|
||||
{
|
||||
columns.Add((FileGroupFile)this[index].Clone(parentObject));
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indica si el nombre del FileGroup existe en la coleccion de tablas del objeto.
|
||||
/// </summary>
|
||||
/// <param name="table">
|
||||
/// Nombre de la tabla a buscar.
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
public Boolean Find(string table)
|
||||
{
|
||||
return hash.ContainsKey(table);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Agrega un objeto columna a la coleccion de columnas.
|
||||
/// </summary>
|
||||
public new void Add(FileGroupFile file)
|
||||
{
|
||||
if (file != null)
|
||||
{
|
||||
hash.Add(file.FullName, file);
|
||||
base.Add(file);
|
||||
}
|
||||
else
|
||||
throw new ArgumentNullException("file");
|
||||
}
|
||||
|
||||
public FileGroupFile this[string name]
|
||||
{
|
||||
get { return (FileGroupFile)hash[name]; }
|
||||
set
|
||||
{
|
||||
hash[name] = value;
|
||||
for (int index = 0; index < base.Count; index++)
|
||||
{
|
||||
if (((FileGroupFile)base[index]).Name.Equals(name))
|
||||
{
|
||||
base[index] = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Devuelve la tabla perteneciente a la coleccion de campos.
|
||||
/// </summary>
|
||||
public FileGroup Parent { get; private set; }
|
||||
|
||||
public string ToSQL()
|
||||
{
|
||||
StringBuilder sql = new StringBuilder();
|
||||
for (int index = 0; index < this.Count; index++)
|
||||
{
|
||||
sql.Append(this[index].ToSql());
|
||||
}
|
||||
return sql.ToString();
|
||||
}
|
||||
|
||||
public string ToSQLDrop()
|
||||
{
|
||||
StringBuilder sql = new StringBuilder();
|
||||
for (int index = 0; index < this.Count; index++)
|
||||
{
|
||||
sql.Append(this[index].ToSqlDrop());
|
||||
}
|
||||
return sql.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
131
OpenDBDiff.Schema.SQLServer.Generates/Model/FullText.cs
Normal file
131
OpenDBDiff.Schema.SQLServer.Generates/Model/FullText.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
using System;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class FullText : SQLServerSchemaBase
|
||||
{
|
||||
public FullText(ISchemaBase parent)
|
||||
: base(parent, ObjectType.FullText)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override string FullName
|
||||
{
|
||||
get { return "[" + Name + "]"; }
|
||||
}
|
||||
|
||||
public string Path { get; set; }
|
||||
|
||||
public Boolean IsDefault { get; set; }
|
||||
|
||||
public Boolean IsAccentSensity { get; set; }
|
||||
|
||||
public string FileGroupName { get; set; }
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
Database database = (Database)this.Parent;
|
||||
|
||||
string sql = "CREATE FULLTEXT CATALOG " + FullName + " ";
|
||||
if (!IsAccentSensity)
|
||||
sql += "WITH ACCENT_SENSITIVITY = OFF\r\n";
|
||||
else
|
||||
sql += "WITH ACCENT_SENSITIVITY = ON\r\n";
|
||||
if (!String.IsNullOrEmpty(this.Path))
|
||||
{
|
||||
if (!database.Options.Ignore.FilterFullTextPath)
|
||||
sql += "--";
|
||||
sql += "IN PATH N'" + Path + "'\r\n";
|
||||
}
|
||||
if (IsDefault)
|
||||
sql += "AS DEFAULT\r\n";
|
||||
sql += "AUTHORIZATION [" + Owner + "]\r\n";
|
||||
return sql + "GO\r\n";
|
||||
}
|
||||
|
||||
private string ToSqlAlterDefault()
|
||||
{
|
||||
if (IsDefault)
|
||||
{
|
||||
string sql = "ALTER FULLTEXT CATALOG " + FullName + "\r\n";
|
||||
sql += "AS DEFAULT";
|
||||
sql += "\r\nGO\r\n";
|
||||
return sql;
|
||||
}
|
||||
else return "";
|
||||
|
||||
}
|
||||
|
||||
private string ToSqlAlterOwner()
|
||||
{
|
||||
string sql = "ALTER AUTHORIZATION ON FULLTEXT CATALOG::" + FullName + "\r\n";
|
||||
sql += "TO [" + Owner + "]\r\nGO\r\n";
|
||||
return sql;
|
||||
}
|
||||
|
||||
private string ToSqlAlter()
|
||||
{
|
||||
string sql = "ALTER FULLTEXT CATALOG " + FullName + "\r\n";
|
||||
sql += "REBUILD WITH ACCENT_SENSITIVITY = ";
|
||||
if (IsAccentSensity) sql += "ON"; else sql += "OFF";
|
||||
sql += "\r\nGO\r\n";
|
||||
return sql;
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
return "DROP FULLTEXT CATALOG " + FullName + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
return ToSql();
|
||||
}
|
||||
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList listDiff = new SQLScriptList();
|
||||
|
||||
if (this.Status == ObjectStatus.Drop)
|
||||
{
|
||||
listDiff.Add(ToSqlDrop(), 0, ScriptAction.DropFullText);
|
||||
}
|
||||
if (this.Status == ObjectStatus.Create)
|
||||
{
|
||||
listDiff.Add(ToSql(), 0, ScriptAction.AddFullText);
|
||||
}
|
||||
if (this.HasState(ObjectStatus.Alter))
|
||||
{
|
||||
listDiff.Add(ToSqlAlter(), 0, ScriptAction.AddFullText);
|
||||
}
|
||||
if (this.HasState(ObjectStatus.Disabled))
|
||||
{
|
||||
listDiff.Add(ToSqlAlterDefault(), 0, ScriptAction.AddFullText);
|
||||
}
|
||||
if (this.HasState(ObjectStatus.ChangeOwner))
|
||||
{
|
||||
listDiff.Add(ToSqlAlterOwner(), 0, ScriptAction.AddFullText);
|
||||
}
|
||||
return listDiff;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compara dos Synonyms y devuelve true si son iguales, caso contrario, devuelve false.
|
||||
/// </summary>
|
||||
public Boolean Compare(FullText destination)
|
||||
{
|
||||
Database database = (Database)this.Parent;
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (!this.IsAccentSensity.Equals(destination.IsAccentSensity)) return false;
|
||||
if (!this.IsDefault.Equals(destination.IsDefault)) return false;
|
||||
if ((!String.IsNullOrEmpty(this.FileGroupName)) && (!String.IsNullOrEmpty(destination.FileGroupName)))
|
||||
if (!this.FileGroupName.Equals(destination.FileGroupName)) return false;
|
||||
if (database.Options.Ignore.FilterFullTextPath)
|
||||
if ((!String.IsNullOrEmpty(this.Path)) && (!String.IsNullOrEmpty(destination.Path)))
|
||||
return this.Path.Equals(destination.Path, StringComparison.CurrentCultureIgnoreCase);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
159
OpenDBDiff.Schema.SQLServer.Generates/Model/FullTextIndex.cs
Normal file
159
OpenDBDiff.Schema.SQLServer.Generates/Model/FullTextIndex.cs
Normal file
@@ -0,0 +1,159 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class FullTextIndex : SQLServerSchemaBase
|
||||
{
|
||||
public FullTextIndex(ISchemaBase parent)
|
||||
: base(parent, ObjectType.FullTextIndex)
|
||||
{
|
||||
Columns = new List<FullTextIndexColumn>();
|
||||
}
|
||||
|
||||
public override ISchemaBase Clone(ISchemaBase parent)
|
||||
{
|
||||
FullTextIndex index = new FullTextIndex(parent);
|
||||
index.ChangeTrackingState = this.ChangeTrackingState;
|
||||
index.FullText = this.FullText;
|
||||
index.Name = this.Name;
|
||||
index.FileGroup = this.FileGroup;
|
||||
index.Id = this.Id;
|
||||
index.Index = this.Index;
|
||||
index.IsDisabled = this.IsDisabled;
|
||||
index.Status = this.Status;
|
||||
index.Owner = this.Owner;
|
||||
index.Columns = this.Columns;
|
||||
this.ExtendedProperties.ForEach(item => index.ExtendedProperties.Add(item));
|
||||
return index;
|
||||
}
|
||||
|
||||
public string FileGroup { get; set; }
|
||||
|
||||
public Boolean IsDisabled { get; set; }
|
||||
|
||||
public string Index { get; set; }
|
||||
|
||||
public string FullText { get; set; }
|
||||
|
||||
public string ChangeTrackingState { get; set; }
|
||||
|
||||
public override string FullName
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Name;
|
||||
}
|
||||
}
|
||||
|
||||
public List<FullTextIndexColumn> Columns { get; set; }
|
||||
|
||||
public override SQLScript Create()
|
||||
{
|
||||
ScriptAction action = ScriptAction.AddFullTextIndex;
|
||||
if (!GetWasInsertInDiffList(action))
|
||||
{
|
||||
SetWasInsertInDiffList(action);
|
||||
return new SQLScript(this.ToSqlAdd(), Parent.DependenciesCount, action);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public override SQLScript Drop()
|
||||
{
|
||||
ScriptAction action = ScriptAction.DropFullTextIndex;
|
||||
if (!GetWasInsertInDiffList(action))
|
||||
{
|
||||
SetWasInsertInDiffList(action);
|
||||
return new SQLScript(this.ToSqlDrop(), Parent.DependenciesCount, action);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
string sql = "CREATE FULLTEXT INDEX ON " + Parent.FullName + "( ";
|
||||
Columns.ForEach(item => { sql += "[" + item.ColumnName + "] LANGUAGE [" + item.Language + "],"; });
|
||||
sql = sql.Substring(0, sql.Length - 1);
|
||||
sql += ")\r\n";
|
||||
if (((Database)this.RootParent).Info.Version == DatabaseInfo.SQLServerVersion.SQLServer2008)
|
||||
{
|
||||
sql += "KEY INDEX " + Index + " ON ([" + FullText + "]";
|
||||
sql += ", FILEGROUP [" + FileGroup + "]";
|
||||
sql += ") WITH (CHANGE_TRACKING " + ChangeTrackingState + ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
sql += "KEY INDEX " + Index + " ON [" + FullText + "]";
|
||||
sql += " WITH CHANGE_TRACKING " + ChangeTrackingState;
|
||||
}
|
||||
sql += "\r\nGO\r\n";
|
||||
if (!this.IsDisabled)
|
||||
sql += "ALTER FULLTEXT INDEX ON " + Parent.FullName + " ENABLE\r\nGO\r\n";
|
||||
return sql;
|
||||
}
|
||||
|
||||
public string ToSqlEnabled()
|
||||
{
|
||||
if (this.IsDisabled)
|
||||
return "ALTER FULLTEXT INDEX ON " + Parent.FullName + " DISABLE\r\nGO\r\n";
|
||||
else
|
||||
return "ALTER FULLTEXT INDEX ON " + Parent.FullName + " ENABLE\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
return "DROP FULLTEXT INDEX ON " + Parent.FullName + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
return ToSqlAdd();
|
||||
}
|
||||
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
if (this.Status != ObjectStatus.Original)
|
||||
RootParent.ActionMessage[Parent.FullName].Add(this);
|
||||
|
||||
if (this.HasState(ObjectStatus.Drop))
|
||||
list.Add(Drop());
|
||||
if (this.HasState(ObjectStatus.Create))
|
||||
list.Add(Create());
|
||||
if (this.HasState(ObjectStatus.Alter))
|
||||
{
|
||||
list.Add(Drop());
|
||||
list.Add(Create());
|
||||
}
|
||||
if (this.Status == ObjectStatus.Disabled)
|
||||
{
|
||||
list.Add(this.ToSqlEnabled(), Parent.DependenciesCount, ScriptAction.AlterFullTextIndex);
|
||||
}
|
||||
/*if (this.Status == StatusEnum.ObjectStatusType.ChangeFileGroup)
|
||||
{
|
||||
listDiff.Add(this.ToSQLDrop(this.FileGroup), ((Table)Parent).DependenciesCount, StatusEnum.ScripActionType.DropIndex);
|
||||
listDiff.Add(this.ToSQLAdd(), ((Table)Parent).DependenciesCount, StatusEnum.ScripActionType.AddIndex);
|
||||
}*/
|
||||
list.AddRange(this.ExtendedProperties.ToSqlDiff());
|
||||
return list;
|
||||
}
|
||||
|
||||
public Boolean Compare(FullTextIndex destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (!this.ChangeTrackingState.Equals(destination.ChangeTrackingState)) return false;
|
||||
if (!this.FullText.Equals(destination.FullText)) return false;
|
||||
if (!this.Index.Equals(destination.Index)) return false;
|
||||
if (this.IsDisabled != destination.IsDisabled) return false;
|
||||
if (this.Columns.Count != destination.Columns.Count) return false;
|
||||
if (this.Columns.Exists(item => { return !destination.Columns.Exists(item2 => item2.ColumnName.Equals(item.ColumnName)); })) return false;
|
||||
if (destination.Columns.Exists(item => { return !this.Columns.Exists(item2 => item2.ColumnName.Equals(item.ColumnName)); })) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class FullTextIndexColumn
|
||||
{
|
||||
public string Language { get; set; }
|
||||
|
||||
public string ColumnName { get; set; }
|
||||
}
|
||||
}
|
||||
80
OpenDBDiff.Schema.SQLServer.Generates/Model/Function.cs
Normal file
80
OpenDBDiff.Schema.SQLServer.Generates/Model/Function.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
using OpenDBDiff.Schema.SQLServer.Generates.Model.Util;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class Function : Code
|
||||
{
|
||||
public Function(ISchemaBase parent)
|
||||
: base(parent, ObjectType.Function, ScriptAction.AddFunction, ScriptAction.DropFunction)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clona el objeto en una nueva instancia.
|
||||
/// </summary>
|
||||
public override ISchemaBase Clone(ISchemaBase parent)
|
||||
{
|
||||
Function item = new Function(parent);
|
||||
item.Text = this.Text;
|
||||
item.Status = this.Status;
|
||||
item.Name = this.Name;
|
||||
item.Id = this.Id;
|
||||
item.Owner = this.Owner;
|
||||
item.Guid = this.Guid;
|
||||
item.IsSchemaBinding = this.IsSchemaBinding;
|
||||
this.DependenciesIn.ForEach(dep => item.DependenciesIn.Add(dep));
|
||||
this.DependenciesOut.ForEach(dep => item.DependenciesOut.Add(dep));
|
||||
return item;
|
||||
}
|
||||
|
||||
public override Boolean IsCodeType
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public string ToSQLAlter()
|
||||
{
|
||||
return ToSQLAlter(false);
|
||||
}
|
||||
|
||||
public string ToSQLAlter(Boolean quitSchemaBinding)
|
||||
{
|
||||
return FormatCode.FormatAlter("FUNCTION", ToSql(), this, quitSchemaBinding);
|
||||
}
|
||||
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
if (this.Status != ObjectStatus.Original)
|
||||
RootParent.ActionMessage.Add(this);
|
||||
|
||||
if (this.HasState(ObjectStatus.Drop))
|
||||
list.Add(Drop());
|
||||
if (this.HasState(ObjectStatus.Create))
|
||||
list.Add(Create());
|
||||
if (this.HasState(ObjectStatus.Alter))
|
||||
{
|
||||
if (this.HasState(ObjectStatus.RebuildDependencies))
|
||||
list.AddRange(RebuildDependencies());
|
||||
|
||||
if (!this.GetWasInsertInDiffList(ScriptAction.DropFunction))
|
||||
{
|
||||
if (this.HasState(ObjectStatus.Rebuild))
|
||||
{
|
||||
list.Add(Drop());
|
||||
list.Add(Create());
|
||||
}
|
||||
if (this.HasState(ObjectStatus.AlterBody))
|
||||
{
|
||||
int iCount = DependenciesCount;
|
||||
list.Add(ToSQLAlter(), iCount, ScriptAction.AlterFunction);
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
13
OpenDBDiff.Schema.SQLServer.Generates/Model/ITableType.cs
Normal file
13
OpenDBDiff.Schema.SQLServer.Generates/Model/ITableType.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public interface ITable<T> where T : ISchemaBase
|
||||
{
|
||||
Columns<T> Columns { get; }
|
||||
SchemaList<Constraint, T> Constraints { get; }
|
||||
SchemaList<Index, T> Indexes { get; }
|
||||
ISchemaBase Parent { get; set; }
|
||||
string Owner { get; set; }
|
||||
}
|
||||
}
|
||||
300
OpenDBDiff.Schema.SQLServer.Generates/Model/Index.cs
Normal file
300
OpenDBDiff.Schema.SQLServer.Generates/Model/Index.cs
Normal file
@@ -0,0 +1,300 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class Index : SQLServerSchemaBase
|
||||
{
|
||||
public enum IndexTypeEnum
|
||||
{
|
||||
Heap = 0,
|
||||
Clustered = 1,
|
||||
Nonclustered = 2,
|
||||
XML = 3,
|
||||
GEO = 4
|
||||
}
|
||||
|
||||
public Index(ISchemaBase parent)
|
||||
: base(parent, ObjectType.Index)
|
||||
{
|
||||
FilterDefintion = "";
|
||||
Columns = new IndexColumns(parent);
|
||||
}
|
||||
|
||||
public override ISchemaBase Clone(ISchemaBase parent)
|
||||
{
|
||||
Index index = new Index(parent)
|
||||
{
|
||||
AllowPageLocks = this.AllowPageLocks,
|
||||
AllowRowLocks = this.AllowRowLocks,
|
||||
Columns = this.Columns.Clone(),
|
||||
FillFactor = this.FillFactor,
|
||||
FileGroup = this.FileGroup,
|
||||
Id = this.Id,
|
||||
IgnoreDupKey = this.IgnoreDupKey,
|
||||
IsAutoStatistics = this.IsAutoStatistics,
|
||||
IsDisabled = this.IsDisabled,
|
||||
IsPadded = this.IsPadded,
|
||||
IsPrimaryKey = this.IsPrimaryKey,
|
||||
IsUniqueKey = this.IsUniqueKey,
|
||||
Name = this.Name,
|
||||
SortInTempDb = this.SortInTempDb,
|
||||
Status = this.Status,
|
||||
Type = this.Type,
|
||||
Owner = this.Owner,
|
||||
FilterDefintion = this.FilterDefintion
|
||||
};
|
||||
ExtendedProperties.ForEach(item => index.ExtendedProperties.Add(item));
|
||||
return index;
|
||||
}
|
||||
|
||||
public string FileGroup { get; set; }
|
||||
|
||||
public Boolean SortInTempDb { get; set; }
|
||||
|
||||
public string FilterDefintion { get; set; }
|
||||
|
||||
public IndexColumns Columns { get; set; }
|
||||
|
||||
public Boolean IsAutoStatistics { get; set; }
|
||||
|
||||
public Boolean IsUniqueKey { get; set; }
|
||||
|
||||
public Boolean IsPrimaryKey { get; set; }
|
||||
|
||||
public IndexTypeEnum Type { get; set; }
|
||||
|
||||
public short FillFactor { get; set; }
|
||||
|
||||
public Boolean IsDisabled { get; set; }
|
||||
|
||||
public Boolean IsPadded { get; set; }
|
||||
|
||||
public Boolean IgnoreDupKey { get; set; }
|
||||
|
||||
public Boolean AllowPageLocks { get; set; }
|
||||
|
||||
public Boolean AllowRowLocks { get; set; }
|
||||
|
||||
public override string FullName
|
||||
{
|
||||
get
|
||||
{
|
||||
return Parent.FullName + ".[" + Name + "]";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compara dos indices y devuelve true si son iguales, caso contrario, devuelve false.
|
||||
/// </summary>
|
||||
public static Boolean Compare(Index origin, Index destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (origin == null) throw new ArgumentNullException("origin");
|
||||
if (origin.AllowPageLocks != destination.AllowPageLocks) return false;
|
||||
if (origin.AllowRowLocks != destination.AllowRowLocks) return false;
|
||||
if (origin.FillFactor != destination.FillFactor) return false;
|
||||
if (origin.IgnoreDupKey != destination.IgnoreDupKey) return false;
|
||||
if (origin.IsAutoStatistics != destination.IsAutoStatistics) return false;
|
||||
if (origin.IsDisabled != destination.IsDisabled) return false;
|
||||
if (origin.IsPadded != destination.IsPadded) return false;
|
||||
if (origin.IsPrimaryKey != destination.IsPrimaryKey) return false;
|
||||
if (origin.IsUniqueKey != destination.IsUniqueKey) return false;
|
||||
if (origin.Type != destination.Type) return false;
|
||||
if (origin.SortInTempDb != destination.SortInTempDb) return false;
|
||||
if (!origin.FilterDefintion.Equals(destination.FilterDefintion)) return false;
|
||||
if (!IndexColumns.Compare(origin.Columns, destination.Columns)) return false;
|
||||
return CompareFileGroup(origin, destination);
|
||||
}
|
||||
|
||||
public static Boolean CompareExceptIsDisabled(Index origin, Index destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (origin == null) throw new ArgumentNullException("origin");
|
||||
if (origin.AllowPageLocks != destination.AllowPageLocks) return false;
|
||||
if (origin.AllowRowLocks != destination.AllowRowLocks) return false;
|
||||
if (origin.FillFactor != destination.FillFactor) return false;
|
||||
if (origin.IgnoreDupKey != destination.IgnoreDupKey) return false;
|
||||
if (origin.IsAutoStatistics != destination.IsAutoStatistics) return false;
|
||||
if (origin.IsPadded != destination.IsPadded) return false;
|
||||
if (origin.IsPrimaryKey != destination.IsPrimaryKey) return false;
|
||||
if (origin.IsUniqueKey != destination.IsUniqueKey) return false;
|
||||
if (origin.Type != destination.Type) return false;
|
||||
if (origin.SortInTempDb != destination.SortInTempDb) return false;
|
||||
if (!origin.FilterDefintion.Equals(destination.FilterDefintion)) return false;
|
||||
if (!IndexColumns.Compare(origin.Columns, destination.Columns)) return false;
|
||||
//return true;
|
||||
return CompareFileGroup(origin, destination);
|
||||
}
|
||||
|
||||
private static Boolean CompareFileGroup(Index origin, Index destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (origin == null) throw new ArgumentNullException("origin");
|
||||
if (origin.FileGroup != null)
|
||||
{
|
||||
if (!origin.FileGroup.Equals(destination.FileGroup)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
Database database = null;
|
||||
ISchemaBase current = this;
|
||||
while (database == null && current.Parent != null)
|
||||
{
|
||||
database = current.Parent as Database;
|
||||
current = current.Parent;
|
||||
}
|
||||
var isAzure10 = database.Info.Version == DatabaseInfo.SQLServerVersion.SQLServerAzure10;
|
||||
|
||||
StringBuilder sql = new StringBuilder();
|
||||
string includes = "";
|
||||
if ((Type == IndexTypeEnum.Clustered) && (IsUniqueKey)) sql.Append("CREATE UNIQUE CLUSTERED ");
|
||||
if ((Type == IndexTypeEnum.Clustered) && (!IsUniqueKey)) sql.Append("CREATE CLUSTERED ");
|
||||
if ((Type == IndexTypeEnum.Nonclustered) && (IsUniqueKey)) sql.Append("CREATE UNIQUE NONCLUSTERED ");
|
||||
if ((Type == IndexTypeEnum.Nonclustered) && (!IsUniqueKey)) sql.Append("CREATE NONCLUSTERED ");
|
||||
if (Type == IndexTypeEnum.XML) sql.Append("CREATE PRIMARY XML ");
|
||||
sql.Append("INDEX [" + Name + "] ON " + Parent.FullName + "\r\n(\r\n");
|
||||
/*Ordena la coleccion de campos del Indice en funcion de la propieda IsIncluded*/
|
||||
Columns.Sort();
|
||||
for (int j = 0; j < Columns.Count; j++)
|
||||
{
|
||||
if (!Columns[j].IsIncluded)
|
||||
{
|
||||
sql.Append("\t[" + Columns[j].Name + "]");
|
||||
if (Type != IndexTypeEnum.XML)
|
||||
{
|
||||
if (Columns[j].Order) sql.Append(" DESC"); else sql.Append(" ASC");
|
||||
}
|
||||
if (j < Columns.Count - 1) sql.Append(",");
|
||||
sql.Append("\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (String.IsNullOrEmpty(includes)) includes = ") INCLUDE (";
|
||||
includes += "[" + Columns[j].Name + "],";
|
||||
}
|
||||
}
|
||||
if (!String.IsNullOrEmpty(includes)) includes = includes.Substring(0, includes.Length - 1);
|
||||
sql.Append(includes);
|
||||
sql.Append(")");
|
||||
if (!String.IsNullOrEmpty(FilterDefintion)) sql.Append("\r\n WHERE " + FilterDefintion + "\r\n");
|
||||
sql.Append(" WITH (");
|
||||
if (Parent.ObjectType == ObjectType.TableType)
|
||||
{
|
||||
if ((IgnoreDupKey) && (IsUniqueKey)) sql.Append("IGNORE_DUP_KEY = ON "); else sql.Append("IGNORE_DUP_KEY = OFF ");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isAzure10)
|
||||
{
|
||||
if (IsPadded) sql.Append("PAD_INDEX = ON, "); else sql.Append("PAD_INDEX = OFF, ");
|
||||
}
|
||||
|
||||
if (IsAutoStatistics) sql.Append("STATISTICS_NORECOMPUTE = ON"); else sql.Append("STATISTICS_NORECOMPUTE = OFF");
|
||||
if (Type != IndexTypeEnum.XML)
|
||||
if ((IgnoreDupKey) && (IsUniqueKey)) sql.Append("IGNORE_DUP_KEY = ON, "); else sql.Append(", IGNORE_DUP_KEY = OFF");
|
||||
|
||||
if (!isAzure10)
|
||||
{
|
||||
if (AllowRowLocks) sql.Append(", ALLOW_ROW_LOCKS = ON"); else sql.Append(", ALLOW_ROW_LOCKS = OFF");
|
||||
if (AllowPageLocks) sql.Append(", ALLOW_PAGE_LOCKS = ON"); else sql.Append(", ALLOW_PAGE_LOCKS = OFF");
|
||||
if (FillFactor != 0) sql.Append(", FILLFACTOR = " + FillFactor.ToString());
|
||||
}
|
||||
}
|
||||
sql.Append(")");
|
||||
if (!isAzure10)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(FileGroup)) sql.Append(" ON [" + FileGroup + "]");
|
||||
}
|
||||
sql.Append("\r\nGO\r\n");
|
||||
if (IsDisabled)
|
||||
sql.Append("ALTER INDEX [" + Name + "] ON " + ((Table)Parent).FullName + " DISABLE\r\nGO\r\n");
|
||||
|
||||
sql.Append(ExtendedProperties.ToSql());
|
||||
return sql.ToString();
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
return ToSql();
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
return ToSqlDrop(null);
|
||||
}
|
||||
|
||||
private string ToSqlDrop(string FileGroupName)
|
||||
{
|
||||
string sql = "DROP INDEX [" + Name + "] ON " + Parent.FullName;
|
||||
if (!String.IsNullOrEmpty(FileGroupName)) sql += " WITH (MOVE TO [" + FileGroupName + "])";
|
||||
sql += "\r\nGO\r\n";
|
||||
return sql;
|
||||
}
|
||||
|
||||
public override SQLScript Create()
|
||||
{
|
||||
ScriptAction action = ScriptAction.AddIndex;
|
||||
if (!GetWasInsertInDiffList(action))
|
||||
{
|
||||
SetWasInsertInDiffList(action);
|
||||
return new SQLScript(ToSqlAdd(), Parent.DependenciesCount, action);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override SQLScript Drop()
|
||||
{
|
||||
ScriptAction action = ScriptAction.DropIndex;
|
||||
if (!GetWasInsertInDiffList(action))
|
||||
{
|
||||
SetWasInsertInDiffList(action);
|
||||
return new SQLScript(ToSqlDrop(), Parent.DependenciesCount, action);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private string ToSqlEnabled()
|
||||
{
|
||||
if (IsDisabled)
|
||||
return "ALTER INDEX [" + Name + "] ON " + Parent.FullName + " DISABLE\r\nGO\r\n";
|
||||
return "ALTER INDEX [" + Name + "] ON " + Parent.FullName + " REBUILD\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
if (Status != ObjectStatus.Original)
|
||||
{
|
||||
var actionMessage = RootParent.ActionMessage[Parent.FullName];
|
||||
if (actionMessage != null)
|
||||
actionMessage.Add(this);
|
||||
}
|
||||
|
||||
if (HasState(ObjectStatus.Drop))
|
||||
list.Add(Drop());
|
||||
if (HasState(ObjectStatus.Create))
|
||||
list.Add(Create());
|
||||
if (HasState(ObjectStatus.Alter))
|
||||
{
|
||||
list.Add(Drop());
|
||||
list.Add(Create());
|
||||
}
|
||||
if (Status == ObjectStatus.Disabled)
|
||||
{
|
||||
list.Add(ToSqlEnabled(), Parent.DependenciesCount, ScriptAction.AlterIndex);
|
||||
}
|
||||
/*if (this.Status == StatusEnum.ObjectStatusType.ChangeFileGroup)
|
||||
{
|
||||
listDiff.Add(this.ToSQLDrop(this.FileGroup), ((Table)Parent).DependenciesCount, StatusEnum.ScripActionType.DropIndex);
|
||||
listDiff.Add(this.ToSQLAdd(), ((Table)Parent).DependenciesCount, StatusEnum.ScripActionType.AddIndex);
|
||||
}*/
|
||||
list.AddRange(ExtendedProperties.ToSqlDiff());
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
72
OpenDBDiff.Schema.SQLServer.Generates/Model/IndexColumn.cs
Normal file
72
OpenDBDiff.Schema.SQLServer.Generates/Model/IndexColumn.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class IndexColumn : SQLServerSchemaBase, IComparable<IndexColumn>
|
||||
{
|
||||
public IndexColumn(ISchemaBase parentObject)
|
||||
: base(parentObject, ObjectType.IndexColumn)
|
||||
{
|
||||
}
|
||||
|
||||
public new IndexColumn Clone(ISchemaBase parent)
|
||||
{
|
||||
IndexColumn column = new IndexColumn(parent);
|
||||
column.Id = this.Id;
|
||||
column.IsIncluded = this.IsIncluded;
|
||||
column.Name = this.Name;
|
||||
column.Order = this.Order;
|
||||
column.Status = this.Status;
|
||||
column.KeyOrder = this.KeyOrder;
|
||||
column.DataTypeId = this.DataTypeId;
|
||||
return column;
|
||||
}
|
||||
|
||||
public int DataTypeId { get; set; }
|
||||
|
||||
public int KeyOrder { get; set; }
|
||||
|
||||
public Boolean IsIncluded { get; set; }
|
||||
|
||||
public Boolean Order { get; set; }
|
||||
|
||||
public static Boolean Compare(IndexColumn origin, IndexColumn destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (origin == null) throw new ArgumentNullException("origin");
|
||||
if (origin.IsIncluded != destination.IsIncluded) return false;
|
||||
if (origin.Order != destination.Order) return false;
|
||||
if (origin.KeyOrder != destination.KeyOrder) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
public int CompareTo(IndexColumn other)
|
||||
{
|
||||
/*if (other.Name.Equals(this.Name))
|
||||
{*/
|
||||
if (other.IsIncluded == this.IsIncluded)
|
||||
return this.KeyOrder.CompareTo(other.KeyOrder);
|
||||
else
|
||||
return other.IsIncluded.CompareTo(this.IsIncluded);
|
||||
/*}
|
||||
else
|
||||
return this.Name.CompareTo(other.Name);*/
|
||||
}
|
||||
}
|
||||
}
|
||||
53
OpenDBDiff.Schema.SQLServer.Generates/Model/IndexColumns.cs
Normal file
53
OpenDBDiff.Schema.SQLServer.Generates/Model/IndexColumns.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class IndexColumns : SchemaList<IndexColumn, ISchemaBase>
|
||||
{
|
||||
public IndexColumns(ISchemaBase parent)
|
||||
: base(parent)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clona el objeto ColumnConstraints en una nueva instancia.
|
||||
/// </summary>
|
||||
public IndexColumns Clone()
|
||||
{
|
||||
IndexColumns columns = new IndexColumns(Parent);
|
||||
for (int index = 0; index < this.Count; index++)
|
||||
{
|
||||
columns.Add(this[index].Clone(Parent));
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compara dos campos y devuelve true si son iguales, caso contrario, devuelve false.
|
||||
/// </summary>
|
||||
public static Boolean Compare(IndexColumns origin, IndexColumns destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (origin == null) throw new ArgumentNullException("origin");
|
||||
if (origin.Count != destination.Count) return false;
|
||||
for (int j = 0; j < origin.Count; j++)
|
||||
{
|
||||
IndexColumn item = destination[origin[j].FullName];
|
||||
if (item == null)
|
||||
return false;
|
||||
else
|
||||
if (!IndexColumn.Compare(origin[j], item)) return false;
|
||||
}
|
||||
for (int j = 0; j < destination.Count; j++)
|
||||
{
|
||||
IndexColumn item = origin[destination[j].FullName];
|
||||
if (item == null)
|
||||
return false;
|
||||
else
|
||||
if (!IndexColumn.Compare(destination[j], item)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public interface ICode : ISchemaBase
|
||||
{
|
||||
SQLScriptList Rebuild();
|
||||
List<string> DependenciesIn { get; set; }
|
||||
List<string> DependenciesOut { get; set; }
|
||||
bool IsSchemaBinding { get; set; }
|
||||
string Text { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public interface ISQLServerSchemaBase
|
||||
{
|
||||
SchemaList<ExtendedProperty, ISchemaBase> ExtendedProperties { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class ObjectDependency
|
||||
{
|
||||
public ObjectDependency(string name, string Column, ObjectType type)
|
||||
{
|
||||
this.Name = name;
|
||||
this.ColumnName = Column;
|
||||
this.Type = type;
|
||||
}
|
||||
|
||||
public ObjectDependency(string name, string Column)
|
||||
{
|
||||
this.Name = name;
|
||||
this.ColumnName = Column;
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string ColumnName { get; set; }
|
||||
|
||||
public ObjectType Type { get; set; }
|
||||
|
||||
public bool IsCodeType
|
||||
{
|
||||
get { return ((Type == ObjectType.StoredProcedure) || (Type == ObjectType.Trigger) || (Type == ObjectType.View) || (Type == ObjectType.Function)); }
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
36
OpenDBDiff.Schema.SQLServer.Generates/Model/Parameter.cs
Normal file
36
OpenDBDiff.Schema.SQLServer.Generates/Model/Parameter.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Globalization;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class Parameter
|
||||
{
|
||||
public bool Output { get; set; }
|
||||
|
||||
public byte Scale { get; set; }
|
||||
|
||||
public byte Precision { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public int Size { get; set; }
|
||||
|
||||
public string Type { get; set; }
|
||||
|
||||
public string ToSql()
|
||||
{
|
||||
string sql = Name + " [" + Type + "]";
|
||||
if (Type.Equals("binary") || Type.Equals("varbinary") || Type.Equals("varchar") || Type.Equals("char") || Type.Equals("nchar") || Type.Equals("nvarchar"))
|
||||
{
|
||||
if (Size == -1)
|
||||
sql += "(max)";
|
||||
else
|
||||
{
|
||||
sql += "(" + Size.ToString(CultureInfo.InvariantCulture) + ")";
|
||||
}
|
||||
}
|
||||
if (Type.Equals("numeric") || Type.Equals("decimal")) sql += "(" + Precision.ToString(CultureInfo.InvariantCulture) + "," + Scale.ToString(CultureInfo.InvariantCulture) + ")";
|
||||
if (Output) sql += " OUTPUT";
|
||||
return sql;
|
||||
}
|
||||
}
|
||||
}
|
||||
214
OpenDBDiff.Schema.SQLServer.Generates/Model/PartitionFunction.cs
Normal file
214
OpenDBDiff.Schema.SQLServer.Generates/Model/PartitionFunction.cs
Normal file
@@ -0,0 +1,214 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class PartitionFunction : SQLServerSchemaBase
|
||||
{
|
||||
private const int IS_STRING = 0;
|
||||
private const int IS_UNIQUE = 1;
|
||||
private const int IS_DATE = 2;
|
||||
private const int IS_NUMERIC = 3;
|
||||
|
||||
public PartitionFunction(ISchemaBase parent)
|
||||
: base(parent, ObjectType.PartitionFunction)
|
||||
{
|
||||
Values = new List<string>();
|
||||
}
|
||||
|
||||
public new PartitionFunction Clone(ISchemaBase parent)
|
||||
{
|
||||
PartitionFunction item = new PartitionFunction(parent);
|
||||
item.Id = this.Id;
|
||||
item.IsBoundaryRight = this.IsBoundaryRight;
|
||||
item.Name = this.Name;
|
||||
item.Precision = this.Precision;
|
||||
item.Scale = this.Scale;
|
||||
item.Size = this.Size;
|
||||
item.Type = this.Type;
|
||||
this.Values.ForEach(value => { item.Values.Add(value); });
|
||||
return item;
|
||||
}
|
||||
|
||||
public List<string> Values { get; set; }
|
||||
|
||||
public PartitionFunction Old { get; set; }
|
||||
|
||||
public int Precision { get; set; }
|
||||
|
||||
public int Scale { get; set; }
|
||||
|
||||
public int Size { get; set; }
|
||||
|
||||
public bool IsBoundaryRight { get; set; }
|
||||
|
||||
public string Type { get; set; }
|
||||
|
||||
private int ValueItem(string typeName)
|
||||
{
|
||||
if ((typeName.Equals("nchar") || typeName.Equals("nvarchar") || typeName.Equals("varchar") || typeName.Equals("char")))
|
||||
return IS_STRING;
|
||||
if (typeName.Equals("uniqueidentifier"))
|
||||
return IS_UNIQUE;
|
||||
if (typeName.Equals("datetime") || typeName.Equals("smalldatetime") || typeName.Equals("datetime2") || typeName.Equals("time") || typeName.Equals("datetimeoffset"))
|
||||
return IS_DATE;
|
||||
if (typeName.Equals("numeric") || typeName.Equals("decimal") || typeName.Equals("float") || typeName.Equals("real") || typeName.Equals("money") || typeName.Equals("smallmoney"))
|
||||
return IS_NUMERIC;
|
||||
|
||||
return IS_NUMERIC;
|
||||
}
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
string sqltype = Type;
|
||||
|
||||
if (Type.Equals("binary") || Type.Equals("varbinary") || Type.Equals("varchar") || Type.Equals("char") || Type.Equals("nchar") || Type.Equals("nvarchar"))
|
||||
{
|
||||
if (Type.Equals("nchar") || Type.Equals("nvarchar"))
|
||||
sqltype += " (" + (Size / 2).ToString(CultureInfo.InvariantCulture) + ")";
|
||||
else
|
||||
sqltype += " (" + Size.ToString(CultureInfo.InvariantCulture) + ")";
|
||||
}
|
||||
if (Type.Equals("numeric") || Type.Equals("decimal")) sqltype += " (" + Precision.ToString(CultureInfo.InvariantCulture) + "," + Scale.ToString(CultureInfo.InvariantCulture) + ")";
|
||||
if (((Database)Parent).Info.Version >= DatabaseInfo.SQLServerVersion.SQLServer2008)
|
||||
{
|
||||
if (Type.Equals("datetime2") || Type.Equals("datetimeoffset") || Type.Equals("time")) sqltype += "(" + Scale.ToString(CultureInfo.InvariantCulture) + ")";
|
||||
}
|
||||
|
||||
string sql = "CREATE PARTITION FUNCTION [" + Name + "](" + sqltype + ") AS RANGE\r\n ";
|
||||
if (IsBoundaryRight)
|
||||
sql += "RIGHT";
|
||||
else
|
||||
sql += "LEFT";
|
||||
sql += " FOR VALUES (";
|
||||
|
||||
string sqlvalues = "";
|
||||
int valueType = ValueItem(Type);
|
||||
|
||||
if (valueType == IS_STRING)
|
||||
Values.ForEach(item => { sqlvalues += "N'" + item + "',"; });
|
||||
else
|
||||
if (valueType == IS_DATE)
|
||||
Values.ForEach(item => { sqlvalues += "'" + DateTime.Parse(item).ToString("yyyyMMdd HH:mm:ss.fff") + "',"; });
|
||||
else
|
||||
if (valueType == IS_UNIQUE)
|
||||
Values.ForEach(item => { sqlvalues += "'{" + item + "}',"; });
|
||||
else
|
||||
if (valueType == IS_NUMERIC)
|
||||
Values.ForEach(item => { sqlvalues += item.Replace(",", ".") + ","; });
|
||||
else
|
||||
Values.ForEach(item => { sqlvalues += item + ","; });
|
||||
sql += sqlvalues.Substring(0, sqlvalues.Length - 1) + ")";
|
||||
|
||||
return sql + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
return "DROP PARTITION FUNCTION [" + Name + "]\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
return ToSql();
|
||||
}
|
||||
|
||||
public string ToSqlAlter()
|
||||
{
|
||||
StringBuilder sqlFinal = new StringBuilder();
|
||||
string sql = "ALTER PARTITION FUNCTION [" + Name + "]()\r\n";
|
||||
string sqlmergue = "";
|
||||
string sqsplit = "";
|
||||
IEnumerable<string> items = Old.Values.Except<string>(this.Values);
|
||||
int valueType = ValueItem(Type);
|
||||
foreach (var item in items)
|
||||
{
|
||||
sqlmergue = "MERGE RANGE (";
|
||||
if (valueType == IS_STRING)
|
||||
sqlmergue += "N'" + item + "'";
|
||||
else
|
||||
if (valueType == IS_DATE)
|
||||
sqlmergue += "'" + DateTime.Parse(item).ToString("yyyyMMdd HH:mm:ss.fff") + "'";
|
||||
else
|
||||
if (valueType == IS_UNIQUE)
|
||||
sqlmergue += "'{" + item + "}'";
|
||||
else
|
||||
if (valueType == IS_NUMERIC)
|
||||
sqlmergue += item.Replace(",", ".");
|
||||
else
|
||||
sqlmergue += item;
|
||||
sqlFinal.Append(sql + sqlmergue + ")\r\nGO\r\n");
|
||||
}
|
||||
IEnumerable<string> items2 = this.Values.Except<string>(this.Old.Values);
|
||||
foreach (var item in items2)
|
||||
{
|
||||
sqsplit = "SPLIT RANGE (";
|
||||
if (valueType == IS_STRING)
|
||||
sqsplit += "N'" + item + "'";
|
||||
else
|
||||
if (valueType == IS_DATE)
|
||||
sqsplit += "'" + DateTime.Parse(item).ToString("yyyyMMdd HH:mm:ss.fff") + "'";
|
||||
else
|
||||
if (valueType == IS_UNIQUE)
|
||||
sqsplit += "'{" + item + "}'";
|
||||
else
|
||||
if (valueType == IS_NUMERIC)
|
||||
sqsplit += item.Replace(",", ".");
|
||||
else
|
||||
sqsplit += item;
|
||||
sqlFinal.Append(sql + sqsplit + ")\r\nGO\r\n");
|
||||
}
|
||||
return sqlFinal.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Devuelve el schema de diferencias del Schema en formato SQL.
|
||||
/// </summary>
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList listDiff = new SQLScriptList();
|
||||
|
||||
if (this.Status == ObjectStatus.Drop)
|
||||
{
|
||||
listDiff.Add(ToSqlDrop(), 0, ScriptAction.DropPartitionFunction);
|
||||
}
|
||||
if (this.Status == ObjectStatus.Rebuild)
|
||||
{
|
||||
listDiff.Add(ToSqlDrop() + ToSqlAdd(), 0, ScriptAction.AlterPartitionFunction);
|
||||
}
|
||||
if (this.Status == ObjectStatus.Alter)
|
||||
listDiff.Add(ToSqlAlter(), 0, ScriptAction.AlterPartitionFunction);
|
||||
|
||||
if (this.Status == ObjectStatus.Create)
|
||||
{
|
||||
listDiff.Add(ToSqlAdd(), 0, ScriptAction.AddPartitionFunction);
|
||||
}
|
||||
return listDiff;
|
||||
}
|
||||
|
||||
public static Boolean Compare(PartitionFunction origin, PartitionFunction destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (origin == null) throw new ArgumentNullException("origin");
|
||||
if (!origin.Type.Equals(destination.Type)) return false;
|
||||
if (origin.Size != destination.Size) return false;
|
||||
if (origin.Precision != destination.Precision) return false;
|
||||
if (origin.Scale != destination.Scale) return false;
|
||||
if (origin.IsBoundaryRight != destination.IsBoundaryRight) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Boolean CompareValues(PartitionFunction origin, PartitionFunction destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (origin == null) throw new ArgumentNullException("origin");
|
||||
if (origin.Values.Count != destination.Values.Count) return false;
|
||||
if (origin.Values.Except(destination.Values).ToList().Count != 0) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class PartitionScheme : SQLServerSchemaBase
|
||||
{
|
||||
public PartitionScheme(ISchemaBase parent)
|
||||
: base(parent, ObjectType.PartitionFunction)
|
||||
{
|
||||
FileGroups = new List<string>();
|
||||
}
|
||||
|
||||
public List<string> FileGroups { get; set; }
|
||||
|
||||
public string PartitionFunction { get; set; }
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
string sql = "CREATE PARTITION SCHEME " + FullName + "\r\n";
|
||||
sql += " AS PARTITION " + PartitionFunction + "\r\n";
|
||||
sql += "TO (";
|
||||
FileGroups.ForEach(item => sql += "[" + item + "],");
|
||||
sql = sql.Substring(0, sql.Length - 1);
|
||||
sql += ")\r\nGO\r\n";
|
||||
return sql;
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
return "DROP PARTITION SCHEME " + FullName + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
return ToSqlAdd();
|
||||
}
|
||||
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList listDiff = new SQLScriptList();
|
||||
|
||||
if (this.Status == ObjectStatus.Drop)
|
||||
{
|
||||
listDiff.Add(ToSqlDrop(), 0, ScriptAction.DropPartitionScheme);
|
||||
}
|
||||
if (this.Status == ObjectStatus.Rebuild)
|
||||
{
|
||||
listDiff.Add(ToSqlDrop(), 0, ScriptAction.DropPartitionScheme);
|
||||
listDiff.Add(ToSqlAdd(), 0, ScriptAction.AddPartitionScheme);
|
||||
}
|
||||
if (this.Status == ObjectStatus.Create)
|
||||
{
|
||||
listDiff.Add(ToSqlAdd(), 0, ScriptAction.AddPartitionScheme);
|
||||
}
|
||||
return listDiff;
|
||||
}
|
||||
|
||||
public static Boolean Compare(PartitionScheme origin, PartitionScheme destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (origin == null) throw new ArgumentNullException("origin");
|
||||
if (!origin.PartitionFunction.Equals(destination.PartitionFunction)) return false;
|
||||
if (origin.FileGroups.Count != destination.FileGroups.Count) return false;
|
||||
for (int j = 0; j < origin.FileGroups.Count; j++)
|
||||
{
|
||||
if (origin.CompareFullNameTo(origin.FileGroups[j], destination.FileGroups[j]) != 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
79
OpenDBDiff.Schema.SQLServer.Generates/Model/Role.cs
Normal file
79
OpenDBDiff.Schema.SQLServer.Generates/Model/Role.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class Role : SQLServerSchemaBase
|
||||
{
|
||||
public enum RoleTypeEnum
|
||||
{
|
||||
ApplicationRole = 1,
|
||||
DatabaseRole = 2
|
||||
}
|
||||
|
||||
public Role(ISchemaBase parent)
|
||||
: base(parent, ObjectType.Role)
|
||||
{
|
||||
}
|
||||
|
||||
public override string FullName
|
||||
{
|
||||
get { return "[" + Name + "]"; }
|
||||
}
|
||||
|
||||
public RoleTypeEnum Type { get; set; }
|
||||
|
||||
public string Password { get; set; }
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
string sql = "";
|
||||
sql += "CREATE " + ((Type == RoleTypeEnum.ApplicationRole) ? "APPLICATION" : "") + " ROLE ";
|
||||
sql += FullName + " ";
|
||||
sql += "WITH PASSWORD = N'" + Password + "'";
|
||||
if (!String.IsNullOrEmpty(Owner))
|
||||
sql += " ,DEFAULT_SCHEMA=[" + Owner + "]";
|
||||
return sql.Trim() + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
return "DROP " + ((Type == RoleTypeEnum.ApplicationRole) ? "APPLICATION" : "") + " ROLE " + FullName + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
return ToSql();
|
||||
}
|
||||
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList listDiff = new SQLScriptList();
|
||||
|
||||
if (this.Status == ObjectStatus.Drop)
|
||||
{
|
||||
listDiff.Add(ToSqlDrop(), 0, ScriptAction.DropRole);
|
||||
}
|
||||
if (this.Status == ObjectStatus.Create)
|
||||
{
|
||||
listDiff.Add(ToSql(), 0, ScriptAction.AddRole);
|
||||
}
|
||||
if ((this.Status & ObjectStatus.Alter) == ObjectStatus.Alter)
|
||||
{
|
||||
listDiff.Add(ToSqlDrop(), 0, ScriptAction.DropRole);
|
||||
listDiff.Add(ToSql(), 0, ScriptAction.AddRole);
|
||||
}
|
||||
return listDiff;
|
||||
}
|
||||
|
||||
|
||||
public Boolean Compare(Role obj)
|
||||
{
|
||||
if (obj == null) throw new ArgumentNullException("destination");
|
||||
if (this.Type != obj.Type) return false;
|
||||
if (!this.Password.Equals(obj.Password)) return false;
|
||||
if (!this.Owner.Equals(obj.Owner)) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
93
OpenDBDiff.Schema.SQLServer.Generates/Model/Rule.cs
Normal file
93
OpenDBDiff.Schema.SQLServer.Generates/Model/Rule.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class Rule : Code
|
||||
{
|
||||
public Rule(ISchemaBase parent)
|
||||
: base(parent, ObjectType.Rule, ScriptAction.AddRule, ScriptAction.DropRule)
|
||||
{
|
||||
}
|
||||
|
||||
public new Rule Clone(ISchemaBase parent)
|
||||
{
|
||||
Rule item = new Rule(parent);
|
||||
item.Id = this.Id;
|
||||
item.Name = this.Name;
|
||||
item.Owner = this.Owner;
|
||||
item.Text = this.Text;
|
||||
item.Guid = this.Guid;
|
||||
return item;
|
||||
}
|
||||
|
||||
public string ToSQLAddBind()
|
||||
{
|
||||
string sql;
|
||||
if (this.Parent.ObjectType == ObjectType.Column)
|
||||
sql = String.Format("EXEC sp_bindrule N'{0}', N'[{1}].[{2}]','futureonly'\r\nGO\r\n", Name, this.Parent.Parent.Name, this.Parent.Name);
|
||||
else
|
||||
sql = String.Format("EXEC sp_bindrule N'{0}', N'{1}','futureonly'\r\nGO\r\n", Name, this.Parent.Name);
|
||||
return sql;
|
||||
}
|
||||
|
||||
public string ToSQLAddUnBind()
|
||||
{
|
||||
string sql;
|
||||
if (this.Parent.ObjectType == ObjectType.Column)
|
||||
sql = String.Format("EXEC sp_unbindrule @objname=N'[{0}].[{1}]'\r\nGO\r\n", this.Parent.Parent.Name, this.Parent.Name);
|
||||
else
|
||||
sql = String.Format("EXEC sp_unbindrule @objname=N'{0}'\r\nGO\r\n", this.Parent.Name);
|
||||
return sql;
|
||||
}
|
||||
|
||||
private SQLScriptList ToSQLUnBindAll()
|
||||
{
|
||||
SQLScriptList listDiff = new SQLScriptList();
|
||||
Hashtable items = new Hashtable();
|
||||
List<UserDataType> useDataTypes = ((Database)this.Parent).UserTypes.FindAll(item => { return item.Rule.FullName.Equals(this.FullName); });
|
||||
foreach (UserDataType item in useDataTypes)
|
||||
{
|
||||
foreach (ObjectDependency dependency in item.Dependencies)
|
||||
{
|
||||
Column column = ((Database)this.Parent).Tables[dependency.Name].Columns[dependency.ColumnName];
|
||||
if ((!column.IsComputed) && (column.Status != ObjectStatus.Create))
|
||||
{
|
||||
if (!items.ContainsKey(column.FullName))
|
||||
{
|
||||
listDiff.Add("EXEC sp_unbindrule '" + column.FullName + "'\r\nGO\r\n", 0, ScriptAction.UnbindRuleColumn);
|
||||
items.Add(column.FullName, column.FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (item.Rule.Status != ObjectStatus.Create)
|
||||
listDiff.Add("EXEC sp_unbindrule '" + item.FullName + "'\r\nGO\r\n", 0, ScriptAction.UnbindRuleType);
|
||||
}
|
||||
return listDiff;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Devuelve el schema de diferencias del Schema en formato SQL.
|
||||
/// </summary>
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList listDiff = new SQLScriptList();
|
||||
|
||||
if (this.Status == ObjectStatus.Drop)
|
||||
{
|
||||
listDiff.AddRange(ToSQLUnBindAll());
|
||||
listDiff.Add(Drop());
|
||||
}
|
||||
if (this.Status == ObjectStatus.Create)
|
||||
listDiff.Add(Create());
|
||||
if (this.Status == ObjectStatus.Alter)
|
||||
{
|
||||
listDiff.AddRange(ToSQLUnBindAll());
|
||||
listDiff.AddRange(Rebuild());
|
||||
}
|
||||
return listDiff;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public abstract class SQLServerSchemaBase : SchemaBase, ISQLServerSchemaBase
|
||||
{
|
||||
protected SQLServerSchemaBase(ISchemaBase parent, ObjectType objectType) : base("[", "]", objectType)
|
||||
{
|
||||
this.Parent = parent;
|
||||
ExtendedProperties = new SchemaList<ExtendedProperty, ISchemaBase>(parent);
|
||||
}
|
||||
|
||||
public SchemaList<ExtendedProperty, ISchemaBase> ExtendedProperties { get; private set; }
|
||||
}
|
||||
}
|
||||
49
OpenDBDiff.Schema.SQLServer.Generates/Model/Schema.cs
Normal file
49
OpenDBDiff.Schema.SQLServer.Generates/Model/Schema.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System.Text;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class Schema : SQLServerSchemaBase
|
||||
{
|
||||
public Schema(Database parent)
|
||||
: base(parent, ObjectType.Schema)
|
||||
{
|
||||
}
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.Append("CREATE SCHEMA ");
|
||||
sql.Append("[" + this.Name + "] AUTHORIZATION [" + Owner + "]");
|
||||
sql.Append("\r\nGO\r\n");
|
||||
return sql.ToString();
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
return ToSql();
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
return "DROP SCHEMA [" + Name + "]\r\nGO\r\n";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Devuelve el schema de diferencias del Schema en formato SQL.
|
||||
/// </summary>
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<OpenDBDiff.Schema.Model.ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList listDiff = new SQLScriptList();
|
||||
|
||||
if (this.Status == ObjectStatus.Drop)
|
||||
{
|
||||
listDiff.Add(ToSqlDrop(), 0, ScriptAction.DropSchema);
|
||||
}
|
||||
if (this.Status == ObjectStatus.Create)
|
||||
{
|
||||
listDiff.Add(ToSql(), 0, ScriptAction.AddSchema);
|
||||
}
|
||||
return listDiff;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
using OpenDBDiff.Schema.SQLServer.Generates.Model.Util;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class StoredProcedure : Code
|
||||
{
|
||||
public StoredProcedure(ISchemaBase parent)
|
||||
: base(parent, ObjectType.StoredProcedure, ScriptAction.AddStoredProcedure, ScriptAction.DropStoredProcedure)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clona el objeto en una nueva instancia.
|
||||
/// </summary>
|
||||
public override ISchemaBase Clone(ISchemaBase parent)
|
||||
{
|
||||
StoredProcedure item = new StoredProcedure(parent);
|
||||
item.Text = this.Text;
|
||||
item.Status = this.Status;
|
||||
item.Name = this.Name;
|
||||
item.Id = this.Id;
|
||||
item.Owner = this.Owner;
|
||||
item.Guid = this.Guid;
|
||||
return item;
|
||||
}
|
||||
|
||||
public override Boolean IsCodeType
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
//if (String.IsNullOrEmpty(sql))
|
||||
sql = FormatCode.FormatCreate("PROC(EDURE)?", Text, this);
|
||||
return sql;
|
||||
}
|
||||
|
||||
public string ToSQLAlter()
|
||||
{
|
||||
return FormatCode.FormatAlter("PROC(EDURE)?", ToSql(), this, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Devuelve el schema de diferencias del Schema en formato SQL.
|
||||
/// </summary>
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
if (this.Status != ObjectStatus.Original)
|
||||
RootParent.ActionMessage.Add(this);
|
||||
|
||||
if (this.HasState(ObjectStatus.Drop))
|
||||
list.Add(Drop());
|
||||
if (this.HasState(ObjectStatus.Create))
|
||||
list.Add(Create());
|
||||
if (this.HasState(ObjectStatus.Alter))
|
||||
list.Add(ToSQLAlter(), 0, ScriptAction.AlterProcedure);
|
||||
if (this.HasState(ObjectStatus.AlterWhitespace))
|
||||
list.Add(ToSQLAlter(), 0, ScriptAction.AlterProcedure);
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
76
OpenDBDiff.Schema.SQLServer.Generates/Model/Synonym.cs
Normal file
76
OpenDBDiff.Schema.SQLServer.Generates/Model/Synonym.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class Synonym : SQLServerSchemaBase
|
||||
{
|
||||
public Synonym(ISchemaBase parent)
|
||||
: base(parent, ObjectType.Synonym)
|
||||
{
|
||||
}
|
||||
|
||||
public override ISchemaBase Clone(ISchemaBase parent)
|
||||
{
|
||||
Synonym item = new Synonym(parent);
|
||||
item.Id = this.Id;
|
||||
item.Name = this.Name;
|
||||
item.Owner = this.Owner;
|
||||
item.Value = this.Value;
|
||||
item.Guid = this.Guid;
|
||||
return item;
|
||||
}
|
||||
|
||||
public string Value { get; set; }
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
string sql = "CREATE SYNONYM " + FullName + " FOR " + Value + "\r\nGO\r\n";
|
||||
return sql;
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
return "DROP SYNONYM " + FullName + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
return ToSql();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Devuelve el schema de diferencias del Schema en formato SQL.
|
||||
/// </summary>
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList listDiff = new SQLScriptList();
|
||||
|
||||
if (this.Status == ObjectStatus.Drop)
|
||||
{
|
||||
listDiff.Add(ToSqlDrop(), 0, ScriptAction.DropSynonyms);
|
||||
}
|
||||
if (this.Status == ObjectStatus.Create)
|
||||
{
|
||||
listDiff.Add(ToSql(), 0, ScriptAction.AddSynonyms);
|
||||
}
|
||||
if (this.Status == ObjectStatus.Alter)
|
||||
{
|
||||
listDiff.Add(ToSqlDrop(), 0, ScriptAction.DropSynonyms);
|
||||
listDiff.Add(ToSql(), 0, ScriptAction.AddSynonyms);
|
||||
}
|
||||
return listDiff;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compara dos Synonyms y devuelve true si son iguales, caso contrario, devuelve false.
|
||||
/// </summary>
|
||||
public static Boolean Compare(Synonym origin, Synonym destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (origin == null) throw new ArgumentNullException("origin");
|
||||
if (!origin.Value.Equals(destination.Value)) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
732
OpenDBDiff.Schema.SQLServer.Generates/Model/Table.cs
Normal file
732
OpenDBDiff.Schema.SQLServer.Generates/Model/Table.cs
Normal file
@@ -0,0 +1,732 @@
|
||||
using OpenDBDiff.Schema.Attributes;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class Table : SQLServerSchemaBase, IComparable<Table>, ITable<Table>
|
||||
{
|
||||
private int dependenciesCount;
|
||||
private List<ISchemaBase> dependencies;
|
||||
private Boolean? hasFileStream;
|
||||
|
||||
public Table(ISchemaBase parent)
|
||||
: base(parent, ObjectType.Table)
|
||||
{
|
||||
dependenciesCount = -1;
|
||||
Columns = new Columns<Table>(this);
|
||||
Constraints = new SchemaList<Constraint, Table>(this, ((Database)parent).AllObjects);
|
||||
Options = new SchemaList<TableOption, Table>(this);
|
||||
Triggers = new SchemaList<Trigger, Table>(this, ((Database)parent).AllObjects);
|
||||
CLRTriggers = new SchemaList<CLRTrigger, Table>(this, ((Database)parent).AllObjects);
|
||||
Indexes = new SchemaList<Index, Table>(this, ((Database)parent).AllObjects);
|
||||
Partitions = new SchemaList<TablePartition, Table>(this, ((Database)parent).AllObjects);
|
||||
FullTextIndex = new SchemaList<FullTextIndex, Table>(this);
|
||||
}
|
||||
|
||||
public string CompressType { get; set; }
|
||||
|
||||
public string FileGroupText { get; set; }
|
||||
|
||||
public Boolean HasChangeDataCapture { get; set; }
|
||||
|
||||
public Boolean HasChangeTrackingTrackColumn { get; set; }
|
||||
|
||||
public Boolean HasChangeTracking { get; set; }
|
||||
|
||||
public string FileGroupStream { get; set; }
|
||||
|
||||
public Boolean HasClusteredIndex { get; set; }
|
||||
|
||||
public string FileGroup { get; set; }
|
||||
|
||||
public Table OriginalTable { get; set; }
|
||||
|
||||
[SchemaNode("Constraints")]
|
||||
public SchemaList<Constraint, Table> Constraints { get; private set; }
|
||||
|
||||
[SchemaNode("Indexes", "Index")]
|
||||
public SchemaList<Index, Table> Indexes { get; private set; }
|
||||
|
||||
[SchemaNode("CLR Triggers")]
|
||||
public SchemaList<CLRTrigger, Table> CLRTriggers { get; private set; }
|
||||
|
||||
[SchemaNode("Triggers")]
|
||||
public SchemaList<Trigger, Table> Triggers { get; private set; }
|
||||
|
||||
public SchemaList<FullTextIndex, Table> FullTextIndex { get; private set; }
|
||||
|
||||
public SchemaList<TablePartition, Table> Partitions { get; set; }
|
||||
|
||||
public SchemaList<TableOption, Table> Options { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indica si la tabla tiene alguna columna que sea Identity.
|
||||
/// </summary>
|
||||
public Boolean HasIdentityColumn
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (Column col in Columns)
|
||||
{
|
||||
if (col.IsIdentity) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean HasFileStream
|
||||
{
|
||||
get
|
||||
{
|
||||
if (hasFileStream == null)
|
||||
{
|
||||
hasFileStream = false;
|
||||
foreach (Column col in Columns)
|
||||
{
|
||||
if (col.IsFileStream) hasFileStream = true;
|
||||
}
|
||||
}
|
||||
return hasFileStream.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean HasBlobColumn
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (Column col in Columns)
|
||||
{
|
||||
if (col.IsBLOB) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indica la cantidad de Constraints dependientes de otra tabla (FK) que tiene
|
||||
/// la tabla.
|
||||
/// </summary>
|
||||
public override int DependenciesCount
|
||||
{
|
||||
get
|
||||
{
|
||||
if (dependenciesCount == -1)
|
||||
dependenciesCount = ((Database)Parent).Dependencies.DependenciesCount(Id,
|
||||
ObjectType.Constraint);
|
||||
return dependenciesCount;
|
||||
}
|
||||
}
|
||||
|
||||
#region IComparable<Table> Members
|
||||
|
||||
/// <summary>
|
||||
/// Compara en primer orden por la operacion
|
||||
/// (Primero van los Drops, luego los Create y finalesmente los Alter).
|
||||
/// Si la operacion es la misma, ordena por cantidad de tablas dependientes.
|
||||
/// </summary>
|
||||
public int CompareTo(Table other)
|
||||
{
|
||||
if (other == null) throw new ArgumentNullException("other");
|
||||
if (Status == other.Status)
|
||||
return DependenciesCount.CompareTo(other.DependenciesCount);
|
||||
return other.Status.CompareTo(Status);
|
||||
}
|
||||
|
||||
#endregion IComparable<Table> Members
|
||||
|
||||
#region ITable<Table> Members
|
||||
|
||||
/// <summary>
|
||||
/// Coleccion de campos de la tabla.
|
||||
/// </summary>
|
||||
[SchemaNode("Columns", "Column")]
|
||||
public Columns<Table> Columns { get; set; }
|
||||
|
||||
#endregion ITable<Table> Members
|
||||
|
||||
/// <summary>
|
||||
/// Clona el objeto Table en una nueva instancia.
|
||||
/// </summary>
|
||||
public override ISchemaBase Clone(ISchemaBase objectParent)
|
||||
{
|
||||
var table = new Table(objectParent)
|
||||
{
|
||||
Owner = Owner,
|
||||
Name = Name,
|
||||
Id = Id,
|
||||
Guid = Guid,
|
||||
Status = Status,
|
||||
FileGroup = FileGroup,
|
||||
FileGroupText = FileGroupText,
|
||||
FileGroupStream = FileGroupStream,
|
||||
HasClusteredIndex = HasClusteredIndex,
|
||||
HasChangeTracking = HasChangeTracking,
|
||||
HasChangeTrackingTrackColumn = HasChangeTrackingTrackColumn,
|
||||
HasChangeDataCapture = HasChangeDataCapture,
|
||||
dependenciesCount = DependenciesCount
|
||||
};
|
||||
table.Columns = Columns.Clone(table);
|
||||
table.Options = Options.Clone(table);
|
||||
table.CompressType = CompressType;
|
||||
table.Triggers = Triggers.Clone(table);
|
||||
table.Indexes = Indexes.Clone(table);
|
||||
table.Partitions = Partitions.Clone(table);
|
||||
table.Constraints = Constraints.Clone(table);
|
||||
return table;
|
||||
}
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
return ToSql(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Devuelve el schema de la tabla en formato SQL.
|
||||
/// </summary>
|
||||
public string ToSql(Boolean showFK)
|
||||
{
|
||||
Database database = null;
|
||||
ISchemaBase current = this;
|
||||
while (database == null && current.Parent != null)
|
||||
{
|
||||
database = current.Parent as Database;
|
||||
current = current.Parent;
|
||||
}
|
||||
|
||||
if (database == null)
|
||||
return string.Empty;
|
||||
|
||||
var isAzure10 = database.Info.Version == DatabaseInfo.SQLServerVersion.SQLServerAzure10;
|
||||
|
||||
string sql = "";
|
||||
string sqlPK = "";
|
||||
string sqlUC = "";
|
||||
string sqlFK = "";
|
||||
if (Columns.Any())
|
||||
{
|
||||
sql += "CREATE TABLE " + FullName + "\r\n(\r\n";
|
||||
sql += Columns.ToSql();
|
||||
if (Constraints.Any())
|
||||
{
|
||||
sql += ",\r\n";
|
||||
Constraints.AsQueryable()
|
||||
// Add the constraint if it's not in DropStatus
|
||||
.Where(c => !c.HasState(ObjectStatus.Drop))
|
||||
.ToList()
|
||||
.ForEach(item =>
|
||||
{
|
||||
if (item.Type == Constraint.ConstraintType.PrimaryKey)
|
||||
sqlPK += "\t" + item.ToSql() + ",\r\n";
|
||||
if (item.Type == Constraint.ConstraintType.Unique)
|
||||
sqlUC += "\t" + item.ToSql() + ",\r\n";
|
||||
if (showFK && item.Type == Constraint.ConstraintType.ForeignKey)
|
||||
sqlFK += "\t" + item.ToSql() + ",\r\n";
|
||||
});
|
||||
sql += sqlPK + sqlUC + sqlFK;
|
||||
sql = sql.Substring(0, sql.Length - 3) + "\r\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
sql += "\r\n";
|
||||
if (!String.IsNullOrEmpty(CompressType))
|
||||
sql += "WITH (DATA_COMPRESSION = " + CompressType + ")\r\n";
|
||||
}
|
||||
sql += ")";
|
||||
|
||||
if (!isAzure10)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(FileGroup)) sql += " ON [" + FileGroup + "]";
|
||||
|
||||
if (!String.IsNullOrEmpty(FileGroupText))
|
||||
{
|
||||
if (HasBlobColumn)
|
||||
sql += " TEXTIMAGE_ON [" + FileGroupText + "]";
|
||||
}
|
||||
if ((!String.IsNullOrEmpty(FileGroupStream)) && (HasFileStream))
|
||||
sql += " FILESTREAM_ON [" + FileGroupStream + "]";
|
||||
}
|
||||
sql += "\r\n";
|
||||
sql += "GO\r\n";
|
||||
Constraints.ForEach(item =>
|
||||
{
|
||||
if (item.Type == Constraint.ConstraintType.Check)
|
||||
sql += item.ToSqlAdd() + "\r\n";
|
||||
});
|
||||
if (HasChangeTracking)
|
||||
sql += ToSqlChangeTracking();
|
||||
sql += Indexes.ToSql();
|
||||
sql += FullTextIndex.ToSql();
|
||||
sql += Options.ToSql();
|
||||
sql += Triggers.ToSql();
|
||||
}
|
||||
return sql;
|
||||
}
|
||||
|
||||
private string ToSqlChangeTracking()
|
||||
{
|
||||
string sql;
|
||||
if (HasChangeTracking)
|
||||
{
|
||||
sql = "ALTER TABLE " + FullName + " ENABLE CHANGE_TRACKING";
|
||||
if (HasChangeTrackingTrackColumn)
|
||||
sql += " WITH(TRACK_COLUMNS_UPDATED = ON)";
|
||||
}
|
||||
else
|
||||
sql = "ALTER TABLE " + FullName + " DISABLE CHANGE_TRACKING";
|
||||
|
||||
return sql + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
return ToSql();
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
return "DROP TABLE " + FullName + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
/*
|
||||
private SQLScriptList BuildSQLFileGroup()
|
||||
{
|
||||
var listDiff = new SQLScriptList();
|
||||
|
||||
Boolean found = false;
|
||||
Index clustered = Indexes.Find(item => item.Type == Index.IndexTypeEnum.Clustered);
|
||||
if (clustered == null)
|
||||
{
|
||||
foreach (Constraint cons in Constraints)
|
||||
{
|
||||
if (cons.Index.Type == Index.IndexTypeEnum.Clustered)
|
||||
{
|
||||
listDiff.Add(cons.ToSqlDrop(FileGroup), dependenciesCount, ScripActionType.DropConstraint);
|
||||
listDiff.Add(cons.ToSqlAdd(), dependenciesCount, ScripActionType.AddConstraint);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
Status = ObjectStatusType.RebuildStatus;
|
||||
listDiff = ToSqlDiff();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
listDiff.Add(clustered.ToSqlDrop(FileGroup), dependenciesCount, ScripActionType.DropIndex);
|
||||
listDiff.Add(clustered.ToSqlAdd(), dependenciesCount, ScripActionType.AddIndex);
|
||||
}
|
||||
return listDiff;
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Devuelve el schema de diferencias de la tabla en formato SQL.
|
||||
/// </summary>
|
||||
public override SQLScriptList ToSqlDiff(ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
var listDiff = new SQLScriptList();
|
||||
|
||||
if (Status != ObjectStatus.Original)
|
||||
{
|
||||
if (((Database)Parent).Options.Ignore.FilterTable)
|
||||
RootParent.ActionMessage.Add(this);
|
||||
}
|
||||
|
||||
if (Status == ObjectStatus.Drop)
|
||||
{
|
||||
if (((Database)Parent).Options.Ignore.FilterTable)
|
||||
{
|
||||
listDiff.Add(ToSqlDrop(), dependenciesCount, ScriptAction.DropTable);
|
||||
listDiff.AddRange(ToSQLDropFKBelow());
|
||||
}
|
||||
}
|
||||
if (Status == ObjectStatus.Create)
|
||||
{
|
||||
string sql = "";
|
||||
Constraints.ForEach(item =>
|
||||
{
|
||||
if (item.Type == Constraint.ConstraintType.ForeignKey)
|
||||
sql += item.ToSqlAdd() + "\r\n";
|
||||
});
|
||||
listDiff.Add(ToSql(false), dependenciesCount, ScriptAction.AddTable);
|
||||
listDiff.Add(sql, dependenciesCount, ScriptAction.AddConstraintFK);
|
||||
}
|
||||
if (HasState(ObjectStatus.RebuildDependencies))
|
||||
{
|
||||
GenerateDependencies();
|
||||
listDiff.AddRange(ToSQLDropDependencies());
|
||||
listDiff.AddRange(Columns.ToSqlDiff(schemas));
|
||||
listDiff.AddRange(ToSQLCreateDependencies());
|
||||
listDiff.AddRange(Constraints.ToSqlDiff());
|
||||
listDiff.AddRange(Indexes.ToSqlDiff());
|
||||
listDiff.AddRange(Options.ToSqlDiff());
|
||||
listDiff.AddRange(Triggers.ToSqlDiff());
|
||||
listDiff.AddRange(CLRTriggers.ToSqlDiff());
|
||||
listDiff.AddRange(FullTextIndex.ToSqlDiff());
|
||||
}
|
||||
if (HasState(ObjectStatus.Alter))
|
||||
{
|
||||
listDiff.AddRange(Columns.ToSqlDiff(schemas));
|
||||
listDiff.AddRange(Constraints.ToSqlDiff());
|
||||
listDiff.AddRange(Indexes.ToSqlDiff());
|
||||
listDiff.AddRange(Options.ToSqlDiff());
|
||||
listDiff.AddRange(Triggers.ToSqlDiff());
|
||||
listDiff.AddRange(CLRTriggers.ToSqlDiff());
|
||||
listDiff.AddRange(FullTextIndex.ToSqlDiff());
|
||||
}
|
||||
if (HasState(ObjectStatus.Rebuild))
|
||||
{
|
||||
GenerateDependencies();
|
||||
listDiff.AddRange(ToSQLRebuild());
|
||||
listDiff.AddRange(Columns.ToSqlDiff());
|
||||
listDiff.AddRange(Constraints.ToSqlDiff());
|
||||
listDiff.AddRange(Indexes.ToSqlDiff());
|
||||
listDiff.AddRange(Options.ToSqlDiff());
|
||||
//Como recrea la tabla, solo pone los nuevos triggers, por eso va ToSQL y no ToSQLDiff
|
||||
listDiff.Add(Triggers.ToSql(), dependenciesCount, ScriptAction.AddTrigger);
|
||||
listDiff.Add(CLRTriggers.ToSql(), dependenciesCount, ScriptAction.AddTrigger);
|
||||
listDiff.AddRange(FullTextIndex.ToSqlDiff());
|
||||
}
|
||||
if (HasState(ObjectStatus.Disabled))
|
||||
{
|
||||
listDiff.Add(ToSqlChangeTracking(), 0, ScriptAction.AlterTableChangeTracking);
|
||||
}
|
||||
return listDiff;
|
||||
}
|
||||
|
||||
private string ToSQLTableRebuild()
|
||||
{
|
||||
string sql = "";
|
||||
string tempTable = "Temp" + Name;
|
||||
Boolean IsIdentityNew = false;
|
||||
|
||||
var columnNamesStringBuilder = new StringBuilder();
|
||||
var valuesStringBuilder = new StringBuilder();
|
||||
|
||||
foreach (Column column in Columns)
|
||||
{
|
||||
if (column.Status != ObjectStatus.Drop &&
|
||||
!(column.Status == ObjectStatus.Create && column.IsNullable) &&
|
||||
!column.IsComputed && !column.Type.ToLower().Equals("timestamp"))
|
||||
{
|
||||
/*Si la nueva columna a agregar es XML, no se inserta ese campo y debe ir a la coleccion de Warnings*/
|
||||
/*Si la nueva columna a agregar es Identity, tampoco se debe insertar explicitamente*/
|
||||
if (
|
||||
!(column.Status == ObjectStatus.Create &&
|
||||
(column.Type.ToLower().Equals("xml") || column.IsIdentity)))
|
||||
{
|
||||
columnNamesStringBuilder.Append("[");
|
||||
columnNamesStringBuilder.Append(column.Name);
|
||||
columnNamesStringBuilder.Append("],");
|
||||
|
||||
if (column.HasToForceValue)
|
||||
{
|
||||
if (column.HasState(ObjectStatus.Update))
|
||||
{
|
||||
valuesStringBuilder.Append("ISNULL([");
|
||||
valuesStringBuilder.Append(column.Name);
|
||||
valuesStringBuilder.Append("],");
|
||||
valuesStringBuilder.Append(column.DefaultForceValue);
|
||||
valuesStringBuilder.Append("),");
|
||||
}
|
||||
else
|
||||
{
|
||||
valuesStringBuilder.Append(column.DefaultForceValue);
|
||||
valuesStringBuilder.Append(",");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
valuesStringBuilder.Append("[");
|
||||
valuesStringBuilder.Append(column.Name);
|
||||
valuesStringBuilder.Append("],");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (column.IsIdentity) IsIdentityNew = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (columnNamesStringBuilder.Length > 0)
|
||||
{
|
||||
var listColumns = columnNamesStringBuilder.ToString(0, columnNamesStringBuilder.Length - 1);
|
||||
var listValues = valuesStringBuilder.ToString(0, valuesStringBuilder.Length - 1);
|
||||
sql += ToSQLTemp(tempTable) + "\r\n";
|
||||
if ((HasIdentityColumn) && (!IsIdentityNew))
|
||||
sql += "SET IDENTITY_INSERT [" + Owner + "].[" + tempTable + "] ON\r\n";
|
||||
sql += "INSERT INTO [" + Owner + "].[" + tempTable + "] (" + listColumns + ")" + " SELECT " +
|
||||
listValues + " FROM " + FullName + "\r\n";
|
||||
if ((HasIdentityColumn) && (!IsIdentityNew))
|
||||
sql += "SET IDENTITY_INSERT [" + Owner + "].[" + tempTable + "] OFF\r\nGO\r\n\r\n";
|
||||
sql += "DROP TABLE " + FullName + "\r\nGO\r\n";
|
||||
|
||||
if (HasFileStream)
|
||||
{
|
||||
Constraints.ForEach(item =>
|
||||
{
|
||||
if (item.Type == Constraint.ConstraintType.Unique &&
|
||||
item.Status != ObjectStatus.Drop)
|
||||
{
|
||||
sql += "EXEC sp_rename N'[" + Owner + "].[Temp_XX_" + item.Name +
|
||||
"]',N'" + item.Name + "', 'OBJECT'\r\nGO\r\n";
|
||||
}
|
||||
});
|
||||
}
|
||||
sql += "EXEC sp_rename N'[" + Owner + "].[" + tempTable + "]',N'" + Name +
|
||||
"', 'OBJECT'\r\nGO\r\n\r\n";
|
||||
sql += OriginalTable.Options.ToSql();
|
||||
}
|
||||
else
|
||||
sql = "";
|
||||
return sql;
|
||||
}
|
||||
|
||||
private SQLScriptList ToSQLRebuild()
|
||||
{
|
||||
var listDiff = new SQLScriptList();
|
||||
listDiff.AddRange(ToSQLDropDependencies());
|
||||
listDiff.Add(ToSQLTableRebuild(), dependenciesCount, ScriptAction.RebuildTable);
|
||||
listDiff.AddRange(ToSQLCreateDependencies());
|
||||
return listDiff;
|
||||
}
|
||||
|
||||
private string ToSQLTemp(String TableName)
|
||||
{
|
||||
string sql = "";
|
||||
|
||||
// Drop constraints first, to avoid duplicate constraints created in temp table
|
||||
foreach (var column in Columns.Where(c => !string.IsNullOrWhiteSpace(c.DefaultConstraint?.Name)))
|
||||
{
|
||||
sql += $"ALTER TABLE {this.FullName} DROP CONSTRAINT [{column.DefaultConstraint.Name}]\r\n";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(sql))
|
||||
sql += "\r\n";
|
||||
|
||||
sql += "CREATE TABLE [" + Owner + "].[" + TableName + "]\r\n(\r\n";
|
||||
|
||||
Columns.Sort();
|
||||
|
||||
for (int index = 0; index < Columns.Count; index++)
|
||||
{
|
||||
if (Columns[index].Status != ObjectStatus.Drop)
|
||||
{
|
||||
sql += "\t" + Columns[index].ToSql(true);
|
||||
if (index != Columns.Count - 1)
|
||||
sql += ",";
|
||||
sql += "\r\n";
|
||||
}
|
||||
}
|
||||
if (HasFileStream)
|
||||
{
|
||||
sql = sql.Substring(0, sql.Length - 2);
|
||||
sql += ",\r\n";
|
||||
Constraints.ForEach(item =>
|
||||
{
|
||||
if (item.Type == Constraint.ConstraintType.Unique &&
|
||||
item.Status != ObjectStatus.Drop)
|
||||
{
|
||||
item.Name = "Temp_XX_" + item.Name;
|
||||
sql += "\t" + item.ToSql() + ",\r\n";
|
||||
item.SetWasInsertInDiffList(ScriptAction.AddConstraint);
|
||||
item.Name = item.Name.Substring(8, item.Name.Length - 8);
|
||||
}
|
||||
});
|
||||
sql = sql.Substring(0, sql.Length - 3) + "\r\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
sql += "\r\n";
|
||||
if (!String.IsNullOrEmpty(CompressType))
|
||||
sql += "WITH (DATA_COMPRESSION = " + CompressType + ")\r\n";
|
||||
}
|
||||
sql += ")";
|
||||
|
||||
if (!String.IsNullOrEmpty(FileGroup)) sql += " ON [" + FileGroup + "]";
|
||||
|
||||
if (!String.IsNullOrEmpty(FileGroupText) && HasBlobColumn)
|
||||
sql += " TEXTIMAGE_ON [" + FileGroupText + "]";
|
||||
|
||||
if (!String.IsNullOrEmpty(FileGroupStream) && HasFileStream)
|
||||
sql += " FILESTREAM_ON [" + FileGroupStream + "]";
|
||||
|
||||
sql += "\r\n";
|
||||
sql += "GO\r\n";
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
private void GenerateDependencies()
|
||||
{
|
||||
List<ISchemaBase> myDependencies;
|
||||
/*Si el estado es AlterRebuildDependeciesStatus, busca las dependencias solamente en las columnas que fueron modificadas*/
|
||||
if (Status == ObjectStatus.RebuildDependencies)
|
||||
{
|
||||
myDependencies = new List<ISchemaBase>();
|
||||
for (int ic = 0; ic < Columns.Count; ic++)
|
||||
{
|
||||
if ((Columns[ic].Status == ObjectStatus.RebuildDependencies) ||
|
||||
(Columns[ic].Status == ObjectStatus.Alter))
|
||||
myDependencies.AddRange(((Database)Parent).Dependencies.Find(Id, 0, Columns[ic].DataUserTypeId));
|
||||
}
|
||||
/*Si no encuentra ninguna, toma todas las de la tabla*/
|
||||
if (myDependencies.Count == 0)
|
||||
myDependencies.AddRange(((Database)Parent).Dependencies.Find(Id));
|
||||
}
|
||||
else
|
||||
myDependencies = ((Database)Parent).Dependencies.Find(Id);
|
||||
|
||||
dependencies = new List<ISchemaBase>();
|
||||
for (int j = 0; j < myDependencies.Count; j++)
|
||||
{
|
||||
ISchemaBase item = null;
|
||||
if (myDependencies[j].ObjectType == ObjectType.Index)
|
||||
item = Indexes[myDependencies[j].FullName];
|
||||
if (myDependencies[j].ObjectType == ObjectType.Constraint)
|
||||
item =
|
||||
((Database)Parent).Tables[myDependencies[j].Parent.FullName].Constraints[
|
||||
myDependencies[j].FullName];
|
||||
if (myDependencies[j].ObjectType == ObjectType.Default)
|
||||
item = Columns[myDependencies[j].FullName].DefaultConstraint;
|
||||
if (myDependencies[j].ObjectType == ObjectType.View)
|
||||
item = ((Database)Parent).Views[myDependencies[j].FullName];
|
||||
if (myDependencies[j].ObjectType == ObjectType.Function)
|
||||
item = ((Database)Parent).Functions[myDependencies[j].FullName];
|
||||
if (item != null)
|
||||
dependencies.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Genera una lista de FK que deben ser eliminadas previamente a la eliminacion de la tablas.
|
||||
/// Esto pasa porque para poder eliminar una tabla, hay que eliminar antes todas las constraints asociadas.
|
||||
/// </summary>
|
||||
private SQLScriptList ToSQLDropFKBelow()
|
||||
{
|
||||
var listDiff = new SQLScriptList();
|
||||
Constraints.ForEach(constraint =>
|
||||
{
|
||||
if ((constraint.Type == Constraint.ConstraintType.ForeignKey) &&
|
||||
(((Table)constraint.Parent).DependenciesCount <= DependenciesCount))
|
||||
{
|
||||
/*Si la FK pertenece a la misma tabla, no se debe explicitar el DROP CONSTRAINT antes de hacer el DROP TABLE*/
|
||||
if (constraint.Parent.Id != constraint.RelationalTableId)
|
||||
{
|
||||
listDiff.Add(constraint.Drop());
|
||||
}
|
||||
}
|
||||
});
|
||||
return listDiff;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Genera una lista de script de DROPS de todas los constraints dependientes de la tabla.
|
||||
/// Se usa cuando se quiere reconstruir una tabla y todos sus objectos dependientes.
|
||||
/// </summary>
|
||||
private SQLScriptList ToSQLDropDependencies()
|
||||
{
|
||||
bool addDependency = true;
|
||||
var listDiff = new SQLScriptList();
|
||||
//Se buscan todas las table constraints.
|
||||
for (int index = 0; index < dependencies.Count; index++)
|
||||
{
|
||||
if ((dependencies[index].Status == ObjectStatus.Original) ||
|
||||
(dependencies[index].Status == ObjectStatus.Drop))
|
||||
{
|
||||
addDependency = true;
|
||||
if (dependencies[index].ObjectType == ObjectType.Constraint)
|
||||
{
|
||||
if ((((Constraint)dependencies[index]).Type == Constraint.ConstraintType.Unique) &&
|
||||
((HasFileStream) || (OriginalTable.HasFileStream)))
|
||||
addDependency = false;
|
||||
if ((((Constraint)dependencies[index]).Type != Constraint.ConstraintType.ForeignKey) &&
|
||||
(dependencies[index].Status == ObjectStatus.Drop))
|
||||
addDependency = false;
|
||||
}
|
||||
if (addDependency)
|
||||
listDiff.Add(dependencies[index].Drop());
|
||||
}
|
||||
}
|
||||
//Se buscan todas las columns constraints.
|
||||
Columns.ForEach(column =>
|
||||
{
|
||||
if (column.DefaultConstraint != null)
|
||||
{
|
||||
if (((column.DefaultConstraint.Status == ObjectStatus.Original) ||
|
||||
(column.DefaultConstraint.Status == ObjectStatus.Drop) ||
|
||||
(column.DefaultConstraint.Status == ObjectStatus.Alter)) &&
|
||||
(column.Status != ObjectStatus.Create))
|
||||
listDiff.Add(column.DefaultConstraint.Drop());
|
||||
}
|
||||
});
|
||||
return listDiff;
|
||||
}
|
||||
|
||||
private SQLScriptList ToSQLCreateDependencies()
|
||||
{
|
||||
bool addDependency = true;
|
||||
var listDiff = new SQLScriptList();
|
||||
//Las constraints de deben recorrer en el orden inverso.
|
||||
for (int index = dependencies.Count - 1; index >= 0; index--)
|
||||
{
|
||||
if ((dependencies[index].Status == ObjectStatus.Original) &&
|
||||
(dependencies[index].Parent.Status != ObjectStatus.Drop))
|
||||
{
|
||||
addDependency = true;
|
||||
if (dependencies[index].ObjectType == ObjectType.Constraint)
|
||||
{
|
||||
if ((((Constraint)dependencies[index]).Type == Constraint.ConstraintType.Unique) &&
|
||||
(HasFileStream))
|
||||
addDependency = false;
|
||||
}
|
||||
if (addDependency)
|
||||
listDiff.Add(dependencies[index].Create());
|
||||
}
|
||||
}
|
||||
//Se buscan todas las columns constraints.
|
||||
for (int index = Columns.Count - 1; index >= 0; index--)
|
||||
{
|
||||
if (Columns[index].DefaultConstraint != null)
|
||||
{
|
||||
if ((Columns[index].DefaultConstraint.CanCreate) &&
|
||||
(Columns.Parent.Status != ObjectStatus.Rebuild))
|
||||
listDiff.Add(Columns[index].DefaultConstraint.Create());
|
||||
}
|
||||
}
|
||||
return listDiff;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compara dos tablas y devuelve true si son iguales, caso contrario, devuelve false.
|
||||
/// </summary>
|
||||
public static Boolean CompareFileGroup(Table origin, Table destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (origin == null) throw new ArgumentNullException("origin");
|
||||
if ((!String.IsNullOrEmpty(destination.FileGroup) && (!String.IsNullOrEmpty(origin.FileGroup))))
|
||||
if (!destination.FileGroup.Equals(origin.FileGroup))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compara dos tablas y devuelve true si son iguales, caso contrario, devuelve false.
|
||||
/// </summary>
|
||||
public static Boolean CompareFileGroupText(Table origin, Table destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (origin == null) throw new ArgumentNullException("origin");
|
||||
if ((!String.IsNullOrEmpty(destination.FileGroupText) && (!String.IsNullOrEmpty(origin.FileGroupText))))
|
||||
if (!destination.FileGroupText.Equals(origin.FileGroupText))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
95
OpenDBDiff.Schema.SQLServer.Generates/Model/TableOption.cs
Normal file
95
OpenDBDiff.Schema.SQLServer.Generates/Model/TableOption.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
using System;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class TableOption : SQLServerSchemaBase
|
||||
{
|
||||
public TableOption(string Name, string value, ISchemaBase parent)
|
||||
: base(parent, ObjectType.TableOption)
|
||||
{
|
||||
this.Name = Name;
|
||||
this.Value = value;
|
||||
}
|
||||
|
||||
public TableOption(ISchemaBase parent)
|
||||
: base(parent, ObjectType.TableOption)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clona el objeto en una nueva instancia.
|
||||
/// </summary>
|
||||
public override ISchemaBase Clone(ISchemaBase parent)
|
||||
{
|
||||
TableOption option = new TableOption(parent);
|
||||
option.Name = this.Name;
|
||||
option.Status = this.Status;
|
||||
option.Value = this.Value;
|
||||
return option;
|
||||
}
|
||||
|
||||
public string Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Compara dos indices y devuelve true si son iguales, caso contrario, devuelve false.
|
||||
/// </summary>
|
||||
public static Boolean Compare(TableOption origin, TableOption destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (origin == null) throw new ArgumentNullException("origin");
|
||||
if (!destination.Value.Equals(origin.Value)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
if (this.Name.Equals("TextInRow"))
|
||||
return "EXEC sp_tableoption " + Parent.Name + ", 'text in row','off'\r\nGO\r\n";
|
||||
if (this.Name.Equals("LargeValues"))
|
||||
return "EXEC sp_tableoption " + Parent.Name + ", 'large value types out of row','0'\r\nGO\r\n";
|
||||
if (this.Name.Equals("VarDecimal"))
|
||||
return "EXEC sp_tableoption " + Parent.Name + ", 'vardecimal storage format','0'\r\nGO\r\n";
|
||||
if (this.Name.Equals("LockEscalation"))
|
||||
return "";
|
||||
return "";
|
||||
}
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
if (this.Name.Equals("TextInRow"))
|
||||
return "EXEC sp_tableoption " + Parent.Name + ", 'text in row'," + Value + "\r\nGO\r\n";
|
||||
if (this.Name.Equals("LargeValues"))
|
||||
return "EXEC sp_tableoption " + Parent.Name + ", 'large value types out of row'," + Value + "\r\nGO\r\n";
|
||||
if (this.Name.Equals("VarDecimal"))
|
||||
return "EXEC sp_tableoption " + Parent.Name + ", 'vardecimal storage format','1'\r\nGO\r\n";
|
||||
if (this.Name.Equals("LockEscalation"))
|
||||
{
|
||||
if ((!this.Value.Equals("TABLE")) || (this.Status != ObjectStatus.Original))
|
||||
return "ALTER TABLE " + Parent.Name + " SET (LOCK_ESCALATION = " + Value + ")\r\nGO\r\n";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
return ToSql();
|
||||
}
|
||||
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList listDiff = new SQLScriptList();
|
||||
|
||||
if (this.Status == ObjectStatus.Drop)
|
||||
listDiff.Add(ToSqlDrop(), 0, ScriptAction.AddOptions);
|
||||
if (this.Status == ObjectStatus.Create)
|
||||
listDiff.Add(ToSql(), 0, ScriptAction.DropOptions);
|
||||
if (this.Status == ObjectStatus.Alter)
|
||||
{
|
||||
listDiff.Add(ToSqlDrop(), 0, ScriptAction.DropOptions);
|
||||
listDiff.Add(ToSql(), 0, ScriptAction.AddOptions);
|
||||
}
|
||||
return listDiff;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class TablePartition : SQLServerSchemaBase
|
||||
{
|
||||
public TablePartition(Table parent)
|
||||
: base(parent, ObjectType.Partition)
|
||||
{
|
||||
}
|
||||
|
||||
public string CompressType { get; set; }
|
||||
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
116
OpenDBDiff.Schema.SQLServer.Generates/Model/TableType.cs
Normal file
116
OpenDBDiff.Schema.SQLServer.Generates/Model/TableType.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
using OpenDBDiff.Schema.Model;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class TableType : SQLServerSchemaBase, ITable<TableType>
|
||||
{
|
||||
public TableType(ISchemaBase parent)
|
||||
: base(parent, ObjectType.TableType)
|
||||
{
|
||||
Columns = new Columns<TableType>(this);
|
||||
Constraints = new SchemaList<Constraint, TableType>(this, ((Database)parent).AllObjects);
|
||||
Indexes = new SchemaList<Index, TableType>(this, ((Database)parent).AllObjects);
|
||||
}
|
||||
|
||||
public override ISchemaBase Clone(ISchemaBase parent)
|
||||
{
|
||||
var tableType = new TableType(parent)
|
||||
{
|
||||
Owner = this.Owner,
|
||||
Name = this.Name,
|
||||
Id = this.Id,
|
||||
Guid = this.Guid,
|
||||
Status = this.Status,
|
||||
Columns = null,
|
||||
Constraints = null,
|
||||
Indexes = null
|
||||
};
|
||||
|
||||
tableType.Columns = this.Columns.Clone(tableType);
|
||||
tableType.Constraints = this.Constraints.Clone(tableType);
|
||||
tableType.Indexes = this.Indexes.Clone(tableType);
|
||||
|
||||
return tableType;
|
||||
}
|
||||
|
||||
public Columns<TableType> Columns { get; private set; }
|
||||
|
||||
public SchemaList<Constraint, TableType> Constraints { get; private set; }
|
||||
|
||||
public SchemaList<Index, TableType> Indexes { get; private set; }
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
string sql = "";
|
||||
if (Columns.Any())
|
||||
{
|
||||
sql += "CREATE TYPE " + FullName + " AS TABLE\r\n(\r\n";
|
||||
sql += Columns.ToSql() + "\r\n";
|
||||
sql += Constraints.ToSql();
|
||||
sql += ")";
|
||||
sql += "\r\nGO\r\n";
|
||||
}
|
||||
return sql;
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
return "DROP TYPE " + FullName + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
return ToSql();
|
||||
}
|
||||
|
||||
public override SQLScript Create()
|
||||
{
|
||||
ScriptAction action = ScriptAction.AddTableType;
|
||||
if (!GetWasInsertInDiffList(action))
|
||||
{
|
||||
SetWasInsertInDiffList(action);
|
||||
return new SQLScript(this.ToSqlAdd(), 0, action);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public override SQLScript Drop()
|
||||
{
|
||||
ScriptAction action = ScriptAction.DropTableType;
|
||||
if (!GetWasInsertInDiffList(action))
|
||||
{
|
||||
SetWasInsertInDiffList(action);
|
||||
return new SQLScript(this.ToSqlDrop(), 0, action);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
try
|
||||
{
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
if (this.Status == ObjectStatus.Drop)
|
||||
{
|
||||
list.Add(Drop());
|
||||
}
|
||||
if (this.HasState(ObjectStatus.Create))
|
||||
{
|
||||
list.Add(Create());
|
||||
}
|
||||
if (this.Status == ObjectStatus.Alter)
|
||||
{
|
||||
list.Add(ToSqlDrop() + ToSql(), 0, ScriptAction.AddTableType);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
96
OpenDBDiff.Schema.SQLServer.Generates/Model/Trigger.cs
Normal file
96
OpenDBDiff.Schema.SQLServer.Generates/Model/Trigger.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class Trigger : Code
|
||||
{
|
||||
public Trigger(ISchemaBase parent)
|
||||
: base(parent, ObjectType.Trigger, ScriptAction.AddTrigger, ScriptAction.DropTrigger)
|
||||
{
|
||||
this.Parent = parent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clona el objeto en una nueva instancia.
|
||||
/// </summary>
|
||||
public override ISchemaBase Clone(ISchemaBase parent)
|
||||
{
|
||||
Trigger trigger = new Trigger(parent);
|
||||
trigger.Text = this.Text;
|
||||
trigger.Status = this.Status;
|
||||
trigger.Name = this.Name;
|
||||
trigger.IsDisabled = this.IsDisabled;
|
||||
trigger.InsteadOf = this.InsteadOf;
|
||||
trigger.NotForReplication = this.NotForReplication;
|
||||
trigger.Owner = this.Owner;
|
||||
trigger.Id = this.Id;
|
||||
trigger.IsDDLTrigger = this.IsDDLTrigger;
|
||||
trigger.Guid = this.Guid;
|
||||
return trigger;
|
||||
}
|
||||
|
||||
public Boolean IsDDLTrigger { get; set; }
|
||||
|
||||
public Boolean InsteadOf { get; set; }
|
||||
|
||||
public Boolean IsDisabled { get; set; }
|
||||
|
||||
public Boolean NotForReplication { get; set; }
|
||||
|
||||
public override Boolean IsCodeType
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
if (!IsDDLTrigger)
|
||||
return "DROP TRIGGER " + FullName + "\r\nGO\r\n";
|
||||
else
|
||||
return "DROP TRIGGER " + FullName + " ON DATABASE\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public string ToSQLEnabledDisabled()
|
||||
{
|
||||
if (!IsDDLTrigger)
|
||||
{
|
||||
if (IsDisabled)
|
||||
return "DISABLE TRIGGER [" + Name + "] ON " + Parent.FullName + "\r\nGO\r\n";
|
||||
else
|
||||
return "ENABLE TRIGGER [" + Name + "] ON " + Parent.FullName + "\r\nGO\r\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsDisabled)
|
||||
return "DISABLE TRIGGER [" + Name + "]\r\nGO\r\n";
|
||||
else
|
||||
return "ENABLE TRIGGER [" + Name + "]\r\nGO\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
if (this.Status == ObjectStatus.Drop)
|
||||
list.Add(Drop());
|
||||
if (this.Status == ObjectStatus.Create)
|
||||
list.Add(Create());
|
||||
if (this.HasState(ObjectStatus.Alter))
|
||||
list.AddRange(Rebuild());
|
||||
if (this.HasState(ObjectStatus.Disabled))
|
||||
list.Add(this.ToSQLEnabledDisabled(), 0, ScriptAction.EnabledTrigger);
|
||||
return list;
|
||||
}
|
||||
|
||||
public override bool Compare(ICode obj)
|
||||
{
|
||||
if (obj == null) throw new ArgumentNullException("obj");
|
||||
if (!this.ToSql().Equals(obj.ToSql())) return false;
|
||||
if (this.InsteadOf != ((Trigger)obj).InsteadOf) return false;
|
||||
if (this.IsDisabled != ((Trigger)obj).IsDisabled) return false;
|
||||
if (this.NotForReplication != ((Trigger)obj).NotForReplication) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
72
OpenDBDiff.Schema.SQLServer.Generates/Model/User.cs
Normal file
72
OpenDBDiff.Schema.SQLServer.Generates/Model/User.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class User : SQLServerSchemaBase
|
||||
{
|
||||
public User(ISchemaBase parent)
|
||||
: base(parent, ObjectType.User)
|
||||
{
|
||||
}
|
||||
|
||||
public override string FullName
|
||||
{
|
||||
get { return "[" + Name + "]"; }
|
||||
}
|
||||
|
||||
public string Login { get; set; }
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
string sql = "";
|
||||
sql += "CREATE USER ";
|
||||
sql += FullName + " ";
|
||||
if (!String.IsNullOrEmpty(Login))
|
||||
sql += "FOR LOGIN [" + Login + "] ";
|
||||
else
|
||||
sql += "WITHOUT LOGIN ";
|
||||
if (!String.IsNullOrEmpty(Owner))
|
||||
sql += "WITH DEFAULT_SCHEMA=[" + Owner + "]";
|
||||
return sql.Trim() + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
return "DROP USER " + FullName + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
return ToSql();
|
||||
}
|
||||
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList listDiff = new SQLScriptList();
|
||||
|
||||
if (this.Status == ObjectStatus.Drop)
|
||||
{
|
||||
listDiff.Add(ToSqlDrop(), 0, ScriptAction.DropUser);
|
||||
}
|
||||
if (this.Status == ObjectStatus.Create)
|
||||
{
|
||||
listDiff.Add(ToSql(), 0, ScriptAction.AddUser);
|
||||
}
|
||||
if ((this.Status & ObjectStatus.Alter) == ObjectStatus.Alter)
|
||||
{
|
||||
listDiff.Add(ToSqlDrop(), 0, ScriptAction.DropUser);
|
||||
listDiff.Add(ToSql(), 0, ScriptAction.AddUser);
|
||||
}
|
||||
return listDiff;
|
||||
}
|
||||
|
||||
public bool Compare(User obj)
|
||||
{
|
||||
if (obj == null) throw new ArgumentNullException("destination");
|
||||
if (!this.Login.Equals(obj.Login)) return false;
|
||||
if (!this.Owner.Equals(obj.Owner)) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
356
OpenDBDiff.Schema.SQLServer.Generates/Model/UserDataType.cs
Normal file
356
OpenDBDiff.Schema.SQLServer.Generates/Model/UserDataType.cs
Normal file
@@ -0,0 +1,356 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class UserDataType : SQLServerSchemaBase
|
||||
{
|
||||
public UserDataType(ISchemaBase parent)
|
||||
: base(parent, ObjectType.UserDataType)
|
||||
{
|
||||
Default = new Default(this);
|
||||
Rule = new Rule(this);
|
||||
Dependencies = new List<ObjectDependency>();
|
||||
}
|
||||
|
||||
public List<ObjectDependency> Dependencies { get; private set; }
|
||||
|
||||
public Rule Rule { get; private set; }
|
||||
|
||||
public Default Default { get; private set; }
|
||||
|
||||
public string AssemblyName { get; set; }
|
||||
|
||||
public Boolean IsAssembly { get; set; }
|
||||
|
||||
public string AssemblyClass { get; set; }
|
||||
|
||||
public int AssemblyId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Cantidad de digitos que permite el campo (solo para campos Numeric).
|
||||
/// </summary>
|
||||
public int Scale { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Cantidad de decimales que permite el campo (solo para campos Numeric).
|
||||
/// </summary>
|
||||
public int Precision { get; set; }
|
||||
|
||||
public Boolean AllowNull { get; set; }
|
||||
|
||||
public int Size { get; set; }
|
||||
|
||||
public string Type { get; set; }
|
||||
|
||||
public String AssemblyFullName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsAssembly)
|
||||
return AssemblyName + "." + AssemblyClass;
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clona el objeto Column en una nueva instancia.
|
||||
/// </summary>
|
||||
public override ISchemaBase Clone(ISchemaBase parent)
|
||||
{
|
||||
var item = new UserDataType(parent)
|
||||
{
|
||||
Name = Name,
|
||||
Id = Id,
|
||||
Owner = Owner,
|
||||
Guid = Guid,
|
||||
AllowNull = AllowNull,
|
||||
Precision = Precision,
|
||||
Scale = Scale,
|
||||
Size = Size,
|
||||
Type = Type,
|
||||
Default = Default.Clone(this),
|
||||
Rule = Rule.Clone(this),
|
||||
Dependencies = Dependencies,
|
||||
IsAssembly = IsAssembly,
|
||||
AssemblyClass = AssemblyClass,
|
||||
AssemblyId = AssemblyId,
|
||||
AssemblyName = AssemblyName
|
||||
};
|
||||
return item;
|
||||
}
|
||||
|
||||
public static Boolean CompareRule(UserDataType origin, UserDataType destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (origin == null) throw new ArgumentNullException("origin");
|
||||
if ((origin.Rule.Name != null) && (destination.Rule.Name == null)) return false;
|
||||
if ((origin.Rule.Name == null) && (destination.Rule.Name != null)) return false;
|
||||
if (origin.Rule.Name != null)
|
||||
if (!origin.Rule.Name.Equals(destination.Rule.Name)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Boolean CompareDefault(UserDataType origin, UserDataType destination)
|
||||
{
|
||||
if (destination == null) throw new ArgumentNullException("destination");
|
||||
if (origin == null) throw new ArgumentNullException("origin");
|
||||
if ((origin.Default.Name != null) && (destination.Default.Name == null)) return false;
|
||||
if ((origin.Default.Name == null) && (destination.Default.Name != null)) return false;
|
||||
if (origin.Default.Name != null)
|
||||
if (!origin.Default.Name.Equals(destination.Default.Name)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
string sql = "CREATE TYPE " + FullName;
|
||||
if (!IsAssembly)
|
||||
{
|
||||
sql += " FROM [" + Type + "]";
|
||||
if (Type.Equals("binary") || Type.Equals("varbinary") || Type.Equals("varchar") || Type.Equals("char") ||
|
||||
Type.Equals("nchar") || Type.Equals("nvarchar"))
|
||||
sql += "(" + Size.ToString(CultureInfo.InvariantCulture) + ")";
|
||||
if (Type.Equals("numeric") || Type.Equals("decimal"))
|
||||
sql += " (" + Precision.ToString(CultureInfo.InvariantCulture) + "," +
|
||||
Scale.ToString(CultureInfo.InvariantCulture) + ")";
|
||||
if (AllowNull)
|
||||
sql += " NULL";
|
||||
else
|
||||
sql += " NOT NULL";
|
||||
}
|
||||
else
|
||||
{
|
||||
sql += " EXTERNAL NAME [" + AssemblyName + "].[" + AssemblyClass + "]";
|
||||
}
|
||||
sql += "\r\nGO\r\n";
|
||||
return sql + ToSQLAddBinds();
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
return "DROP TYPE " + FullName + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
return ToSql();
|
||||
}
|
||||
|
||||
private string ToSQLAddBinds()
|
||||
{
|
||||
string sql = "";
|
||||
if (!String.IsNullOrEmpty(Default.Name))
|
||||
sql += Default.ToSQLAddBind();
|
||||
if (!String.IsNullOrEmpty(Rule.Name))
|
||||
sql += Rule.ToSQLAddBind();
|
||||
return sql;
|
||||
}
|
||||
|
||||
private SQLScriptList RebuildDependencies(Table table)
|
||||
{
|
||||
var list = new SQLScriptList();
|
||||
List<ISchemaBase> items = ((Database)table.Parent).Dependencies.Find(table.Id);
|
||||
items.ForEach(item =>
|
||||
{
|
||||
ISchemaBase realItem = ((Database)table.Parent).Find(item.FullName);
|
||||
if (realItem.IsCodeType)
|
||||
list.AddRange(((ICode)realItem).Rebuild());
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
private SQLScriptList ToSQLChangeColumns()
|
||||
{
|
||||
var fields = new Hashtable();
|
||||
var list = new SQLScriptList();
|
||||
var listDependencies = new SQLScriptList();
|
||||
if ((Status == ObjectStatus.Alter) || (Status == ObjectStatus.Rebuild))
|
||||
{
|
||||
foreach (ObjectDependency dependency in Dependencies)
|
||||
{
|
||||
ISchemaBase itemDepens = ((Database)Parent).Find(dependency.Name);
|
||||
/*Si la dependencia es una funcion o una vista, reconstruye el objecto*/
|
||||
if (dependency.IsCodeType)
|
||||
{
|
||||
if (itemDepens != null)
|
||||
list.AddRange(((ICode)itemDepens).Rebuild());
|
||||
}
|
||||
/*Si la dependencia es una tabla, reconstruye los indices, constraint y columnas asociadas*/
|
||||
if (dependency.Type == ObjectType.Table)
|
||||
{
|
||||
Column column = ((Table)itemDepens).Columns[dependency.ColumnName];
|
||||
if ((column.Parent.Status != ObjectStatus.Drop) &&
|
||||
(column.Parent.Status != ObjectStatus.Create) &&
|
||||
((column.Status != ObjectStatus.Create) || (column.IsComputed)))
|
||||
{
|
||||
if (!fields.ContainsKey(column.FullName))
|
||||
{
|
||||
listDependencies.AddRange(RebuildDependencies((Table)itemDepens));
|
||||
if (column.HasToRebuildOnlyConstraint)
|
||||
//column.Parent.Status = ObjectStatusType.AlterRebuildDependenciesStatus;
|
||||
list.AddRange(column.RebuildDependencies());
|
||||
if (!column.IsComputed)
|
||||
{
|
||||
list.AddRange(column.RebuildConstraint(true));
|
||||
list.Add(
|
||||
"ALTER TABLE " + column.Parent.FullName + " ALTER COLUMN " +
|
||||
column.ToSQLRedefine(Type, Size, null) + "\r\nGO\r\n", 0,
|
||||
ScriptAction.AlterColumn);
|
||||
/*Si la columna va a ser eliminada o la tabla va a ser reconstruida, no restaura la columna*/
|
||||
if ((column.Status != ObjectStatus.Drop) &&
|
||||
(column.Parent.Status != ObjectStatus.Rebuild))
|
||||
list.AddRange(column.Alter(ScriptAction.AlterColumnRestore));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (column.Status != ObjectStatus.Create)
|
||||
{
|
||||
if (!column.GetWasInsertInDiffList(ScriptAction.AlterColumnFormula))
|
||||
{
|
||||
column.SetWasInsertInDiffList(ScriptAction.AlterColumnFormula);
|
||||
list.Add(column.ToSqlDrop(), 0, ScriptAction.AlterColumnFormula);
|
||||
List<ISchemaBase> drops =
|
||||
((Database)column.Parent.Parent).Dependencies.Find(column.Parent.Id,
|
||||
column.Id, 0);
|
||||
drops.ForEach(item =>
|
||||
{
|
||||
if (item.Status != ObjectStatus.Create)
|
||||
list.Add(item.Drop());
|
||||
if (item.Status != ObjectStatus.Drop)
|
||||
list.Add(item.Create());
|
||||
});
|
||||
/*Si la columna va a ser eliminada o la tabla va a ser reconstruida, no restaura la columna*/
|
||||
if ((column.Status != ObjectStatus.Drop) &&
|
||||
(column.Parent.Status != ObjectStatus.Rebuild))
|
||||
list.Add(column.ToSqlAdd(), 0,
|
||||
ScriptAction.AlterColumnFormulaRestore);
|
||||
}
|
||||
}
|
||||
}
|
||||
fields.Add(column.FullName, column.FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
list.AddRange(listDependencies);
|
||||
return list;
|
||||
}
|
||||
|
||||
private Boolean HasAnotherUDTClass()
|
||||
{
|
||||
if (IsAssembly)
|
||||
{
|
||||
/*If another UDT exists in the same assembly to bre created. It must be deleted BEFORE creating the new one.*/
|
||||
UserDataType other =
|
||||
((Database)Parent).UserTypes.Find(
|
||||
item =>
|
||||
(item.Status == ObjectStatus.Drop) &&
|
||||
(item.AssemblyName + "." + item.AssemblyClass).Equals((AssemblyName + "." + AssemblyClass)));
|
||||
if (other != null)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private string SQLDropOlder()
|
||||
{
|
||||
UserDataType other =
|
||||
((Database)Parent).UserTypes.Find(
|
||||
item =>
|
||||
(item.Status == ObjectStatus.Drop) &&
|
||||
(item.AssemblyName + "." + item.AssemblyClass).Equals((AssemblyName + "." + AssemblyClass)));
|
||||
return other.ToSqlDrop();
|
||||
}
|
||||
|
||||
public override SQLScript Create()
|
||||
{
|
||||
ScriptAction action = ScriptAction.AddUserDataType;
|
||||
if (!GetWasInsertInDiffList(action))
|
||||
{
|
||||
SetWasInsertInDiffList(action);
|
||||
return new SQLScript(ToSqlAdd(), 0, action);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public override SQLScript Drop()
|
||||
{
|
||||
const ScriptAction action = ScriptAction.DropUserDataType;
|
||||
if (!GetWasInsertInDiffList(action))
|
||||
{
|
||||
SetWasInsertInDiffList(action);
|
||||
return new SQLScript(ToSqlDrop(), 0, action);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
try
|
||||
{
|
||||
var list = new SQLScriptList();
|
||||
if (Status == ObjectStatus.Drop)
|
||||
{
|
||||
if (!HasAnotherUDTClass())
|
||||
list.Add(Drop());
|
||||
}
|
||||
if (HasState(ObjectStatus.Create))
|
||||
{
|
||||
list.Add(Create());
|
||||
}
|
||||
if (Status == ObjectStatus.Alter)
|
||||
{
|
||||
if (Default.Status == ObjectStatus.Create)
|
||||
list.Add(Default.ToSQLAddBind(), 0, ScriptAction.AddUserDataType);
|
||||
if (Default.Status == ObjectStatus.Drop)
|
||||
list.Add(Default.ToSQLAddUnBind(), 0, ScriptAction.UnbindRuleType);
|
||||
if (Rule.Status == ObjectStatus.Create)
|
||||
list.Add(Rule.ToSQLAddBind(), 0, ScriptAction.AddUserDataType);
|
||||
if (Rule.Status == ObjectStatus.Drop)
|
||||
list.Add(Rule.ToSQLAddUnBind(), 0, ScriptAction.UnbindRuleType);
|
||||
}
|
||||
if (Status == ObjectStatus.Rebuild)
|
||||
{
|
||||
list.AddRange(ToSQLChangeColumns());
|
||||
if (!GetWasInsertInDiffList(ScriptAction.DropUserDataType))
|
||||
{
|
||||
list.Add(ToSqlDrop() + ToSql(), 0, ScriptAction.AddUserDataType);
|
||||
}
|
||||
else
|
||||
list.Add(Create());
|
||||
}
|
||||
if (HasState(ObjectStatus.DropOlder))
|
||||
{
|
||||
list.Add(SQLDropOlder(), 0, ScriptAction.AddUserDataType);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Compare(UserDataType obj)
|
||||
{
|
||||
if (obj == null) throw new ArgumentNullException("obj");
|
||||
if (Scale != obj.Scale) return false;
|
||||
if (Precision != obj.Precision) return false;
|
||||
if (AllowNull != obj.AllowNull) return false;
|
||||
if (Size != obj.Size) return false;
|
||||
if (!Type.Equals(obj.Type)) return false;
|
||||
if (IsAssembly != obj.IsAssembly) return false;
|
||||
if (!AssemblyClass.Equals(obj.AssemblyClass)) return false;
|
||||
if (!AssemblyName.Equals(obj.AssemblyName)) return false;
|
||||
if (!CompareDefault(this, obj)) return false;
|
||||
if (!CompareRule(this, obj)) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
138
OpenDBDiff.Schema.SQLServer.Generates/Model/Util/FormatCode.cs
Normal file
138
OpenDBDiff.Schema.SQLServer.Generates/Model/Util/FormatCode.cs
Normal file
@@ -0,0 +1,138 @@
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model.Util
|
||||
{
|
||||
internal static class FormatCode
|
||||
{
|
||||
private static readonly char[] TrimCharacters = { ' ', '\r', '\n', '\t' };
|
||||
|
||||
private class SearchItem
|
||||
{
|
||||
public int FindPosition;
|
||||
public string Body = "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all unnecessary characters that are after the END statement of the body, and whitespaces at the beginning.
|
||||
/// </summary>
|
||||
private static string CleanLast(string body)
|
||||
{
|
||||
if (string.IsNullOrEmpty(body))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return body.TrimStart().TrimEnd(TrimCharacters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserta la sentencia GO dentro del body
|
||||
/// </summary>
|
||||
private static string SmartGO(string code)
|
||||
{
|
||||
string prevText = code;
|
||||
try
|
||||
{
|
||||
if (!prevText.Substring(prevText.Length - 2, 2).Equals("\r\n"))
|
||||
prevText += "\r\n";
|
||||
return prevText + "GO\r\n";
|
||||
}
|
||||
catch
|
||||
{
|
||||
return prevText;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Busca la primer entrada con el nombre completo dentro de una funcion, store, vista, trigger o rule.
|
||||
/// Ignora los comentarios.
|
||||
/// </summary>
|
||||
private static SearchItem FindCreate(string ObjectType, ISchemaBase item, string prevText)
|
||||
{
|
||||
SearchItem sitem = new SearchItem();
|
||||
Regex regex = new Regex(@"((/\*)(\w|\s|\d|\[|\]|\.)*(\*/))|((\-\-)(.)*)", RegexOptions.IgnoreCase);
|
||||
Regex reg2 = new Regex(@"CREATE " + ObjectType + @"(\s|\r|\n|\t|\w|\/|\*|-|@|_|&|#)*((\[)?" + item.Owner + @"(\])?((\s)*)?\.)?((\s)*)?(\[)?" + item.Name + @"(\])?", (RegexOptions)((int)RegexOptions.IgnoreCase + (int)RegexOptions.Multiline));
|
||||
Regex reg3 = new Regex(@"((\[)?" + item.Owner + @"(\])?\.)?((\s)+\.)?(\s)*(\[)?" + item.Name + @"(\])?", RegexOptions.IgnoreCase);
|
||||
Regex reg4 = new Regex(@"( )*\[");
|
||||
//Regex reg3 = new Regex(@"((\[)?" + item.Owner + @"(\])?.)?(\[)?" + item.Name + @"(\])?", RegexOptions.Multiline);
|
||||
|
||||
MatchCollection abiertas = regex.Matches(prevText);
|
||||
Boolean finish = false;
|
||||
int indexStart = 0;
|
||||
int indexBegin = 0;
|
||||
int iAux = -1;
|
||||
|
||||
while (!finish)
|
||||
{
|
||||
Match match = reg2.Match(prevText, indexBegin);
|
||||
if (match.Success)
|
||||
iAux = match.Index;
|
||||
else
|
||||
iAux = -1;
|
||||
if ((abiertas.Count == indexStart) || (match.Success))
|
||||
finish = true;
|
||||
else
|
||||
{
|
||||
if ((iAux < abiertas[indexStart].Index) || (iAux > abiertas[indexStart].Index + abiertas[indexStart].Length))
|
||||
finish = true;
|
||||
else
|
||||
{
|
||||
//indexBegin = abiertas[indexStart].Index + abiertas[indexStart].Length;
|
||||
indexBegin = iAux + 1;
|
||||
indexStart++;
|
||||
}
|
||||
}
|
||||
}
|
||||
string result = reg3.Replace(prevText, " " + item.FullName, 1, iAux + 1);
|
||||
if (iAux != -1)
|
||||
sitem.Body = reg4.Replace(result, " [", 1, iAux);
|
||||
sitem.FindPosition = iAux;
|
||||
return sitem;
|
||||
}
|
||||
|
||||
public static string FormatCreate(string ObjectType, string body, ISchemaBase item)
|
||||
{
|
||||
try
|
||||
{
|
||||
string prevText = (string)body.Clone();
|
||||
prevText = FindCreate(ObjectType, item, prevText).Body;
|
||||
if (String.IsNullOrEmpty(prevText))
|
||||
prevText = body;
|
||||
prevText = CleanLast(prevText);
|
||||
return SmartGO(prevText);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return SmartGO(CleanLast(body));
|
||||
}
|
||||
}
|
||||
|
||||
public static string FormatAlter(string ObjectType, string body, ISchemaBase item, Boolean quitSchemaBinding)
|
||||
{
|
||||
string prevText = null;
|
||||
try
|
||||
{
|
||||
prevText = (string)body.Clone();
|
||||
SearchItem sitem = FindCreate(ObjectType, item, prevText);
|
||||
Regex regAlter = new Regex("CREATE");
|
||||
|
||||
if (!quitSchemaBinding)
|
||||
return regAlter.Replace(sitem.Body, "ALTER", 1, sitem.FindPosition);
|
||||
//return prevText.Substring(0, iFind) + "ALTER " + sitem.ObjectType + " " + prevText.Substring(iFind + sitem.ObjectType.Length + 7, prevText.Length - (iFind + sitem.ObjectType.Length + 7)).TrimStart();
|
||||
else
|
||||
{
|
||||
string text = regAlter.Replace(sitem.Body, "ALTER", 1, sitem.FindPosition);
|
||||
Regex regex = new Regex("WITH SCHEMABINDING", RegexOptions.IgnoreCase);
|
||||
return regex.Replace(text, "");
|
||||
}
|
||||
//return "";
|
||||
}
|
||||
catch
|
||||
{
|
||||
return prevText;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
123
OpenDBDiff.Schema.SQLServer.Generates/Model/View.cs
Normal file
123
OpenDBDiff.Schema.SQLServer.Generates/Model/View.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
using System;
|
||||
using OpenDBDiff.Schema.Attributes;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
using OpenDBDiff.Schema.SQLServer.Generates.Model.Util;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class View : Code
|
||||
{
|
||||
public View(ISchemaBase parent)
|
||||
: base(parent, ObjectType.View, ScriptAction.AddView, ScriptAction.DropView)
|
||||
{
|
||||
Indexes = new SchemaList<Index, View>(this, ((Database)parent).AllObjects);
|
||||
Triggers = new SchemaList<Trigger, View>(this, ((Database)parent).AllObjects);
|
||||
CLRTriggers = new SchemaList<CLRTrigger, View>(this, ((Database)parent).AllObjects);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clona el objeto en una nueva instancia.
|
||||
/// </summary>
|
||||
public override ISchemaBase Clone(ISchemaBase parent)
|
||||
{
|
||||
View item = new View(parent);
|
||||
item.Text = this.Text;
|
||||
item.Status = this.Status;
|
||||
item.Name = this.Name;
|
||||
item.Id = this.Id;
|
||||
item.Owner = this.Owner;
|
||||
item.IsSchemaBinding = this.IsSchemaBinding;
|
||||
item.DependenciesIn = this.DependenciesIn;
|
||||
item.DependenciesOut = this.DependenciesOut;
|
||||
item.Indexes = this.Indexes.Clone(item);
|
||||
item.Triggers = this.Triggers.Clone(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
[SchemaNode("CLR Triggers")]
|
||||
public SchemaList<CLRTrigger, View> CLRTriggers { get; set; }
|
||||
|
||||
[SchemaNode("Triggers")]
|
||||
public SchemaList<Trigger, View> Triggers { get; set; }
|
||||
|
||||
[SchemaNode("Indexes", "Index")]
|
||||
public SchemaList<Index, View> Indexes { get; set; }
|
||||
|
||||
public override Boolean IsCodeType
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
string sql = ToSql();
|
||||
this.Indexes.ForEach(item =>
|
||||
{
|
||||
if (item.Status != ObjectStatus.Drop)
|
||||
{
|
||||
item.SetWasInsertInDiffList(ScriptAction.AddIndex);
|
||||
sql += item.ToSql();
|
||||
}
|
||||
}
|
||||
);
|
||||
this.Triggers.ForEach(item =>
|
||||
{
|
||||
if (item.Status != ObjectStatus.Drop)
|
||||
{
|
||||
item.SetWasInsertInDiffList(ScriptAction.AddTrigger);
|
||||
sql += item.ToSql();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
sql += this.ExtendedProperties.ToSql();
|
||||
return sql;
|
||||
}
|
||||
|
||||
public string ToSQLAlter()
|
||||
{
|
||||
return ToSQLAlter(false);
|
||||
}
|
||||
|
||||
public string ToSQLAlter(Boolean quitSchemaBinding)
|
||||
{
|
||||
return FormatCode.FormatAlter("VIEW", ToSql(), this, quitSchemaBinding);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Devuelve el schema de diferencias del Schema en formato SQL.
|
||||
/// </summary>
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
if (this.Status != ObjectStatus.Original)
|
||||
RootParent.ActionMessage.Add(this);
|
||||
|
||||
if (this.HasState(ObjectStatus.Drop))
|
||||
list.Add(Drop());
|
||||
if (this.HasState(ObjectStatus.Create))
|
||||
list.Add(Create());
|
||||
|
||||
if (this.HasState(ObjectStatus.Alter))
|
||||
{
|
||||
if (this.HasState(ObjectStatus.RebuildDependencies))
|
||||
list.AddRange(RebuildDependencies());
|
||||
if (this.HasState(ObjectStatus.Rebuild))
|
||||
{
|
||||
list.Add(Drop());
|
||||
list.Add(Create());
|
||||
}
|
||||
if (this.HasState(ObjectStatus.AlterBody))
|
||||
{
|
||||
int iCount = DependenciesCount;
|
||||
list.Add(ToSQLAlter(), iCount, ScriptAction.AlterView);
|
||||
}
|
||||
if (!this.GetWasInsertInDiffList(ScriptAction.DropFunction) && (!this.GetWasInsertInDiffList(ScriptAction.AddFunction)))
|
||||
list.AddRange(Indexes.ToSqlDiff());
|
||||
|
||||
list.AddRange(Triggers.ToSqlDiff());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
123
OpenDBDiff.Schema.SQLServer.Generates/Model/XMLSchema.cs
Normal file
123
OpenDBDiff.Schema.SQLServer.Generates/Model/XMLSchema.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using OpenDBDiff.Schema.Model;
|
||||
|
||||
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
|
||||
{
|
||||
public class XMLSchema : SQLServerSchemaBase
|
||||
{
|
||||
public XMLSchema(ISchemaBase parent)
|
||||
: base(parent, ObjectType.XMLSchema)
|
||||
{
|
||||
this.Dependencies = new List<ObjectDependency>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clona el objeto en una nueva instancia.
|
||||
/// </summary>
|
||||
public new XMLSchema Clone(ISchemaBase parent)
|
||||
{
|
||||
XMLSchema item = new XMLSchema(parent);
|
||||
item.Text = this.Text;
|
||||
item.Status = this.Status;
|
||||
item.Name = this.Name;
|
||||
item.Id = this.Id;
|
||||
item.Owner = this.Owner;
|
||||
item.Guid = this.Guid;
|
||||
item.Dependencies = this.Dependencies;
|
||||
return item;
|
||||
}
|
||||
|
||||
public List<ObjectDependency> Dependencies { get; set; }
|
||||
|
||||
public string Text { get; set; }
|
||||
|
||||
public override string ToSql()
|
||||
{
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.Append("CREATE XML SCHEMA COLLECTION ");
|
||||
sql.Append(this.FullName + " AS ");
|
||||
sql.Append("N'" + this.Text + "'");
|
||||
sql.Append("\r\nGO\r\n");
|
||||
return sql.ToString();
|
||||
}
|
||||
|
||||
public override string ToSqlAdd()
|
||||
{
|
||||
return ToSql();
|
||||
}
|
||||
|
||||
public override string ToSqlDrop()
|
||||
{
|
||||
return "DROP XML SCHEMA COLLECTION " + FullName + "\r\nGO\r\n";
|
||||
}
|
||||
|
||||
private SQLScriptList ToSQLChangeColumns()
|
||||
{
|
||||
Hashtable fields = new Hashtable();
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
if ((this.Status == ObjectStatus.Alter) || (this.Status == ObjectStatus.Rebuild))
|
||||
{
|
||||
foreach (ObjectDependency dependency in this.Dependencies)
|
||||
{
|
||||
ISchemaBase itemDepens = ((Database)this.Parent).Find(dependency.Name);
|
||||
if (dependency.IsCodeType)
|
||||
{
|
||||
list.AddRange(((ICode)itemDepens).Rebuild());
|
||||
}
|
||||
if (dependency.Type == ObjectType.Table)
|
||||
{
|
||||
Column column = ((Table)itemDepens).Columns[dependency.ColumnName];
|
||||
if ((column.Parent.Status != ObjectStatus.Drop) && (column.Parent.Status != ObjectStatus.Create) && ((column.Status != ObjectStatus.Create)))
|
||||
{
|
||||
if (!fields.ContainsKey(column.FullName))
|
||||
{
|
||||
if (column.HasToRebuildOnlyConstraint)
|
||||
column.Parent.Status = ObjectStatus.RebuildDependencies;
|
||||
list.AddRange(column.RebuildConstraint(true));
|
||||
list.Add("ALTER TABLE " + column.Parent.FullName + " ALTER COLUMN " + column.ToSQLRedefine(null, 0, "") + "\r\nGO\r\n", 0, ScriptAction.AlterColumn);
|
||||
/*Si la columna va a ser eliminada o la tabla va a ser reconstruida, no restaura la columna*/
|
||||
if ((column.Status != ObjectStatus.Drop) && (column.Parent.Status != ObjectStatus.Rebuild))
|
||||
list.AddRange(column.Alter(ScriptAction.AlterColumnRestore));
|
||||
fields.Add(column.FullName, column.FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Devuelve el schema de diferencias del Schema en formato SQL.
|
||||
/// </summary>
|
||||
public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection<ISchemaBase> schemas)
|
||||
{
|
||||
SQLScriptList list = new SQLScriptList();
|
||||
|
||||
if (this.Status == ObjectStatus.Drop)
|
||||
{
|
||||
list.Add(ToSqlDrop(), 0, ScriptAction.DropXMLSchema);
|
||||
}
|
||||
if (this.Status == ObjectStatus.Create)
|
||||
{
|
||||
list.Add(ToSql(), 0, ScriptAction.AddXMLSchema);
|
||||
}
|
||||
if (this.Status == ObjectStatus.Alter)
|
||||
{
|
||||
list.AddRange(ToSQLChangeColumns());
|
||||
list.Add(ToSqlDrop() + ToSql(), 0, ScriptAction.AddXMLSchema);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public bool Compare(XMLSchema obj)
|
||||
{
|
||||
if (obj == null) throw new ArgumentNullException("obj");
|
||||
if (!this.Text.Equals(obj.Text)) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user