Merge pull request #1380 from umbraco/temp-U4-8522
U4-8522 cmsPropertyData needs unique constraint indexes and index refactoring
This commit is contained in:
@@ -16,7 +16,7 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
|
||||
[Column("contentNodeId")]
|
||||
[ForeignKey(typeof(NodeDto))]
|
||||
[Index(IndexTypes.NonClustered, Name = "IX_cmsPropertyData_1")]
|
||||
[Index(IndexTypes.UniqueNonClustered, Name = "IX_cmsPropertyData_1", ForColumns = "contentNodeId,versionId,propertytypeid")]
|
||||
public int NodeId { get; set; }
|
||||
|
||||
[Column("versionId")]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using System;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Index
|
||||
@@ -17,12 +18,14 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Index
|
||||
return this;
|
||||
}
|
||||
|
||||
[Obsolete("I don't think this would ever be used when dropping an index, see DeleteIndexExpression.ToString")]
|
||||
public void OnColumn(string columnName)
|
||||
{
|
||||
var column = new IndexColumnDefinition { Name = columnName };
|
||||
Expression.Index.Columns.Add(column);
|
||||
}
|
||||
|
||||
[Obsolete("I don't think this would ever be used when dropping an index, see DeleteIndexExpression.ToString")]
|
||||
public void OnColumns(params string[] columnNames)
|
||||
{
|
||||
foreach (string columnName in columnNames)
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Index
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Index
|
||||
{
|
||||
public interface IDeleteIndexOnColumnSyntax : IFluentSyntax
|
||||
{
|
||||
[Obsolete("I don't think this would ever be used when dropping an index, see DeleteIndexExpression.ToString")]
|
||||
void OnColumn(string columnName);
|
||||
|
||||
[Obsolete("I don't think this would ever be used when dropping an index, see DeleteIndexExpression.ToString")]
|
||||
void OnColumns(params string[] columnNames);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFiveZero
|
||||
{
|
||||
/// <summary>
|
||||
/// See: http://issues.umbraco.org/issue/U4-8522
|
||||
/// </summary>
|
||||
[Migration("7.5.0", 2, GlobalSettings.UmbracoMigrationName)]
|
||||
public class UpdateUniqueIndexOnCmsPropertyData : MigrationBase
|
||||
{
|
||||
public UpdateUniqueIndexOnCmsPropertyData(ISqlSyntaxProvider sqlSyntax, ILogger logger)
|
||||
: base(sqlSyntax, logger)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Up()
|
||||
{
|
||||
//Clear all stylesheet data if the tables exist
|
||||
//tuple = tablename, indexname, columnname, unique
|
||||
var indexes = SqlSyntax.GetDefinedIndexes(Context.Database).ToArray();
|
||||
var found = indexes.FirstOrDefault(
|
||||
x => x.Item1.InvariantEquals("cmsPropertyData")
|
||||
&& x.Item2.InvariantEquals("IX_cmsPropertyData_1")
|
||||
//we're searching for the old index which is not unique
|
||||
&& x.Item4 == false);
|
||||
|
||||
if (found != null)
|
||||
{
|
||||
//Check for MySQL
|
||||
if (Context.CurrentDatabaseProvider == DatabaseProviders.MySql)
|
||||
{
|
||||
//Use the special double nested sub query for MySQL since that is the only
|
||||
//way delete sub queries works
|
||||
SqlSyntax.GetDeleteSubquery(
|
||||
"cmsPropertyData",
|
||||
"id",
|
||||
new Sql("SELECT MIN(id) FROM cmsPropertyData GROUP BY contentNodeId, versionId, propertytypeid HAVING MIN(id) IS NOT NULL"),
|
||||
WhereInType.NotIn);
|
||||
}
|
||||
else
|
||||
{
|
||||
//NOTE: Even though the above will work for MSSQL, we are not going to execute the
|
||||
// nested delete sub query logic since it will be slower and there could be a ton of property
|
||||
// data here so needs to be as fast as possible.
|
||||
Execute.Sql("DELETE FROM cmsPropertyData WHERE id NOT IN (SELECT MIN(id) FROM cmsPropertyData GROUP BY contentNodeId, versionId, propertytypeid HAVING MIN(id) IS NOT NULL)");
|
||||
}
|
||||
|
||||
//we need to re create this index
|
||||
Delete.Index("IX_cmsPropertyData_1").OnTable("cmsPropertyData");
|
||||
Create.Index("IX_cmsPropertyData_1").OnTable("cmsPropertyData")
|
||||
.OnColumn("contentNodeId").Ascending()
|
||||
.OnColumn("versionId").Ascending()
|
||||
.OnColumn("propertytypeid").Ascending()
|
||||
.WithOptions().NonClustered()
|
||||
.WithOptions().Unique();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,12 +22,23 @@
|
||||
/// <remarks>
|
||||
/// See: http://issues.umbraco.org/issue/U4-3876
|
||||
/// </remarks>
|
||||
public static Sql GetDeleteSubquery(this ISqlSyntaxProvider sqlProvider, string tableName, string columnName, Sql subQuery)
|
||||
public static Sql GetDeleteSubquery(this ISqlSyntaxProvider sqlProvider, string tableName, string columnName, Sql subQuery, WhereInType whereInType = WhereInType.In)
|
||||
{
|
||||
return new Sql(string.Format(@"DELETE FROM {0} WHERE {1} IN (SELECT {1} FROM ({2}) x)",
|
||||
|
||||
return
|
||||
new Sql(string.Format(
|
||||
whereInType == WhereInType.In
|
||||
? @"DELETE FROM {0} WHERE {1} IN (SELECT {1} FROM ({2}) x)"
|
||||
: @"DELETE FROM {0} WHERE {1} NOT IN (SELECT {1} FROM ({2}) x)",
|
||||
sqlProvider.GetQuotedTableName(tableName),
|
||||
sqlProvider.GetQuotedColumnName(columnName),
|
||||
subQuery.SQL), subQuery.Arguments);
|
||||
}
|
||||
}
|
||||
|
||||
internal enum WhereInType
|
||||
{
|
||||
In,
|
||||
NotIn
|
||||
}
|
||||
}
|
||||
@@ -433,6 +433,7 @@
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenFiveZero\EnsureServersLockObject.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenFiveZero\AddRedirectUrlTable.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenFiveZero\RemoveStylesheetDataAndTablesAgain.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenFiveZero\UpdateUniqueIndexOnCmsPropertyData.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenFourZero\FixListViewMediaSortOrder.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenFourZero\AddDataDecimalColumn.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenFourZero\AddUmbracoDeployTables.cs" />
|
||||
|
||||
@@ -81,14 +81,16 @@ namespace Umbraco.Tests.Migrations
|
||||
{
|
||||
NodeId = n.NodeId,
|
||||
PropertyTypeId = pt.Id,
|
||||
Text = "text"
|
||||
Text = "text",
|
||||
VersionId = Guid.NewGuid()
|
||||
};
|
||||
DatabaseContext.Database.Insert(data);
|
||||
data = new PropertyDataDto
|
||||
{
|
||||
NodeId = n.NodeId,
|
||||
PropertyTypeId = pt.Id,
|
||||
Text = "<root><node title=\"\" type=\"\" newwindow=\"\" link=\"\" /></root>"
|
||||
Text = "<root><node title=\"\" type=\"\" newwindow=\"\" link=\"\" /></root>",
|
||||
VersionId = Guid.NewGuid()
|
||||
};
|
||||
DatabaseContext.Database.Insert(data);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user