diff --git a/src/Umbraco.Core/Persistence/DatabaseModelDefinitions/ConstraintDefinition.cs b/src/Umbraco.Core/Persistence/DatabaseModelDefinitions/ConstraintDefinition.cs index a3b7d99802..cba71387ee 100644 --- a/src/Umbraco.Core/Persistence/DatabaseModelDefinitions/ConstraintDefinition.cs +++ b/src/Umbraco.Core/Persistence/DatabaseModelDefinitions/ConstraintDefinition.cs @@ -6,17 +6,17 @@ namespace Umbraco.Core.Persistence.DatabaseModelDefinitions { public ConstraintDefinition(ConstraintType type) { - constraintType = type; + _constraintType = type; } - private ConstraintType constraintType; - public bool IsPrimaryKeyConstraint { get { return ConstraintType.PrimaryKey == constraintType; } } - public bool IsUniqueConstraint { get { return ConstraintType.Unique == constraintType; } } - public bool IsNonUniqueConstraint { get { return ConstraintType.NonUnique == constraintType; } } + private readonly ConstraintType _constraintType; + public bool IsPrimaryKeyConstraint => ConstraintType.PrimaryKey == _constraintType; + public bool IsUniqueConstraint => ConstraintType.Unique == _constraintType; + public bool IsNonUniqueConstraint => ConstraintType.NonUnique == _constraintType; public string SchemaName { get; set; } public string ConstraintName { get; set; } public string TableName { get; set; } public ICollection Columns = new HashSet(); } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Persistence/DatabaseModelDefinitions/DbIndexDefinition.cs b/src/Umbraco.Core/Persistence/DatabaseModelDefinitions/DbIndexDefinition.cs index e495d61550..ca0e51e699 100644 --- a/src/Umbraco.Core/Persistence/DatabaseModelDefinitions/DbIndexDefinition.cs +++ b/src/Umbraco.Core/Persistence/DatabaseModelDefinitions/DbIndexDefinition.cs @@ -1,3 +1,5 @@ +using System; + namespace Umbraco.Core.Persistence.DatabaseModelDefinitions { /// @@ -5,9 +7,17 @@ namespace Umbraco.Core.Persistence.DatabaseModelDefinitions /// internal class DbIndexDefinition { - public virtual string IndexName { get; set; } - public virtual string TableName { get; set; } - public virtual string ColumnName { get; set; } - public virtual bool IsUnique { get; set; } + public DbIndexDefinition(Tuple data) + { + TableName = data.Item1; + IndexName = data.Item2; + ColumnName = data.Item3; + IsUnique = data.Item4; + } + + public string IndexName { get; } + public string TableName { get; } + public string ColumnName { get; } + public bool IsUnique { get; } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs index 06d801992e..e3ac16473d 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs @@ -159,13 +159,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial //get the db index defs result.DbIndexDefinitions = _sqlSyntaxProvider.GetDefinedIndexes(_database) - .Select(x => new DbIndexDefinition() - { - TableName = x.Item1, - IndexName = x.Item2, - ColumnName = x.Item3, - IsUnique = x.Item4 - }).ToArray(); + .Select(x => new DbIndexDefinition(x)).ToArray(); foreach (var item in OrderedTables.OrderBy(x => x.Key)) { @@ -184,6 +178,14 @@ namespace Umbraco.Core.Persistence.Migrations.Initial return result; } + /// + /// This validates the Primary/Foreign keys in the database + /// + /// + /// + /// This does not validate any database constraints that are not PKs or FKs because Umbraco does not create a database with non PK/FK contraints. + /// Any unique "constraints" in the database are done with unique indexes. + /// private void ValidateDbConstraints(DatabaseSchemaResult result) { //MySql doesn't conform to the "normal" naming of constraints, so there is currently no point in doing these checks. @@ -196,8 +198,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial var constraintsInDatabase = _sqlSyntaxProvider.GetConstraintsPerColumn(_database).DistinctBy(x => x.Item3).ToList(); var foreignKeysInDatabase = constraintsInDatabase.Where(x => x.Item3.InvariantStartsWith("FK_")).Select(x => x.Item3).ToList(); var primaryKeysInDatabase = constraintsInDatabase.Where(x => x.Item3.InvariantStartsWith("PK_")).Select(x => x.Item3).ToList(); - var indexesInDatabase = constraintsInDatabase.Where(x => x.Item3.InvariantStartsWith("IX_")).Select(x => x.Item3).ToList(); - var indexesInSchema = result.TableDefinitions.SelectMany(x => x.Indexes.Select(y => y.Name)).ToList(); + var unknownConstraintsInDatabase = constraintsInDatabase.Where( x => @@ -212,7 +213,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial // In theory you could have: FK_ or fk_ ...or really any standard that your development department (or developer) chooses to use. foreach (var unknown in unknownConstraintsInDatabase) { - if (foreignKeysInSchema.InvariantContains(unknown) || primaryKeysInSchema.InvariantContains(unknown) || indexesInSchema.InvariantContains(unknown)) + if (foreignKeysInSchema.InvariantContains(unknown) || primaryKeysInSchema.InvariantContains(unknown)) { result.ValidConstraints.Add(unknown); } @@ -254,23 +255,6 @@ namespace Umbraco.Core.Persistence.Migrations.Initial result.Errors.Add(new Tuple("Constraint", primaryKey)); } - //Constaints: - - //NOTE: SD: The colIndex checks above should really take care of this but I need to keep this here because it was here before - // and some schema validation checks might rely on this data remaining here! - //Add valid and invalid index differences to the result object - var validIndexDifferences = indexesInDatabase.Intersect(indexesInSchema, StringComparer.InvariantCultureIgnoreCase); - foreach (var index in validIndexDifferences) - { - result.ValidConstraints.Add(index); - } - var invalidIndexDifferences = - indexesInDatabase.Except(indexesInSchema, StringComparer.InvariantCultureIgnoreCase) - .Union(indexesInSchema.Except(indexesInDatabase, StringComparer.InvariantCultureIgnoreCase)); - foreach (var index in invalidIndexDifferences) - { - result.Errors.Add(new Tuple("Constraint", index)); - } } private void ValidateDbColumns(DatabaseSchemaResult result) diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AddIndexToCmsMacroPropertyTable.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AddIndexToCmsMacroPropertyTable.cs index 8dfe51f8dc..73e6e91288 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AddIndexToCmsMacroPropertyTable.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AddIndexToCmsMacroPropertyTable.cs @@ -28,13 +28,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven public override void Up() { var dbIndexes = _skipIndexCheck ? new DbIndexDefinition[]{} : SqlSyntax.GetDefinedIndexes(Context.Database) - .Select(x => new DbIndexDefinition() - { - TableName = x.Item1, - IndexName = x.Item2, - ColumnName = x.Item3, - IsUnique = x.Item4 - }).ToArray(); + .Select(x => new DbIndexDefinition(x)).ToArray(); //make sure it doesn't already exist if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsMacroProperty_Alias")) == false) @@ -54,4 +48,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven Delete.Index("IX_cmsMacroProperty_Alias").OnTable("cmsMacroProperty"); } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AddIndexToCmsMacroTable.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AddIndexToCmsMacroTable.cs index e6c237d4d6..ada45adf06 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AddIndexToCmsMacroTable.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AddIndexToCmsMacroTable.cs @@ -30,13 +30,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven public override void Up() { var dbIndexes = _forTesting ? new DbIndexDefinition[] { } : SqlSyntax.GetDefinedIndexes(Context.Database) - .Select(x => new DbIndexDefinition() - { - TableName = x.Item1, - IndexName = x.Item2, - ColumnName = x.Item3, - IsUnique = x.Item4 - }).ToArray(); + .Select(x => new DbIndexDefinition(x)).ToArray(); //make sure it doesn't already exist if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsMacro_Alias")) == false) @@ -75,4 +69,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven Delete.Index("IX_cmsMacro_Alias").OnTable("cmsMacro"); } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterTagsTable.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterTagsTable.cs index 32bd9d1403..cf99db6d64 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterTagsTable.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AlterTagsTable.cs @@ -18,13 +18,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven public override void Up() { var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database) - .Select(x => new DbIndexDefinition() - { - TableName = x.Item1, - IndexName = x.Item2, - ColumnName = x.Item3, - IsUnique = x.Item4 - }).ToArray(); + .Select(x => new DbIndexDefinition(x)).ToArray(); //add a foreign key to the parent id column too! @@ -54,4 +48,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven throw new DataLossException("Cannot downgrade from a version 7 database to a prior version, the database schema has already been modified"); } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AssignMissingKeysAndIndexes.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AssignMissingKeysAndIndexes.cs index c76031e4e4..f9e0914fb9 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AssignMissingKeysAndIndexes.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/AssignMissingKeysAndIndexes.cs @@ -26,13 +26,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven // it is absolutely required to exist in order to have it as a foreign key reference, so we'll need to check it's existence // this came to light from this issue: http://issues.umbraco.org/issue/U4-4133 var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database) - .Select(x => new DbIndexDefinition() - { - TableName = x.Item1, - IndexName = x.Item2, - ColumnName = x.Item3, - IsUnique = x.Item4 - }).ToArray(); + .Select(x => new DbIndexDefinition(x)).ToArray(); if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsContent")) == false) { Create.Index("IX_cmsContent").OnTable("cmsContent").OnColumn("nodeId").Ascending().WithOptions().Unique(); @@ -95,4 +89,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven //don't do anything, these keys should have always existed! } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenEightZero/AddIndexToPropertyTypeAliasColumn.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenEightZero/AddIndexToPropertyTypeAliasColumn.cs index d5d13acc91..b6b7c06564 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenEightZero/AddIndexToPropertyTypeAliasColumn.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenEightZero/AddIndexToPropertyTypeAliasColumn.cs @@ -15,7 +15,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenEightZe { Execute.Code(database => { - var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(Context.Database); + var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(database); //make sure it doesn't already exist if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsPropertyTypeAlias")) == false) diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/AddForeignKeysForLanguageAndDictionaryTables.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/AddForeignKeysForLanguageAndDictionaryTables.cs index 0baf5bff1a..8ec961fc1d 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/AddForeignKeysForLanguageAndDictionaryTables.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/AddForeignKeysForLanguageAndDictionaryTables.cs @@ -62,13 +62,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe } var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database) - .Select(x => new DbIndexDefinition - { - TableName = x.Item1, - IndexName = x.Item2, - ColumnName = x.Item3, - IsUnique = x.Item4 - }).ToArray(); + .Select(x => new DbIndexDefinition(x)).ToArray(); //make sure it doesn't already exist if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsDictionary_id")) == false) @@ -104,4 +98,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe throw new NotImplementedException(); } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MigrateAndRemoveTemplateMasterColumn.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MigrateAndRemoveTemplateMasterColumn.cs index 59236106ab..6bc9f3da37 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MigrateAndRemoveTemplateMasterColumn.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MigrateAndRemoveTemplateMasterColumn.cs @@ -120,13 +120,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database) - .Select(x => new DbIndexDefinition() - { - TableName = x.Item1, - IndexName = x.Item2, - ColumnName = x.Item3, - IsUnique = x.Item4 - }).ToArray(); + .Select(x => new DbIndexDefinition(x)).ToArray(); //in some databases there's an index (IX_Master) on the master column which needs to be dropped first var foundIndex = dbIndexes.FirstOrDefault(x => x.TableName.InvariantEquals("cmsTemplate") && x.ColumnName.InvariantEquals("master")); @@ -167,4 +161,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe return path; } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/UpdateUniqueIdToHaveCorrectIndexType.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/UpdateUniqueIdToHaveCorrectIndexType.cs index dc8415a9f8..db1ae95081 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/UpdateUniqueIdToHaveCorrectIndexType.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/UpdateUniqueIdToHaveCorrectIndexType.cs @@ -15,13 +15,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe public override void Up() { var indexes = SqlSyntax.GetDefinedIndexes(Context.Database) - .Select(x => new DbIndexDefinition() - { - TableName = x.Item1, - IndexName = x.Item2, - ColumnName = x.Item3, - IsUnique = x.Item4 - }).ToArray(); + .Select(x => new DbIndexDefinition(x)).ToArray(); // drop the index if it exists if (indexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoNodeUniqueID"))) @@ -38,4 +32,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe public override void Down() { } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwelveZero/IncreaseLanguageIsoCodeColumnLength.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwelveZero/IncreaseLanguageIsoCodeColumnLength.cs index 4341aa4bf4..d79ff24517 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwelveZero/IncreaseLanguageIsoCodeColumnLength.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwelveZero/IncreaseLanguageIsoCodeColumnLength.cs @@ -15,21 +15,35 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwelveZ public override void Up() { - var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database) - .Select(x => new DbIndexDefinition() - { - TableName = x.Item1, - IndexName = x.Item2, - ColumnName = x.Item3, - IsUnique = x.Item4 - }).ToArray(); - - //Ensure the index exists before dropping it - if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoLanguage_languageISOCode"))) + Execute.Code(database => { - Delete.Index("IX_umbracoLanguage_languageISOCode").OnTable("umbracoLanguage"); - } - + var localContext = new LocalMigrationContext(Context.CurrentDatabaseProvider, database, SqlSyntax, Logger); + // Some people seem to have a constraint in their DB instead of an index, we'd need to drop that one + // See: https://our.umbraco.com/forum/using-umbraco-and-getting-started/93282-upgrade-from-711-to-712-fails + var constraints = SqlSyntax.GetConstraintsPerTable(database).Distinct().ToArray(); + if (constraints.Any(x => x.Item2.InvariantEquals("IX_umbracoLanguage_languageISOCode"))) + { + localContext.Delete.UniqueConstraint("IX_umbracoLanguage_languageISOCode").FromTable("umbracoLanguage"); + return localContext.GetSql(); + } + return null; + }); + + Execute.Code(database => + { + var localContext = new LocalMigrationContext(Context.CurrentDatabaseProvider, database, SqlSyntax, Logger); + + //Now check for indexes of that name and drop that if it exists + var dbIndexes = SqlSyntax.GetDefinedIndexes(database) + .Select(x => new DbIndexDefinition(x)).ToArray(); + if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoLanguage_languageISOCode"))) + { + localContext.Delete.Index("IX_umbracoLanguage_languageISOCode").OnTable("umbracoLanguage"); + return localContext.GetSql(); + } + return null; + }); + Alter.Table("umbracoLanguage") .AlterColumn("languageISOCode") .AsString(14) @@ -38,6 +52,8 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwelveZ Create.Index("IX_umbracoLanguage_languageISOCode") .OnTable("umbracoLanguage") .OnColumn("languageISOCode") + .Ascending() + .WithOptions() .Unique(); } diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/AddMissingForeignKeyForContentType.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/AddMissingForeignKeyForContentType.cs index 47b1f334d3..f5ae00d94e 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/AddMissingForeignKeyForContentType.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/AddMissingForeignKeyForContentType.cs @@ -48,14 +48,8 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwoZero //Some very old schemas don't have an index on the cmsContentType.nodeId column, I'm not actually sure when it was added but // it is absolutely required to exist in order to add other foreign keys and much better for perf, so we'll need to check it's existence // this came to light from this issue: http://issues.umbraco.org/issue/U4-4133 - var dbIndexes = SqlSyntaxContext.SqlSyntaxProvider.GetDefinedIndexes(Context.Database) - .Select(x => new DbIndexDefinition() - { - TableName = x.Item1, - IndexName = x.Item2, - ColumnName = x.Item3, - IsUnique = x.Item4 - }).ToArray(); + var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database) + .Select(x => new DbIndexDefinition(x)).ToArray(); if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsContentType")) == false) { Create.Index("IX_cmsContentType").OnTable("cmsContentType").OnColumn("nodeId").Ascending().WithOptions().Unique(); @@ -82,4 +76,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwoZero throw new DataLossException("Cannot downgrade from a version 7.2 database to a prior version, the database schema has already been modified"); } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AdditionalIndexesAndKeys.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AdditionalIndexesAndKeys.cs index 64f2970bdf..50ffdf7ede 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AdditionalIndexesAndKeys.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AdditionalIndexesAndKeys.cs @@ -20,13 +20,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixTwoZero { var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database) - .Select(x => new DbIndexDefinition() - { - TableName = x.Item1, - IndexName = x.Item2, - ColumnName = x.Item3, - IsUnique = x.Item4 - }).ToArray(); + .Select(x => new DbIndexDefinition(x)).ToArray(); //do not create any indexes if they already exist in the database @@ -118,4 +112,4 @@ DROP TABLE ""umbracoUserLogins_temp"""); } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/ISqlSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/ISqlSyntaxProvider.cs index 366376b953..b856d1d77e 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/ISqlSyntaxProvider.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/ISqlSyntaxProvider.cs @@ -53,6 +53,8 @@ namespace Umbraco.Core.Persistence.SqlSyntax string TruncateTable { get; } string CreateConstraint { get; } string DeleteConstraint { get; } + + [Obsolete("This is never used, use the Format(ForeignKeyDefinition) instead")] string CreateForeignKeyConstraint { get; } string DeleteDefaultConstraint { get; } string FormatDateTime(DateTime date, bool includeTime = true); @@ -78,9 +80,32 @@ namespace Umbraco.Core.Persistence.SqlSyntax IEnumerable GetTablesInSchema(Database db); IEnumerable GetColumnsInSchema(Database db); + + /// + /// Returns all constraints defined in the database (Primary keys, foreign keys, unique constraints...) (does not include indexes) + /// + /// + /// + /// A Tuple containing: TableName, ConstraintName + /// IEnumerable> GetConstraintsPerTable(Database db); + + /// + /// Returns all constraints defined in the database (Primary keys, foreign keys, unique constraints...) (does not include indexes) + /// + /// + /// + /// A Tuple containing: TableName, ColumnName, ConstraintName + /// IEnumerable> GetConstraintsPerColumn(Database db); + /// + /// Returns all defined Indexes in the database excluding primary keys + /// + /// + /// + /// A Tuple containing: TableName, IndexName, ColumnName, IsUnique + /// IEnumerable> GetDefinedIndexes(Database db); } -} \ 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 ceb8e9c83f..c3ad8f48c4 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/MySqlSyntaxProvider.cs @@ -78,6 +78,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax return list; } + /// public override IEnumerable> GetConstraintsPerTable(Database db) { List> list; @@ -100,6 +101,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax return list; } + /// public override IEnumerable> GetConstraintsPerColumn(Database db) { List> list; @@ -126,6 +128,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax return list; } + /// public override IEnumerable> GetDefinedIndexes(Database db) { List> list; @@ -401,4 +404,4 @@ ORDER BY TABLE_NAME, INDEX_NAME", return PetaPocoExtensions.EscapeAtSymbols(MySql.Data.MySqlClient.MySqlHelper.EscapeString(val)); } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs index 69ebe11a14..fd317c5a6b 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs @@ -10,7 +10,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax /// /// Represents an SqlSyntaxProvider for Sql Ce /// - [SqlSyntaxProviderAttribute(Constants.DatabaseProviders.SqlCe)] + [SqlSyntaxProvider(Constants.DatabaseProviders.SqlCe)] public class SqlCeSyntaxProvider : MicrosoftSqlSyntaxProviderBase { public SqlCeSyntaxProvider() @@ -123,40 +123,27 @@ namespace Umbraco.Core.Persistence.SqlSyntax item.IS_NULLABLE, item.DATA_TYPE)).ToList(); } + /// public override IEnumerable> GetConstraintsPerTable(Database db) { var items = db.Fetch("SELECT TABLE_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS"); - var indexItems = db.Fetch("SELECT TABLE_NAME, INDEX_NAME FROM INFORMATION_SCHEMA.INDEXES"); - return - items.Select(item => new Tuple(item.TABLE_NAME, item.CONSTRAINT_NAME)) - .Union( - indexItems.Select( - indexItem => new Tuple(indexItem.TABLE_NAME, indexItem.INDEX_NAME))) - .ToList(); + return items.Select(item => new Tuple(item.TABLE_NAME, item.CONSTRAINT_NAME)).ToList(); } + /// public override IEnumerable> GetConstraintsPerColumn(Database db) { - var items = - db.Fetch( - "SELECT CONSTRAINT_NAME, TABLE_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE"); - var indexItems = db.Fetch("SELECT INDEX_NAME, TABLE_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.INDEXES"); - return - items.Select( - item => new Tuple(item.TABLE_NAME, item.COLUMN_NAME, item.CONSTRAINT_NAME)) - .Union( - indexItems.Select( - indexItem => - new Tuple(indexItem.TABLE_NAME, indexItem.COLUMN_NAME, - indexItem.INDEX_NAME))).ToList(); + var items = db.Fetch("SELECT TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE"); + return items.Select(item => new Tuple(item.TABLE_NAME, item.COLUMN_NAME, item.CONSTRAINT_NAME)).ToList(); } + /// public override IEnumerable> GetDefinedIndexes(Database db) { var items = db.Fetch( @"SELECT TABLE_NAME, INDEX_NAME, COLUMN_NAME, [UNIQUE] FROM INFORMATION_SCHEMA.INDEXES -WHERE INDEX_NAME NOT LIKE 'PK_%' +WHERE PRIMARY_KEY=0 ORDER BY TABLE_NAME, INDEX_NAME"); return items.Select( @@ -215,4 +202,4 @@ ORDER BY TABLE_NAME, INDEX_NAME"); public override string DropIndex { get { return "DROP INDEX {1}.{0}"; } } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs index 6cc97bdfb3..2258268631 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs @@ -88,6 +88,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax item.IS_NULLABLE, item.DATA_TYPE)).ToList(); } + /// public override IEnumerable> GetConstraintsPerTable(Database db) { var items = @@ -96,6 +97,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax return items.Select(item => new Tuple(item.TABLE_NAME, item.CONSTRAINT_NAME)).ToList(); } + /// public override IEnumerable> GetConstraintsPerColumn(Database db) { var items = @@ -104,6 +106,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax return items.Select(item => new Tuple(item.TABLE_NAME, item.COLUMN_NAME, item.CONSTRAINT_NAME)).ToList(); } + /// public override IEnumerable> GetDefinedIndexes(Database db) { var items = @@ -113,7 +116,7 @@ CASE WHEN I.is_unique_constraint = 1 OR I.is_unique = 1 THEN 1 ELSE 0 END AS [U from sys.tables as T inner join sys.indexes as I on T.[object_id] = I.[object_id] inner join sys.index_columns as IC on IC.[object_id] = I.[object_id] and IC.[index_id] = I.[index_id] inner join sys.all_columns as AC on IC.[object_id] = AC.[object_id] and IC.[column_id] = AC.[column_id] -WHERE I.name NOT LIKE 'PK_%' +WHERE I.is_primary_key = 0 order by T.name, I.name"); return items.Select(item => new Tuple(item.TABLE_NAME, item.INDEX_NAME, item.COLUMN_NAME, item.UNIQUE == 1)).ToList(); @@ -183,4 +186,4 @@ order by T.name, I.name"); } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderBase.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderBase.cs index a2baa8132d..3f31809289 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderBase.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderBase.cs @@ -537,10 +537,11 @@ namespace Umbraco.Core.Persistence.SqlSyntax public virtual string CreateConstraint { get { return "ALTER TABLE {0} ADD CONSTRAINT {1} {2} ({3})"; } } public virtual string DeleteConstraint { get { return "ALTER TABLE {0} DROP CONSTRAINT {1}"; } } + public virtual string CreateForeignKeyConstraint { get { return "ALTER TABLE {0} ADD CONSTRAINT {1} FOREIGN KEY ({2}) REFERENCES {3} ({4}){5}{6}"; } } public virtual string ConvertIntegerToOrderableString { get { return "REPLACE(STR({0}, 8), SPACE(1), '0')"; } } public virtual string ConvertDateToOrderableString { get { return "CONVERT(nvarchar, {0}, 102)"; } } public virtual string ConvertDecimalToOrderableString { get { return "REPLACE(STR({0}, 20, 9), SPACE(1), '0')"; } } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderExtensions.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderExtensions.cs index f0bafdacf7..991ad79692 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderExtensions.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderExtensions.cs @@ -9,13 +9,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax public static IEnumerable GetDefinedIndexesDefinitions(this ISqlSyntaxProvider sql, Database db) { return sql.GetDefinedIndexes(db) - .Select(x => new DbIndexDefinition() - { - TableName = x.Item1, - IndexName = x.Item2, - ColumnName = x.Item3, - IsUnique = x.Item4 - }).ToArray(); + .Select(x => new DbIndexDefinition(x)).ToArray(); } /// @@ -57,4 +51,4 @@ namespace Umbraco.Core.Persistence.SqlSyntax In, NotIn } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/HealthCheck/Checks/DataIntegrity/DatabaseSchemaValidationHealthCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/DataIntegrity/DatabaseSchemaValidationHealthCheck.cs index 6ea562b2c7..4371d80309 100644 --- a/src/Umbraco.Web/HealthCheck/Checks/DataIntegrity/DatabaseSchemaValidationHealthCheck.cs +++ b/src/Umbraco.Web/HealthCheck/Checks/DataIntegrity/DatabaseSchemaValidationHealthCheck.cs @@ -17,11 +17,13 @@ namespace Umbraco.Web.HealthCheck.Checks.DataIntegrity { private readonly DatabaseContext _databaseContext; private readonly ILocalizedTextService _textService; + private readonly ILogger _logger; public DatabaseSchemaValidationHealthCheck(HealthCheckContext healthCheckContext) : base(healthCheckContext) { _databaseContext = HealthCheckContext.ApplicationContext.DatabaseContext; _textService = healthCheckContext.ApplicationContext.Services.TextService; + _logger = healthCheckContext.ApplicationContext.ProfilingLogger.Logger; } public override HealthCheckStatus ExecuteAction(HealthCheckAction action) @@ -39,10 +41,10 @@ namespace Umbraco.Web.HealthCheck.Checks.DataIntegrity { var results = _databaseContext.ValidateDatabaseSchema(); - LogHelper.Warn(typeof(DatabaseSchemaValidationHealthCheck), _textService.Localize("databaseSchemaValidationCheckDatabaseLogMessage")); + _logger.Warn(typeof(DatabaseSchemaValidationHealthCheck), _textService.Localize("databaseSchemaValidationCheckDatabaseLogMessage")); foreach(var error in results.Errors) { - LogHelper.Warn(typeof(DatabaseSchemaValidationHealthCheck), error.Item1 + ": " + error.Item2); + _logger.Warn(typeof(DatabaseSchemaValidationHealthCheck), error.Item1 + ": " + error.Item2); } if(results.Errors.Count > 0)