diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AddIndexToCmsMacroTable.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AddIndexToCmsMacroTable.cs index 4ca0a6eeb8..c67bd72fd6 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AddIndexToCmsMacroTable.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AddIndexToCmsMacroTable.cs @@ -3,6 +3,7 @@ using System.CodeDom; 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; @@ -40,6 +41,26 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven //make sure it doesn't already exist if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsMacro_Alias")) == false) { + //in order to create this index, we need to ensure that there are no duplicates. This could have happened with very old/corrupt umbraco versions. + // So we'll remove any duplicates based on alias and only keep the one with the smallest id since I'm pretty sure we'd always choose the 'first' one + // when running a query. + + //NOTE: Using full SQL statement here in case the DTO has changed between versions + var macros = Context.Database.Fetch("SELECT * FROM cmsMacro") + .GroupBy(x => x.Alias) + .Where(x => x.Count() > 1); + + foreach (var m in macros) + { + //get the min id (to keep) + var minId = m.Min(x => x.Id); + //delete all the others + foreach (var macroDto in m.Where(x => x.Id != minId)) + { + Delete.FromTable("cmsMacro").Row(new { id = macroDto.Id }); + } + } + Create.Index("IX_cmsMacro_Alias").OnTable("cmsMacro").OnColumn("macroAlias").Unique(); } diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterTagsTable.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterTagsTable.cs index 6060b76fa4..d069d8222d 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterTagsTable.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterTagsTable.cs @@ -27,6 +27,11 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven }).ToArray(); //add a foreign key to the parent id column too! + + //In some cases in very old corrupted db's this will fail, so it means we need to clean the data first + //set the parentID to NULL where it doesn't actually exist in the normal ids + Execute.Sql(@"UPDATE cmsTags SET parentId = NULL WHERE parentId IS NOT NULL AND parentId NOT IN (SELECT id FROM cmsTags)"); + Create.ForeignKey("FK_cmsTags_cmsTags") .FromTable("cmsTags") .ForeignColumn("ParentId") diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/UpdateRelatedLinksData.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/UpdateRelatedLinksData.cs index a2e2056d3a..830adfd7fb 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/UpdateRelatedLinksData.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/UpdateRelatedLinksData.cs @@ -55,9 +55,11 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven } var propertyTypeIds = propertyData.Select(x => x.PropertyTypeId).Distinct(); - var propertyTypes = database.Fetch( - "WHERE id in (@propertyTypeIds)", new { propertyTypeIds = propertyTypeIds }); + //NOTE: We are writing the full query because we've added a column to the PropertyTypeDto in later versions so one of the columns + // won't exist yet + var propertyTypes = database.Fetch("SELECT * FROM cmsPropertyType WHERE id in (@propertyTypeIds)", new { propertyTypeIds = propertyTypeIds }); + foreach (var data in propertyData) { if (string.IsNullOrEmpty(data.Text) == false) diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MigrateAndRemoveTemplateMasterColumn.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MigrateAndRemoveTemplateMasterColumn.cs index 3cea873f73..ac0310b0cf 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MigrateAndRemoveTemplateMasterColumn.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MigrateAndRemoveTemplateMasterColumn.cs @@ -30,16 +30,46 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe } //update the parentId column for all templates to be correct so it matches the current 'master' template - //NOTE: we are using dynamic because we need to get the data in a column that no longer exists in the schema - var templates = Context.Database.Fetch(new Sql().Select("*").From()); - foreach (var template in templates) - { - Update.Table("umbracoNode").Set(new {parentID = template.master ?? -1}).Where(new {id = template.nodeId}); - //now build the correct path for the template - Update.Table("umbracoNode").Set(new { path = BuildPath (template, templates)}).Where(new { id = template.nodeId }); - - } + //In some old corrupted databases, the information will not be correct in the master column so we need to fix that + //first by nulling out the master column where the id doesn't actually exist + Execute.Sql(@"UPDATE cmsTemplate SET master = NULL WHERE " + + SqlSyntax.GetQuotedColumnName("master") + @" IS NOT NULL AND " + + SqlSyntax.GetQuotedColumnName("master") + @" NOT IN (SELECT nodeId FROM cmsTemplate)"); + + //Now we can bulk update the parentId column + Execute.Sql(@"UPDATE umbracoNode +SET parentID = COALESCE(t2." + SqlSyntax.GetQuotedColumnName("master") + @", -1) +FROM umbracoNode t1 +INNER JOIN cmsTemplate t2 +ON t1.id = t2.nodeId"); + + //Now we can update the path, but this needs to be done in a delegate callback so that the query runs after the updates just completed + Execute.Code(database => + { + //NOTE: we are using dynamic because we need to get the data in a column that no longer exists in the schema + var templates = Context.Database.Fetch(new Sql().Select("*").From()); + foreach (var template in templates) + { + var sql = string.Format(SqlSyntax.UpdateData, + SqlSyntax.GetQuotedTableName("umbracoNode"), + "path=@buildPath", + "id=@nodeId"); + + LogHelper.Info("Executing sql statement: " + sql); + + //now build the correct path for the template + database.Execute(sql, new + { + buildPath = BuildPath(template, templates), + nodeId = template.nodeId + }); + } + + return string.Empty; + }); + + //now remove the master column and key if (this.Context.CurrentDatabaseProvider == DatabaseProviders.MySql) diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixZeroOne/UpdatePropertyTypesAndGroups.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixZeroOne/UpdatePropertyTypesAndGroups.cs index 5f27bfa4f5..6598719454 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixZeroOne/UpdatePropertyTypesAndGroups.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixZeroOne/UpdatePropertyTypesAndGroups.cs @@ -28,8 +28,11 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixZeroOne { if (database != null) { - //Fetch all PropertyTypes that belongs to a PropertyTypeGroup - var propertyTypes = database.Fetch("WHERE propertyTypeGroupId > 0"); + //Fetch all PropertyTypes that belongs to a PropertyTypeGroup + //NOTE: We are writing the full query because we've added a column to the PropertyTypeDto in later versions so one of the columns + // won't exist yet + var propertyTypes = database.Fetch("SELECT * FROM cmsPropertyType WHERE propertyTypeGroupId > 0"); + var propertyGroups = database.Fetch("WHERE id > 0"); foreach (var propertyType in propertyTypes)