diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs index 4c7c49f9c6..e3ac16473d 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs @@ -178,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. @@ -190,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 => @@ -206,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); } @@ -248,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/SqlSyntax/ISqlSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/ISqlSyntaxProvider.cs index 458853309c..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); 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.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)