diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Insert/Expressions/InsertDataExpression.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Insert/Expressions/InsertDataExpression.cs index 568087733b..7cbfe8b773 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Insert/Expressions/InsertDataExpression.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Insert/Expressions/InsertDataExpression.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Text; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.SqlSyntax; @@ -9,55 +10,79 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Insert.Expressions { private readonly List _rows = new List(); + [Obsolete("Use the other constructors specifying an ISqlSyntaxProvider instead")] public InsertDataExpression() { } + [Obsolete("Use the other constructors specifying an ISqlSyntaxProvider instead")] public InsertDataExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders) : base(current, databaseProviders) { } + public InsertDataExpression(ISqlSyntaxProvider sqlSyntax) : base(sqlSyntax) + { + } + + public InsertDataExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ISqlSyntaxProvider sqlSyntax) : base(current, databaseProviders, sqlSyntax) + { + } + public string SchemaName { get; set; } public string TableName { get; set; } + public bool EnabledIdentityInsert { get; set; } - public List Rows { get { return _rows; } } - - public override string ToString() { - //TODO: This works for single insertion entries, not sure if it is valid for bulk insert operations!!! - if (IsExpressionSupported() == false) return string.Empty; var insertItems = new List(); - - foreach (var item in Rows) + var sb = new StringBuilder(); + + if (EnabledIdentityInsert && SqlSyntax.SupportsIdentityInsert()) { - var cols = ""; - var vals = ""; - foreach (var keyVal in item) - { - cols += keyVal.Key + ","; - vals += GetQuotedValue(keyVal.Value) + ","; - } - cols = cols.TrimEnd(','); - vals = vals.TrimEnd(','); - - - var sql = string.Format(SqlSyntaxContext.SqlSyntaxProvider.InsertData, - SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(TableName), - cols, vals); - - insertItems.Add(sql); + sb.AppendLine(string.Format("SET IDENTITY_INSERT {0} ON;", SqlSyntax.GetQuotedTableName(TableName))); } - return string.Join(",", insertItems); + try + { + foreach (var item in Rows) + { + var cols = ""; + var vals = ""; + foreach (var keyVal in item) + { + cols += keyVal.Key + ","; + vals += GetQuotedValue(keyVal.Value) + ","; + } + cols = cols.TrimEnd(','); + vals = vals.TrimEnd(','); + + + var sql = string.Format(SqlSyntax.InsertData, + SqlSyntax.GetQuotedTableName(TableName), + cols, vals); + + insertItems.Add(sql); + } + + sb.AppendLine(string.Join(",", insertItems)); + } + finally + { + if (EnabledIdentityInsert && SqlSyntax.SupportsIdentityInsert()) + { + sb.AppendLine(string.Format(";SET IDENTITY_INSERT {0} OFF;", SqlSyntax.GetQuotedTableName(TableName))); + } + } + + return sb.ToString(); } diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Insert/IInsertDataSyntax.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Insert/IInsertDataSyntax.cs index fb0585f0e6..5791f0cb83 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Insert/IInsertDataSyntax.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Insert/IInsertDataSyntax.cs @@ -2,6 +2,7 @@ { public interface IInsertDataSyntax : IFluentSyntax { + IInsertDataSyntax EnableIdentityInsert(); IInsertDataSyntax Row(object dataAsAnonymousType); } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Insert/InsertDataBuilder.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Insert/InsertDataBuilder.cs index 9b419f8daf..4f8bf2dfcc 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Insert/InsertDataBuilder.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Insert/InsertDataBuilder.cs @@ -14,6 +14,12 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Insert _expression = expression; } + public IInsertDataSyntax EnableIdentityInsert() + { + _expression.EnabledIdentityInsert = true; + return this; + } + public IInsertDataSyntax Row(object dataAsAnonymousType) { _expression.Rows.Add(GetData(dataAsAnonymousType)); diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/AddForeignKeysForLanguageAndDictionaryTables.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/AddForeignKeysForLanguageAndDictionaryTables.cs index 81b93a8883..eea56031d4 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/AddForeignKeysForLanguageAndDictionaryTables.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/AddForeignKeysForLanguageAndDictionaryTables.cs @@ -3,6 +3,8 @@ using System.Data; using System.Linq; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; +using Umbraco.Core.Models.Rdbms; +using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.SqlSyntax; namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZero @@ -30,6 +32,53 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe Delete.FromTable("cmsLanguageText").Row(new { pk = pk }); } + var columns = SqlSyntax.GetColumnsInSchema(Context.Database).Distinct().ToArray(); + + if (columns.Any(x => x.ColumnName.InvariantEquals("id") + && x.TableName.InvariantEquals("umbracoLanguage") + && x.DataType.InvariantEquals("smallint"))) + { + //Ensure that the umbracoLanguage PK is INT and not SmallInt (which it might be in older db versions) + // In order to 'change' this to an INT, we have to run a full migration script which is super annoying + Create.Table("umbracoLanguage_TEMP") + .WithColumn("id").AsInt32().NotNullable().Identity() + .WithColumn("languageISOCode").AsString(10).Nullable() + .WithColumn("languageCultureName").AsString(50).Nullable(); + + var currentData = this.Context.Database.Fetch(new Sql().Select("*").From(SqlSyntax)); + foreach (var languageDto in currentData) + { + Insert.IntoTable("umbracoLanguage_TEMP") + .EnableIdentityInsert() + .Row(new {id = languageDto.Id, languageISOCode = languageDto.IsoCode, languageCultureName = languageDto.CultureName}); + } + + //ok, all data has been copied over, drop the old table, rename the temp table and re-add constraints. + Delete.Table("umbracoLanguage"); + Rename.Table("umbracoLanguage_TEMP").To("umbracoLanguage"); + + //add the pk + Create.PrimaryKey("PK_language").OnTable("umbracoLanguage").Column("id"); + } + + var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database) + .Select(x => new DbIndexDefinition + { + TableName = x.Item1, + IndexName = x.Item2, + ColumnName = x.Item3, + IsUnique = x.Item4 + }).ToArray(); + + //make sure it doesn't already exist + if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsDictionary_id")) == false) + { + Create.Index("IX_cmsDictionary_id").OnTable("cmsDictionary") + .OnColumn("id").Ascending() + .WithOptions().NonClustered() + .WithOptions().Unique(); + } + //now we need to create a foreign key Create.ForeignKey("FK_cmsLanguageText_umbracoLanguage_id").FromTable("cmsLanguageText").ForeignColumn("languageId") .ToTable("umbracoLanguage").PrimaryColumn("id").OnDeleteOrUpdate(Rule.None); @@ -52,7 +101,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe public override void Down() { - throw new System.NotImplementedException(); + throw new NotImplementedException(); } } } \ No newline at end of file