From e1a134f5870c53a570debe7fbc1083c2afca60e8 Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 14 Mar 2014 17:11:21 +1100 Subject: [PATCH] Fixes: U4-4430 MySql primary key issues --- .../Models/Rdbms/PreviewXmlDto.cs | 2 +- .../Initial/DatabaseSchemaResult.cs | 2 +- .../Persistence/Migrations/MigrationRunner.cs | 22 +- .../AssignMissingPrimaryForMySqlKeys.cs | 97 ++++++ .../SqlSyntax/MySqlSyntaxProvider.cs | 2 +- src/Umbraco.Core/Umbraco.Core.csproj | 1 + .../MySqlSyntaxProviderTests.cs | 49 ++++ ...erTests.cs => SqlCeSyntaxProviderTests.cs} | 277 +++++++++--------- src/Umbraco.Tests/Umbraco.Tests.csproj | 3 +- 9 files changed, 307 insertions(+), 148 deletions(-) create mode 100644 src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AssignMissingPrimaryForMySqlKeys.cs create mode 100644 src/Umbraco.Tests/Persistence/SyntaxProvider/MySqlSyntaxProviderTests.cs rename src/Umbraco.Tests/Persistence/SyntaxProvider/{SqlSyntaxProviderTests.cs => SqlCeSyntaxProviderTests.cs} (97%) diff --git a/src/Umbraco.Core/Models/Rdbms/PreviewXmlDto.cs b/src/Umbraco.Core/Models/Rdbms/PreviewXmlDto.cs index f0f3ebffd0..d981855f24 100644 --- a/src/Umbraco.Core/Models/Rdbms/PreviewXmlDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/PreviewXmlDto.cs @@ -10,7 +10,7 @@ namespace Umbraco.Core.Models.Rdbms internal class PreviewXmlDto { [Column("nodeId")] - [PrimaryKeyColumn(AutoIncrement = false, Name = "", OnColumns = "nodeId, versionId")] + [PrimaryKeyColumn(AutoIncrement = false, Name = "PK_cmsContentPreviewXml", OnColumns = "nodeId, versionId")] [ForeignKey(typeof(ContentDto), Column = "nodeId")] public int NodeId { get; set; } diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaResult.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaResult.cs index 4db0f7222a..3fa8cd4ab0 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaResult.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaResult.cs @@ -74,7 +74,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial return new Version(6, 0, 0); } - //if the error is for an index + //if the error is for this IX_umbracoNodeTrashed which is added in 6.2, then it must mean we are on 6.1 if (Errors.Any(x => x.Item1.Equals("Index") && (x.Item2.InvariantEquals("IX_umbracoNodeTrashed")))) { return new Version(6, 1, 0); diff --git a/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs b/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs index b4117003fb..bb14bb67f3 100644 --- a/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs +++ b/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs @@ -69,7 +69,7 @@ namespace Umbraco.Core.Persistence.Migrations { ExecuteMigrations(schemaMigrationContext, database); } - catch (Exception) + catch (Exception ex) { //if this fails then the transaction will be rolled back, BUT if we are using MySql this is not the case, //since it does not support schema changes in a transaction, see: http://dev.mysql.com/doc/refman/5.0/en/implicit-commit.html @@ -77,11 +77,21 @@ namespace Umbraco.Core.Persistence.Migrations if (databaseProvider == DatabaseProviders.MySql) { - var downgrades = OrderedDowngradeMigrations(foundMigrations.Where(x => (x is SchemaMigration))).ToList(); - var downgradeMigrationContext = InitializeMigrations(downgrades, database, databaseProvider, false); - //lets hope that works! - if something cannot be rolled back then a CatastrophicDataLossException should - // be thrown. - ExecuteMigrations(downgradeMigrationContext, database); + try + { + var downgrades = OrderedDowngradeMigrations(foundMigrations.Where(x => (x is SchemaMigration))).ToList(); + var downgradeMigrationContext = InitializeMigrations(downgrades, database, databaseProvider, false); + //lets hope that works! - if something cannot be rolled back then a CatastrophicDataLossException should + // be thrown. + ExecuteMigrations(downgradeMigrationContext, database); + } + catch (Exception e) + { + throw new CatastrophicDataLossException( + "An error occurred running a schema migration but the changes could not be rolled back. Error: " + ex.Message + ". In some cases, it may be required that the database be restored to it's original state before running this upgrade process again.", + ex); + + } } //continue throwing the exception diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AssignMissingPrimaryForMySqlKeys.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AssignMissingPrimaryForMySqlKeys.cs new file mode 100644 index 0000000000..27c0dc91ba --- /dev/null +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AssignMissingPrimaryForMySqlKeys.cs @@ -0,0 +1,97 @@ +using System.Linq; +using System.Web.UI; +using Umbraco.Core.Configuration; +using Umbraco.Core.Persistence.SqlSyntax; + +namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixTwoZero +{ + //see: http://issues.umbraco.org/issue/U4-4430 + [Migration("6.2.0", 3, GlobalSettings.UmbracoMigrationName)] + public class AssignMissingPrimaryForMySqlKeys : SchemaMigration + { + public override void Up() + { + if (Context.CurrentDatabaseProvider == DatabaseProviders.MySql) + { + var constraints = SqlSyntaxContext.SqlSyntaxProvider.GetConstraintsPerColumn(Context.Database).Distinct().ToArray(); + + //This should be 2 because this table has 2 keys + if (constraints.Count(x => x.Item1.InvariantEquals("cmsContentType2ContentType") && x.Item3.InvariantEquals("PRIMARY")) == 0) + { + Create.PrimaryKey("PK_cmsContentType2ContentType") + .OnTable("cmsContentType2ContentType") + .Columns(new[] {"parentContentTypeId", "childContentTypeId"}); + } + + //This should be 2 because this table has 2 keys + if (constraints.Count(x => x.Item1.InvariantEquals("cmsContentTypeAllowedContentType") && x.Item3.InvariantEquals("PRIMARY")) == 0) + { + Create.PrimaryKey("PK_cmsContentTypeAllowedContentType") + .OnTable("cmsContentTypeAllowedContentType") + .Columns(new[] { "Id", "AllowedId" }); + } + + //This should be 2 because this table has 2 keys + if (constraints.Count(x => x.Item1.InvariantEquals("cmsDocumentType") && x.Item3.InvariantEquals("PRIMARY")) == 0) + { + Create.PrimaryKey("PK_cmsDocumentType") + .OnTable("cmsDocumentType") + .Columns(new[] { "contentTypeNodeId", "templateNodeId" }); + } + + //This should be 2 because this table has 2 keys + if (constraints.Count(x => x.Item1.InvariantEquals("cmsMember2MemberGroup") && x.Item3.InvariantEquals("PRIMARY")) == 0) + { + Create.PrimaryKey("PK_cmsMember2MemberGroup") + .OnTable("cmsMember2MemberGroup") + .Columns(new[] { "Member", "MemberGroup" }); + } + + //This should be 2 because this table has 2 keys + if (constraints.Count(x => x.Item1.InvariantEquals("cmsPreviewXml") && x.Item3.InvariantEquals("PRIMARY")) == 0) + { + Create.PrimaryKey("PK_cmsContentPreviewXml") + .OnTable("cmsPreviewXml") + .Columns(new[] { "nodeId", "versionId" }); + } + + //This should be 2 because this table has 2 keys + if (constraints.Count(x => x.Item1.InvariantEquals("cmsTagRelationship") && x.Item3.InvariantEquals("PRIMARY")) == 0) + { + Create.PrimaryKey("PK_cmsTagRelationship") + .OnTable("cmsTagRelationship") + .Columns(new[] { "nodeId", "tagId" }); + } + + //This should be 2 because this table has 2 keys + if (constraints.Count(x => x.Item1.InvariantEquals("umbracoUser2app") && x.Item3.InvariantEquals("PRIMARY")) == 0) + { + Create.PrimaryKey("PK_user2app") + .OnTable("umbracoUser2app") + .Columns(new[] { "user", "app" }); + } + + //This should be 2 because this table has 3 keys + if (constraints.Count(x => x.Item1.InvariantEquals("umbracoUser2NodeNotify") && x.Item3.InvariantEquals("PRIMARY")) == 0) + { + Create.PrimaryKey("PK_umbracoUser2NodeNotify") + .OnTable("umbracoUser2NodeNotify") + .Columns(new[] { "userId", "nodeId", "action" }); + } + + //This should be 2 because this table has 3 keys + if (constraints.Count(x => x.Item1.InvariantEquals("umbracoUser2NodePermission") && x.Item3.InvariantEquals("PRIMARY")) == 0) + { + Create.PrimaryKey("PK_umbracoUser2NodePermission") + .OnTable("umbracoUser2NodePermission") + .Columns(new[] { "userId", "nodeId", "permission" }); + } + } + } + + public override void Down() + { + //don't do anything, these keys should have always existed! + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs index 7e8d7b7566..ba6f4dcc7e 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs @@ -218,7 +218,7 @@ ORDER BY TABLE_NAME, INDEX_NAME", { string primaryKey = string.Empty; var columnDefinition = table.Columns.FirstOrDefault(x => x.IsPrimaryKey); - if (columnDefinition != null && columnDefinition.PrimaryKeyColumns.Contains(",") == false) + if (columnDefinition != null) { string columns = string.IsNullOrEmpty(columnDefinition.PrimaryKeyColumns) ? GetQuotedColumnName(columnDefinition.Name) diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 549c1378bc..2158fb1409 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -216,6 +216,7 @@ + diff --git a/src/Umbraco.Tests/Persistence/SyntaxProvider/MySqlSyntaxProviderTests.cs b/src/Umbraco.Tests/Persistence/SyntaxProvider/MySqlSyntaxProviderTests.cs new file mode 100644 index 0000000000..00319c2ccc --- /dev/null +++ b/src/Umbraco.Tests/Persistence/SyntaxProvider/MySqlSyntaxProviderTests.cs @@ -0,0 +1,49 @@ +using System; +using NUnit.Framework; +using Umbraco.Core.Models.Rdbms; +using Umbraco.Core.Persistence.DatabaseModelDefinitions; +using Umbraco.Core.Persistence.SqlSyntax; + +namespace Umbraco.Tests.Persistence.SyntaxProvider +{ + [NUnit.Framework.Ignore("This doesn't actually test anything")] + [TestFixture] + public class MySqlSyntaxProviderTests + { + [SetUp] + public void SetUp() + { + SqlSyntaxContext.SqlSyntaxProvider = MySqlSyntax.Provider; + } + + [Test] + public void Can_Generate_Create_Table_Statement() + { + var type = typeof(TagRelationshipDto); + var definition = DefinitionFactory.GetTableDefinition(type); + + string create = SqlSyntaxContext.SqlSyntaxProvider.Format(definition); + string primaryKey = SqlSyntaxContext.SqlSyntaxProvider.FormatPrimaryKey(definition); + var indexes = SqlSyntaxContext.SqlSyntaxProvider.Format(definition.Indexes); + var keys = SqlSyntaxContext.SqlSyntaxProvider.Format(definition.ForeignKeys); + + Console.WriteLine(create); + Console.WriteLine(primaryKey); + foreach (var sql in keys) + { + Console.WriteLine(sql); + } + + foreach (var sql in indexes) + { + Console.WriteLine(sql); + } + } + + [TearDown] + public void TearDown() + { + SqlSyntaxContext.SqlSyntaxProvider = null; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/Persistence/SyntaxProvider/SqlSyntaxProviderTests.cs b/src/Umbraco.Tests/Persistence/SyntaxProvider/SqlCeSyntaxProviderTests.cs similarity index 97% rename from src/Umbraco.Tests/Persistence/SyntaxProvider/SqlSyntaxProviderTests.cs rename to src/Umbraco.Tests/Persistence/SyntaxProvider/SqlCeSyntaxProviderTests.cs index 7802ea6d58..4862333b07 100644 --- a/src/Umbraco.Tests/Persistence/SyntaxProvider/SqlSyntaxProviderTests.cs +++ b/src/Umbraco.Tests/Persistence/SyntaxProvider/SqlCeSyntaxProviderTests.cs @@ -1,139 +1,140 @@ -using System; -using System.Collections.Generic; -using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.DatabaseAnnotations; -using Umbraco.Core.Persistence.DatabaseModelDefinitions; -using Umbraco.Core.Persistence.Migrations.Syntax.Create.Index; -using Umbraco.Core.Persistence.Migrations.Syntax.Expressions; -using Umbraco.Core.Persistence.SqlSyntax; - -namespace Umbraco.Tests.Persistence.SyntaxProvider -{ - [TestFixture] - public class SqlSyntaxProviderTests - { - [SetUp] - public void SetUp() - { - SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; - } - - [Test] - public void Can_Generate_Delete_SubQuery_Statement() - { - var mediaObjectType = Guid.Parse(Constants.ObjectTypes.Media); - var subQuery = new Sql() - .Select("DISTINCT cmsContentXml.nodeId") - .From() - .InnerJoin() - .On(left => left.NodeId, right => right.NodeId) - .Where(dto => dto.NodeObjectType == mediaObjectType); - - var sql = SqlSyntaxContext.SqlSyntaxProvider.GetDeleteSubquery("cmsContentXml", "nodeId", subQuery); - - Assert.AreEqual(@"DELETE FROM [cmsContentXml] WHERE [nodeId] IN (SELECT [nodeId] FROM (SELECT DISTINCT cmsContentXml.nodeId -FROM [cmsContentXml] -INNER JOIN [umbracoNode] -ON [cmsContentXml].[nodeId] = [umbracoNode].[id] -WHERE ([umbracoNode].[nodeObjectType] = 'b796f64c-1f99-4ffb-b886-4bf4bc011a9c')) x)".Replace(Environment.NewLine, " ").Replace("\n", " ").Replace("\r", " "), sql.Replace(Environment.NewLine, " ").Replace("\n", " ").Replace("\r", " ")); - } - - [Test] - public void Can_Generate_Create_Table_Statement() - { - var type = typeof (NodeDto); - var definition = DefinitionFactory.GetTableDefinition(type); - - string create = SqlSyntaxContext.SqlSyntaxProvider.Format(definition); - string primaryKey = SqlSyntaxContext.SqlSyntaxProvider.FormatPrimaryKey(definition); - var indexes = SqlSyntaxContext.SqlSyntaxProvider.Format(definition.Indexes); - var keys = SqlSyntaxContext.SqlSyntaxProvider.Format(definition.ForeignKeys); - - Console.WriteLine(create); - Console.WriteLine(primaryKey); - foreach (var sql in keys) - { - Console.WriteLine(sql); - } - - foreach (var sql in indexes) - { - Console.WriteLine(sql); - } - } - - [Test] - public void Format_SqlServer_NonClusteredIndexDefinition_AddsNonClusteredDirective() - { - SqlSyntaxContext.SqlSyntaxProvider = SqlServerSyntax.Provider; - - var indexDefinition = CreateIndexDefinition(); - indexDefinition.IndexType = IndexTypes.NonClustered; - - var actual = SqlSyntaxContext.SqlSyntaxProvider.Format(indexDefinition); - Assert.AreEqual("CREATE NONCLUSTERED INDEX [IX_A] ON [TheTable] ([A])", actual); - } - - [Test] - public void Format_SqlServer_NonClusteredIndexDefinition_UsingIsClusteredFalse_AddsClusteredDirective() - { - SqlSyntaxContext.SqlSyntaxProvider = SqlServerSyntax.Provider; - - var indexDefinition = CreateIndexDefinition(); - indexDefinition.IsClustered = false; - - var actual = SqlSyntaxContext.SqlSyntaxProvider.Format(indexDefinition); - Assert.AreEqual("CREATE CLUSTERED INDEX [IX_A] ON [TheTable] ([A])", actual); - } - - [Test] - public void CreateIndexBuilder_SqlServer_NonClustered_CreatesNonClusteredIndex() - { - SqlSyntaxContext.SqlSyntaxProvider = SqlServerSyntax.Provider; - var createExpression = new CreateIndexExpression { Index = { Name = "IX_A" } }; - var builder = new CreateIndexBuilder(createExpression); - builder.OnTable("TheTable").OnColumn("A").Ascending().WithOptions().NonClustered(); - Assert.AreEqual("CREATE NONCLUSTERED INDEX [IX_A] ON [TheTable] ([A])", createExpression.ToString()); - } - - [Test] - public void CreateIndexBuilder_SqlServer_Unique_CreatesUniqueNonClusteredIndex() - { - SqlSyntaxContext.SqlSyntaxProvider = SqlServerSyntax.Provider; - var createExpression = new CreateIndexExpression { Index = { Name = "IX_A" } }; - var builder = new CreateIndexBuilder(createExpression); - builder.OnTable("TheTable").OnColumn("A").Ascending().WithOptions().Unique(); - Assert.AreEqual("CREATE UNIQUE NONCLUSTERED INDEX [IX_A] ON [TheTable] ([A])", createExpression.ToString()); - } - - [Test] - public void CreateIndexBuilder_SqlServer_Clustered_CreatesClusteredIndex() - { - SqlSyntaxContext.SqlSyntaxProvider = SqlServerSyntax.Provider; - var createExpression = new CreateIndexExpression { Index = { Name = "IX_A" } }; - var builder = new CreateIndexBuilder(createExpression); - builder.OnTable("TheTable").OnColumn("A").Ascending().WithOptions().Clustered(); - Assert.AreEqual("CREATE CLUSTERED INDEX [IX_A] ON [TheTable] ([A])", createExpression.ToString()); - } - - private static IndexDefinition CreateIndexDefinition() - { - return new IndexDefinition - { - ColumnName = "A", - Name = "IX_A", - TableName = "TheTable", - SchemaName = "dbo" - }; - } - - [TearDown] - public void TearDown() - { - SqlSyntaxContext.SqlSyntaxProvider = null; - } - } +using System; +using System.Collections.Generic; +using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Core.Models.Rdbms; +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.DatabaseAnnotations; +using Umbraco.Core.Persistence.DatabaseModelDefinitions; +using Umbraco.Core.Persistence.Migrations.Syntax.Create.Index; +using Umbraco.Core.Persistence.Migrations.Syntax.Expressions; +using Umbraco.Core.Persistence.SqlSyntax; + +namespace Umbraco.Tests.Persistence.SyntaxProvider +{ + [TestFixture] + public class SqlCeSyntaxProviderTests + { + [SetUp] + public void SetUp() + { + SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider; + } + + [Test] + public void Can_Generate_Delete_SubQuery_Statement() + { + var mediaObjectType = Guid.Parse(Constants.ObjectTypes.Media); + var subQuery = new Sql() + .Select("DISTINCT cmsContentXml.nodeId") + .From() + .InnerJoin() + .On(left => left.NodeId, right => right.NodeId) + .Where(dto => dto.NodeObjectType == mediaObjectType); + + var sql = SqlSyntaxContext.SqlSyntaxProvider.GetDeleteSubquery("cmsContentXml", "nodeId", subQuery); + + Assert.AreEqual(@"DELETE FROM [cmsContentXml] WHERE [nodeId] IN (SELECT [nodeId] FROM (SELECT DISTINCT cmsContentXml.nodeId +FROM [cmsContentXml] +INNER JOIN [umbracoNode] +ON [cmsContentXml].[nodeId] = [umbracoNode].[id] +WHERE ([umbracoNode].[nodeObjectType] = 'b796f64c-1f99-4ffb-b886-4bf4bc011a9c')) x)".Replace(Environment.NewLine, " ").Replace("\n", " ").Replace("\r", " "), sql.Replace(Environment.NewLine, " ").Replace("\n", " ").Replace("\r", " ")); + } + + [NUnit.Framework.Ignore("This doesn't actually test anything")] + [Test] + public void Can_Generate_Create_Table_Statement() + { + var type = typeof (NodeDto); + var definition = DefinitionFactory.GetTableDefinition(type); + + string create = SqlSyntaxContext.SqlSyntaxProvider.Format(definition); + string primaryKey = SqlSyntaxContext.SqlSyntaxProvider.FormatPrimaryKey(definition); + var indexes = SqlSyntaxContext.SqlSyntaxProvider.Format(definition.Indexes); + var keys = SqlSyntaxContext.SqlSyntaxProvider.Format(definition.ForeignKeys); + + Console.WriteLine(create); + Console.WriteLine(primaryKey); + foreach (var sql in keys) + { + Console.WriteLine(sql); + } + + foreach (var sql in indexes) + { + Console.WriteLine(sql); + } + } + + [Test] + public void Format_SqlServer_NonClusteredIndexDefinition_AddsNonClusteredDirective() + { + SqlSyntaxContext.SqlSyntaxProvider = SqlServerSyntax.Provider; + + var indexDefinition = CreateIndexDefinition(); + indexDefinition.IndexType = IndexTypes.NonClustered; + + var actual = SqlSyntaxContext.SqlSyntaxProvider.Format(indexDefinition); + Assert.AreEqual("CREATE NONCLUSTERED INDEX [IX_A] ON [TheTable] ([A])", actual); + } + + [Test] + public void Format_SqlServer_NonClusteredIndexDefinition_UsingIsClusteredFalse_AddsClusteredDirective() + { + SqlSyntaxContext.SqlSyntaxProvider = SqlServerSyntax.Provider; + + var indexDefinition = CreateIndexDefinition(); + indexDefinition.IsClustered = false; + + var actual = SqlSyntaxContext.SqlSyntaxProvider.Format(indexDefinition); + Assert.AreEqual("CREATE CLUSTERED INDEX [IX_A] ON [TheTable] ([A])", actual); + } + + [Test] + public void CreateIndexBuilder_SqlServer_NonClustered_CreatesNonClusteredIndex() + { + SqlSyntaxContext.SqlSyntaxProvider = SqlServerSyntax.Provider; + var createExpression = new CreateIndexExpression { Index = { Name = "IX_A" } }; + var builder = new CreateIndexBuilder(createExpression); + builder.OnTable("TheTable").OnColumn("A").Ascending().WithOptions().NonClustered(); + Assert.AreEqual("CREATE NONCLUSTERED INDEX [IX_A] ON [TheTable] ([A])", createExpression.ToString()); + } + + [Test] + public void CreateIndexBuilder_SqlServer_Unique_CreatesUniqueNonClusteredIndex() + { + SqlSyntaxContext.SqlSyntaxProvider = SqlServerSyntax.Provider; + var createExpression = new CreateIndexExpression { Index = { Name = "IX_A" } }; + var builder = new CreateIndexBuilder(createExpression); + builder.OnTable("TheTable").OnColumn("A").Ascending().WithOptions().Unique(); + Assert.AreEqual("CREATE UNIQUE NONCLUSTERED INDEX [IX_A] ON [TheTable] ([A])", createExpression.ToString()); + } + + [Test] + public void CreateIndexBuilder_SqlServer_Clustered_CreatesClusteredIndex() + { + SqlSyntaxContext.SqlSyntaxProvider = SqlServerSyntax.Provider; + var createExpression = new CreateIndexExpression { Index = { Name = "IX_A" } }; + var builder = new CreateIndexBuilder(createExpression); + builder.OnTable("TheTable").OnColumn("A").Ascending().WithOptions().Clustered(); + Assert.AreEqual("CREATE CLUSTERED INDEX [IX_A] ON [TheTable] ([A])", createExpression.ToString()); + } + + private static IndexDefinition CreateIndexDefinition() + { + return new IndexDefinition + { + ColumnName = "A", + Name = "IX_A", + TableName = "TheTable", + SchemaName = "dbo" + }; + } + + [TearDown] + public void TearDown() + { + SqlSyntaxContext.SqlSyntaxProvider = null; + } + } } \ No newline at end of file diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 4f632ed9d9..b19066f0d6 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -220,6 +220,7 @@ + @@ -276,7 +277,7 @@ - +