diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs index 3e0ecb7f94..600ce902a2 100644 --- a/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs +++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs @@ -141,6 +141,9 @@ public class UmbracoPlan : MigrationPlan To("{8B2C830A-4FFB-4433-8337-8649B0BF52C8}"); To("{1C38D589-26BB-4A46-9ABE-E4A0DF548A87}"); + // To 17.1.0 + To("{BE5CA411-E12D-4455-A59E-F12A669E5363}"); + // To 18.0.0 // TODO (V18): Enable on 18 branch //// To("{74332C49-B279-4945-8943-F8F00B1F5949}"); diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/V_17_1_0/EnsureUmbracoPropertyDataColumnCasing.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_17_1_0/EnsureUmbracoPropertyDataColumnCasing.cs new file mode 100644 index 0000000000..9aba6acd1f --- /dev/null +++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_17_1_0/EnsureUmbracoPropertyDataColumnCasing.cs @@ -0,0 +1,57 @@ +using Microsoft.Extensions.Logging; +using NPoco; +using Umbraco.Cms.Core; +using Umbraco.Cms.Core.Models.Membership; +using Umbraco.Cms.Infrastructure.Persistence; +using static Umbraco.Cms.Core.Constants; +using ColumnInfo = Umbraco.Cms.Infrastructure.Persistence.SqlSyntax.ColumnInfo; + +namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_17_1_0; + +/// +/// Ensures the propertyTypeId column in umbracoPropertyData has correct camel case naming. +/// +/// +/// SQL Server is case sensitive for columns used in a SQL Bulk insert statement(which is used in publishing +/// operations on umbracoPropertyData). +/// Earlier versions of Umbraco used all lower case for the propertyTypeId column name (propertytypeid), whereas newer versions +/// use camel case (propertyTypeId). +/// +public class EnsureUmbracoPropertyDataColumnCasing : AsyncMigrationBase +{ + private readonly ILogger _logger; + + /// + /// Initializes a new instance of the class. + /// + public EnsureUmbracoPropertyDataColumnCasing(IMigrationContext context, ILogger logger) + : base(context) => _logger = logger; + + /// + protected override Task MigrateAsync() + { + // We only need to do this for SQL Server. + if (DatabaseType == DatabaseType.SQLite) + { + return Task.CompletedTask; + } + + const string oldColumnName = "propertytypeid"; + const string newColumnName = "propertyTypeId"; + ColumnInfo[] columns = [.. SqlSyntax.GetColumnsInSchema(Context.Database)]; + ColumnInfo? targetColumn = columns + .FirstOrDefault(x => x.TableName == DatabaseSchema.Tables.PropertyData && string.Equals(x.ColumnName, oldColumnName, StringComparison.InvariantCulture)); + if (targetColumn is not null) + { + // The column exists with incorrect casing, we need to rename it. + Rename.Column(oldColumnName) + .OnTable(DatabaseSchema.Tables.PropertyData) + .To(newColumnName) + .Do(); + + _logger.LogInformation("Renamed column {OldColumnName} to {NewColumnName} on table {TableName}", oldColumnName, newColumnName, DatabaseSchema.Tables.PropertyData); + } + + return Task.CompletedTask; + } +}