Fixes: U4-7079 Upgrade issue from an older version

This commit is contained in:
Shannon
2015-09-09 23:20:46 +02:00
parent 3a62fb5900
commit c4b8dcd88b
5 changed files with 74 additions and 13 deletions

View File

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

View File

@@ -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")

View File

@@ -55,9 +55,11 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
}
var propertyTypeIds = propertyData.Select(x => x.PropertyTypeId).Distinct();
var propertyTypes = database.Fetch<PropertyTypeDto>(
"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<PropertyTypeDto>("SELECT * FROM cmsPropertyType WHERE id in (@propertyTypeIds)", new { propertyTypeIds = propertyTypeIds });
foreach (var data in propertyData)
{
if (string.IsNullOrEmpty(data.Text) == false)

View File

@@ -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<dynamic>(new Sql().Select("*").From<TemplateDto>());
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<dynamic>(new Sql().Select("*").From<TemplateDto>());
foreach (var template in templates)
{
var sql = string.Format(SqlSyntax.UpdateData,
SqlSyntax.GetQuotedTableName("umbracoNode"),
"path=@buildPath",
"id=@nodeId");
LogHelper.Info<MigrateAndRemoveTemplateMasterColumn>("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)

View File

@@ -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<PropertyTypeDto>("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<PropertyTypeDto>("SELECT * FROM cmsPropertyType WHERE propertyTypeGroupId > 0");
var propertyGroups = database.Fetch<PropertyTypeGroupDto>("WHERE id > 0");
foreach (var propertyType in propertyTypes)