Initial commit

This commit is contained in:
2021-08-26 20:59:17 +02:00
commit 3afa4c82ef
524 changed files with 52428 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareAssemblies : CompareBase<Assembly>
{
protected override void DoUpdate<Root>(SchemaList<Assembly, Root> originFields, Assembly node)
{
if (!node.Compare(originFields[node.FullName]))
{
Assembly newNode = (Assembly)node.Clone(originFields.Parent);
newNode.Status = ObjectStatus.Alter;
if (node.Text.Equals(originFields[node.FullName].Text))
{
if (!node.PermissionSet.Equals(originFields[node.FullName].PermissionSet))
newNode.Status += (int)ObjectStatus.PermissionSet;
if (!node.Owner.Equals(originFields[node.FullName].Owner))
newNode.Status += (int)ObjectStatus.ChangeOwner;
}
else
newNode.Status = ObjectStatus.Rebuild;
originFields[node.FullName].Files.ForEach(item =>
{
if (!newNode.Files.Contains(item.FullName))
newNode.Files.Add(new AssemblyFile(newNode, item, ObjectStatus.Drop));
else
item.Status = ObjectStatus.Alter;
});
newNode.Files.ForEach(item =>
{
if (!originFields[node.FullName].Files.Contains(item.FullName))
{
item.Status = ObjectStatus.Create;
}
});
CompareExtendedProperties(originFields[node.FullName], newNode);
originFields[node.FullName] = newNode;
}
}
protected override void DoNew<Root>(SchemaList<Assembly, Root> originFields, Assembly node)
{
bool pass = true;
Assembly newNode = (Assembly)node.Clone(originFields.Parent);
if ((((Database)newNode.RootParent).Info.Version == DatabaseInfo.SQLServerVersion.SQLServer2005)
&& (((Database)node.RootParent).Info.Version == DatabaseInfo.SQLServerVersion.SQLServer2008))
pass = node.FullName.Equals("Microsoft.SqlServer.Types");
if (pass)
{
newNode.Status = ObjectStatus.Create;
originFields.Add(newNode);
}
}
}
}

View File

@@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Generates;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal abstract class CompareBase<T> where T : ISchemaBase
{
protected virtual void DoUpdate<Root>(SchemaList<T, Root> originFields, T node) where Root : ISchemaBase
{
}
protected virtual void DoNew<Root>(SchemaList<T, Root> originFields, T node) where Root : ISchemaBase
{
T newNode = node;//.Clone(originFields.Parent);
newNode.Parent = originFields.Parent;
newNode.Status = ObjectStatus.Create;
originFields.Add(newNode);
}
protected void DoDelete(T node)
{
node.Status = ObjectStatus.Drop;
}
public void GenerateDifferences<Root>(SchemaList<T, Root> originFields, SchemaList<T, Root> destinationFields) where Root : ISchemaBase
{
bool has = true;
int destinationIndex = 0;
int originIndex = 0;
int destinationCount = destinationFields.Count;
int originCount = originFields.Count;
T node;
while (has)
{
has = false;
if (destinationCount > destinationIndex)
{
node = destinationFields[destinationIndex];
Generate.RaiseOnCompareProgress("Comparing Destination {0}: [{1}]", node.ObjectType, node.Name);
if (!originFields.Contains(node.FullName))
{
Generate.RaiseOnCompareProgress("Adding {0}: [{1}]", node.ObjectType, node.Name);
DoNew<Root>(originFields, node);
}
else
{
Generate.RaiseOnCompareProgress("Updating {0}: [{1}]", node.ObjectType, node.Name);
DoUpdate<Root>(originFields, node);
}
destinationIndex++;
has = true;
}
if (originCount > originIndex)
{
node = originFields[originIndex];
Generate.RaiseOnCompareProgress("Comparing Source {0}: [{1}]", node.ObjectType, node.Name);
if (!destinationFields.Contains(node.FullName))
{
Generate.RaiseOnCompareProgress("Deleting {0}: [{1}]", node.ObjectType, node.Name);
DoDelete(node);
}
originIndex++;
has = true;
}
}
}
protected static void CompareExtendedProperties(ISQLServerSchemaBase origin, ISQLServerSchemaBase destination)
{
List<ExtendedProperty> dropList = (from node in origin.ExtendedProperties
where !destination.ExtendedProperties.Exists(item => item.Name.Equals(node.Name, StringComparison.CurrentCultureIgnoreCase))
select node).ToList<ExtendedProperty>();
List<ExtendedProperty> addList = (from node in destination.ExtendedProperties
where !origin.ExtendedProperties.Exists(item => item.Name.Equals(node.Name, StringComparison.CurrentCultureIgnoreCase))
select node).ToList<ExtendedProperty>();
dropList.ForEach(item => { item.Status = ObjectStatus.Drop; });
addList.ForEach(item => { item.Status = ObjectStatus.Create; });
origin.ExtendedProperties.AddRange(addList);
}
}
}

View File

@@ -0,0 +1,18 @@
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareCLRFunction : CompareBase<CLRFunction>
{
protected override void DoUpdate<Root>(SchemaList<CLRFunction, Root> originFields, CLRFunction node)
{
if (!node.Compare(originFields[node.FullName]))
{
CLRFunction newNode = node; //.Clone(originFields.Parent);
newNode.Status = ObjectStatus.Alter;
originFields[node.FullName] = newNode;
}
}
}
}

View File

@@ -0,0 +1,18 @@
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareCLRStoredProcedure : CompareBase<CLRStoredProcedure>
{
protected override void DoUpdate<Root>(SchemaList<CLRStoredProcedure, Root> originFields, CLRStoredProcedure node)
{
if (!node.Compare(originFields[node.FullName]))
{
CLRStoredProcedure newNode = node; //.Clone(originFields.Parent);
newNode.Status = ObjectStatus.Alter;
originFields[node.FullName] = newNode;
}
}
}
}

View File

@@ -0,0 +1,19 @@
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareCLRTriggers : CompareBase<CLRTrigger>
{
protected override void DoUpdate<Root>(SchemaList<CLRTrigger, Root> originFields, CLRTrigger node)
{
if (!node.Compare(originFields[node.FullName]))
{
CLRTrigger newNode = node;
newNode.Status = ObjectStatus.Alter;
CompareExtendedProperties(newNode, originFields[node.FullName]);
originFields[node.FullName] = newNode;
}
}
}
}

View File

@@ -0,0 +1,91 @@
using System;
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
public class CompareColumns
{
public void GenerateDifferences<T>(Columns<T> originFields, Columns<T> destinationFields) where T : ISchemaBase
{
int restPosition = 0;
int sumPosition = 0;
foreach (Column node in originFields)
{
if (!destinationFields.Contains(node.FullName))
{
node.Status = ObjectStatus.Drop;
restPosition++;
}
else
originFields[node.FullName].Position -= restPosition;
}
foreach (Column node in destinationFields)
{
if (!originFields.Contains(node.FullName))
{
Column newNode = node.Clone(originFields.Parent);
if ((newNode.Position == 1) || ((newNode.DefaultConstraint == null) && (!newNode.IsNullable) && (!newNode.IsComputed) && (!newNode.IsIdentity) && (!newNode.IsIdentityForReplication)))
{
newNode.Status = ObjectStatus.Create;
newNode.Parent.Status = ObjectStatus.Rebuild;
}
else
newNode.Status = ObjectStatus.Create;
sumPosition++;
originFields.Add(newNode);
}
else
{
Column originField = originFields[node.FullName];
/*ColumnConstraint oldDefault = null;
if (originField.DefaultConstraint != null)
oldDefault = originField.DefaultConstraint.Clone(originField);*/
Boolean IsColumnEqual = Column.Compare(originField, node);
if ((!IsColumnEqual) || (originField.Position != node.Position))
{
if (Column.CompareIdentity(originField, node))
{
if (node.HasToRebuildOnlyConstraint)
{
node.Status = ObjectStatus.Alter;
if ((originField.IsNullable) && (!node.IsNullable))
node.Status += (int)ObjectStatus.Update;
}
else
{
if (node.HasToRebuild(originField.Position + sumPosition, originField.Type, originField.IsFileStream))
node.Status = ObjectStatus.Rebuild;
else
{
if (!IsColumnEqual)
{
node.Status = ObjectStatus.Alter;
if ((originField.IsNullable) && (!node.IsNullable))
node.Status += (int)ObjectStatus.Update;
}
}
}
if (node.Status != ObjectStatus.Rebuild)
{
if (!Column.CompareRule(originField, node))
{
node.Status += (int)ObjectStatus.Bind;
}
}
}
else
{
node.Status = ObjectStatus.Rebuild;
}
originFields[node.FullName] = node.Clone(originFields.Parent);
}
originFields[node.FullName].DefaultConstraint = CompareColumnsConstraints.GenerateDifferences(originField, node);
}
}
}
}
}

View File

@@ -0,0 +1,72 @@
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareColumnsConstraints : CompareBase<ColumnConstraint>
{
public static ColumnConstraint GenerateDifferences(Column originFields, Column destinationFields)
{
if ((originFields.DefaultConstraint == null) && (destinationFields.DefaultConstraint != null))
{
originFields.DefaultConstraint = destinationFields.DefaultConstraint.Clone(originFields);
originFields.DefaultConstraint.Status = ObjectStatus.Create;
originFields.DefaultConstraint.Parent.Status = ObjectStatus.Original;
originFields.DefaultConstraint.Parent.Parent.Status = ObjectStatus.Alter;
}
else
{
if ((originFields.DefaultConstraint != null) && (destinationFields.DefaultConstraint != null))
{
if (!ColumnConstraint.Compare(originFields.DefaultConstraint, destinationFields.DefaultConstraint))
{
originFields.DefaultConstraint = destinationFields.DefaultConstraint.Clone(originFields);
//Indico que hay un ALTER TABLE, pero sobre la columna, no seteo ningun estado.
originFields.DefaultConstraint.Status = ObjectStatus.Alter;
originFields.DefaultConstraint.Parent.Status = ObjectStatus.Original;
originFields.DefaultConstraint.Parent.Parent.Status = ObjectStatus.Alter;
}
}
else
if ((originFields.DefaultConstraint != null) && (destinationFields.DefaultConstraint == null))
{
originFields.DefaultConstraint.Status = ObjectStatus.Drop;
originFields.DefaultConstraint.Parent.Status = ObjectStatus.Original;
originFields.DefaultConstraint.Parent.Parent.Status = ObjectStatus.Alter;
}
}
/*foreach (ColumnConstraint node in destinationFields)
{
if (!originFields.Exists(node.FullName))
{
node.Status = ObjectStatusType.CreateStatus;
originFields.Parent.Status = ObjectStatusType.OriginalStatus;
originFields.Parent.Parent.Status = ObjectStatusType.AlterStatus;
originFields.Add(node);
}
else
{
if (!ColumnConstraint.Compare(originFields[node.FullName], node))
{
ColumnConstraint newNode = node.Clone(originFields.Parent);
//Indico que hay un ALTER TABLE, pero sobre la columna, no seteo ningun estado.
newNode.Status = ObjectStatusType.AlterStatus;
newNode.Parent.Status = ObjectStatusType.OriginalStatus;
newNode.Parent.Parent.Status = ObjectStatusType.AlterStatus;
originFields[node.FullName] = newNode;
}
}
}
MarkDrop(originFields, destinationFields, node =>
{
node.Status = ObjectStatusType.DropStatus;
originFields.Parent.Status = ObjectStatusType.OriginalStatus;
originFields.Parent.Parent.Status = ObjectStatusType.AlterStatus;
}
);
*/
return originFields.DefaultConstraint;
}
}
}

View File

@@ -0,0 +1,40 @@
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareConstraints : CompareBase<Constraint>
{
protected override void DoUpdate<Root>(SchemaList<Constraint, Root> originFields, Constraint node)
{
Constraint origin = originFields[node.FullName];
if (!Constraint.Compare(origin, node))
{
Constraint newNode = (Constraint)node.Clone(originFields.Parent);
if (node.IsDisabled == origin.IsDisabled)
{
newNode.Status = ObjectStatus.Alter;
}
else
newNode.Status = ObjectStatus.Alter + (int)ObjectStatus.Disabled;
originFields[node.FullName] = newNode;
}
else
{
if (node.IsDisabled != origin.IsDisabled)
{
Constraint newNode = (Constraint)node.Clone(originFields.Parent);
newNode.Status = ObjectStatus.Disabled;
originFields[node.FullName] = newNode;
}
}
}
protected override void DoNew<Root>(SchemaList<Constraint, Root> originFields, Constraint node)
{
Constraint newNode = (Constraint)node.Clone(originFields.Parent);
newNode.Status = ObjectStatus.Create;
originFields.Add(newNode);
}
}
}

View File

@@ -0,0 +1,28 @@
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareDDLTriggers : CompareBase<Trigger>
{
protected override void DoUpdate<Root>(SchemaList<Trigger, Root> originFields, Trigger node)
{
if (!node.Compare(originFields[node.FullName]))
{
Trigger newNode = (Trigger)node.Clone(originFields.Parent);
if (!newNode.Text.Equals(originFields[node.FullName].Text))
newNode.Status = ObjectStatus.Alter;
if (node.IsDisabled != originFields[node.FullName].IsDisabled)
newNode.Status = newNode.Status + (int)ObjectStatus.Disabled;
originFields[node.FullName] = newNode;
}
}
protected override void DoNew<Root>(SchemaList<Trigger, Root> originFields, Trigger node)
{
Trigger newNode = (Trigger)node.Clone(originFields.Parent);
newNode.Status = ObjectStatus.Create;
originFields.Add(newNode);
}
}
}

View File

@@ -0,0 +1,54 @@
using OpenDBDiff.Schema.Misc;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
using System;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal static class CompareDatabase
{
/// <summary>
/// Generates the differences to migrate a schema from origin to destination
/// </summary>
/// <param name="origin">The Origin schema is the schema before our generated actions are applied.</param>
/// <param name="destination">The Destination schema is the schema after our actions are applied.</param>
/// <returns></returns>
/// <exception cref="SchemaException"></exception>
public static Database GenerateDifferences(Database origin, Database destination)
{
try
{
Database data = origin;
(new CompareTables()).GenerateDifferences<Database>(origin.Tables, destination.Tables);
(new CompareAssemblies()).GenerateDifferences<Database>(origin.Assemblies, destination.Assemblies);
(new CompareUserDataTypes()).GenerateDifferences<Database>(origin.UserTypes, destination.UserTypes);
(new CompareXMLSchemas()).GenerateDifferences<Database>(origin.XmlSchemas, destination.XmlSchemas);
(new CompareSchemas()).GenerateDifferences<Database>(origin.Schemas, destination.Schemas);
(new CompareFileGroups()).GenerateDifferences<Database>(origin.FileGroups, destination.FileGroups);
(new CompareRules()).GenerateDifferences<Database>(origin.Rules, destination.Rules);
(new CompareDDLTriggers()).GenerateDifferences<Database>(origin.DDLTriggers, destination.DDLTriggers);
(new CompareSynonyms()).GenerateDifferences<Database>(origin.Synonyms, destination.Synonyms);
(new CompareUsers()).GenerateDifferences<Database>(origin.Users, destination.Users);
(new CompareStoredProcedures()).GenerateDifferences<Database>(origin.Procedures, destination.Procedures);
(new CompareCLRStoredProcedure()).GenerateDifferences<Database>(origin.CLRProcedures, destination.CLRProcedures);
(new CompareCLRFunction()).GenerateDifferences<Database>(origin.CLRFunctions, destination.CLRFunctions);
(new CompareViews()).GenerateDifferences<Database>(origin.Views, destination.Views);
(new CompareFunctions()).GenerateDifferences<Database>(origin.Functions, destination.Functions);
(new CompareRoles()).GenerateDifferences<Database>(origin.Roles, destination.Roles);
(new ComparePartitionFunction()).GenerateDifferences<Database>(origin.PartitionFunctions, destination.PartitionFunctions);
(new ComparePartitionSchemes()).GenerateDifferences<Database>(origin.PartitionSchemes, destination.PartitionSchemes);
(new CompareTableType()).GenerateDifferences<Database>(origin.TablesTypes, destination.TablesTypes);
(new CompareFullText()).GenerateDifferences<Database>(origin.FullText, destination.FullText);
data.SourceInfo = destination.Info;
return data;
}
catch (SchemaException)
{
throw;
}
catch (Exception ex)
{
throw new SchemaException(ex.Message, ex);
}
}
}
}

View File

@@ -0,0 +1,44 @@
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareFileGroups : CompareBase<FileGroup>
{
protected override void DoNew<Root>(SchemaList<FileGroup, Root> originFields, FileGroup node)
{
FileGroup newNode = (FileGroup)node.Clone(originFields.Parent);
newNode.Status = ObjectStatus.Create;
/*If the Logical File Name exists in another filegroup,
* we must change the new Logical File Name.
*/
originFields.ForEach(file =>
{
if (file.Status != ObjectStatus.Drop)
{
file.Files.ForEach(group =>
{
newNode.Files.ForEach(ngroup =>
{
if (group.CompareFullNameTo(group.FullName, ngroup.FullName) == 0)
{
newNode.Files[ngroup.FullName].Name = group.Name + "_2";
}
});
});
}
});
originFields.Add(newNode);
}
protected override void DoUpdate<Root>(SchemaList<FileGroup, Root> originFields, FileGroup node)
{
if (!FileGroup.Compare(node, originFields[node.FullName]))
{
FileGroup newNode = (FileGroup)node.Clone(originFields.Parent);
newNode.Status = ObjectStatus.Alter;
originFields[node.FullName] = newNode;
}
}
}
}

View File

@@ -0,0 +1,23 @@
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareFullText : CompareBase<FullText>
{
protected override void DoUpdate<Root>(SchemaList<FullText, Root> originFields, FullText node)
{
if (!node.Compare(originFields[node.FullName]))
{
FullText newNode = node; //.Clone(originFields.Parent);
if (node.IsDefault != originFields[node.FullName].IsDefault)
newNode.Status += (int)ObjectStatus.Disabled;
if (!node.Owner.Equals(originFields[node.FullName].Owner))
newNode.Status += (int)ObjectStatus.ChangeOwner;
if (node.IsAccentSensity != originFields[node.FullName].IsAccentSensity)
newNode.Status += (int)ObjectStatus.Alter;
originFields[node.FullName] = newNode;
}
}
}
}

View File

@@ -0,0 +1,28 @@
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareFullTextIndex : CompareBase<FullTextIndex>
{
protected override void DoNew<Root>(SchemaList<FullTextIndex, Root> originFields, FullTextIndex node)
{
FullTextIndex newNode = (FullTextIndex)node.Clone(originFields.Parent);
newNode.Status = ObjectStatus.Create;
originFields.Add(newNode);
}
protected override void DoUpdate<Root>(SchemaList<FullTextIndex, Root> originFields, FullTextIndex node)
{
if (!node.Compare(originFields[node.FullName]))
{
FullTextIndex newNode = (FullTextIndex)node.Clone(originFields.Parent);
if (node.IsDisabled != originFields[node.FullName].IsDisabled)
newNode.Status += (int)ObjectStatus.Disabled;
else
newNode.Status += (int)ObjectStatus.Alter;
originFields[node.FullName] = newNode;
}
}
}
}

View File

@@ -0,0 +1,44 @@
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareFunctions : CompareBase<Function>
{
protected override void DoNew<Root>(SchemaList<Function, Root> originFields, Function node)
{
Function newNode = (Function)node.Clone(originFields.Parent);
newNode.Status = ObjectStatus.Create;
originFields.Add(newNode);
newNode.DependenciesIn.ForEach(dep =>
{
ISchemaBase item = ((Database)((ISchemaBase)originFields.Parent)).Find(dep);
if (item != null)
{
if (item.IsCodeType)
((ICode)item).DependenciesOut.Add(newNode.FullName);
}
}
);
}
protected override void DoUpdate<Root>(SchemaList<Function, Root> originFields, Function node)
{
if (!node.Compare(originFields[node.FullName]))
{
Function newNode = (Function)node.Clone(originFields.Parent);
newNode.DependenciesIn.AddRange(originFields[node.FullName].DependenciesIn);
newNode.DependenciesOut.AddRange(originFields[node.FullName].DependenciesOut);
newNode.Status = ObjectStatus.Alter;
if (newNode.IsSchemaBinding)
newNode.Status += (int)ObjectStatus.RebuildDependencies;
if (newNode.HasToRebuild)
newNode.Status += (int)ObjectStatus.Rebuild;
else
newNode.Status += (int)ObjectStatus.AlterBody;
originFields[node.FullName] = newNode;
}
}
}
}

View File

@@ -0,0 +1,30 @@
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareIndexes : CompareBase<Index>
{
protected override void DoNew<Root>(SchemaList<Index, Root> originFields, Index node)
{
Index newNode = (Index)node.Clone(originFields.Parent);
newNode.Status = ObjectStatus.Create;
originFields.Add(newNode);
}
protected override void DoUpdate<Root>(SchemaList<Index, Root> originFields, Index node)
{
if (!Index.Compare(node, originFields[node.FullName]))
{
Index newNode = (Index)node.Clone(originFields.Parent);
if (!Index.CompareExceptIsDisabled(node, originFields[node.FullName]))
{
newNode.Status = ObjectStatus.Alter;
}
else
newNode.Status = ObjectStatus.Disabled;
originFields[node.FullName] = newNode;
}
}
}
}

