using OpenDBDiff.Abstractions.Schema; using OpenDBDiff.Abstractions.Schema.Model; using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; namespace OpenDBDiff.SqlServer.Schema.Model { public class PartitionFunction : SQLServerSchemaBase { private const int IS_STRING = 0; private const int IS_UNIQUE = 1; private const int IS_DATE = 2; private const int IS_NUMERIC = 3; public PartitionFunction(ISchemaBase parent) : base(parent, ObjectType.PartitionFunction) { Values = new List(); } public new PartitionFunction Clone(ISchemaBase parent) { PartitionFunction item = new PartitionFunction(parent); item.Id = this.Id; item.IsBoundaryRight = this.IsBoundaryRight; item.Name = this.Name; item.Precision = this.Precision; item.Scale = this.Scale; item.Size = this.Size; item.Type = this.Type; this.Values.ForEach(value => { item.Values.Add(value); }); return item; } public List Values { get; set; } public PartitionFunction Old { get; set; } public int Precision { get; set; } public int Scale { get; set; } public int Size { get; set; } public bool IsBoundaryRight { get; set; } public string Type { get; set; } private int ValueItem(string typeName) { if ((typeName.Equals("nchar") || typeName.Equals("nvarchar") || typeName.Equals("varchar") || typeName.Equals("char"))) return IS_STRING; if (typeName.Equals("uniqueidentifier")) return IS_UNIQUE; if (typeName.Equals("datetime") || typeName.Equals("smalldatetime") || typeName.Equals("datetime2") || typeName.Equals("time") || typeName.Equals("datetimeoffset")) return IS_DATE; if (typeName.Equals("numeric") || typeName.Equals("decimal") || typeName.Equals("float") || typeName.Equals("real") || typeName.Equals("money") || typeName.Equals("smallmoney")) return IS_NUMERIC; return IS_NUMERIC; } public override string ToSql() { string sqltype = Type; if (Type.Equals("binary") || Type.Equals("varbinary") || Type.Equals("varchar") || Type.Equals("char") || Type.Equals("nchar") || Type.Equals("nvarchar")) { if (Type.Equals("nchar") || Type.Equals("nvarchar")) sqltype += " (" + (Size / 2).ToString(CultureInfo.InvariantCulture) + ")"; else sqltype += " (" + Size.ToString(CultureInfo.InvariantCulture) + ")"; } if (Type.Equals("numeric") || Type.Equals("decimal")) sqltype += " (" + Precision.ToString(CultureInfo.InvariantCulture) + "," + Scale.ToString(CultureInfo.InvariantCulture) + ")"; if (((Database)Parent).Info.Version >= DatabaseInfo.SQLServerVersion.SQLServer2008) { if (Type.Equals("datetime2") || Type.Equals("datetimeoffset") || Type.Equals("time")) sqltype += "(" + Scale.ToString(CultureInfo.InvariantCulture) + ")"; } string sql = "CREATE PARTITION FUNCTION [" + Name + "](" + sqltype + ") AS RANGE\r\n "; if (IsBoundaryRight) sql += "RIGHT"; else sql += "LEFT"; sql += " FOR VALUES ("; string sqlvalues = ""; int valueType = ValueItem(Type); if (valueType == IS_STRING) Values.ForEach(item => { sqlvalues += "N'" + item + "',"; }); else if (valueType == IS_DATE) Values.ForEach(item => { sqlvalues += "'" + DateTime.Parse(item).ToString("yyyyMMdd HH:mm:ss.fff") + "',"; }); else if (valueType == IS_UNIQUE) Values.ForEach(item => { sqlvalues += "'{" + item + "}',"; }); else if (valueType == IS_NUMERIC) Values.ForEach(item => { sqlvalues += item.Replace(",", ".") + ","; }); else Values.ForEach(item => { sqlvalues += item + ","; }); sql += sqlvalues.Substring(0, sqlvalues.Length - 1) + ")"; return sql + "\r\nGO\r\n"; } public override string ToSqlDrop() { return "DROP PARTITION FUNCTION [" + Name + "]\r\nGO\r\n"; } public override string ToSqlAdd() { return ToSql(); } public string ToSqlAlter() { StringBuilder sqlFinal = new StringBuilder(); string sql = "ALTER PARTITION FUNCTION [" + Name + "]()\r\n"; string sqlmergue = ""; string sqsplit = ""; IEnumerable items = Old.Values.Except(this.Values); int valueType = ValueItem(Type); foreach (var item in items) { sqlmergue = "MERGE RANGE ("; if (valueType == IS_STRING) sqlmergue += "N'" + item + "'"; else if (valueType == IS_DATE) sqlmergue += "'" + DateTime.Parse(item).ToString("yyyyMMdd HH:mm:ss.fff") + "'"; else if (valueType == IS_UNIQUE) sqlmergue += "'{" + item + "}'"; else if (valueType == IS_NUMERIC) sqlmergue += item.Replace(",", "."); else sqlmergue += item; sqlFinal.Append(sql + sqlmergue + ")\r\nGO\r\n"); } IEnumerable items2 = this.Values.Except(this.Old.Values); foreach (var item in items2) { sqsplit = "SPLIT RANGE ("; if (valueType == IS_STRING) sqsplit += "N'" + item + "'"; else if (valueType == IS_DATE) sqsplit += "'" + DateTime.Parse(item).ToString("yyyyMMdd HH:mm:ss.fff") + "'"; else if (valueType == IS_UNIQUE) sqsplit += "'{" + item + "}'"; else if (valueType == IS_NUMERIC) sqsplit += item.Replace(",", "."); else sqsplit += item; sqlFinal.Append(sql + sqsplit + ")\r\nGO\r\n"); } return sqlFinal.ToString(); } /// /// Devuelve el schema de diferencias del Schema en formato SQL. /// public override SQLScriptList ToSqlDiff(System.Collections.Generic.ICollection schemas) { SQLScriptList listDiff = new SQLScriptList(); if (this.Status == ObjectStatus.Drop) { listDiff.Add(ToSqlDrop(), 0, ScriptAction.DropPartitionFunction); } if (this.Status == ObjectStatus.Rebuild) { listDiff.Add(ToSqlDrop() + ToSqlAdd(), 0, ScriptAction.AlterPartitionFunction); } if (this.Status == ObjectStatus.Alter) listDiff.Add(ToSqlAlter(), 0, ScriptAction.AlterPartitionFunction); if (this.Status == ObjectStatus.Create) { listDiff.Add(ToSqlAdd(), 0, ScriptAction.AddPartitionFunction); } return listDiff; } public static Boolean Compare(PartitionFunction origin, PartitionFunction destination) { if (destination == null) throw new ArgumentNullException("destination"); if (origin == null) throw new ArgumentNullException("origin"); if (!origin.Type.Equals(destination.Type)) return false; if (origin.Size != destination.Size) return false; if (origin.Precision != destination.Precision) return false; if (origin.Scale != destination.Scale) return false; if (origin.IsBoundaryRight != destination.IsBoundaryRight) return false; return true; } public static Boolean CompareValues(PartitionFunction origin, PartitionFunction destination) { if (destination == null) throw new ArgumentNullException("destination"); if (origin == null) throw new ArgumentNullException("origin"); if (origin.Values.Count != destination.Values.Count) return false; if (origin.Values.Except(destination.Values).ToList().Count != 0) return false; return true; } } }