View File

@@ -0,0 +1,31 @@
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class ComparePartitionFunction : CompareBase<PartitionFunction>
{
protected override void DoUpdate<Root>(SchemaList<PartitionFunction, Root> originFields, PartitionFunction node)
{
if (!PartitionFunction.Compare(node, originFields[node.FullName]))
{
PartitionFunction newNode = node; //.Clone(originFields.Parent);
newNode.Status = ObjectStatus.Rebuild;
originFields[node.FullName] = newNode;
}
else
{
if (!PartitionFunction.CompareValues(node, originFields[node.FullName]))
{
PartitionFunction newNode = node.Clone(originFields.Parent);
if (newNode.Values.Count == originFields[node.FullName].Values.Count)
newNode.Status = ObjectStatus.Rebuild;
else
newNode.Status = ObjectStatus.Alter;
newNode.Old = originFields[node.FullName].Clone(originFields.Parent);
originFields[node.FullName] = newNode;
}
}
}
}
}

View File

@@ -0,0 +1,18 @@
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class ComparePartitionSchemes : CompareBase<PartitionScheme>
{
protected override void DoUpdate<Root>(SchemaList<PartitionScheme, Root> originFields, PartitionScheme node)
{
if (!PartitionScheme.Compare(node, originFields[node.FullName]))
{
PartitionScheme newNode = node; //.Clone(originFields.Parent);
newNode.Status = ObjectStatus.Rebuild;
originFields[node.FullName] = newNode;
}
}
}
}

View File

@@ -0,0 +1,18 @@
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareRoles : CompareBase<Role>
{
protected override void DoUpdate<Root>(SchemaList<Role, Root> originFields, Role node)
{
if (!node.Compare(originFields[node.FullName]))
{
Role newNode = node;
newNode.Status = ObjectStatus.Alter;
originFields[node.FullName] = newNode;
}
}
}
}

View File

@@ -0,0 +1,25 @@
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareRules : CompareBase<Rule>
{
protected override void DoUpdate<Root>(SchemaList<Rule, Root> originFields, Rule node)
{
if (!node.Compare(originFields[node.FullName]))
{
Rule newNode = node.Clone(originFields.Parent);
newNode.Status = ObjectStatus.Alter;
originFields[node.FullName] = newNode;
}
}
protected override void DoNew<Root>(SchemaList<Rule, Root> originFields, Rule node)
{
Rule newNode = node.Clone(originFields.Parent);
newNode.Status = ObjectStatus.Create;
originFields.Add(newNode);
}
}
}

View File

@@ -0,0 +1,7 @@
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareSchemas : CompareBase<Model.Schema>
{
}
}

View File

@@ -0,0 +1,27 @@
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareStoredProcedures : CompareBase<StoredProcedure>
{
protected override void DoUpdate<Root>(SchemaList<StoredProcedure, Root> originFields, StoredProcedure node)
{
if (!node.Compare(originFields[node.FullName]))
{
StoredProcedure newNode = node; //.Clone(originFields.Parent);
if (node.CompareExceptWhitespace(originFields[node.FullName]))
{
newNode.Status = ObjectStatus.AlterWhitespace;
}
else
{
newNode.Status = ObjectStatus.Alter;
}
originFields[node.FullName] = newNode;
}
}
}
}

View File

@@ -0,0 +1,18 @@
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareSynonyms : CompareBase<Synonym>
{
protected override void DoUpdate<Root>(SchemaList<Synonym, Root> originFields, Synonym node)
{
if (!Synonym.Compare(node, originFields[node.FullName]))
{
Synonym newNode = node; //.Clone(originFields.Parent);
newNode.Status = ObjectStatus.Alter;
originFields[node.FullName] = newNode;
}
}
}
}

View File

@@ -0,0 +1,44 @@
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareTableType : CompareBase<TableType>
{
protected override void DoUpdate<Root>(SchemaList<TableType, Root> originFields, TableType node)
{
if (node.Status != ObjectStatus.Drop)
{
TableType tablaOriginal = originFields[node.FullName];
(new CompareColumns()).GenerateDifferences<TableType>(tablaOriginal.Columns, node.Columns);
(new CompareConstraints()).GenerateDifferences<TableType>(tablaOriginal.Constraints, node.Constraints);
(new CompareIndexes()).GenerateDifferences<TableType>(tablaOriginal.Indexes, node.Indexes);
}
}
/*public static void GenerateDifferences(SchemaList<TableType, Database> originTables, SchemaList<TableType, Database> destinationTables)
{
MarkDrop(originTables, destinationTables);
foreach (TableType node in destinationTables)
{
if (!originTables.Exists(node.FullName))
{
node.Status = ObjectStatusType.CreateStatus;
node.Parent = originTables.Parent;
originTables.Add(node);
}
else
{
if (node.Status != ObjectStatusType.DropStatus)
{
TableType tablaOriginal = originTables[node.FullName];
CompareColumns.GenerateDifferences<TableType>(tablaOriginal.Columns, node.Columns);
CompareConstraints.GenerateDifferences<TableType>(tablaOriginal.Constraints, node.Constraints);
CompareIndexes.GenerateDifferences(tablaOriginal.Indexes, node.Indexes);
}
}
}
}*/
}
}

View File

@@ -0,0 +1,92 @@
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareTables : CompareBase<Table>
{
protected override void DoUpdate<Root>(SchemaList<Table, Root> originFields, Table node)
{
if (node.Status != ObjectStatus.Drop)
{
Table tablaOriginal = originFields[node.FullName];
tablaOriginal.OriginalTable = (Table)originFields[node.FullName].Clone((Database)tablaOriginal.Parent);
(new CompareColumns()).GenerateDifferences<Table>(tablaOriginal.Columns, node.Columns);
(new CompareConstraints()).GenerateDifferences<Table>(tablaOriginal.Constraints, node.Constraints);
(new CompareIndexes()).GenerateDifferences<Table>(tablaOriginal.Indexes, node.Indexes);
(new CompareTablesOptions()).GenerateDifferences<Table>(tablaOriginal.Options, node.Options);
(new CompareTriggers()).GenerateDifferences<Table>(tablaOriginal.Triggers, node.Triggers);
(new CompareCLRTriggers()).GenerateDifferences<Table>(tablaOriginal.CLRTriggers, node.CLRTriggers);
(new CompareFullTextIndex()).GenerateDifferences<Table>(tablaOriginal.FullTextIndex, node.FullTextIndex);
if (!Table.CompareFileGroup(tablaOriginal, node))
{
tablaOriginal.FileGroup = node.FileGroup;
/*Esto solo aplica a las tablas heap, el resto hace el campo en el filegroup del indice clustered*/
if (!tablaOriginal.HasClusteredIndex)
tablaOriginal.Status = ObjectStatus.Rebuild;
}
if (!Table.CompareFileGroupText(tablaOriginal, node))
{
tablaOriginal.FileGroupText = node.FileGroupText;
tablaOriginal.Status = ObjectStatus.Rebuild;
}
if (node.HasChangeTracking != tablaOriginal.HasChangeTracking)
{
tablaOriginal.HasChangeTracking = node.HasChangeTracking;
tablaOriginal.HasChangeTrackingTrackColumn = node.HasChangeTrackingTrackColumn;
tablaOriginal.Status += (int)ObjectStatus.Disabled;
}
}
}
/// <summary>
/// Compara las colecciones de tablas de dos bases diferentes y marca el estado de los objetos
/// dependiendo si existen o si deben borrarse.
/// </summary>
/// <param name="originTables"></param>
/// Tablas originales, donde se guardaran los estados de las tablas.
/// <param name="destinationTables">
/// Tablas comparativas, que se usa para comparar con la base original.
/// </param>
/*public static void GenerateDifferences(SchemaList<Table, Database> originTables, SchemaList<Table, Database> destinationTables)
{
MarkDrop(originTables, destinationTables);
foreach (Table node in destinationTables)
{
if (!originTables.Exists(node.FullName))
{
node.Status = ObjectStatusType.CreateStatus;
node.Parent = originTables.Parent;
originTables.Add(node);
}
else
{
if (node.Status != ObjectStatusType.DropStatus)
{
Table tablaOriginal = originTables[node.FullName];
tablaOriginal.OriginalTable = (Table)originTables[node.FullName].Clone((Database)tablaOriginal.Parent);
CompareColumns.GenerateDifferences<Table>(tablaOriginal.Columns, node.Columns);
CompareConstraints.GenerateDifferences<Table>(tablaOriginal.Constraints, node.Constraints);
CompareIndexes.GenerateDifferences(tablaOriginal.Indexes, node.Indexes);
CompareTablesOptions.GenerateDifferences(tablaOriginal.Options, node.Options);
(new CompareTriggers()).GenerateDifferences<Table>(tablaOriginal.Triggers, node.Triggers);
(new CompareCLRTriggers()).GenerateDifferences<Table>(tablaOriginal.CLRTriggers, node.CLRTriggers);
if (!Table.CompareFileGroup(tablaOriginal, node))
{
tablaOriginal.FileGroup = node.FileGroup;
//Esto solo aplica a las tablas heap, el resto hace el campo en el filegroup del indice clustered
if (!tablaOriginal.HasClusteredIndex)
tablaOriginal.Status = ObjectStatusType.RebuildStatus;
}
if (!Table.CompareFileGroupText(tablaOriginal, node))
{
tablaOriginal.FileGroupText = node.FileGroupText;
tablaOriginal.Status = ObjectStatusType.RebuildStatus;
}
}
}
}
}*/
}
}

View File

@@ -0,0 +1,25 @@
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareTablesOptions : CompareBase<TableOption>
{
protected override void DoNew<Root>(SchemaList<TableOption, Root> originFields, TableOption node)
{
TableOption newNode = (TableOption)node.Clone(originFields.Parent);
newNode.Status = ObjectStatus.Create;
originFields.Add(newNode);
}
protected override void DoUpdate<Root>(SchemaList<TableOption, Root> originFields, TableOption node)
{
if (!TableOption.Compare(node, originFields[node.FullName]))
{
TableOption newNode = (TableOption)node.Clone(originFields.Parent);
newNode.Status = ObjectStatus.Alter;
originFields[node.FullName] = newNode;
}
}
}
}

View File

@@ -0,0 +1,28 @@
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareTriggers : CompareBase<Trigger>
{
protected override void DoNew<Root>(SchemaList<Trigger, Root> originFields, Trigger node)
{
Trigger newNode = (Trigger)node.Clone(originFields.Parent);
newNode.Status = ObjectStatus.Create;
originFields.Add(newNode);
}
protected override void DoUpdate<Root>(SchemaList<Trigger, Root> originFields, Trigger node)
{
if (!node.Compare(originFields[node.FullName]))
{
Trigger newNode = (Trigger)node.Clone(originFields.Parent);
if (!newNode.Text.Equals(originFields[node.FullName].Text))
newNode.Status = ObjectStatus.Alter;
if (node.IsDisabled != originFields[node.FullName].IsDisabled)
newNode.Status = newNode.Status + (int)ObjectStatus.Disabled;
originFields[node.FullName] = newNode;
}
}
}
}

View File

@@ -0,0 +1,51 @@
using System;
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareUserDataTypes : CompareBase<UserDataType>
{
protected override void DoNew<Root>(SchemaList<UserDataType, Root> originFields, UserDataType node)
{
UserDataType newNode = (UserDataType)node.Clone(originFields.Parent);
newNode.Status = ObjectStatus.Create;
Boolean HasAssembly = originFields.Exists(item => item.AssemblyFullName.Equals(node.AssemblyFullName) && item.IsAssembly);
if (HasAssembly)
newNode.Status += (int)ObjectStatus.DropOlder;
originFields.Add(newNode);
}
protected override void DoUpdate<Root>(SchemaList<UserDataType, Root> originFields, UserDataType node)
{
if (!node.Compare(originFields[node.FullName]))
{
UserDataType newNode = (UserDataType)node.Clone(originFields.Parent);
newNode.Dependencies.AddRange(originFields[node.FullName].Dependencies);
if (!UserDataType.CompareDefault(node, originFields[node.FullName]))
{
if (!String.IsNullOrEmpty(node.Default.Name))
newNode.Default.Status = ObjectStatus.Create;
else
newNode.Default.Status = ObjectStatus.Drop;
newNode.Status = ObjectStatus.Alter;
}
else
{
if (!UserDataType.CompareRule(node, originFields[node.FullName]))
{
if (!String.IsNullOrEmpty(node.Rule.Name))
newNode.Rule.Status = ObjectStatus.Create;
else
newNode.Rule.Status = ObjectStatus.Drop;
newNode.Status = ObjectStatus.Alter;
}
else
newNode.Status = ObjectStatus.Rebuild;
}
originFields[node.FullName] = newNode;
}
}
}
}

View File

@@ -0,0 +1,8 @@
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareUsers : CompareBase<User>
{
}
}

View File

@@ -0,0 +1,52 @@
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareViews : CompareBase<View>
{
protected override void DoUpdate<Root>(SchemaList<View, Root> originFields, View node)
{
View original = originFields[node.FullName];
if (!node.Compare(original))
{
View newNode = (View)node.Clone(originFields.Parent);
newNode.DependenciesOut.AddRange(original.DependenciesOut);
newNode.DependenciesIn.AddRange(original.DependenciesIn);
newNode.Status = ObjectStatus.Alter;
newNode.Indexes = original.Indexes;
newNode.Triggers = original.Triggers;
if (newNode.IsSchemaBinding)
newNode.Status += (int)ObjectStatus.RebuildDependencies;
if (newNode.HasToRebuild)
newNode.Status += (int)ObjectStatus.Rebuild;
else
newNode.Status += (int)ObjectStatus.AlterBody;
originFields[node.FullName] = newNode;
original = newNode;
}
(new CompareIndexes()).GenerateDifferences<View>(original.Indexes, node.Indexes);
(new CompareTriggers()).GenerateDifferences<View>(original.Triggers, node.Triggers);
}
protected override void DoNew<Root>(SchemaList<View, Root> originFields, View node)
{
View newNode = (View)node.Clone(originFields.Parent);
newNode.Status = ObjectStatus.Create;
originFields.Add(newNode);
newNode.DependenciesIn.ForEach(dep =>
{
ISchemaBase item = ((Database)((ISchemaBase)originFields.Parent)).Find(dep);
if (item != null)
{
if (item.IsCodeType)
((ICode)item).DependenciesOut.Add(newNode.FullName);
}
}
);
}
}
}

View File

@@ -0,0 +1,18 @@
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Compare
{
internal class CompareXMLSchemas : CompareBase<XMLSchema>
{
protected override void DoUpdate<Root>(SchemaList<XMLSchema, Root> originFields, XMLSchema node)
{
if (!node.Compare(originFields[node.FullName]))
{
XMLSchema newNode = node.Clone(originFields.Parent);
newNode.Status = ObjectStatus.Alter;
originFields[node.FullName] = newNode;
}
}
}
}

View File

@@ -0,0 +1,191 @@
using OpenDBDiff.Schema.Errors;
using OpenDBDiff.Schema.Events;
using OpenDBDiff.Schema.Misc;
using OpenDBDiff.Schema.SQLServer.Generates.Compare;
using OpenDBDiff.Schema.SQLServer.Generates.Generates.Util;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Options;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class Generate
{
private readonly List<MessageLog> messages;
private ProgressEventArgs currentlyReading;
public Generate()
{
messages = new List<MessageLog>();
OnReading += Generate_OnReading;
}
public static int MaxValue
{
get { return Constants.READING_MAX; }
}
public string ConnectionString { get; set; }
private string Name
{
get
{
string name;
using (var conn = new SqlConnection(ConnectionString))
{
name = conn.Database;
}
return name;
}
}
public SqlOption Options { get; set; }
private event ProgressEventHandler.ProgressHandler OnReading;
public event ProgressEventHandler.ProgressHandler OnProgress;
private void Generate_OnReading(ProgressEventArgs e)
{
if (OnProgress != null) OnProgress(e);
}
public void RaiseOnReading(ProgressEventArgs e)
{
this.currentlyReading = e;
if (OnReading != null) OnReading(e);
}
public void RaiseOnReadingOne(object name)
{
if (name != null && this.OnReading != null && this.currentlyReading != null)
{
var eOne = new ProgressEventArgs(this.currentlyReading.Message, this.currentlyReading.Progress);
eOne.Message = eOne.Message.Replace("...", String.Format(": [{0}]", name));
this.OnReading(eOne);
}
}
/// <summary>
/// Genera el schema de la base de datos seleccionada y devuelve un objeto Database.
/// </summary>
public Database Process()
{
string error = "";
var databaseSchema = new Database();
//tables.OnTableProgress += new Progress.ProgressHandler(tables_OnTableProgress);
databaseSchema.Options = Options;
databaseSchema.Name = Name;
databaseSchema.Info = (new GenerateDatabase(ConnectionString, Options)).Get(databaseSchema);
/*Thread t1 = new Thread(delegate()
{
try
{*/
(new GenerateRules(this)).Fill(databaseSchema, ConnectionString);
(new GenerateTables(this)).Fill(databaseSchema, ConnectionString, messages);
(new GenerateViews(this)).Fill(databaseSchema, ConnectionString, messages);
if (Options.Ignore.FilterIndex)
{
(new GenerateIndex(this)).Fill(databaseSchema, ConnectionString);
(new GenerateFullTextIndex(this)).Fill(databaseSchema, ConnectionString);
}
(new GenerateUserDataTypes(this)).Fill(databaseSchema, ConnectionString, messages);
(new GenerateXMLSchemas(this)).Fill(databaseSchema, ConnectionString);
(new GenerateSchemas(this)).Fill(databaseSchema, ConnectionString);
/*}
catch (Exception ex)
{
error = ex.StackTrace;
}
});
Thread t2 = new Thread(delegate()
{
try
{*/
//not supported in azure yet
if (databaseSchema.Info.Version != DatabaseInfo.SQLServerVersion.SQLServerAzure10)
{
(new GeneratePartitionFunctions(this)).Fill(databaseSchema, ConnectionString);
(new GeneratePartitionScheme(this)).Fill(databaseSchema, ConnectionString);
(new GenerateFileGroups(this)).Fill(databaseSchema, ConnectionString);
}
(new GenerateDDLTriggers(this)).Fill(databaseSchema, ConnectionString);
(new GenerateSynonyms(this)).Fill(databaseSchema, ConnectionString);
//not supported in azure yet
if (databaseSchema.Info.Version != DatabaseInfo.SQLServerVersion.SQLServerAzure10)
{
(new GenerateAssemblies(this)).Fill(databaseSchema, ConnectionString);
(new GenerateFullText(this)).Fill(databaseSchema, ConnectionString);
}
/*}
catch (Exception ex)
{
error = ex.StackTrace;
}
});
Thread t3 = new Thread(delegate()
{
try
{*/
(new GenerateStoredProcedures(this)).Fill(databaseSchema, ConnectionString);
(new GenerateFunctions(this)).Fill(databaseSchema, ConnectionString);
(new GenerateTriggers(this)).Fill(databaseSchema, ConnectionString, messages);
(new GenerateTextObjects(this)).Fill(databaseSchema, ConnectionString);
(new GenerateUsers(this)).Fill(databaseSchema, ConnectionString);
/*}
catch (Exception ex)
{
error = ex.StackTrace;
}
});
t1.Start();
t2.Start();
t3.Start();
t1.Join();
t2.Join();
t3.Join();*/
if (String.IsNullOrEmpty(error))
{
/*Las propiedades extendidas deben ir despues de haber capturado el resto de los objetos de la base*/
(new GenerateExtendedProperties(this)).Fill(databaseSchema, ConnectionString, messages);
databaseSchema.BuildDependency();
return databaseSchema;
}
else
throw new SchemaException(error);
}
private void tables_OnTableProgress(object sender, ProgressEventArgs e)
{
ProgressEventHandler.RaiseOnChange(e);
}
// TODO: Static because Compare method is static; static events are not my favorite
public static event ProgressEventHandler.ProgressHandler OnCompareProgress;
internal static void RaiseOnCompareProgress(string formatString, params object[] formatParams)
{
OnCompareProgress?.Invoke(new ProgressEventArgs(String.Format(formatString, formatParams), -1));
}
/// <summary>
/// Generates the differences to migrate a schema from origin to destination
/// </summary>
/// <param name="origin">The Origin schema is the schema before our generated actions are applied.</param>
/// <param name="destination">The Destination schema is the schema after our actions are applied.</param>
/// <returns></returns>
public static Database Compare(Database origin, Database destination)
{
Database merge = CompareDatabase.GenerateDifferences(origin, destination);
return merge;
}
}
}

View File

@@ -0,0 +1,103 @@
using System;
using System.Data.SqlClient;
using OpenDBDiff.Schema.SQLServer.Generates.Generates.Util;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GenerateAssemblies
{
private Generate root;
public GenerateAssemblies(Generate root)
{
this.root = root;
}
private static string GetSQLFiles()
{
return SQLQueries.SQLQueryFactory.Get("GetAssemblyFiles");
}
private static string GetSQL()
{
return SQLQueries.SQLQueryFactory.Get("GetAssemblies");
}
private static string ToHex(byte[] stream)
{
return ByteToHexEncoder.ByteArrayToHex(stream);
}
private static void FillFiles(Database database, string connectionString)
{
if (database.Options.Ignore.FilterAssemblies)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(GetSQLFiles(), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
if (((int)reader["FileId"]) != 1)
{
Assembly assem = database.Assemblies[reader["Name"].ToString()];
AssemblyFile file = new AssemblyFile(assem, reader["FileName"].ToString(), ToHex((byte[])reader["FileContent"]));
assem.Files.Add(file);
}
}
}
}
}
}
}
public void Fill(Database database, string connectionString)
{
int lastViewId = 0;
if (database.Options.Ignore.FilterAssemblies)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(GetSQL(), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
Assembly item = null;
while (reader.Read())
{
if (lastViewId != (int)reader["assembly_id"])
{
item = new Assembly(database)
{
Id = (int)reader["assembly_id"],
Name = reader["Name"].ToString(),
Owner = reader["Owner"].ToString(),
CLRName = reader["clr_name"].ToString(),
PermissionSet = reader["permission_set_desc"].ToString(),
Text = ToHex((byte[])reader["content"]),
Visible = (bool)reader["is_visible"]
};
lastViewId = item.Id;
database.Assemblies.Add(item);
}
if (!String.IsNullOrEmpty(reader["Dependency"].ToString()))
item.DependenciesOut.Add(reader["Dependency"].ToString());
if (!String.IsNullOrEmpty(reader["ObjectDependency"].ToString()))
item.DependenciesOut.Add(reader["ObjectDependency"].ToString());
if (!String.IsNullOrEmpty(reader["UDTName"].ToString()))
item.DependenciesOut.Add(reader["UDTName"].ToString());
}
}
}
FillFiles(database, connectionString);
}
}
}
}
}

View File

@@ -0,0 +1,303 @@
using System;
using System.Data.SqlClient;
using System.Text;
using OpenDBDiff.Schema.Events;
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands;
using OpenDBDiff.Schema.SQLServer.Generates.Generates.Util;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GenerateConstraint
{
private Generate root;
public GenerateConstraint(Generate root)
{
this.root = root;
}
#region Check Functions...
public void FillCheck(Database database, string connectionString)
{
int parentId = 0;
ISchemaBase table = null;
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(ConstraintSQLCommand.GetCheck(database.Info.Version), conn))
{
root.RaiseOnReading(new ProgressEventArgs("Reading constraint...", Constants.READING_CONSTRAINTS));
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
Constraint item = null;
while (reader.Read())
{
root.RaiseOnReadingOne(reader["Name"]);
if (parentId != (int)reader["parent_object_id"])
{
parentId = (int)reader["parent_object_id"];
if (reader["ObjectType"].ToString().Trim().Equals("U"))
table = database.Tables.Find(parentId);
else
table = database.TablesTypes.Find(parentId);
}
if (table != null)
{
item = new Constraint(table);
item.Id = (int)reader["id"];
item.Name = reader["Name"].ToString();
item.Type = Constraint.ConstraintType.Check;
item.Definition = reader["Definition"].ToString();
item.WithNoCheck = (bool)reader["WithCheck"];
item.IsDisabled = (bool)reader["is_disabled"];
item.Owner = reader["Owner"].ToString();
if (database.Options.Ignore.FilterNotForReplication)
item.NotForReplication = (bool)reader["is_not_for_replication"];
if (reader["ObjectType"].ToString().Trim().Equals("U"))
((Table)table).Constraints.Add(item);
else
((TableType)table).Constraints.Add(item);
}
}
}
}
}
}
#endregion
#region ForeignKey Functions...
private static string GetSQLForeignKey()
{
return SQLQueries.SQLQueryFactory.Get("GetForeignKeys");
}
private static void FillForeignKey(Database database, string connectionString)
{
int lastid = 0;
int parentId = 0;
Table table = null;
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(GetSQLForeignKey(), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
Constraint con = null;
while (reader.Read())
{
if (parentId != (int)reader["parent_object_id"])
{
parentId = (int)reader["parent_object_id"];
table = database.Tables.Find(parentId);
}
if (table != null)
{
if (lastid != (int)reader["object_id"])
{
con = new Constraint(table);
con.Id = (int)reader["object_id"];
con.Name = reader["Name"].ToString();
con.Type = Constraint.ConstraintType.ForeignKey;
con.WithNoCheck = (bool)reader["is_not_trusted"];
con.RelationalTableFullName = "[" + reader["ReferenceOwner"].ToString() + "].[" + reader["TableRelationalName"].ToString() + "]";
con.RelationalTableId = (int)reader["TableRelationalId"];
con.Owner = reader["Owner"].ToString();
con.IsDisabled = (bool)reader["is_disabled"];
con.OnDeleteCascade = (byte)reader["delete_referential_action"];
con.OnUpdateCascade = (byte)reader["update_referential_action"];
if (database.Options.Ignore.FilterNotForReplication)
con.NotForReplication = (bool)reader["is_not_for_replication"];
lastid = (int)reader["object_id"];
table.Constraints.Add(con);
}
ConstraintColumn ccon = new ConstraintColumn(con);
ccon.Name = reader["ColumnName"].ToString();
ccon.ColumnRelationalName = reader["ColumnRelationalName"].ToString();
ccon.ColumnRelationalId = (int)reader["ColumnRelationalId"];
ccon.Id = (int)reader["ColumnId"];
ccon.KeyOrder = con.Columns.Count;
ccon.ColumnRelationalDataTypeId = (int)reader["user_type_id"];
//table.DependenciesCount++;
con.Columns.Add(ccon);
}
}
}
}
}
}
#endregion
#region UniqueKey Functions...
private static void FillUniqueKey(Database database, string connectionString)
{
int lastId = 0;
int parentId = 0;
bool change = false;
ISchemaBase table = null;
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(ConstraintSQLCommand.GetUniqueKey(database.Info.Version, database.Info.Edition), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
Constraint con = null;
while (reader.Read())
{
if (parentId != (int)reader["ID"])
{
parentId = (int)reader["ID"];
if (reader["ObjectType"].ToString().Trim().Equals("U"))
table = database.Tables.Find(parentId);
else
table = database.TablesTypes.Find(parentId);
change = true;
}
else
change = false;
if (table != null)
{
if ((lastId != (int)reader["Index_id"]) || (change))
{
con = new Constraint(table);
con.Name = reader["Name"].ToString();
con.Owner = (string)reader["Owner"];
con.Id = (int)reader["Index_id"];
con.Type = Constraint.ConstraintType.Unique;
con.Index.Id = (int)reader["Index_id"];
con.Index.AllowPageLocks = (bool)reader["allow_page_locks"];
con.Index.AllowRowLocks = (bool)reader["allow_row_locks"];
con.Index.FillFactor = (byte)reader["fill_factor"];
con.Index.IgnoreDupKey = (bool)reader["ignore_dup_key"];
con.Index.IsAutoStatistics = (bool)reader["ignore_dup_key"];
con.Index.IsDisabled = (bool)reader["is_disabled"];
con.Index.IsPadded = (bool)reader["is_padded"];
con.Index.IsPrimaryKey = false;
con.Index.IsUniqueKey = true;
con.Index.Type = (Index.IndexTypeEnum)(byte)reader["type"];
con.Index.Name = con.Name;
if (database.Options.Ignore.FilterTableFileGroup)
con.Index.FileGroup = reader["FileGroup"].ToString();
lastId = (int)reader["Index_id"];
if (reader["ObjectType"].ToString().Trim().Equals("U"))
((Table)table).Constraints.Add(con);
else
((TableType)table).Constraints.Add(con);
}
ConstraintColumn ccon = new ConstraintColumn(con);
ccon.Name = reader["ColumnName"].ToString();
ccon.IsIncluded = (bool)reader["is_included_column"];
ccon.Order = (bool)reader["is_descending_key"];
ccon.Id = (int)reader["column_id"];
ccon.DataTypeId = (int)reader["user_type_id"];
con.Columns.Add(ccon);
}
}
}
}
}
}
#endregion
#region PrimaryKey Functions...
private static void FillPrimaryKey(Database database, string connectionString)
{
int lastId = 0;
int parentId = 0;
bool change = false;
ISchemaBase table = null;
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(ConstraintSQLCommand.GetPrimaryKey(database.Info.Version, null), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
Constraint con = null;
while (reader.Read())
{
if (parentId != (int)reader["ID"])
{
parentId = (int)reader["ID"];
if (reader["ObjectType"].ToString().Trim().Equals("U"))
table = database.Tables.Find(parentId);
else
table = database.TablesTypes.Find(parentId);
change = true;
}
else
change = false;
if (table != null)
{
if ((lastId != (int)reader["Index_id"]) || (change))
{
con = new Constraint(table);
con.Id = (int)reader["Index_id"];
con.Name = (string)reader["Name"];
con.Owner = (string)reader["Owner"];
con.Type = Constraint.ConstraintType.PrimaryKey;
con.Index.Id = (int)reader["Index_id"];
con.Index.AllowPageLocks = (bool)reader["allow_page_locks"];
con.Index.AllowRowLocks = (bool)reader["allow_row_locks"];
con.Index.FillFactor = (byte)reader["fill_factor"];
con.Index.IgnoreDupKey = (bool)reader["ignore_dup_key"];
con.Index.IsAutoStatistics = (bool)reader["ignore_dup_key"];
con.Index.IsDisabled = (bool)reader["is_disabled"];
con.Index.IsPadded = (bool)reader["is_padded"];
con.Index.IsPrimaryKey = true;
con.Index.IsUniqueKey = false;
con.Index.Type = (Index.IndexTypeEnum)(byte)reader["type"];
con.Index.Name = con.Name;
if (database.Options.Ignore.FilterTableFileGroup)
con.Index.FileGroup = reader["FileGroup"].ToString();
lastId = (int)reader["Index_id"];
if (reader["ObjectType"].ToString().Trim().Equals("U"))
((Table)table).Constraints.Add(con);
else
((TableType)table).Constraints.Add(con);
}
ConstraintColumn ccon = new ConstraintColumn(con);
ccon.Name = (string)reader["ColumnName"];
ccon.IsIncluded = (bool)reader["is_included_column"];
ccon.Order = (bool)reader["is_descending_key"];
ccon.KeyOrder = (byte)reader["key_ordinal"];
ccon.Id = (int)reader["column_id"];
ccon.DataTypeId = (int)reader["user_type_id"];
con.Columns.Add(ccon);
}
}
}
}
}
}
#endregion
public void Fill(Database database, string connectionString)
{
if (database.Options.Ignore.FilterConstraintPK)
FillPrimaryKey(database, connectionString);
if (database.Options.Ignore.FilterConstraintFK)
FillForeignKey(database, connectionString);
if (database.Options.Ignore.FilterConstraintUK)
FillUniqueKey(database, connectionString);
if (database.Options.Ignore.FilterConstraintCheck)
FillCheck(database, connectionString);
}
}
}

View File

@@ -0,0 +1,50 @@
using System.Data.SqlClient;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GenerateDDLTriggers
{
private Generate root;
public GenerateDDLTriggers(Generate root)
{
this.root = root;
}
private static string GetSQL()
{
return SQLQueries.SQLQueryFactory.Get("GetDDLTriggers");
}
public void Fill(Database database, string connectionString)
{
if (database.Options.Ignore.FilterDDLTriggers)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
using (SqlCommand command = new SqlCommand(GetSQL(), conn))
{
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Trigger trigger = new Trigger(database);
trigger.Text = reader["Text"].ToString();
trigger.Name = reader["Name"].ToString();
trigger.InsteadOf = (bool)reader["is_instead_of_trigger"];
trigger.IsDisabled = (bool)reader["is_disabled"];
trigger.IsDDLTrigger = true;
trigger.NotForReplication = (bool)reader["is_not_for_replication"];
trigger.Owner = "";
database.DDLTriggers.Add(trigger);
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,97 @@
using System;
using System.Data.SqlClient;
using System.Globalization;
using OpenDBDiff.Schema.Misc;
using OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Options;
#if DEBUG
using System.Runtime.InteropServices;
#endif
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GenerateDatabase
{
private string connectioString;
private SqlOption objectFilter;
public bool UseDefaultVersionOnVersionParseError { get; private set; }
/// <summary>
/// Constructor de la clase.
/// </summary>
/// <param name="connectioString">Connection string de la base</param>
public GenerateDatabase(string connectioString, SqlOption filter)
{
this.connectioString = connectioString;
this.objectFilter = filter;
}
public DatabaseInfo Get(Database database)
{
DatabaseInfo item = new DatabaseInfo();
using (SqlConnection conn = new SqlConnection(connectioString))
{
using (SqlCommand command = new SqlCommand(DatabaseSQLCommand.GetVersion(database), conn))
{
conn.Open();
item.Server = conn.DataSource;
item.Database = conn.Database;
using (SqlDataReader reader = command.ExecuteReader())
{
if (reader.Read())
{
string versionValue = reader["Version"] as string;
try
{
// used to use the decimal as well when Azure was 10.25
var version = new Version(versionValue);
item.VersionNumber = float.Parse(String.Format("{0}.{1}", version.Major, version.Minor), CultureInfo.InvariantCulture);
if (reader.FieldCount > 1 && !reader.IsDBNull(1))
{
int edition;
if (int.TryParse(reader[1].ToString(), out edition)
&& Enum.IsDefined(typeof(DatabaseInfo.SQLServerEdition), edition))
{
item.SetEdition((DatabaseInfo.SQLServerEdition)edition);
}
}
}
catch (Exception notAGoodIdeaToCatchAllErrors)
{
var exception = new SchemaException(
String.Format("Error parsing ProductVersion. ({0})", versionValue ?? "[null]")
, notAGoodIdeaToCatchAllErrors);
if (!UseDefaultVersionOnVersionParseError)
{
throw exception;
}
}
}
}
}
using (SqlCommand command = new SqlCommand(DatabaseSQLCommand.Get(item.Version, item.Edition, database), conn))
{
using (SqlDataReader reader = command.ExecuteReader())
{
if (reader.Read())
{
item.Collation = reader["Collation"].ToString();
item.HasFullTextEnabled = ((int)reader["IsFulltextEnabled"]) == 1;
}
}
}
}
return item;
}
}
}

View File

@@ -0,0 +1,46 @@
using System.Data.SqlClient;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GenerateDefaults
{
private Generate root;
public GenerateDefaults(Generate root)
{
this.root = root;
}
private static string GetSQL()
{
return SQLQueries.SQLQueryFactory.Get("GetDefaults");
}
public void Fill(Database database, string connectionString)
{
if (database.Options.Ignore.FilterRules)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(GetSQL(), conn))
{
conn.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Default item = new Default(database);
item.Id = (int)reader["object_id"];
item.Name = reader["Name"].ToString();
item.Owner = reader["Owner"].ToString();
item.Value = reader["Definition"].ToString();
database.Defaults.Add(item);
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,118 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using OpenDBDiff.Schema.Errors;
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GenerateExtendedProperties
{
private Generate root;
public GenerateExtendedProperties(Generate root)
{
this.root = root;
}
private static string GetSQL()
{
return SQLQueries.SQLQueryFactory.Get("GetExtendedProperties");
}
private static string GetTypeDescription(string type)
{
if (type.Equals("PC")) return "PROCEDURE";
if (type.Equals("P")) return "PROCEDURE";
if (type.Equals("V")) return "VIEW";
if (type.Equals("U")) return "TABLE";
if (type.Equals("TR")) return "TRIGGER";
if (type.Equals("TA")) return "TRIGGER";
if (type.Equals("FS")) return "FUNCTION";
if (type.Equals("FN")) return "FUNCTION";
if (type.Equals("IF")) return "FUNCTION";
if (type.Equals("TF")) return "FUNCTION";
return "";
}
public void Fill(Database database, string connectionString, List<MessageLog> messages)
{
ISQLServerSchemaBase parent;
try
{
if (database.Options.Ignore.FilterExtendedProperties)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(GetSQL(), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
ExtendedProperty item = new ExtendedProperty(null);
if (((byte)reader["Class"]) == 5)
{
item.Level0type = "ASSEMBLY";
item.Level0name = reader["AssemblyName"].ToString();
}
if (((byte)reader["Class"]) == 1)
{
string ObjectType = GetTypeDescription(reader["type"].ToString().Trim());
item.Level0type = "SCHEMA";
item.Level0name = reader["Owner"].ToString();
if (!ObjectType.Equals("TRIGGER"))
{
item.Level1name = reader["ObjectName"].ToString();
item.Level1type = ObjectType;
}
else
{
item.Level1type = "TABLE";
item.Level1name = reader["ParentName"].ToString();
item.Level2name = reader["ObjectName"].ToString();
item.Level2type = ObjectType;
}
}
if (((byte)reader["Class"]) == 6)
{
item.Level0type = "SCHEMA";
item.Level0name = reader["OwnerType"].ToString();
item.Level1name = reader["TypeName"].ToString();
item.Level1type = "TYPE";
}
if (((byte)reader["Class"]) == 7)
{
item.Level0type = "SCHEMA";
item.Level0name = reader["Owner"].ToString();
item.Level1type = "TABLE";
item.Level1name = reader["ObjectName"].ToString();
item.Level2type = reader["class_desc"].ToString();
item.Level2name = reader["IndexName"].ToString();
}
item.Value = reader["Value"].ToString();
item.Name = reader["Name"].ToString();
parent = ((ISQLServerSchemaBase)database.Find(item.FullName));
if (parent != null)
{
item.Parent = (ISchemaBase)parent;
parent.ExtendedProperties.Add(item);
}
else
messages.Add(new MessageLog(item.FullName + " not found in extended properties.", "", MessageLog.LogType.Error));
}
}
}
}
}
}
catch (Exception ex)
{
messages.Add(new MessageLog(ex.Message, ex.StackTrace, MessageLog.LogType.Error));
}
}
}
}

View File

@@ -0,0 +1,92 @@
using System.Data.SqlClient;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GenerateFileGroups
{
private Generate root;
public GenerateFileGroups(Generate root)
{
this.root = root;
}
private static string GetSQLFile(FileGroup filegroup)
{
string query = SQLQueries.SQLQueryFactory.Get("GetDatabaseFile");
return query.Replace("{ID}", filegroup.Id.ToString());
}
private static string GetSQL()
{
return SQLQueries.SQLQueryFactory.Get("GetFileGroups");
}
private static void FillFiles(FileGroup filegroup, string connectionString)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(GetSQLFile(filegroup), conn))
{
conn.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
FileGroupFile item = new FileGroupFile(filegroup);
item.Id = (int)reader["file_id"];
item.Name = reader["name"].ToString();
item.Owner = "";
item.Growth = (int)reader["growth"];
item.IsPercentGrowth = (bool)reader["is_percent_growth"];
item.IsSparse = (bool)reader["is_sparse"];
item.MaxSize = (int)reader["max_size"];
item.PhysicalName = reader["physical_name"].ToString();
item.Size = (int)reader["size"];
item.Type = (byte)reader["type"];
filegroup.Files.Add(item);
}
}
}
}
}
public void Fill(Database database, string connectionString)
{
try
{
if (database.Options.Ignore.FilterTableFileGroup)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(GetSQL(), conn))
{
conn.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
FileGroup item = new FileGroup(database);
item.Id = (int)reader["ID"];
item.Name = reader["name"].ToString();
item.Owner = "";
item.IsDefaultFileGroup = (bool)reader["is_default"];
item.IsReadOnly = (bool)reader["is_read_only"];
item.IsFileStream = reader["type"].Equals("FD");
FillFiles(item, connectionString);
database.FileGroups.Add(item);
}
}
}
}
}
}
catch
{
throw;
}
}
}
}

View File

@@ -0,0 +1,51 @@
using System.Data.SqlClient;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GenerateFullText
{
private Generate root;
public GenerateFullText(Generate root)
{
this.root = root;
}
private static string GetSQL()
{
return SQLQueries.SQLQueryFactory.Get("GetFullTextCatalogs");
}
public void Fill(Database database, string connectionString)
{
if (database.Options.Ignore.FilterFullText)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(GetSQL(), conn))
{
conn.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
FullText item = new FullText(database);
item.Id = (int)reader["fulltext_catalog_id"];
item.Name = reader["Name"].ToString();
item.Owner = reader["Owner"].ToString();
item.IsAccentSensity = (bool)reader["is_accent_sensitivity_on"];
item.IsDefault = (bool)reader["is_default"];
if (!reader.IsDBNull(reader.GetOrdinal("path")))
item.Path = reader["path"].ToString().Substring(0, reader["path"].ToString().Length - item.Name.Length);
if (!reader.IsDBNull(reader.GetOrdinal("FileGroupName")))
item.FileGroupName = reader["FileGroupName"].ToString();
database.FullText.Add(item);
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,70 @@
using System.Data.SqlClient;
using OpenDBDiff.Schema.Events;
using OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands;
using OpenDBDiff.Schema.SQLServer.Generates.Generates.Util;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GenerateFullTextIndex
{
private Generate root;
public GenerateFullTextIndex(Generate root)
{
this.root = root;
}
public void Fill(Database database, string connectionString)
{
//not supported in azure yet
if (database.Info.Version == DatabaseInfo.SQLServerVersion.SQLServerAzure10) return;
int parentId = 0;
bool change = false;
Table parent = null;
root.RaiseOnReading(new ProgressEventArgs("Reading FullText Index...", Constants.READING_INDEXES));
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(FullTextIndexSQLCommand.Get(database.Info.Version), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
FullTextIndex item = null;
while (reader.Read())
{
root.RaiseOnReadingOne(reader["Name"]);
if (parentId != (int)reader["object_id"])
{
parentId = (int)reader["object_id"];
parent = database.Tables.Find(parentId);
change = true;
}
else
change = false;
if (change)
{
item = new FullTextIndex(parent);
item.Name = reader["Name"].ToString();
item.Owner = parent.Owner;
item.FullText = reader["FullTextCatalogName"].ToString();
item.Index = reader["IndexName"].ToString();
item.IsDisabled = !(bool)reader["is_enabled"];
item.ChangeTrackingState = reader["ChangeTracking"].ToString();
if (database.Info.Version == DatabaseInfo.SQLServerVersion.SQLServer2008)
item.FileGroup = reader["FileGroupName"].ToString();
((Table)parent).FullTextIndex.Add(item);
}
FullTextIndexColumn ccon = new FullTextIndexColumn();
ccon.ColumnName = reader["ColumnName"].ToString();
ccon.Language = reader["LanguageName"].ToString();
item.Columns.Add(ccon);
}
}
}
}
}
}
}

View File

@@ -0,0 +1,138 @@
using OpenDBDiff.Schema.Events;
using OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands;
using OpenDBDiff.Schema.SQLServer.Generates.Generates.Util;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
using System;
using System.Data.SqlClient;
using System.Linq;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GenerateFunctions
{
private Generate root;
public GenerateFunctions(Generate root)
{
this.root = root;
}
private static string GetSQLParameters()
{
return SQLQueries.SQLQueryFactory.Get("GetParameters");
}
private static void FillParameters(Database database, string connectionString)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(GetSQLParameters(), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
var objectName = reader["ObjectName"].ToString();
if (database.CLRFunctions.Contains(objectName))
{
Parameter param = new Parameter();
param.Name = reader["Name"].ToString();
param.Type = reader["TypeName"].ToString();
param.Size = (short)reader["max_length"];
param.Scale = (byte)reader["scale"];
param.Precision = (byte)reader["precision"];
param.Output = (bool)reader["is_output"];
if (param.Type.Equals("nchar") || param.Type.Equals("nvarchar"))
{
if (param.Size != -1)
param.Size = param.Size / 2;
}
database.CLRFunctions[objectName].Parameters.Add(param);
}
}
}
}
}
}
public void Fill(Database database, string connectionString)
{
int lastViewId = 0;
if ((database.Options.Ignore.FilterFunction) || (database.Options.Ignore.FilterCLRFunction))
{
root.RaiseOnReading(new ProgressEventArgs("Reading functions...", Constants.READING_FUNCTIONS));
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(FunctionSQLCommand.Get(database.Info.Version, database.Info.Edition), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
Function itemF = null;
CLRFunction itemC = null;
while (reader.Read())
{
root.RaiseOnReadingOne(reader["name"]);
if ((!reader["type"].ToString().Trim().Equals("FS")) && (database.Options.Ignore.FilterFunction))
{
if (lastViewId != (int)reader["object_id"])
{
itemF = new Function(database);
itemF.Id = (int)reader["object_id"];
itemF.Name = reader["name"].ToString();
itemF.Owner = reader["owner"].ToString();
itemF.IsSchemaBinding = reader["IsSchemaBound"].ToString().Equals("1");
database.Functions.Add(itemF);
lastViewId = itemF.Id;
}
if (itemF.IsSchemaBinding)
{
if (!reader.IsDBNull(reader.GetOrdinal("referenced_major_id")))
database.Dependencies.Add(database, (int)reader["referenced_major_id"], itemF);
if (!String.IsNullOrEmpty(reader["TableName"].ToString()))
itemF.DependenciesIn.Add(reader["TableName"].ToString());
if (!String.IsNullOrEmpty(reader["DependOut"].ToString()))
itemF.DependenciesOut.Add(reader["DependOut"].ToString());
}
}
if ((reader["type"].ToString().Trim().Equals("FS")) && (database.Options.Ignore.FilterCLRFunction))
{
itemC = new CLRFunction(database);
if (lastViewId != (int)reader["object_id"])
{
itemC.Id = (int)reader["object_id"];
itemC.Name = reader["name"].ToString();
itemC.Owner = reader["owner"].ToString();
itemC.IsAssembly = true;
itemC.AssemblyId = (int)reader["assembly_id"];
itemC.AssemblyName = reader["assembly_name"].ToString();
itemC.AssemblyClass = reader["assembly_class"].ToString();
itemC.AssemblyExecuteAs = reader["ExecuteAs"].ToString();
itemC.AssemblyMethod = reader["assembly_method"].ToString();
itemC.ReturnType.Type = reader["ReturnType"].ToString();
itemC.ReturnType.Size = (short)reader["max_length"];
itemC.ReturnType.Scale = (byte)reader["Scale"];
itemC.ReturnType.Precision = (byte)reader["precision"];
if (itemC.ReturnType.Type.Equals("nchar") || itemC.ReturnType.Type.Equals("nvarchar"))
{
if (itemC.ReturnType.Size != -1)
itemC.ReturnType.Size = itemC.ReturnType.Size / 2;
}
database.CLRFunctions.Add(itemC);
lastViewId = itemC.Id;
}
}
}
}
}
}
}
if (database.CLRFunctions.Any())
FillParameters(database, connectionString);
}
}
}

View File

@@ -0,0 +1,105 @@
using System.Data.SqlClient;
using OpenDBDiff.Schema.Events;
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands;
using OpenDBDiff.Schema.SQLServer.Generates.Generates.Util;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GenerateIndex
{
private Generate root;
public GenerateIndex(Generate root)
{
this.root = root;
}
public void Fill(Database database, string connectionString)
{
int indexid = 0;
int parentId = 0;
bool change = false;
string type;
ISchemaBase parent = null;
root.RaiseOnReading(new ProgressEventArgs("Reading Index...", Constants.READING_INDEXES));
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(IndexSQLCommand.Get(database.Info.Version, database.Info.Edition), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
Index item = null;
while (reader.Read())
{
root.RaiseOnReadingOne(reader["Name"]);
type = reader["ObjectType"].ToString().Trim();
if (parentId != (int)reader["object_id"])
{
parentId = (int)reader["object_id"];
if (type.Equals("V"))
parent = database.Views.Find(parentId);
else
parent = database.Tables.Find(parentId);
change = true;
}
else
change = false;
if (parent != null)
{
if (indexid != (int)reader["index_id"] || change)
{
item = new Index(parent);
item.Name = reader["Name"].ToString();
item.Owner = parent.Owner;
item.Type = (Index.IndexTypeEnum)(byte)reader["type"];
item.Id = (int)reader["index_id"];
item.IgnoreDupKey = (bool)reader["ignore_dup_key"];
item.IsAutoStatistics = (bool)reader["NoAutomaticRecomputation"];
item.IsDisabled = (bool)reader["is_disabled"];
item.IsPrimaryKey = (bool)reader["is_primary_key"];
item.IsUniqueKey = (bool)reader["is_unique"];
if (database.Options.Ignore.FilterIndexRowLock)
{
item.AllowPageLocks = (bool)reader["allow_page_locks"];
item.AllowRowLocks = (bool)reader["allow_row_locks"];
}
if (database.Options.Ignore.FilterIndexFillFactor)
{
item.FillFactor = (byte)reader["fill_factor"];
item.IsPadded = (bool)reader["is_padded"];
}
if ((database.Options.Ignore.FilterTableFileGroup) && (item.Type != Index.IndexTypeEnum.XML))
item.FileGroup = reader["FileGroup"].ToString();
if ((database.Info.Version == DatabaseInfo.SQLServerVersion.SQLServer2008) && (database.Options.Ignore.FilterIndexFilter))
{
item.FilterDefintion = reader["FilterDefinition"].ToString();
}
indexid = (int)reader["index_id"];
if (type.Equals("V"))
((View)parent).Indexes.Add(item);
else
((Table)parent).Indexes.Add(item);
}
IndexColumn ccon = new IndexColumn(item.Parent);
ccon.Name = reader["ColumnName"].ToString();
ccon.IsIncluded = (bool)reader["is_included_column"];
ccon.Order = (bool)reader["is_descending_key"];
ccon.Id = (int)reader["column_id"];
ccon.KeyOrder = (byte)reader["key_ordinal"];
ccon.DataTypeId = (int)reader["user_type_id"];
if ((!ccon.IsIncluded) || (ccon.IsIncluded && database.Options.Ignore.FilterIndexIncludeColumns))
item.Columns.Add(ccon);
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,84 @@
using System;
using System.Data.SqlClient;
using System.Text;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GeneratePartitionFunctions
{
private Generate root;
public GeneratePartitionFunctions(Generate root)
{
this.root = root;
}
private static string GetSQL()
{
return SQLQueries.SQLQueryFactory.Get("GetPartitionFunctions");
}
private static string ToHex(byte[] stream)
{
StringBuilder sHex = new StringBuilder(2 * stream.Length);
for (int i = 0; i < stream.Length; i++)
sHex.AppendFormat("{0:X2} ", stream[i]);
return "0x" + sHex.ToString().Replace(" ", String.Empty);
}
public void Fill(Database database, string connectioString)
{
int lastObjectId = 0;
PartitionFunction item = null;
if (database.Options.Ignore.FilterPartitionFunction)
{
using (SqlConnection conn = new SqlConnection(connectioString))
{
using (SqlCommand command = new SqlCommand(GetSQL(), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
if (lastObjectId != (int)reader["function_id"])
{
lastObjectId = (int)reader["function_id"];
item = new PartitionFunction(database);
item.Id = (int)reader["function_id"];
item.Name = reader["name"].ToString();
item.IsBoundaryRight = (bool)reader["IsRight"];
item.Precision = (byte)reader["precision"];
item.Scale = (byte)reader["scale"];
item.Size = (short)reader["max_length"];
item.Type = reader["TypeName"].ToString();
database.PartitionFunctions.Add(item);
}
switch (item.Type) {
case "binary":
case "varbinary":
item.Values.Add(ToHex((byte[])reader["value"]));
break;
case "date":
item.Values.Add(String.Format("'{0:yyyy/MM/dd}'", (DateTime)reader["value"]));
break;
case "smalldatetime":
case "datetime":
item.Values.Add(String.Format("'{0:yyyy/MM/dd HH:mm:ss.fff}'", (DateTime)reader["value"]));
break;
default:
item.Values.Add(reader["value"].ToString());
break;
}
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,53 @@
using System.Data.SqlClient;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GeneratePartitionScheme
{
private Generate root;
public GeneratePartitionScheme(Generate root)
{
this.root = root;
}
private static string GetSQL()
{
return SQLQueries.SQLQueryFactory.Get("GetPartitionSchemes");
}
public void Fill(Database database, string connectioString)
{
int lastObjectId = 0;
PartitionScheme item = null;
if (database.Options.Ignore.FilterPartitionScheme)
{
using (SqlConnection conn = new SqlConnection(connectioString))
{
using (SqlCommand command = new SqlCommand(GetSQL(), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
if (lastObjectId != (int)reader["ID"])
{
lastObjectId = (int)reader["ID"];
item = new PartitionScheme(database);
item.Id = (int)reader["ID"];
item.Name = reader["name"].ToString();
item.PartitionFunction = reader["FunctionName"].ToString();
database.PartitionSchemes.Add(item);
}
item.FileGroups.Add(reader["FileGroupName"].ToString());
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,46 @@
using System.Data.SqlClient;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GenerateRules
{
private Generate root;
public GenerateRules(Generate root)
{
this.root = root;
}
private static string GetSQL()
{
return SQLQueries.SQLQueryFactory.Get("GetRules");
}
public void Fill(Database database, string connectionString)
{
if (database.Options.Ignore.FilterRules)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(GetSQL(), conn))
{
conn.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Rule item = new Rule(database);
item.Id = (int)reader["object_id"];
item.Name = reader["Name"].ToString();
item.Owner = reader["Owner"].ToString();
item.Text = reader["Definition"].ToString();
database.Rules.Add(item);
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,46 @@
using System.Data.SqlClient;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GenerateSchemas
{
private Generate root;
public GenerateSchemas(Generate root)
{
this.root = root;
}
private static string GetSQL()
{
return SQLQueries.SQLQueryFactory.Get("GetSchemas");
}
public void Fill(Database database, string connectioString)
{
if (database.Options.Ignore.FilterSchema)
{
using (SqlConnection conn = new SqlConnection(connectioString))
{
using (SqlCommand command = new SqlCommand(GetSQL(), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Model.Schema item = new Model.Schema(database);
item.Id = (int)reader["schema_id"];
item.Name = reader["name"].ToString();
item.Owner = reader["owner"].ToString();
database.Schemas.Add(item);
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,145 @@
using OpenDBDiff.Schema.Events;
using OpenDBDiff.Schema.SQLServer.Generates.Generates.Util;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
using System.Data.SqlClient;
using System.Linq;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GenerateStoredProcedures
{
private static int NameIndex = -1;
private static int object_idIndex = -1;
private static int ownerIndex = -1;
private static int typeIndex = -1;
private Generate root;
public GenerateStoredProcedures(Generate root)
{
this.root = root;
}
private static void InitIndex(SqlDataReader reader)
{
if (NameIndex == -1)
{
object_idIndex = reader.GetOrdinal("object_id");
NameIndex = reader.GetOrdinal("Name");
ownerIndex = reader.GetOrdinal("owner");
typeIndex = reader.GetOrdinal("type");
}
}
private static string GetSQLParameters()
{
return SQLQueries.SQLQueryFactory.Get("GetParameters");
}
private static string GetSQL(DatabaseInfo.SQLServerVersion version)
{
if (version == DatabaseInfo.SQLServerVersion.SQLServerAzure10)
{
return SQLQueries.SQLQueryFactory.Get("GetProcedures", DatabaseInfo.SQLServerVersion.SQLServerAzure10);
}
else
{
return SQLQueries.SQLQueryFactory.Get("GetProcedures");
}
}
private static void FillParameters(Database database, string connectionString)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(GetSQLParameters(), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
var objectName = reader["ObjectName"].ToString();
if (database.CLRProcedures.Contains(objectName))
{
Parameter param = new Parameter();
param.Name = reader["Name"].ToString();
param.Type = reader["TypeName"].ToString();
param.Size = (short)reader["max_length"];
param.Scale = (byte)reader["scale"];
param.Precision = (byte)reader["precision"];
param.Output = (bool)reader["is_output"];
if (param.Type.Equals("nchar") || param.Type.Equals("nvarchar"))
{
if (param.Size != -1)
param.Size = param.Size / 2;
}
database.CLRProcedures[objectName].Parameters.Add(param);
}
}
}
}
}
}
public void Fill(Database database, string connectionString)
{
if ((database.Options.Ignore.FilterStoredProcedure) || (database.Options.Ignore.FilterCLRStoredProcedure))
{
root.RaiseOnReading(new ProgressEventArgs("Reading stored procedures...", Constants.READING_PROCEDURES));
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(GetSQL(database.Info.Version), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
InitIndex(reader);
root.RaiseOnReadingOne(reader[NameIndex]);
var objectType = reader[typeIndex].ToString().Trim();
switch (objectType)
{
case "P":
if (database.Options.Ignore.FilterStoredProcedure)
{
StoredProcedure item = new StoredProcedure(database);
item.Id = (int)reader[object_idIndex];
item.Name = (string)reader[NameIndex];
item.Owner = (string)reader[ownerIndex];
database.Procedures.Add(item);
}
break;
case "PC":
if (database.Options.Ignore.FilterCLRStoredProcedure)
{
CLRStoredProcedure item = new CLRStoredProcedure(database);
item.Id = (int)reader[object_idIndex];
item.Name = reader[NameIndex].ToString();
item.Owner = reader[ownerIndex].ToString();
item.IsAssembly = true;
item.AssemblyId = (int)reader["assembly_id"];
item.AssemblyName = reader["assembly_name"].ToString();
item.AssemblyClass = reader["assembly_class"].ToString();
item.AssemblyExecuteAs = reader["ExecuteAs"].ToString();
item.AssemblyMethod = reader["assembly_method"].ToString();
database.CLRProcedures.Add(item);
}
break;
}
}
}
}
}
if (database.CLRProcedures.Any())
FillParameters(database, connectionString);
}
}
}
}

View File

@@ -0,0 +1,47 @@
using System.Data.SqlClient;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GenerateSynonyms
{
private Generate root;
public GenerateSynonyms(Generate root)
{
this.root = root;
}
private static string GetSQL()
{
return SQLQueries.SQLQueryFactory.Get("GetSynonyms");
}
public void Fill(Database database, string connectionString)
{
if (database.Options.Ignore.FilterSynonyms)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(GetSQL(), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Synonym item = new Synonym(database);
item.Id = (int)reader["object_id"];
item.Name = reader["Name"].ToString();
item.Owner = reader["Owner"].ToString();
item.Value = reader["base_object_name"].ToString();
database.Synonyms.Add(item);
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,313 @@
using OpenDBDiff.Schema.Errors;
using OpenDBDiff.Schema.Events;
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands;
using OpenDBDiff.Schema.SQLServer.Generates.Generates.Util;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Globalization;
using System.Linq;
using Constraint = OpenDBDiff.Schema.SQLServer.Generates.Model.Constraint;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GenerateTables
{
private int colIDIndex = -1;
private int colNameIndex = -1;
private int colFormulaIndex = -1;
private int colIsPersistedIndex = -1;
private int colIsComputedIndex = -1;
private int colNullableIndex = -1;
private int colXmlSchemaIndex = -1;
private int colIs_xml_documentIndex = -1;
private int colPrecisionIndex = -1;
private int colScaleIndex = -1;
private int colDataUserTypeIdIndex = -1;
private int colIsUserDefinedTypeIndex = -1;
private int colSizeIndex = -1;
private int colHasIndexIndex = -1;
private int colHasComputedFormulaIndex = -1;
private int colIsRowGuidIndex = -1;
private int colTypeIndex = -1;
private int colOwnerType = -1;
private int colis_sparseIndex = -1;
private int colIs_FileStream = -1;
private int colDefaultIdIndex = -1;
private int colDefaultNameIndex = -1;
private int colDefaultDefinitionIndex = -1;
private int colrule_object_idIndex = -1;
private int colIsIdentityReplIndex = -1;
private int colCollationIndex = -1;
private int colIsIdentityIndex = -1;
private int colIdentSeedIndex = -1;
private int colIdentIncrementIndex = -1;
private int TableIdIndex = -1;
private int TableNameIndex = -1;
private int TableOwnerIndex = -1;
private int TableHasChangeTracking = -1;
private int TableHasChangeTrackingTrackColumn = -1;
private int TableLockEscalation = -1;
private int Text_In_Row_limitIndex = -1;
private int HasClusteredIndexIndex = -1;
private int large_value_types_out_of_rowIndex = -1;
private int HasVarDecimalIndex = -1;
private int FileGroupIndex = -1;
private int FileGroupTextIndex = -1;
private int FileGroupStreamIndex = -1;
private Generate root;
public GenerateTables(Generate root)
{
this.root = root;
}
private void InitTableIndex(Database database, IDataRecord reader)
{
if (reader == null) throw new ArgumentNullException("reader");
if (TableIdIndex == -1)
{
TableIdIndex = reader.GetOrdinal("TableId");
TableNameIndex = reader.GetOrdinal("TableName");
TableOwnerIndex = reader.GetOrdinal("TableOwner");
Text_In_Row_limitIndex = reader.GetOrdinal("Text_In_Row_limit");
HasClusteredIndexIndex = reader.GetOrdinal("HasClusteredIndex");
large_value_types_out_of_rowIndex = reader.GetOrdinal("large_value_types_out_of_row");
HasVarDecimalIndex = reader.GetOrdinal("HasVarDecimal");
FileGroupIndex = reader.GetOrdinal("FileGroup");
FileGroupTextIndex = reader.GetOrdinal("FileGroupText");
if (database.Info.Version == DatabaseInfo.SQLServerVersion.SQLServer2008)
{
FileGroupStreamIndex = reader.GetOrdinal("FileGroupStream");
TableHasChangeTracking = reader.GetOrdinal("HasChangeTracking");
TableHasChangeTrackingTrackColumn = reader.GetOrdinal("HasChangeTrackingTrackColumn");
TableLockEscalation = reader.GetOrdinal("lock_escalation_desc");
}
}
}
private void InitColIndex(Database database, IDataRecord reader)
{
if (reader == null) throw new ArgumentNullException("reader");
if (colNameIndex == -1)
{
colIDIndex = reader.GetOrdinal("ID");
colNameIndex = reader.GetOrdinal("Name");
colFormulaIndex = reader.GetOrdinal("Formula");
colIsPersistedIndex = reader.GetOrdinal("FormulaPersisted");
colIsComputedIndex = reader.GetOrdinal("IsComputed");
colNullableIndex = reader.GetOrdinal("IsNullable");
colOwnerType = reader.GetOrdinal("OwnerType");
colXmlSchemaIndex = reader.GetOrdinal("XmlSchema");
colIs_xml_documentIndex = reader.GetOrdinal("Is_xml_document");
colPrecisionIndex = reader.GetOrdinal("Precision");
colScaleIndex = reader.GetOrdinal("Scale");
colDataUserTypeIdIndex = reader.GetOrdinal("user_type_id");
colIsUserDefinedTypeIndex = reader.GetOrdinal("is_user_defined");
colSizeIndex = reader.GetOrdinal("Size");
colHasIndexIndex = reader.GetOrdinal("HasIndex");
colHasComputedFormulaIndex = reader.GetOrdinal("HasComputedFormula");
colIsRowGuidIndex = reader.GetOrdinal("IsRowGuid");
colTypeIndex = reader.GetOrdinal("Type");
colDefaultIdIndex = reader.GetOrdinal("DefaultId");
colDefaultNameIndex = reader.GetOrdinal("DefaultName");
colDefaultDefinitionIndex = reader.GetOrdinal("DefaultDefinition");
colrule_object_idIndex = reader.GetOrdinal("rule_object_id");
colIsIdentityReplIndex = reader.GetOrdinal("IsIdentityRepl");
colCollationIndex = reader.GetOrdinal("Collation");
colIsIdentityIndex = reader.GetOrdinal("IsIdentity");
colIdentSeedIndex = reader.GetOrdinal("IdentSeed");
colIdentIncrementIndex = reader.GetOrdinal("IdentIncrement");
if (database.Info.Version == DatabaseInfo.SQLServerVersion.SQLServer2008)
{
colis_sparseIndex = reader.GetOrdinal("is_sparse");
colIs_FileStream = reader.GetOrdinal("is_filestream");
}
}
}
private void FillColumn<T>(ITable<T> table, SqlDataReader reader) where T : ISchemaBase
{
Database database = (Database)table.Parent;
InitColIndex(database, reader);
Column col = new Column((ISchemaBase)table);
col.Id = (int)reader[colIDIndex];
if (database.Options.Ignore.FilterColumnOrder)
col.Position = table.Columns.Count + 1;
if (database.Options.Ignore.FilterColumnCollation)
col.Collation = (string)reader[colCollationIndex];
if (database.Options.Ignore.FilterColumnIdentity)
{
col.IsIdentity = (bool)reader[colIsIdentityIndex];
if ((col.IsIdentity) || (col.IsIdentityForReplication))
{
if (!reader.IsDBNull(colIdentSeedIndex))
col.IdentitySeed = (long)(decimal)reader[colIdentSeedIndex];
else
col.IdentitySeed = 1;
if (!reader.IsDBNull(colIdentIncrementIndex))
col.IdentityIncrement = (int)(decimal)reader[colIdentIncrementIndex];
else
col.IdentityIncrement = 1;
}
if (database.Options.Ignore.FilterNotForReplication)
col.IsIdentityForReplication = ((int)reader[colIsIdentityReplIndex] == 1);
}
col.Name = (string)reader[colNameIndex];
col.Owner = table.Owner;
col.ComputedFormula = (string)reader[colFormulaIndex];
col.IsPersisted = (bool)reader[colIsPersistedIndex];
col.IsComputed = (bool)reader[colIsComputedIndex];
col.IsNullable = (bool)reader[colNullableIndex];
col.XmlSchema = reader[colXmlSchemaIndex].ToString();
col.IsXmlDocument = (bool)reader[colIs_xml_documentIndex];
col.Precision = (byte)reader[colPrecisionIndex];
col.Scale = (byte)reader[colScaleIndex];
col.DataUserTypeId = (int)reader[colDataUserTypeIdIndex];
col.IsUserDefinedType = (bool)reader[colIsUserDefinedTypeIndex];
if (!String.IsNullOrEmpty(reader[colSizeIndex].ToString()))
col.Size = (short)reader[colSizeIndex];
col.HasIndexDependencies = ((int)reader[colHasIndexIndex] == 1);
col.HasComputedDependencies = ((int)reader[colHasComputedFormulaIndex] == 1);
col.IsRowGuid = (bool)reader[colIsRowGuidIndex];
if (col.IsUserDefinedType)
col.Type = "[" + (string)reader[colOwnerType] + "].[" + (string)reader[colTypeIndex] + "]";
else
col.Type = (string)reader[colTypeIndex];
if (((Database)table.Parent).Info.Version == DatabaseInfo.SQLServerVersion.SQLServer2008)
{
col.IsSparse = (bool)reader[colis_sparseIndex];
col.IsFileStream = (bool)reader[colIs_FileStream];
}
if ((int)reader[colDefaultIdIndex] != 0)
{
col.DefaultConstraint = new ColumnConstraint(col)
{
Id = (int)reader[colDefaultIdIndex],
Owner = table.Owner,
Name = (string)reader[colDefaultNameIndex],
Type = Constraint.ConstraintType.Default,
Definition = (string)reader[colDefaultDefinitionIndex]
};
}
if ((int)reader[colrule_object_idIndex] != 0)
col.Rule = ((Database)table.Parent).Rules.Find((int)reader[colrule_object_idIndex]);
table.Columns.Add(col);
}
public void Fill(Database database, string connectionString, List<MessageLog> messages)
{
try
{
root.RaiseOnReading(new ProgressEventArgs("Reading tables...", Constants.READING_TABLES));
FillTables(database, connectionString);
if (database.Tables.Any() || database.TablesTypes.Any())
{
if (database.Options.Ignore.FilterConstraint)
(new GenerateConstraint(root)).Fill(database, connectionString);
}
}
catch (Exception ex)
{
messages.Add(new MessageLog(ex.Message, ex.StackTrace, MessageLog.LogType.Error));
}
}
private void FillTables(Database database, string connectionString)
{
int textInRow;
Boolean largeValues;
Boolean varDecimal;
int lastObjectId = 0;
bool isTable = true;
ISchemaBase item = null;
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(TableSQLCommand.GetTableDetail(database.Info.Version, database.Info.Edition), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
InitTableIndex(database, reader);
root.RaiseOnReadingOne(reader[TableNameIndex]);
if (lastObjectId != (int)reader[TableIdIndex])
{
lastObjectId = (int)reader[TableIdIndex];
isTable = reader["ObjectType"].ToString().Trim().Equals("U");
if (isTable)
{
item = new Table(database);
item.Id = (int)reader[TableIdIndex];
item.Name = (string)reader[TableNameIndex];
item.Owner = (string)reader[TableOwnerIndex];
((Table)item).HasClusteredIndex = (int)reader[HasClusteredIndexIndex] == 1;
textInRow = (int)reader[Text_In_Row_limitIndex];
largeValues = (Boolean)reader[large_value_types_out_of_rowIndex];
varDecimal = ((int)reader[HasVarDecimalIndex]) == 1;
if (database.Options.Ignore.FilterTableFileGroup)
{
((Table)item).FileGroup = (string)reader[FileGroupIndex];
((Table)item).FileGroupText = (string)reader[FileGroupTextIndex];
if (database.Info.Version == DatabaseInfo.SQLServerVersion.SQLServer2008)
{
if (database.Options.Ignore.FilterTableChangeTracking)
{
((Table)item).FileGroupStream = (string)reader[FileGroupStreamIndex];
((Table)item).HasChangeTracking = ((int)reader[TableHasChangeTracking]) == 1;
((Table)item).HasChangeTrackingTrackColumn = ((int)reader[TableHasChangeTrackingTrackColumn]) == 1;
}
}
}
if (database.Options.Ignore.FilterTableOption)
{
if (textInRow > 0) ((Table)item).Options.Add(new TableOption("TextInRow", textInRow.ToString(CultureInfo.InvariantCulture), item));
if (largeValues) ((Table)item).Options.Add(new TableOption("LargeValues", "1", item));
if (varDecimal) ((Table)item).Options.Add(new TableOption("VarDecimal", "1", item));
}
if ((database.Options.Ignore.FilterTableLockEscalation) && (database.Info.Version == DatabaseInfo.SQLServerVersion.SQLServer2008))
((Table)item).Options.Add(new TableOption("LockEscalation", (string)reader[TableLockEscalation], item));
else
((Table)item).Options.Add(new TableOption("LockEscalation", "TABLE", item));
database.Tables.Add((Table)item);
}
else
{
item = new TableType(database)
{
Id = (int)reader[TableIdIndex],
Name = (string)reader[TableNameIndex],
Owner = (string)reader[TableOwnerIndex]
};
database.TablesTypes.Add((TableType)item);
}
}
if (isTable)
{
if (database.Options.Ignore.FilterTable)
FillColumn((ITable<Table>)item, reader);
}
else
{
if (database.Options.Ignore.FilterUserDataType)
FillColumn((ITable<TableType>)item, reader);
}
}
}
}
}
//tables.ToSQL();
}
}
}

View File

@@ -0,0 +1,120 @@
using System;
using System.Data.SqlClient;
using System.Text.RegularExpressions;
using OpenDBDiff.Schema.Events;
using OpenDBDiff.Schema.SQLServer.Generates.Generates.Util;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Options;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GenerateTextObjects
{
private Generate root;
public GenerateTextObjects(Generate root)
{
this.root = root;
}
private static string GetSQL(SqlOption options)
{
var filterQuery = SQLQueries.SQLQueryFactory.Get("GetTextObjectsQuery");
string filter = "";
if (options.Ignore.FilterStoredProcedure)
filter += "O.type = 'P' OR ";
if (options.Ignore.FilterView)
filter += "O.type = 'V' OR ";
if (options.Ignore.FilterTrigger)
filter += "O.type = 'TR' OR ";
if (options.Ignore.FilterFunction)
filter += "O.type IN ('IF','FN','TF') OR ";
filter = filter.Substring(0, filter.Length - 4);
return filterQuery.Replace("{FILTER}", filter);
}
public void Fill(Database database, string connectionString)
{
ICode code = null;
try
{
if ((database.Options.Ignore.FilterStoredProcedure) || (database.Options.Ignore.FilterView) || (database.Options.Ignore.FilterFunction) || (database.Options.Ignore.FilterTrigger))
{
root.RaiseOnReading(new ProgressEventArgs("Reading Text Objects...", Constants.READING_TEXTOBJECTS));
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(GetSQL(database.Options), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
code = null;
root.RaiseOnReadingOne(reader["name"]);
string type = reader["Type"].ToString().Trim();
string name = reader["name"].ToString();
string definition = reader["Text"].ToString();
int id = (int)reader["object_id"];
if (type.Equals("V"))
code = (ICode)database.Views.Find(id);
if (type.Equals("TR"))
code = (ICode)database.Find(id);
if (type.Equals("P"))
{
var procedure = database.Procedures.Find(id);
if (procedure != null)
((ICode)procedure).Text = GetObjectDefinition(type, name, definition);
}
if (type.Equals("IF") || type.Equals("FN") || type.Equals("TF"))
code = (ICode)database.Functions.Find(id);
if (code != null)
code.Text = reader["Text"].ToString();
}
}
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}
private string GetObjectDefinition(string type, string name, string definition)
{
string rv = definition;
string sqlDelimiters = @"(\r|\n|\s)+?";
RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Multiline;
Regex re = new Regex(@"CREATE" + sqlDelimiters + @"PROC(EDURE)?" + sqlDelimiters + @"(\w+\.|\[\w+\]\.)?\[?(?<spname>\w+)\]?" + sqlDelimiters, options);
switch (type)
{
case "P":
Match match = re.Match(definition);
if (match != null && match.Success)
{
// Try to replace the name saved in the definition when the object was created by the one used for the object in sys.object
string oldName = match.Groups["spname"].Value;
//if (String.IsNullOrEmpty(oldName)) System.Diagnostics.Debugger.Break();
if (String.Compare(oldName, name) != 0)
{
rv = rv.Replace(oldName, name);
}
}
break;
default:
//TODO : Add the logic used for other objects than procedures
break;
}
return rv;
}
}
}

View File

@@ -0,0 +1,114 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using OpenDBDiff.Schema.Errors;
using OpenDBDiff.Schema.Events;
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Generates.Util;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Options;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GenerateTriggers
{
private Generate root;
public GenerateTriggers(Generate root)
{
this.root = root;
}
private static string GetSQL(DatabaseInfo.SQLServerVersion version, SqlOption options)
{
if (version == DatabaseInfo.SQLServerVersion.SQLServerAzure10)
{
return SQLQueries.SQLQueryFactory.Get("GetTriggers", version);
}
else
{
return SQLQueries.SQLQueryFactory.Get("GetTriggers");
}
}
public void Fill(Database database, string connectionString, List<MessageLog> messages)
{
int parentId = 0;
ISchemaBase parent = null;
string type;
try
{
if (database.Options.Ignore.FilterTrigger)
{
root.RaiseOnReading(new ProgressEventArgs("Reading Triggers...", Constants.READING_TRIGGERS));
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(GetSQL(database.Info.Version, database.Options), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
root.RaiseOnReadingOne(reader["Name"]);
type = reader["ObjectType"].ToString().Trim();
if (parentId != (int)reader["parent_id"])
{
parentId = (int)reader["parent_id"];
if (type.Equals("V"))
parent = database.Views.Find(parentId);
else
parent = database.Tables.Find(parentId);
}
if (reader["type"].Equals("TR"))
{
Trigger item = new Trigger(parent);
item.Id = (int)reader["object_id"];
item.Name = reader["Name"].ToString();
item.InsteadOf = (bool)reader["is_instead_of_trigger"];
item.IsDisabled = (bool)reader["is_disabled"];
item.IsDDLTrigger = false;
item.Owner = reader["Owner"].ToString();
if (database.Options.Ignore.FilterNotForReplication)
item.NotForReplication = (bool)reader["is_not_for_replication"];
if (type.Equals("V"))
((View)parent).Triggers.Add(item);
else
((Table)parent).Triggers.Add(item);
}
else
{
CLRTrigger item = new CLRTrigger(parent);
item.Id = (int)reader["object_id"];
item.Name = reader["Name"].ToString();
item.IsDelete = (bool)reader["IsDelete"];
item.IsUpdate = (bool)reader["IsUpdate"];
item.IsInsert = (bool)reader["IsInsert"];
item.Owner = reader["Owner"].ToString();
item.IsAssembly = true;
item.AssemblyId = (int)reader["assembly_id"];
item.AssemblyName = reader["assembly_name"].ToString();
item.AssemblyClass = reader["assembly_class"].ToString();
item.AssemblyExecuteAs = reader["ExecuteAs"].ToString();
item.AssemblyMethod = reader["assembly_method"].ToString();
if (type.Equals("V"))
((View)parent).CLRTriggers.Add(item);
else
((Table)parent).CLRTriggers.Add(item);
/*if (!database.Options.Ignore.FilterIgnoreNotForReplication)
trigger.NotForReplication = (bool)reader["is_not_for_replication"];*/
}
}
}
}
}
}
}
catch (Exception ex)
{
messages.Add(new MessageLog(ex.Message, ex.StackTrace, MessageLog.LogType.Error));
}
}
}
}

View File

@@ -0,0 +1,106 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using OpenDBDiff.Schema.Errors;
using OpenDBDiff.Schema.Events;
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands;
using OpenDBDiff.Schema.SQLServer.Generates.Generates.Util;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GenerateUserDataTypes
{
private readonly Generate root;
public GenerateUserDataTypes(Generate root)
{
this.root = root;
}
private static string GetSQLColumnsDependencies()
{
return SQLQueries.SQLQueryFactory.Get("GetSQLColumnsDependencies");
}
private static void FillColumnsDependencies(SchemaList<UserDataType, Database> types, string connectionString)
{
if (types == null) throw new ArgumentNullException("types");
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(GetSQLColumnsDependencies(), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
types[reader["TypeName"].ToString()].Dependencies.Add(new ObjectDependency(reader["TableName"].ToString(), reader["ColumnName"].ToString(), ConvertType.GetObjectType(reader["Type"].ToString())));
}
}
}
}
}
public void Fill(Database database, string connectionString, List<MessageLog> messages)
{
//not supported in azure yet http://msdn.microsoft.com/en-us/library/ee336233.aspx
if (database.Info.Version == DatabaseInfo.SQLServerVersion.SQLServerAzure10) return;
try
{
if (database.Options.Ignore.FilterUserDataType)
{
root.RaiseOnReading(new ProgressEventArgs("Reading UDT...", Constants.READING_UDT));
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(UserDataTypeCommand.Get(database.Info.Version, database.Info.Edition), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
root.RaiseOnReadingOne(reader["Name"]);
UserDataType item = new UserDataType(database);
item.Id = (int)reader["tid"];
item.AllowNull = (bool)reader["is_nullable"];
item.Size = (short)reader["max_length"];
item.Name = reader["Name"].ToString();
item.Owner = reader["owner"].ToString();
item.Precision = int.Parse(reader["precision"].ToString());
item.Scale = int.Parse(reader["scale"].ToString());
if (!String.IsNullOrEmpty(reader["defaultname"].ToString()))
{
item.Default.Name = reader["defaultname"].ToString();
item.Default.Owner = reader["defaultowner"].ToString();
}
if (!String.IsNullOrEmpty(reader["rulename"].ToString()))
{
item.Rule.Name = reader["rulename"].ToString();
item.Rule.Owner = reader["ruleowner"].ToString();
}
item.Type = reader["basetypename"].ToString();
item.IsAssembly = (bool)reader["is_assembly_type"];
item.AssemblyId = (int)reader["assembly_id"];
item.AssemblyName = reader["assembly_name"].ToString();
item.AssemblyClass = reader["assembly_class"].ToString();
database.UserTypes.Add(item);
}
}
}
}
if (database.Options.Ignore.FilterTable)
FillColumnsDependencies(database.UserTypes, connectionString);
}
}
catch (Exception ex)
{
messages.Add(new MessageLog(ex.Message, ex.StackTrace, MessageLog.LogType.Error));
}
}
}
}

View File

@@ -0,0 +1,63 @@
using System;
using System.Data.SqlClient;
using OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GenerateUsers
{
private Generate root;
public GenerateUsers(Generate root)
{
this.root = root;
}
public void Fill(Database database, string connectioString)
{
string type;
if ((database.Options.Ignore.FilterUsers) || (database.Options.Ignore.FilterRoles))
{
using (SqlConnection conn = new SqlConnection(connectioString))
{
using (SqlCommand command = new SqlCommand(UserSQLCommand.Get(database.Info.Version, database.Info.Edition), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
type = reader["type"].ToString();
if (database.Options.Ignore.FilterUsers && (type.Equals("S") || type.Equals("U")))
{
User item = new User(database);
item.Id = (int)reader["principal_id"];
item.Name = reader["name"].ToString();
item.Login = reader["Login"].ToString();
item.Owner = reader["default_schema_name"].ToString();
database.Users.Add(item);
}
if (database.Options.Ignore.FilterRoles && (type.Equals("A") || type.Equals("R")))
{
Role item = new Role(database);
item.Id = (int)reader["principal_id"];
item.Name = reader["name"].ToString();
item.Owner = reader["default_schema_name"].ToString();
item.Password = "";
item.IsSystem = (Boolean)reader["is_fixed_role"];
if (type.Equals("A"))
item.Type = Role.RoleTypeEnum.ApplicationRole;
else
item.Type = Role.RoleTypeEnum.DatabaseRole;
database.Roles.Add(item);
}
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using OpenDBDiff.Schema.Errors;
using OpenDBDiff.Schema.Events;
using OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands;
using OpenDBDiff.Schema.SQLServer.Generates.Generates.Util;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GenerateViews
{
private Generate root;
public GenerateViews(Generate root)
{
this.root = root;
}
public void Fill(Database database, string connectionString, List<MessageLog> messages)
{
try
{
root.RaiseOnReading(new ProgressEventArgs("Reading views...", Constants.READING_VIEWS));
if (database.Options.Ignore.FilterView)
{
FillView(database, connectionString);
}
}
catch (Exception ex)
{
messages.Add(new MessageLog(ex.Message, ex.StackTrace, MessageLog.LogType.Error));
}
}
private void FillView(Database database, string connectionString)
{
int lastViewId = 0;
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(ViewSQLCommand.GetView(database.Info.Version, database.Info.Edition), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
View item = null;
while (reader.Read())
{
root.RaiseOnReadingOne(reader["name"]);
if (lastViewId != (int)reader["object_id"])
{
item = new View(database);
item.Id = (int)reader["object_id"];
item.Name = reader["name"].ToString();
item.Owner = reader["owner"].ToString();
item.IsSchemaBinding = reader["IsSchemaBound"].ToString().Equals("1");
database.Views.Add(item);
lastViewId = item.Id;
}
if (item.IsSchemaBinding)
{
if (!reader.IsDBNull(reader.GetOrdinal("referenced_major_id")))
database.Dependencies.Add(database, (int)reader["referenced_major_id"], item);
if (!String.IsNullOrEmpty(reader["TableName"].ToString()))
item.DependenciesIn.Add(reader["TableName"].ToString());
if (!String.IsNullOrEmpty(reader["DependOut"].ToString()))
item.DependenciesOut.Add(reader["DependOut"].ToString());
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,85 @@
using System.Data.SqlClient;
using System.Text;
using OpenDBDiff.Schema.Events;
using OpenDBDiff.Schema.Model;
using OpenDBDiff.Schema.SQLServer.Generates.Generates.Util;
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates
{
public class GenerateXMLSchemas
{
private Generate root;
public GenerateXMLSchemas(Generate root)
{
this.root = root;
}
private static string GetSQLColumnsDependencies()
{
return SQLQueries.SQLQueryFactory.Get("GetXMLSchemaCollections");
}
private static string GetSQLXMLSchema()
{
return SQLQueries.SQLQueryFactory.Get("GetSQLXMLSchema");
}
private static void FillColumnsDependencies(SchemaList<XMLSchema, Database> items, string connectionString)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(GetSQLColumnsDependencies(), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
items[reader["XMLName"].ToString()].Dependencies.Add(new ObjectDependency(reader["TableName"].ToString(), reader["ColumnName"].ToString(), ConvertType.GetObjectType(reader["Type"].ToString())));
}
}
}
}
}
public void Fill(Database database, string connectionString)
{
//TODO XML_SCHEMA_NAMESPACE function not supported in Azure, is there a workaround?
//not supported in azure yet
if (database.Info.Version == DatabaseInfo.SQLServerVersion.SQLServerAzure10) return;
if (database.Options.Ignore.FilterXMLSchema)
{
root.RaiseOnReading(new ProgressEventArgs("Reading XML Schema...", Constants.READING_XMLSCHEMAS));
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(GetSQLXMLSchema(), conn))
{
conn.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
root.RaiseOnReadingOne(reader["name"]);
XMLSchema item = new XMLSchema(database);
item.Id = (int)reader["ID"];
item.Name = reader["name"].ToString();
item.Owner = reader["owner"].ToString();
item.Text = reader["Text"].ToString();
database.XmlSchemas.Add(item);
}
}
}
}
if (database.Options.Ignore.FilterTable)
FillColumnsDependencies(database.XmlSchemas, connectionString);
}
}
}
}

View File

@@ -0,0 +1,192 @@
using OpenDBDiff.Schema.SQLServer.Generates.Model;
using System.Text;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands
{
internal static class ConstraintSQLCommand
{
public static string GetUniqueKey(DatabaseInfo.SQLServerVersion version, DatabaseInfo.SQLServerEdition edition)
{
switch (version)
{
case DatabaseInfo.SQLServerVersion.SQLServer2005:
return GetUniqueKey2005();
case DatabaseInfo.SQLServerVersion.SQLServerAzure10:
return GetUniqueKeyAzure();
default:
if (edition == DatabaseInfo.SQLServerEdition.Azure)
return GetUniqueKeyAzure();
else
return GetUniqueKey2008();
}
}
public static string GetCheck(DatabaseInfo.SQLServerVersion version)
{
if (version == DatabaseInfo.SQLServerVersion.SQLServer2005) return GetCheck2005();
//Fall back to highest compatible version
return GetCheck2008();
}
public static string GetPrimaryKey(DatabaseInfo.SQLServerVersion version, Table table)
{
switch (version)
{
case DatabaseInfo.SQLServerVersion.SQLServer2000:
return GetPrimaryKey2000(table);
case DatabaseInfo.SQLServerVersion.SQLServer2005:
return GetPrimaryKey2005();
case DatabaseInfo.SQLServerVersion.SQLServerAzure10:
return GetPrimaryKeyAzure();
default:
return GetPrimaryKey2008();
}
}
private static string GetUniqueKeyAzure()
{
//File Groups not supported in Azure
StringBuilder sql = new StringBuilder();
sql.Append("SELECT O.type as ObjectType, S.Name as Owner, I.object_Id AS id,'' as FileGroup, C.user_type_id, C.column_id, I.Index_id, C.Name AS ColumnName, I.Name, I.type, I.fill_factor, I.is_padded, I.allow_row_locks, I.allow_page_locks, I.ignore_dup_key, I.is_disabled, IC.is_descending_key, IC.is_included_column ");
sql.Append("FROM sys.indexes I ");
sql.Append("INNER JOIN sys.objects O ON O.object_id = I.object_id ");
sql.Append("INNER JOIN sys.schemas S ON S.schema_id = O.schema_id ");
sql.Append("INNER JOIN sys.index_columns IC ON IC.index_id = I.index_id AND IC.object_id = I.object_id ");
sql.Append("INNER JOIN sys.columns C ON C.column_id = IC.column_id AND IC.object_id = C.object_id ");
//sql.Append("LEFT JOIN sys.data_spaces AS dsidx ON dsidx.data_space_id = I.data_space_id ");
sql.Append("WHERE is_unique_constraint = 1 AND O.type <> 'TF' ORDER BY I.object_id,I.Name");
return sql.ToString();
}
private static string GetUniqueKey2008()
{
StringBuilder sql = new StringBuilder();
sql.Append("SELECT O.type as ObjectType, S.Name as Owner, I.object_Id AS id,dsidx.Name as FileGroup, C.user_type_id, C.column_id, I.Index_id, C.Name AS ColumnName, I.Name, I.type, I.fill_factor, I.is_padded, I.allow_row_locks, I.allow_page_locks, I.ignore_dup_key, I.is_disabled, IC.is_descending_key, IC.is_included_column ");
sql.Append("FROM sys.indexes I ");
sql.Append("INNER JOIN sys.objects O ON O.object_id = I.object_id ");
sql.Append("INNER JOIN sys.schemas S ON S.schema_id = O.schema_id ");
sql.Append("INNER JOIN sys.index_columns IC ON IC.index_id = I.index_id AND IC.object_id = I.object_id ");
sql.Append("INNER JOIN sys.columns C ON C.column_id = IC.column_id AND IC.object_id = C.object_id ");
sql.Append("LEFT JOIN sys.data_spaces AS dsidx ON dsidx.data_space_id = I.data_space_id ");
sql.Append("WHERE is_unique_constraint = 1 AND O.type <> 'TF' ORDER BY I.object_id,I.Name");
return sql.ToString();
}
private static string GetUniqueKey2005()
{
StringBuilder sql = new StringBuilder();
sql.Append("SELECT O.type as ObjectType, S.Name as Owner, I.object_Id AS id,dsidx.Name as FileGroup, C.user_type_id, C.column_id, I.Index_id, C.Name AS ColumnName, I.Name, I.type, I.fill_factor, I.is_padded, I.allow_row_locks, I.allow_page_locks, I.ignore_dup_key, I.is_disabled, IC.is_descending_key, IC.is_included_column ");
sql.Append("FROM sys.indexes I ");
sql.Append("INNER JOIN sys.objects O ON O.object_id = I.object_id ");
sql.Append("INNER JOIN sys.schemas S ON S.schema_id = O.schema_id ");
sql.Append("INNER JOIN sys.index_columns IC ON IC.index_id = I.index_id AND IC.object_id = I.object_id ");
sql.Append("INNER JOIN sys.columns C ON C.column_id = IC.column_id AND IC.object_id = C.object_id ");
sql.Append("LEFT JOIN sys.data_spaces AS dsidx ON dsidx.data_space_id = I.data_space_id ");
sql.Append("WHERE is_unique_constraint = 1 AND O.type <> 'TF' ORDER BY I.object_id,I.Name");
return sql.ToString();
}
private static string GetCheck2008()
{
string sql;
sql = "SELECT ";
sql += "CC.parent_object_id, ";
sql += "O.type as ObjectType, ";
sql += "CC.object_id AS ID, ";
sql += "CC.parent_column_id, ";
sql += "CC.name, ";
sql += "CC.type, ";
sql += "CC.definition, ";
sql += "CC.is_disabled, ";
sql += "CC.is_not_trusted AS WithCheck, ";
sql += "CC.is_not_for_replication, ";
sql += "0, ";
sql += "schema_name(CC.schema_id) AS Owner ";
sql += "FROM sys.check_constraints CC ";
sql += "INNER JOIN sys.objects O ON O.object_id = CC.parent_object_id ";
sql += "ORDER BY CC.parent_object_id,CC.name";
return sql;
}
private static string GetCheck2005()
{
string sql;
sql = "SELECT ";
sql += "CC.parent_object_id, ";
sql += "O.Type as ObjectType, ";
sql += "CC.object_id AS ID, ";
sql += "CC.parent_column_id, ";
sql += "CC.name, ";
sql += "CC.type, ";
sql += "CC.definition, ";
sql += "CC.is_disabled, ";
sql += "CC.is_not_trusted AS WithCheck, ";
sql += "CC.is_not_for_replication, ";
sql += "0, ";
sql += "schema_name(CC.schema_id) AS Owner ";
sql += "FROM sys.check_constraints CC ";
sql += "INNER JOIN sys.objects O ON O.object_id = CC.parent_object_id ";
sql += "ORDER BY CC.parent_object_id,CC.name";
return sql;
}
private static string GetPrimaryKeyAzure()
{
//File Groups not supported in Azure
StringBuilder sql = new StringBuilder();
sql.Append("SELECT O.type as ObjectType, S.Name as Owner, IC.key_ordinal, C.user_type_id, I.object_id AS ID, '' AS FileGroup, C.column_id, I.Index_id, C.Name AS ColumnName, I.Name, I.type, I.fill_factor, I.is_padded, I.allow_row_locks, I.allow_page_locks, I.ignore_dup_key, I.is_disabled, IC.is_descending_key, IC.is_included_column, CONVERT(bit,INDEXPROPERTY(I.object_id,I.name,'IsAutoStatistics')) AS IsAutoStatistics ");
sql.Append("FROM sys.indexes I ");
sql.Append("INNER JOIN sys.objects O ON O.object_id = I.object_id ");
sql.Append("INNER JOIN sys.schemas S ON S.schema_id = O.schema_id ");
sql.Append("INNER JOIN sys.index_columns IC ON IC.index_id = I.index_id AND IC.object_id = I.object_id ");
sql.Append("INNER JOIN sys.columns C ON C.column_id = IC.column_id AND IC.object_id = C.object_id ");
//sql.Append("LEFT JOIN sys.data_spaces AS dsidx ON dsidx.data_space_id = I.data_space_id ");
sql.Append("WHERE is_primary_key = 1 AND O.type <> 'TF' ORDER BY I.object_id");
return sql.ToString();
}
private static string GetPrimaryKey2008()
{
StringBuilder sql = new StringBuilder();
sql.Append("SELECT O.type as ObjectType, S.Name as Owner, IC.key_ordinal, C.user_type_id, I.object_id AS ID, dsidx.Name AS FileGroup, C.column_id, I.Index_id, C.Name AS ColumnName, I.Name, I.type, I.fill_factor, I.is_padded, I.allow_row_locks, I.allow_page_locks, I.ignore_dup_key, I.is_disabled, IC.is_descending_key, IC.is_included_column, CONVERT(bit,INDEXPROPERTY(I.object_id,I.name,'IsAutoStatistics')) AS IsAutoStatistics ");
sql.Append("FROM sys.indexes I ");
sql.Append("INNER JOIN sys.objects O ON O.object_id = I.object_id ");
sql.Append("INNER JOIN sys.schemas S ON S.schema_id = O.schema_id ");
sql.Append("INNER JOIN sys.index_columns IC ON IC.index_id = I.index_id AND IC.object_id = I.object_id ");
sql.Append("INNER JOIN sys.columns C ON C.column_id = IC.column_id AND IC.object_id = C.object_id ");
sql.Append("LEFT JOIN sys.data_spaces AS dsidx ON dsidx.data_space_id = I.data_space_id ");
sql.Append("WHERE is_primary_key = 1 AND O.type <> 'TF' ORDER BY I.object_id");
return sql.ToString();
}
private static string GetPrimaryKey2005()
{
StringBuilder sql = new StringBuilder();
sql.Append("SELECT O.type as ObjectType, S.Name as Owner, IC.key_ordinal, C.user_type_id, I.object_id AS ID, dsidx.Name AS FileGroup, C.column_id, I.Index_id, C.Name AS ColumnName, I.Name, I.type, I.fill_factor, I.is_padded, I.allow_row_locks, I.allow_page_locks, I.ignore_dup_key, I.is_disabled, IC.is_descending_key, IC.is_included_column, CONVERT(bit,INDEXPROPERTY(I.object_id,I.name,'IsAutoStatistics')) AS IsAutoStatistics ");
sql.Append("FROM sys.indexes I ");
sql.Append("INNER JOIN sys.objects O ON O.object_id = I.object_id ");
sql.Append("INNER JOIN sys.schemas S ON S.schema_id = O.schema_id ");
sql.Append("INNER JOIN sys.index_columns IC ON IC.index_id = I.index_id AND IC.object_id = I.object_id ");
sql.Append("INNER JOIN sys.columns C ON C.column_id = IC.column_id AND IC.object_id = C.object_id ");
sql.Append("INNER JOIN sys.data_spaces AS dsidx ON dsidx.data_space_id = I.data_space_id ");
sql.Append("WHERE is_primary_key = 1 AND O.type <> 'TF' ORDER BY I.object_id");
return sql.ToString();
}
private static string GetPrimaryKey2000(Table table)
{
StringBuilder sql = new StringBuilder();
sql.Append("SELECT CONVERT(tinyint,CASE WHEN SI.indid = 0 THEN 0 WHEN SI.indid = 1 THEN 1 WHEN SI.indid > 1 THEN 2 END) AS Type,f.groupname AS FileGroup,CONVERT(int,SI.indid) AS Index_id, CONVERT(int,SI.indid) AS ID, SI.name, SC.colid, SC.Name AS ColumnName, CONVERT(bit,0) AS is_included_column, SIK.keyno AS key_ordinal, CONVERT(bit,INDEXPROPERTY(SI.id,SI.name,'IsPadIndex')) AS is_padded, CONVERT(bit,INDEXPROPERTY(SI.id,SI.name,'IsRowLockDisallowed')) AS allow_row_locks, CONVERT(bit,INDEXPROPERTY(SI.id,SI.name,'IsPageLockDisallowed')) AS allow_page_locks, CONVERT(bit,INDEXPROPERTY(SI.id,SI.name,'IsAutoStatistics')) AS IsAutoStatistics, CONVERT(tinyint,INDEXPROPERTY(SI.id,SI.name,'IndexFillFactor')) AS fill_factor, INDEXKEY_PROPERTY(SI.id, SI.indid,SC.colid,'IsDescending') AS is_descending_key, CONVERT(bit,0) AS is_disabled, CONVERT(bit,0) AS is_included_column ");
sql.Append("FROM sysindexes SI INNER JOIN sysindexkeys SIK ON SI.indid = SIK.indid AND SIK.id = SI.ID ");
sql.Append("INNER JOIN syscolumns SC ON SC.colid = SIK.colid AND SC.id = SI.ID ");
sql.Append("inner join sysfilegroups f on f.groupid = SI.groupid ");
sql.Append("WHERE (SI.status & 0x800) = 0x800 AND SI.id = " + table.Id.ToString() + " ORDER BY SIK.keyno");
return sql.ToString();
}
}
}

View File

@@ -0,0 +1,67 @@
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands
{
internal class DatabaseSQLCommand
{
public static string GetVersion(Database databaseSchema)
{
string sql;
sql = "SELECT SERVERPROPERTY('productversion') AS Version, SERVERPROPERTY('EngineEdition') AS Edition";
return sql;
}
public static string Get(DatabaseInfo.SQLServerVersion version, DatabaseInfo.SQLServerEdition edition, Database databaseSchema)
{
switch (version)
{
case DatabaseInfo.SQLServerVersion.SQLServer2005:
return Get2005(databaseSchema);
case DatabaseInfo.SQLServerVersion.SQLServer2008:
return Get2008(databaseSchema);
case DatabaseInfo.SQLServerVersion.SQLServer2008R2:
return Get2008R2(databaseSchema);
case DatabaseInfo.SQLServerVersion.SQLServerAzure10:
return GetAzure(databaseSchema);
default:
if (edition == DatabaseInfo.SQLServerEdition.Azure)
return GetAzure(databaseSchema);
else
return Get2008R2(databaseSchema);
}
}
private static string Get2005(Database databaseSchema)
{
string sql;
sql = "SELECT DATABASEPROPERTYEX('" + databaseSchema.Name + "','IsFulltextEnabled') AS IsFullTextEnabled, DATABASEPROPERTYEX('" + databaseSchema.Name + "','Collation') AS Collation";
return sql;
}
private static string Get2008(Database databaseSchema)
{
string sql;
sql = "SELECT DATABASEPROPERTYEX('" + databaseSchema.Name + "','IsFulltextEnabled') AS IsFullTextEnabled, DATABASEPROPERTYEX('" + databaseSchema.Name + "','Collation') AS Collation";
return sql;
}
private static string Get2008R2(Database databaseSchema)
{
string sql;
sql = "SELECT DATABASEPROPERTYEX('" + databaseSchema.Name + "','IsFulltextEnabled') AS IsFullTextEnabled, DATABASEPROPERTYEX('" + databaseSchema.Name + "','Collation') AS Collation";
return sql;
}
private static string GetAzure(Database databaseSchema)
{
string sql;
//DATABASEPROPERTYEX('IsFullTextEnabled') is deprecated http://technet.microsoft.com/en-us/library/cc646010(SQL.110).aspx
sql = "SELECT 0 AS IsFullTextEnabled, DATABASEPROPERTYEX('" + databaseSchema.Name + "','Collation') AS Collation";
return sql;
}
}
}

View File

@@ -0,0 +1,72 @@
using OpenDBDiff.Schema.SQLServer.Generates.Model;
using System.Text;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands
{
internal static class FullTextIndexSQLCommand
{
public static string Get(DatabaseInfo.SQLServerVersion version)
{
switch (version)
{
case DatabaseInfo.SQLServerVersion.SQLServer2005:
return Get2005();
default:
return Get2008();
}
}
private static string Get2005()
{
StringBuilder sql = new StringBuilder();
sql.Append("SELECT ");
sql.Append("FI.object_id, ");
sql.Append("T.Name AS TableName, ");
sql.Append("FC.name AS FullTextCatalogName, ");
sql.Append("I.name AS IndexName, ");
sql.Append("FI.is_enabled, ");
sql.Append("'['+ S.name + '].['+ T.name + '].[' + FC.name + ']' AS Name, ");
sql.Append("C.name as ColumnName, ");
sql.Append("FI.change_tracking_state_desc AS ChangeTracking, ");
sql.Append("FL.name AS LanguageName ");
sql.Append("FROM sys.fulltext_indexes FI ");
sql.Append("INNER JOIN sys.fulltext_catalogs FC ON FC.fulltext_catalog_id = FI.fulltext_catalog_id ");
sql.Append("INNER JOIN sys.indexes I ON I.index_id = FI.unique_index_id and I.object_id = FI.object_id ");
sql.Append("INNER JOIN sys.tables T ON T.object_id = FI.object_id ");
sql.Append("INNER JOIN sys.schemas S ON S.schema_id = T.schema_id ");
sql.Append("INNER JOIN sys.fulltext_index_columns FIC ON FIC.object_id = FI.object_id ");
sql.Append("INNER JOIN sys.columns C ON C.object_id = FIC.object_id AND C.column_id = FIC.column_id ");
sql.Append("INNER JOIN sys.fulltext_languages FL ON FL.lcid = FIC.language_id ");
sql.Append("ORDER BY OBJECT_NAME(FI.object_id), I.name ");
return sql.ToString();
}
private static string Get2008()
{
StringBuilder sql = new StringBuilder();
sql.Append("SELECT ");
sql.Append("FI.object_id, ");
sql.Append("T.Name AS TableName, ");
sql.Append("FC.name AS FullTextCatalogName, ");
sql.Append("I.name AS IndexName, ");
sql.Append("FI.is_enabled, ");
sql.Append("'['+ S.name + '].['+ T.name + '].[' + FC.name + ']' AS Name, ");
sql.Append("C.name as ColumnName, ");
sql.Append("FL.name AS LanguageName,");
sql.Append("DS.name AS FileGroupName, ");
sql.Append("FI.change_tracking_state_desc AS ChangeTracking ");
sql.Append("FROM sys.fulltext_indexes FI ");
sql.Append("INNER JOIN sys.fulltext_catalogs FC ON FC.fulltext_catalog_id = FI.fulltext_catalog_id ");
sql.Append("INNER JOIN sys.indexes I ON I.index_id = FI.unique_index_id and I.object_id = FI.object_id ");
sql.Append("INNER JOIN sys.tables T ON T.object_id = FI.object_id ");
sql.Append("INNER JOIN sys.schemas S ON S.schema_id = T.schema_id ");
sql.Append("INNER JOIN sys.fulltext_index_columns FIC ON FIC.object_id = FI.object_id ");
sql.Append("INNER JOIN sys.columns C ON C.object_id = FIC.object_id AND C.column_id = FIC.column_id ");
sql.Append("INNER JOIN sys.data_spaces DS ON DS.data_space_id = FI.data_space_id ");
sql.Append("INNER JOIN sys.fulltext_languages FL ON FL.lcid = FIC.language_id ");
sql.Append("ORDER BY OBJECT_NAME(FI.object_id), I.name ");
return sql.ToString();
}
}
}

View File

@@ -0,0 +1,111 @@
using OpenDBDiff.Schema.SQLServer.Generates.Model;
using System.Text;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands
{
internal static class FunctionSQLCommand
{
public static string Get(DatabaseInfo.SQLServerVersion version, DatabaseInfo.SQLServerEdition edition)
{
switch (version)
{
case DatabaseInfo.SQLServerVersion.SQLServer2005:
return Get2005();
case DatabaseInfo.SQLServerVersion.SQLServer2008:
return Get2008();
case DatabaseInfo.SQLServerVersion.SQLServerAzure10:
return GetAzure();
default:
if (edition == DatabaseInfo.SQLServerEdition.Azure)
return GetAzure();
else
return Get2008();
}
}
private static string Get2005()
{
string sql = "";
sql += "select distinct ";
sql += "T.name AS ReturnType, PP.max_length, PP.precision, PP.Scale, ";
sql += "ISNULL(CONVERT(varchar,AM.execute_as_principal_id),'CALLER') as ExecuteAs, ";
sql += "P.type, ";
sql += "AF.name AS assembly_name, ";
sql += "AM.assembly_class, ";
sql += "AM.assembly_id, ";
sql += "AM.assembly_method, ";
sql += "ISNULL('[' + S3.Name + '].[' + object_name(D2.object_id) + ']','') AS DependOut, '[' + S2.Name + '].[' + object_name(D.referenced_major_id) + ']' AS TableName, D.referenced_major_id, OBJECTPROPERTY (P.object_id,'IsSchemaBound') AS IsSchemaBound, P.object_id, S.name as owner, P.name as name from sys.objects P ";
sql += "INNER JOIN sys.schemas S ON S.schema_id = P.schema_id ";
sql += "LEFT JOIN sys.sql_dependencies D ON P.object_id = D.object_id ";
sql += "LEFT JOIN sys.objects O ON O.object_id = D.referenced_major_id ";
sql += "LEFT JOIN sys.schemas S2 ON S2.schema_id = O.schema_id ";
sql += "LEFT JOIN sys.sql_dependencies D2 ON P.object_id = D2.referenced_major_id ";
sql += "LEFT JOIN sys.objects O2 ON O2.object_id = D2.object_id ";
sql += "LEFT JOIN sys.schemas S3 ON S3.schema_id = O2.schema_id ";
sql += "LEFT JOIN sys.assembly_modules AM ON AM.object_id = P.object_id ";
sql += "LEFT JOIN sys.assemblies AF ON AF.assembly_id = AM.assembly_id ";
sql += "LEFT JOIN sys.parameters PP ON PP.object_id = AM.object_id AND PP.parameter_id = 0 and PP.is_output = 1 ";
sql += "LEFT JOIN sys.types T ON T.system_type_id = PP.system_type_id ";
sql += "WHERE P.type IN ('IF','FN','TF','FS') ORDER BY P.object_id";
return sql;
}
private static string Get2008()
{
var sql = new StringBuilder();
sql.AppendLine("SELECT DISTINCT ");
sql.AppendLine("T.name AS ReturnType, PP.max_length, PP.precision, PP.Scale, ");
sql.AppendLine("ISNULL(CONVERT(varchar,AM.execute_as_principal_id),'CALLER') as ExecuteAs, ");
sql.AppendLine("P.type, ");
sql.AppendLine("AF.name AS assembly_name, ");
sql.AppendLine("AM.assembly_class, ");
sql.AppendLine("AM.assembly_id, ");
sql.AppendLine("AM.assembly_method, ");
sql.AppendLine("ISNULL('[' + S3.Name + '].[' + object_name(D2.object_id) + ']','') AS DependOut, '[' + S2.Name + '].[' + object_name(D.referenced_major_id) + ']' AS TableName, D.referenced_major_id, OBJECTPROPERTY (P.object_id,'IsSchemaBound') AS IsSchemaBound, P.object_id, S.name as owner, P.name as name from sys.objects P ");
sql.AppendLine("INNER JOIN sys.schemas S ON S.schema_id = P.schema_id ");
sql.AppendLine("LEFT JOIN sys.sql_dependencies D ON P.object_id = D.object_id ");
sql.AppendLine("LEFT JOIN sys.objects O ON O.object_id = D.referenced_major_id ");
sql.AppendLine("LEFT JOIN sys.schemas S2 ON S2.schema_id = O.schema_id ");
sql.AppendLine("LEFT JOIN sys.sql_dependencies D2 ON P.object_id = D2.referenced_major_id ");
sql.AppendLine("LEFT JOIN sys.objects O2 ON O2.object_id = D2.object_id ");
sql.AppendLine("LEFT JOIN sys.schemas S3 ON S3.schema_id = O2.schema_id ");
sql.AppendLine("LEFT JOIN sys.assembly_modules AM ON AM.object_id = P.object_id ");
sql.AppendLine("LEFT JOIN sys.assemblies AF ON AF.assembly_id = AM.assembly_id ");
sql.AppendLine("LEFT JOIN sys.parameters PP ON PP.object_id = AM.object_id AND PP.parameter_id = 0 and PP.is_output = 1 ");
sql.AppendLine("LEFT JOIN sys.types T ON T.system_type_id = PP.system_type_id ");
sql.AppendLine("WHERE P.type IN ('IF','FN','TF','FS') ORDER BY P.object_id");
return sql.ToString();
}
private static string GetAzure()
{
var sql = new StringBuilder();
sql.AppendLine("SELECT DISTINCT ");
sql.AppendLine("T.name AS ReturnType, PP.max_length, PP.precision, PP.Scale, ");
sql.AppendLine("ISNULL(CONVERT(varchar,AM.execute_as_principal_id),'CALLER') as ExecuteAs, ");
sql.AppendLine("P.type, ");
sql.AppendLine("AF.name AS assembly_name, ");
sql.AppendLine("AM.assembly_class, ");
sql.AppendLine("AM.assembly_id, ");
sql.AppendLine("AM.assembly_method, ");
sql.AppendLine("ISNULL('[' + S3.Name + '].[' + object_name(D2.referencing_id) + ']','') AS DependOut, ");
sql.AppendLine("'[' + S2.Name + '].[' + object_name(D.referenced_id) + ']' AS TableName, D.referenced_id AS referenced_major_id, OBJECTPROPERTY (P.object_id,'IsSchemaBound') AS IsSchemaBound, P.object_id, S.name as owner, P.name as name from sys.objects P ");
sql.AppendLine("INNER JOIN sys.schemas S ON S.schema_id = P.schema_id ");
sql.AppendLine("LEFT JOIN sys.sql_expression_dependencies D ON P.object_id = D.referencing_id ");
sql.AppendLine("LEFT JOIN sys.objects O ON O.object_id = D.referenced_id ");
sql.AppendLine("LEFT JOIN sys.schemas S2 ON S2.schema_id = O.schema_id ");
sql.AppendLine("LEFT JOIN sys.sql_expression_dependencies D2 ON P.object_id = D2.referenced_id ");
sql.AppendLine("LEFT JOIN sys.objects O2 ON O2.object_id = D2.referencing_id ");
sql.AppendLine("LEFT JOIN sys.schemas S3 ON S3.schema_id = O2.schema_id ");
sql.AppendLine("CROSS JOIN (SELECT null as object_id, null as execute_as_principal_id, null as assembly_class, null as assembly_id, null as assembly_method) AS AM ");
sql.AppendLine("CROSS JOIN (SELECT null AS name) AS AF");
sql.AppendLine("LEFT JOIN sys.parameters PP ON PP.object_id = AM.object_id AND PP.parameter_id = 0 and PP.is_output = 1 ");
sql.AppendLine("LEFT JOIN sys.types T ON T.system_type_id = PP.system_type_id ");
sql.AppendLine("WHERE P.type IN ('IF','FN','TF','FS') ORDER BY P.object_id");
return sql.ToString();
}
}
}

View File

@@ -0,0 +1,81 @@
using OpenDBDiff.Schema.SQLServer.Generates.Model;
using System.Text;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands
{
internal static class IndexSQLCommand
{
public static string Get(DatabaseInfo.SQLServerVersion version, DatabaseInfo.SQLServerEdition edition)
{
switch (version)
{
case DatabaseInfo.SQLServerVersion.SQLServer2005:
return Get2005();
case DatabaseInfo.SQLServerVersion.SQLServer2008:
case DatabaseInfo.SQLServerVersion.SQLServer2008R2:
return Get2008();
case DatabaseInfo.SQLServerVersion.SQLServerAzure10:
return GetAzure();
default:
if (edition == DatabaseInfo.SQLServerEdition.Azure)
return GetAzure();
else
return Get2008();
}
}
private static string Get2005()
{
StringBuilder sql = new StringBuilder();
sql.Append("SELECT OO.type AS ObjectType, IC.key_ordinal, C.user_type_id, I.object_id, dsidx.Name as FileGroup, C.column_id,C.Name AS ColumnName, I.Name, I.index_id, I.type, is_unique, ignore_dup_key, is_primary_key, is_unique_constraint, fill_factor, is_padded, is_disabled, allow_row_locks, allow_page_locks, IC.is_descending_key, IC.is_included_column, ISNULL(ST.no_recompute,0) AS NoAutomaticRecomputation ");
sql.Append("FROM sys.indexes I ");
sql.Append("INNER JOIN sys.objects OO ON OO.object_id = I.object_id ");
sql.Append("INNER JOIN sys.index_columns IC ON IC.index_id = I.index_id AND IC.object_id = I.object_id ");
sql.Append("INNER JOIN sys.data_spaces AS dsidx ON dsidx.data_space_id = I.data_space_id ");
sql.Append("INNER JOIN sys.columns C ON C.column_id = IC.column_id AND IC.object_id = C.object_id ");
sql.Append("LEFT JOIN sys.stats AS ST ON ST.stats_id = I.index_id AND ST.object_id = I.object_id ");
sql.Append("WHERE I.type IN (1,2,3) ");
sql.Append("AND is_unique_constraint = 0 AND is_primary_key = 0 "); //AND I.object_id = " + table.Id.ToString(CultureInfo.InvariantCulture) + " ");
sql.Append("AND objectproperty(I.object_id, 'IsMSShipped') <> 1 ");
sql.Append("ORDER BY I.object_id, I.Name, IC.column_id");
return sql.ToString();
}
private static string Get2008()
{
StringBuilder sql = new StringBuilder();
sql.Append("SELECT ISNULL(I.filter_definition,'') AS FilterDefinition, OO.type AS ObjectType, IC.key_ordinal, C.user_type_id, I.object_id, dsidx.Name as FileGroup, C.column_id,C.Name AS ColumnName, I.Name, I.index_id, I.type, is_unique, ignore_dup_key, is_primary_key, is_unique_constraint, fill_factor, is_padded, is_disabled, allow_row_locks, allow_page_locks, IC.is_descending_key, IC.is_included_column, ISNULL(ST.no_recompute,0) AS NoAutomaticRecomputation ");
sql.Append("FROM sys.indexes I ");
sql.Append("INNER JOIN sys.objects OO ON OO.object_id = I.object_id ");
sql.Append("INNER JOIN sys.index_columns IC ON IC.index_id = I.index_id AND IC.object_id = I.object_id ");
sql.Append("INNER JOIN sys.data_spaces AS dsidx ON dsidx.data_space_id = I.data_space_id ");
sql.Append("INNER JOIN sys.columns C ON C.column_id = IC.column_id AND IC.object_id = C.object_id ");
sql.Append("LEFT JOIN sys.stats AS ST ON ST.stats_id = I.index_id AND ST.object_id = I.object_id ");
sql.Append("WHERE I.type IN (1,2,3) ");
sql.Append("AND is_unique_constraint = 0 AND is_primary_key = 0 "); //AND I.object_id = " + table.Id.ToString(CultureInfo.InvariantCulture) + " ");
sql.Append("AND objectproperty(I.object_id, 'IsMSShipped') <> 1 ");
sql.Append("ORDER BY I.object_id, I.Name, IC.column_id");
return sql.ToString();
}
private static string GetAzure()
{
StringBuilder sql = new StringBuilder();
sql.Append("SELECT ISNULL(I.filter_definition,'') AS FilterDefinition, OO.type AS ObjectType, IC.key_ordinal, C.user_type_id, I.object_id, '' as FileGroup, C.column_id,C.Name AS ColumnName, I.Name, I.index_id, I.type, is_unique, ignore_dup_key, is_primary_key, is_unique_constraint, fill_factor, is_padded, is_disabled, allow_row_locks, allow_page_locks, IC.is_descending_key, IC.is_included_column, ISNULL(ST.no_recompute,0) AS NoAutomaticRecomputation ");
sql.Append("FROM sys.indexes I ");
sql.Append("INNER JOIN sys.objects OO ON OO.object_id = I.object_id ");
sql.Append("INNER JOIN sys.index_columns IC ON IC.index_id = I.index_id AND IC.object_id = I.object_id ");
//sql.Append("INNER JOIN sys.data_spaces AS dsidx ON dsidx.data_space_id = I.data_space_id ");
sql.Append("INNER JOIN sys.columns C ON C.column_id = IC.column_id AND IC.object_id = C.object_id ");
sql.Append("LEFT JOIN sys.stats AS ST ON ST.stats_id = I.index_id AND ST.object_id = I.object_id ");
sql.Append("WHERE I.type IN (1,2,3) ");
sql.Append("AND is_unique_constraint = 0 AND is_primary_key = 0 "); //AND I.object_id = " + table.Id.ToString(CultureInfo.InvariantCulture) + " ");
sql.Append("AND objectproperty(I.object_id, 'IsMSShipped') <> 1 ");
sql.Append("ORDER BY I.object_id, I.Name, IC.column_id");
return sql.ToString();
}
}
}

View File

@@ -0,0 +1,166 @@
using OpenDBDiff.Schema.SQLServer.Generates.Model;
using System.Text;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands
{
internal static class TableSQLCommand
{
#region Table Count
public static string GetTableCount(DatabaseInfo.SQLServerVersion version, DatabaseInfo.SQLServerEdition edition)
{
switch (version)
{
case DatabaseInfo.SQLServerVersion.SQLServer2000:
return GetTableCount2000();
default:
return GetTableCount2005();
}
}
private static string GetTableCount2000()
{
return "SELECT Count(*) FROM sysobjects SO WHERE type = 'U'";
}
private static string GetTableCount2005()
{
return "SELECT Count(*) from sys.tables";
}
#endregion Table Count
#region Table Detail
public static string GetTableDetail(DatabaseInfo.SQLServerVersion version, DatabaseInfo.SQLServerEdition edition)
{
switch (version)
{
case DatabaseInfo.SQLServerVersion.SQLServer2000:
return GetTableDetail2000();
case DatabaseInfo.SQLServerVersion.SQLServer2005:
return GetTableDetail2005();
case DatabaseInfo.SQLServerVersion.SQLServer2008:
case DatabaseInfo.SQLServerVersion.SQLServer2008R2:
return GetTableDetail2008();
case DatabaseInfo.SQLServerVersion.SQLServerAzure10:
return GetTableDetailAzure();
default:
if (edition == DatabaseInfo.SQLServerEdition.Azure)
return GetTableDetailAzure();
else
return GetTableDetail2008();
}
}
private static string GetTableDetailAzure()
{
var sql = new StringBuilder();
sql.AppendLine("SELECT DISTINCT 0 AS HasChangeTrackingTrackColumn, 0 AS HasChangeTracking, TTT.lock_escalation_desc, T.type AS ObjectType, C.Name, C.is_filestream, C.is_sparse, S4.Name as OwnerType,C.user_type_id, C.Column_Id AS ID, C.max_length AS Size, C.Precision, C.Scale, ISNULL(C.Collation_Name,'') as Collation, C.Is_nullable AS IsNullable, C.Is_RowGuidcol AS IsRowGuid, C.Is_Computed AS IsComputed, C.Is_Identity AS IsIdentity, COLUMNPROPERTY(T.object_id,C.name,'IsIdNotForRepl') AS IsIdentityRepl,IDENT_SEED('[' + S1.name + '].[' + T.Name + ']') AS IdentSeed, IDENT_INCR('[' + S1.name + '].[' + T.Name + ']') AS IdentIncrement, ISNULL(CC.Definition,'') AS Formula, ISNULL(CC.Is_Persisted,0) AS FormulaPersisted, ");
sql.AppendLine("CASE WHEN ISNULL(DEP.referencing_minor_id,0) = 0 THEN 0 ELSE 1 END AS HasComputedFormula, CASE WHEN ISNULL(IC.column_id,0) = 0 THEN 0 ELSE 1 END AS HasIndex, TY.Name AS Type, '[' + S3.Name + '].' + XSC.Name AS XMLSchema, C.Is_xml_document, TY.is_user_defined, ");
sql.AppendLine("ISNULL(TT.Name,T.Name) AS TableName, T.object_id AS TableId,S1.name AS TableOwner,Text_In_Row_limit, large_value_types_out_of_row,ISNULL(objectproperty(T.object_id, N'TableHasVarDecimalStorageFormat'),0) AS HasVarDecimal,OBJECTPROPERTY(T.OBJECT_ID,'TableHasClustIndex') AS HasClusteredIndex, ");
sql.AppendLine(" '' AS FileGroup, '' AS FileGroupText, '' AS FileGroupStream,ISNULL(DC.object_id,0) AS DefaultId, DC.name AS DefaultName, DC.definition AS DefaultDefinition, C.rule_object_id, C.default_object_id ");
sql.AppendLine("FROM sys.columns C ");
sql.AppendLine("INNER JOIN sys.objects T ON T.object_id = C.object_id ");
sql.AppendLine("INNER JOIN sys.types TY ON TY.user_type_id = C.user_type_id ");
sql.AppendLine("LEFT JOIN sys.indexes IDX ON IDX.object_id = T.object_id and IDX.index_id < 2 ");
//sql.Append("LEFT JOIN sys.data_spaces AS DSIDX ON DSIDX.data_space_id = IDX.data_space_id ");
sql.AppendLine("LEFT JOIN sys.table_types TT ON TT.type_table_object_id = C.object_id ");
sql.AppendLine("LEFT JOIN sys.tables TTT ON TTT.object_id = C.object_id ");
sql.AppendLine("LEFT JOIN sys.schemas S1 ON (S1.schema_id = TTT.schema_id and T.type = 'U') OR (S1.schema_id = TT.schema_id and T.type = 'TT')");
sql.AppendLine("LEFT JOIN sys.xml_schema_collections XSC ON XSC.xml_collection_id = C.xml_collection_id ");
sql.AppendLine("LEFT JOIN sys.schemas S3 ON S3.schema_id = XSC.schema_id ");
sql.AppendLine("LEFT JOIN sys.schemas S4 ON S4.schema_id = TY.schema_id ");
sql.AppendLine("LEFT JOIN sys.computed_columns CC ON CC.column_id = C.column_Id AND C.object_id = CC.object_id ");
sql.AppendLine("LEFT JOIN sys.sql_expression_dependencies DEP ON DEP.referenced_id = C.object_id AND DEP.referenced_minor_id = C.column_Id AND DEP.referencing_id = C.object_id ");
sql.AppendLine("LEFT JOIN sys.index_columns IC ON IC.object_id = T.object_id AND IC.column_Id = C.column_Id ");
//sql.Append("LEFT JOIN sys.data_spaces AS lob ON lob.data_space_id = TTT.lob_data_space_id ");
//sql.Append("LEFT JOIN sys.data_spaces AS filestr ON filestr.data_space_id = TTT.filestream_data_space_id ");
sql.AppendLine("LEFT JOIN sys.default_constraints DC ON DC.parent_object_id = T.object_id AND parent_column_id = C.Column_Id ");
//sql.Append("LEFT JOIN sys.change_tracking_tables CTT ON CTT.object_id = T.object_id ");
sql.AppendLine("WHERE T.type IN ('U','TT') ");
sql.AppendLine("ORDER BY ISNULL(TT.Name,T.Name),T.object_id,C.column_id");
return sql.ToString();
}
private static string GetTableDetail2008()
{
string sql = "";
sql += "SELECT DISTINCT (CASE WHEN ISNULL(CTT.is_track_columns_updated_on,0) <> 0 THEN is_track_columns_updated_on ELSE 0 END) AS HasChangeTrackingTrackColumn, (CASE WHEN ISNULL(CTT.object_id,0) <> 0 THEN 1 ELSE 0 END) AS HasChangeTracking, TTT.lock_escalation_desc, T.type AS ObjectType, C.Name, C.is_filestream, C.is_sparse, S4.Name as OwnerType,C.user_type_id, C.Column_Id AS ID, C.max_length AS Size, C.Precision, C.Scale, ISNULL(C.Collation_Name,'') as Collation, C.Is_nullable AS IsNullable, C.Is_RowGuidcol AS IsRowGuid, C.Is_Computed AS IsComputed, C.Is_Identity AS IsIdentity, COLUMNPROPERTY(T.object_id,C.name,'IsIdNotForRepl') AS IsIdentityRepl,IDENT_SEED('[' + S1.name + '].[' + T.Name + ']') AS IdentSeed, IDENT_INCR('[' + S1.name + '].[' + T.Name + ']') AS IdentIncrement, ISNULL(CC.Definition,'') AS Formula, ISNULL(CC.Is_Persisted,0) AS FormulaPersisted, CASE WHEN ISNULL(DEP.column_id,0) = 0 THEN 0 ELSE 1 END AS HasComputedFormula, CASE WHEN ISNULL(IC.column_id,0) = 0 THEN 0 ELSE 1 END AS HasIndex, TY.Name AS Type, '[' + S3.Name + '].' + XSC.Name AS XMLSchema, C.Is_xml_document, TY.is_user_defined, ISNULL(TT.Name,T.Name) AS TableName, T.object_id AS TableId,S1.name AS TableOwner,Text_In_Row_limit, large_value_types_out_of_row,ISNULL(objectproperty(T.object_id, N'TableHasVarDecimalStorageFormat'),0) AS HasVarDecimal,OBJECTPROPERTY(T.OBJECT_ID,'TableHasClustIndex') AS HasClusteredIndex,DSIDX.Name AS FileGroup,ISNULL(lob.Name,'') AS FileGroupText, ISNULL(filestr.Name,'') AS FileGroupStream,ISNULL(DC.object_id,0) AS DefaultId, DC.name AS DefaultName, DC.definition AS DefaultDefinition, C.rule_object_id, C.default_object_id ";
sql += "FROM sys.columns C ";
sql += "INNER JOIN sys.objects T ON T.object_id = C.object_id ";
sql += "INNER JOIN sys.types TY ON TY.user_type_id = C.user_type_id ";
sql += "LEFT JOIN sys.indexes IDX ON IDX.object_id = T.object_id and IDX.index_id < 2 ";
sql += "LEFT JOIN sys.data_spaces AS DSIDX ON DSIDX.data_space_id = IDX.data_space_id ";
sql += "LEFT JOIN sys.table_types TT ON TT.type_table_object_id = C.object_id ";
sql += "LEFT JOIN sys.tables TTT ON TTT.object_id = C.object_id ";
sql += "LEFT JOIN sys.schemas S1 ON (S1.schema_id = TTT.schema_id and T.type = 'U') OR (S1.schema_id = TT.schema_id and T.type = 'TT')";
sql += "LEFT JOIN sys.xml_schema_collections XSC ON XSC.xml_collection_id = C.xml_collection_id ";
sql += "LEFT JOIN sys.schemas S3 ON S3.schema_id = XSC.schema_id ";
sql += "LEFT JOIN sys.schemas S4 ON S4.schema_id = TY.schema_id ";
sql += "LEFT JOIN sys.computed_columns CC ON CC.column_id = C.column_Id AND C.object_id = CC.object_id ";
sql += "LEFT JOIN sys.sql_dependencies DEP ON DEP.referenced_major_id = C.object_id AND DEP.referenced_minor_id = C.column_Id AND DEP.object_id = C.object_id ";
sql += "LEFT JOIN sys.index_columns IC ON IC.object_id = T.object_id AND IC.column_Id = C.column_Id ";
sql += "LEFT JOIN sys.data_spaces AS lob ON lob.data_space_id = TTT.lob_data_space_id ";
sql += "LEFT JOIN sys.data_spaces AS filestr ON filestr.data_space_id = TTT.filestream_data_space_id ";
sql += "LEFT JOIN sys.default_constraints DC ON DC.parent_object_id = T.object_id AND parent_column_id = C.Column_Id ";
sql += "LEFT JOIN sys.change_tracking_tables CTT ON CTT.object_id = T.object_id ";
sql += "WHERE T.type IN ('U','TT') ";
sql += "ORDER BY ISNULL(TT.Name,T.Name),T.object_id,C.column_id";
return sql;
}
private static string GetTableDetail2005()
{
string sql = "";
sql += "SELECT DISTINCT T.type AS ObjectType, C.Name, S4.Name as OwnerType,";
sql += "C.user_type_id, C.Column_Id AS ID, C.max_length AS Size, C.Precision, C.Scale, ISNULL(C.Collation_Name,'') as Collation, C.Is_nullable AS IsNullable, C.Is_RowGuidcol AS IsRowGuid, C.Is_Computed AS IsComputed, C.Is_Identity AS IsIdentity, COLUMNPROPERTY(T.object_id,C.name,'IsIdNotForRepl') AS IsIdentityRepl,IDENT_SEED('[' + S1.name + '].[' + T.Name + ']') AS IdentSeed, IDENT_INCR('[' + S1.name + '].[' + T.Name + ']') AS IdentIncrement, ISNULL(CC.Definition,'') AS Formula, ISNULL(CC.Is_Persisted,0) AS FormulaPersisted, CASE WHEN ISNULL(DEP.column_id,0) = 0 THEN 0 ELSE 1 END AS HasComputedFormula, CASE WHEN ISNULL(IC.column_id,0) = 0 THEN 0 ELSE 1 END AS HasIndex, TY.Name AS Type, '[' + S3.Name + '].' + XSC.Name AS XMLSchema, C.Is_xml_document, TY.is_user_defined, ";
sql += "T.Name AS TableName, T.object_id AS TableId,S1.name AS TableOwner,Text_In_Row_limit, large_value_types_out_of_row,ISNULL(objectproperty(T.object_id, N'TableHasVarDecimalStorageFormat'),0) AS HasVarDecimal,OBJECTPROPERTY(T.OBJECT_ID,'TableHasClustIndex') AS HasClusteredIndex,DSIDX.Name AS FileGroup,ISNULL(LOB.Name,'') AS FileGroupText, ";
sql += "ISNULL(DC.object_id,0) AS DefaultId, DC.name AS DefaultName, DC.definition AS DefaultDefinition, C.rule_object_id, C.default_object_id ";
sql += "FROM sys.columns C ";
sql += "INNER JOIN sys.tables T ON T.object_id = C.object_id ";
sql += "INNER JOIN sys.types TY ON TY.user_type_id = C.user_type_id ";
sql += "INNER JOIN sys.schemas S1 ON S1.schema_id = T.schema_id ";
sql += "INNER JOIN sys.indexes IDX ON IDX.object_id = T.object_id and IDX.index_id < 2 ";
sql += "INNER JOIN sys.data_spaces AS DSIDX ON DSIDX.data_space_id = IDX.data_space_id ";
sql += "LEFT JOIN sys.xml_schema_collections XSC ON XSC.xml_collection_id = C.xml_collection_id ";
sql += "LEFT JOIN sys.schemas S3 ON S3.schema_id = XSC.schema_id ";
sql += "LEFT JOIN sys.schemas S4 ON S4.schema_id = TY.schema_id ";
sql += "LEFT JOIN sys.computed_columns CC ON CC.column_id = C.column_Id AND C.object_id = CC.object_id ";
sql += "LEFT JOIN sys.sql_dependencies DEP ON DEP.referenced_major_id = C.object_id AND DEP.referenced_minor_id = C.column_Id AND DEP.object_id = C.object_id ";
sql += "LEFT JOIN sys.index_columns IC ON IC.object_id = T.object_id AND IC.column_Id = C.column_Id ";
sql += "LEFT JOIN sys.data_spaces AS LOB ON LOB.data_space_id = T.lob_data_space_id ";
sql += "LEFT JOIN sys.default_constraints DC ON DC.parent_object_id = T.object_id AND parent_column_id = C.Column_Id ";
sql += "ORDER BY T.Name,T.object_id,C.column_id";
return sql;
}
private static string GetTableDetail2000()
{
string sql = "";
sql += "SELECT SO.name, ";
sql += "SO.id as object_id, ";
sql += "SU.name as Owner, ";
sql += "OBJECTPROPERTY(SO.ID,'TableTextInRowLimit') AS Text_In_Row_limit,";
sql += "0 AS HasVarDecimal, ";
sql += "CONVERT(bit,0) AS large_value_types_out_of_row, ";
sql += "F.groupname AS FileGroup, ";
sql += "ISNULL(F2.groupname,'') AS FileGroupText, ";
sql += "OBJECTPROPERTY(SO.ID,'TableHasClustIndex') AS HasClusteredIndex ";
sql += "FROM sysobjects SO ";
sql += "inner join sysindexes I ON I.id = SO.id and I.indid < 2 ";
sql += "inner join sysfilegroups f on f.groupid = i.groupid ";
sql += "left join sysindexes I2 ON I2.id = SO.id and I2.indid = 255 ";
sql += "left join sysfilegroups f2 on f2.groupid = i2.groupid ";
sql += "INNER JOIN sysusers SU ON SU.uid = SO.uid WHERE type = 'U' ORDER BY SO.name";
return sql;
}
#endregion Table Detail
}
}

View File

@@ -0,0 +1,58 @@
using OpenDBDiff.Schema.SQLServer.Generates.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands
{
internal static class UserDataTypeCommand
{
public static string Get(DatabaseInfo.SQLServerVersion version, DatabaseInfo.SQLServerEdition edition)
{
switch (version)
{
case DatabaseInfo.SQLServerVersion.SQLServer2000:
return Get2000();
case DatabaseInfo.SQLServerVersion.SQLServer2005:
return Get2005();
default:
return Get2008();
}
}
public static string Get2008()
{
string sql = "SELECT ISNULL(AF.name,'') AS assembly_name, ISNULL(AT.assembly_id,0) AS assembly_id, ISNULL(assembly_class,'') AS assembly_class, T.max_length, S2.name as defaultowner, O2.name as defaultname, S1.name as ruleowner, O.name as rulename, ISNULL(T2.Name,'') AS basetypename, S.Name AS Owner, T.Name, T.is_assembly_type, T.user_type_id AS tid, T.is_nullable, T.precision, T.scale ";
sql += "FROM sys.types T ";
sql += "INNER JOIN sys.schemas S ON S.schema_id = T.schema_id ";
sql += "LEFT JOIN sys.types T2 ON T2.user_type_id = T.system_type_id ";
sql += "LEFT JOIN sys.objects O ON O.type = 'R' and O.object_id = T.rule_object_id ";
sql += "LEFT JOIN sys.schemas S1 ON S1.schema_id = O.schema_id ";
sql += "LEFT JOIN sys.objects O2 ON O2.type = 'D' and O2.object_id = T.default_object_id ";
sql += "LEFT JOIN sys.schemas S2 ON S2.schema_id = O2.schema_id ";
sql += "LEFT JOIN sys.assembly_types AT ON AT.user_type_id = T.user_type_id AND T.is_assembly_type = 1 ";
sql += "LEFT JOIN sys.assemblies AF ON AF.assembly_id = AT.assembly_id ";
sql += "WHERE T.is_user_defined = 1 AND T.is_table_type = 0 ORDER BY T.Name";
return sql;
}
public static string Get2005()
{
string sql = "select ISNULL(AF.name,'') AS assembly_name, ISNULL(AT.assembly_id,0) AS assembly_id, ISNULL(assembly_class,'') AS assembly_class, T.max_length, S2.name as defaultowner, O2.name as defaultname, S1.name as ruleowner, O.name as rulename, ISNULL(T2.Name,'') AS basetypename, S.Name AS Owner, T.Name, T.is_assembly_type, T.user_type_id AS tid, T.is_nullable, T.precision, T.scale from sys.types T ";
sql += "INNER JOIN sys.schemas S ON S.schema_id = T.schema_id ";
sql += "LEFT JOIN sys.types T2 ON T2.user_type_id = T.system_type_id ";
sql += "LEFT JOIN sys.objects O ON O.type = 'R' and O.object_id = T.rule_object_id ";
sql += "LEFT JOIN sys.schemas S1 ON S1.schema_id = O.schema_id ";
sql += "LEFT JOIN sys.objects O2 ON O2.type = 'D' and O2.object_id = T.default_object_id ";
sql += "LEFT JOIN sys.schemas S2 ON S2.schema_id = O2.schema_id ";
sql += "LEFT JOIN sys.assembly_types AT ON AT.user_type_id = T.user_type_id AND T.is_assembly_type = 1 ";
sql += "LEFT JOIN sys.assemblies AF ON AF.assembly_id = AT.assembly_id ";
sql += "WHERE T.is_user_defined = 1 ORDER BY T.Name";
return sql;
}
public static string Get2000()
{
return "";
}
}
}

View File

@@ -0,0 +1,51 @@
using OpenDBDiff.Schema.SQLServer.Generates.Model;
using System.Text;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands
{
internal static class UserSQLCommand
{
public static string Get(DatabaseInfo.SQLServerVersion version, DatabaseInfo.SQLServerEdition edition)
{
switch (version)
{
case DatabaseInfo.SQLServerVersion.SQLServer2000:
case DatabaseInfo.SQLServerVersion.SQLServer2005:
case DatabaseInfo.SQLServerVersion.SQLServer2008:
case DatabaseInfo.SQLServerVersion.SQLServer2008R2:
return Get2008();
case DatabaseInfo.SQLServerVersion.SQLServerAzure10:
return GetAzure();
default:
if (edition == DatabaseInfo.SQLServerEdition.Azure)
return GetAzure();
else
return Get2008();
}
}
private static string Get2008()
{
var sql = new StringBuilder();
sql.AppendLine("SELECT is_fixed_role, type, ISNULL(suser_sname(sid),'') AS Login,Name,principal_id, ISNULL(default_schema_name,'') AS default_schema_name ");
sql.AppendLine("FROM sys.database_principals ");
sql.AppendLine("WHERE type IN ('S','U','A','R') ");
sql.AppendLine("ORDER BY Name");
return sql.ToString();
}
private static string GetAzure()
{
var sql = new StringBuilder();
//to get LoginName in Azure (asside for the current login) you would have to link to master and query sys.sysusers or sys.sql_users
//the CASE test below will at least get you the Current login
sql.AppendLine("SELECT is_fixed_role, type, CASE WHEN suser_sid()=sid THEN suser_sname() ELSE '' END AS Login,Name,principal_id, ISNULL(default_schema_name,'') AS default_schema_name ");
sql.AppendLine("FROM sys.database_principals ");
sql.AppendLine("WHERE type IN ('S','U','A','R') ");
sql.AppendLine("ORDER BY Name");
return sql.ToString();
}
}
}

View File

@@ -0,0 +1,68 @@
using OpenDBDiff.Schema.SQLServer.Generates.Model;
using System.Text;
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates.SQLCommands
{
internal static class ViewSQLCommand
{
#region View
public static string GetView(DatabaseInfo.SQLServerVersion version, DatabaseInfo.SQLServerEdition edition)
{
switch (version)
{
case DatabaseInfo.SQLServerVersion.SQLServer2000:
case DatabaseInfo.SQLServerVersion.SQLServer2005:
case DatabaseInfo.SQLServerVersion.SQLServer2008:
case DatabaseInfo.SQLServerVersion.SQLServer2008R2:
return GetViewSql2008();
case DatabaseInfo.SQLServerVersion.SQLServerAzure10:
return GetViewSqlAzure();
default:
if (edition == DatabaseInfo.SQLServerEdition.Azure)
return GetViewSqlAzure();
else
return GetViewSql2008();
}
}
private static string GetViewSql2008()
{
string sql = "";
sql += "select distinct ISNULL('[' + S3.Name + '].[' + object_name(D2.object_id) + ']','') AS DependOut, '[' + S2.Name + '].[' + object_name(D.referenced_major_id) + ']' AS TableName, D.referenced_major_id, OBJECTPROPERTY (P.object_id,'IsSchemaBound') AS IsSchemaBound, P.object_id, S.name as owner, P.name as name from sys.views P ";
sql += "INNER JOIN sys.schemas S ON S.schema_id = P.schema_id ";
sql += "LEFT JOIN sys.sql_dependencies D ON P.object_id = D.object_id ";
sql += "LEFT JOIN sys.objects O ON O.object_id = D.referenced_major_id ";
sql += "LEFT JOIN sys.schemas S2 ON S2.schema_id = O.schema_id ";
sql += "LEFT JOIN sys.sql_dependencies D2 ON P.object_id = D2.referenced_major_id ";
sql += "LEFT JOIN sys.objects O2 ON O2.object_id = D2.object_id ";
sql += "LEFT JOIN sys.schemas S3 ON S3.schema_id = O2.schema_id ";
sql += "ORDER BY P.object_id";
return sql;
}
private static string GetViewSqlAzure()
{
var sql = new StringBuilder();
//Avoid using sql_dependencies. Use sys.sql_expression_dependencies instead. http://msdn.microsoft.com/en-us/library/ms174402.aspx
sql.Append("SELECT DISTINCT ISNULL('[' + S3.Name + '].[' + object_name(D2.referencing_id) + ']','') AS DependOut, ");
sql.Append("'[' + S2.Name + '].[' + object_name(D.referenced_id) + ']' AS TableName, ");
sql.Append("D.referenced_id AS referenced_major_id, OBJECTPROPERTY (P.object_id,'IsSchemaBound') AS IsSchemaBound, ");
sql.Append("P.object_id, S.name as owner, P.name as name ");
sql.Append("FROM sys.views P ");
sql.Append("INNER JOIN sys.schemas S ON S.schema_id = P.schema_id ");
sql.Append("LEFT JOIN sys.sql_expression_dependencies D ON P.object_id = D.referencing_id ");
sql.Append("LEFT JOIN sys.objects O ON O.object_id = D.referenced_id ");
sql.Append("LEFT JOIN sys.schemas S2 ON S2.schema_id = O.schema_id ");
sql.Append("LEFT JOIN sys.sql_expression_dependencies D2 ON P.object_id = D2.referenced_id ");
sql.Append("LEFT JOIN sys.objects O2 ON O2.object_id = D2.referencing_id ");
sql.Append("LEFT JOIN sys.schemas S3 ON S3.schema_id = O2.schema_id ");
sql.Append("ORDER BY P.object_id ");
return sql.ToString();
}
#endregion View
}
}

View File

@@ -0,0 +1,38 @@
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates.Util
{
/// <summary>
/// This class implements a fast conversion from a byte array to an hex string.
/// </summary>
public class ByteToHexEncoder
{
private static readonly uint[] _lookup32 = CreateLookup32();
private static uint[] CreateLookup32()
{
var result = new uint[256];
for (int i = 0; i < 256; i++)
{
var s = i.ToString("X2");
result[i] = ((uint)s[0]) + ((uint)s[1] << 16);
}
return result;
}
public static string ByteArrayToHex(byte[] bytes)
{
var result = new char[2 + bytes.Length * 2];
result[0] = '0';
result[1] = 'x';
for (int i = 0; i < bytes.Length; i++)
{
var val = _lookup32[bytes[i]];
result[2 * i + 2] = (char)val;
result[2 * i + 3] = (char)(val >> 16);
}
return new string(result);
}
}
}

View File

@@ -0,0 +1,28 @@
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates.Util
{
internal class Constants
{
public const int READING_RULES = 0;
public const int READING_TABLES = 1;
public const int READING_CONSTRAINTS = 2;
public const int READING_UDT = 3;
public const int READING_XMLSCHEMAS = 4;
public const int READING_SCHEMAS = 5;
public const int READING_USER = 6;
public const int READING_PARTITIONFUNCTION = 7;
public const int READING_PARTITIONSCHEME = 8;
public const int READING_FILEGROUPS = 9;
public const int READING_DLLTRIGGERS = 10;
public const int READING_SYNONYMS = 11;
public const int READING_ASSEMBLIES = 12;
public const int READING_PROCEDURES = 13;
public const int READING_VIEWS = 14;
public const int READING_FUNCTIONS = 15;
public const int READING_INDEXES = 16;
public const int READING_TRIGGERS = 17;
public const int READING_TEXTOBJECTS = 18;
public const int READING_EXTENDED_PROPERTIES = 19;
public const int READING_MAX = 20;
}
}

View File

@@ -0,0 +1,17 @@
namespace OpenDBDiff.Schema.SQLServer.Generates.Generates.Util
{
internal static class ConvertType
{
public static ObjectType GetObjectType(string type)
{
if (type.Trim().Equals("V")) return ObjectType.View;
if (type.Trim().Equals("U")) return ObjectType.Table;
if (type.Trim().Equals("FN")) return ObjectType.Function;
if (type.Trim().Equals("TF")) return ObjectType.Function;
if (type.Trim().Equals("IF")) return ObjectType.Function;
if (type.Trim().Equals("P")) return ObjectType.StoredProcedure;
if (type.Trim().Equals("TR")) return ObjectType.Trigger;
return ObjectType.None;
}
}
}

View 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; }
}
}
}

View 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;
}
}
}

View 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; }
}
}
}

View 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;
}
}
}

View File

@@ -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;
}
}
}

View 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;
}
}
}

View 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));
}
}
}

View 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);
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}
}

View 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
}
}

View 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;
}
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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; }
}
}

View File

@@ -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;
}
}
}

View 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;
}
}
}

View 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";
}
}
}

View 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();
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View File

@@ -0,0 +1,9 @@
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
{
public class FullTextIndexColumn
{
public string Language { get; set; }
public string ColumnName { get; set; }
}
}

View 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;
}
}
}

View 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; }
}
}

View 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;
}
}
}

View 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);*/
}
}
}

View 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;
}
}
}

View File

@@ -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; }
}
}

View File

@@ -0,0 +1,9 @@
using OpenDBDiff.Schema.Model;
namespace OpenDBDiff.Schema.SQLServer.Generates.Model
{
public interface ISQLServerSchemaBase
{
SchemaList<ExtendedProperty, ISchemaBase> ExtendedProperties { get; }
}
}

View File

@@ -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)); }
}
}
}

Some files were not shown because too many files have changed in this diff Show More