From e5b22bf7316feb11006263665ceb8286679e7744 Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 1 Nov 2017 10:42:46 +0100 Subject: [PATCH] Migrate PropertyData table --- src/Umbraco.Core/Models/Rdbms/NodeDto.cs | 43 ++-- .../Models/Rdbms/PropertyDataDto.cs | 89 ++++---- .../Persistence/Constants-DatabaseSchema.cs | 16 +- .../Persistence/Factories/PropertyFactory.cs | 14 +- .../Persistence/Mappers/MemberMapper.cs | 28 +-- .../Migrations/IMigrationExpression.cs | 6 +- .../Initial/DatabaseSchemaCreation.cs | 2 +- .../Persistence/Migrations/LocalMigration.cs | 2 +- .../Migrations/MigrationExpressionBase.cs | 2 +- .../Persistence/Migrations/MigrationRunner.cs | 4 +- .../Migrations/Syntax/Create/CreateBuilder.cs | 22 ++ .../Syntax/Create/ICreateBuilder.cs | 5 +- .../Migrations/Syntax/Delete/DeleteBuilder.cs | 3 +- .../Syntax/Execute/ExecuteBuilder.cs | 2 +- .../Execute/ExecuteBuilderExtensions.cs | 56 +++++ .../ExecuteCodeStatementExpression.cs | 9 +- .../Syntax/Execute/IExecuteBuilder.cs | 2 +- .../Expressions/RenameColumnExpression.cs | 4 +- .../TargetVersionEight/AddLockObjects.cs | 3 +- .../TargetVersionEight/AddRedirectUrlTable.cs | 3 +- .../TargetVersionEight/VariantsMigration.cs | 71 ++++++ .../UpdateRelatedLinksData.cs | 25 +- .../AddLockObjects.cs | 3 +- .../RemoveStylesheetDataAndTablesAgain.cs | 2 +- .../UpdateUniqueIndexOnCmsPropertyData.cs | 6 +- .../AddUniqueIdPropertyTypeGroupColumn.cs | 3 +- .../AddIndexToDictionaryKeyColumn.cs | 3 +- .../EnsureContentTemplatePermissions.cs | 3 +- .../ReduceDictionaryKeyColumnsSize.cs | 3 +- .../AddIndexToCmsMemberLoginName.cs | 4 +- .../AddIndexesToUmbracoRelationTables.cs | 4 +- .../AddLockObjects.cs | 3 +- .../AddMacroUniqueIdColumn.cs | 8 +- .../AddRelationTypeUniqueIdColumn.cs | 3 +- .../NormalizeTemplateGuids.cs | 4 +- .../ReduceLoginNameColumnsSize.cs | 3 +- .../EnsureMigrationsTableIdentityIsCorrect.cs | 3 +- .../MigrateAndRemoveTemplateMasterColumn.cs | 7 +- .../AddMissingForeignKeyForContentType.cs | 2 +- .../Repositories/ContentRepository.cs | 4 +- .../Repositories/EntityRepository.cs | 38 +-- .../Repositories/MediaRepository.cs | 12 +- .../Repositories/MemberRepository.cs | 4 +- .../Repositories/VersionableRepositoryBase.cs | 20 +- src/Umbraco.Core/Umbraco.Core.csproj | 2 + .../Migrations/AdvancedMigrationTests.cs | 216 ++++++++++++++++++ .../Migrations/CreateTableMigrationTests.cs | 71 ------ .../Migrations/MigrationIssuesTests.cs | 10 +- .../ContentRepositorySqlClausesTest.cs | 2 +- .../Repositories/MemberRepositoryTest.cs | 2 +- .../Services/MemberServiceTests.cs | 8 +- src/Umbraco.Tests/Umbraco.Tests.csproj | 2 +- 52 files changed, 598 insertions(+), 268 deletions(-) create mode 100644 src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/ExecuteBuilderExtensions.cs create mode 100644 src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionEight/VariantsMigration.cs create mode 100644 src/Umbraco.Tests/Migrations/AdvancedMigrationTests.cs delete mode 100644 src/Umbraco.Tests/Migrations/CreateTableMigrationTests.cs diff --git a/src/Umbraco.Core/Models/Rdbms/NodeDto.cs b/src/Umbraco.Core/Models/Rdbms/NodeDto.cs index 2cd58d87aa..b1d4cb3c64 100644 --- a/src/Umbraco.Core/Models/Rdbms/NodeDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/NodeDto.cs @@ -5,56 +5,57 @@ using Umbraco.Core.Persistence.DatabaseModelDefinitions; namespace Umbraco.Core.Models.Rdbms { - [TableName(Constants.DatabaseSchema.Tables.Node)] + [TableName(TableName)] [PrimaryKey("id")] [ExplicitColumns] internal class NodeDto { + private const string TableName = Constants.DatabaseSchema.Tables.Node; public const int NodeIdSeed = 1060; [Column("id")] - [PrimaryKeyColumn(Name = "PK_structure", IdentitySeed = NodeIdSeed)] + [PrimaryKeyColumn(Name = "PK_" + TableName, IdentitySeed = NodeIdSeed)] public int NodeId { get; set; } - [Column("trashed")] - [Constraint(Default = "0")] - [Index(IndexTypes.NonClustered, Name = "IX_umbracoNodeTrashed")] - public bool Trashed { get; set; } + [Column("uniqueId")] + [NullSetting(NullSetting = NullSettings.NotNull)] + [Index(IndexTypes.UniqueNonClustered, Name = "IX_" + TableName + "_UniqueId")] + [Constraint(Default = SystemMethods.NewGuid)] + public Guid UniqueId { get; set; } - [Column("parentID")] + [Column("parentId")] [ForeignKey(typeof(NodeDto))] - [Index(IndexTypes.NonClustered, Name = "IX_umbracoNodeParentId")] + [Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_ParentId")] public int ParentId { get; set; } - [Column("nodeUser")] - [NullSetting(NullSetting = NullSettings.Null)] - public int? UserId { get; set; } - [Column("level")] public short Level { get; set; } [Column("path")] [Length(150)] - [Index(IndexTypes.NonClustered, Name = "IX_umbracoNodePath")] + [Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_Path")] public string Path { get; set; } [Column("sortOrder")] public int SortOrder { get; set; } - [Column("uniqueID")] - [NullSetting(NullSetting = NullSettings.NotNull)] - [Index(IndexTypes.UniqueNonClustered, Name = "IX_umbracoNodeUniqueID")] - [Constraint(Default = SystemMethods.NewGuid)] - public Guid UniqueId { get; set; } + [Column("trashed")] + [Constraint(Default = "0")] + [Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_Trashed")] + public bool Trashed { get; set; } + + [Column("nodeUser")] // fixme dbfix rename userId + [NullSetting(NullSetting = NullSettings.Null)] + public int? UserId { get; set; } [Column("text")] [NullSetting(NullSetting = NullSettings.Null)] public string Text { get; set; } - [Column("nodeObjectType")] + [Column("nodeObjectType")] // fixme dbfix rename objectType [NullSetting(NullSetting = NullSettings.Null)] - [Index(IndexTypes.NonClustered, Name = "IX_umbracoNodeObjectType")] - public Guid? NodeObjectType { get; set; } + [Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_ObjectType")] + public Guid? NodeObjectType { get; set; } // fixme dbfix rename ObjectType [Column("createDate")] [Constraint(Default = SystemMethods.CurrentDateTime)] diff --git a/src/Umbraco.Core/Models/Rdbms/PropertyDataDto.cs b/src/Umbraco.Core/Models/Rdbms/PropertyDataDto.cs index a850e9d905..54425dbf75 100644 --- a/src/Umbraco.Core/Models/Rdbms/PropertyDataDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/PropertyDataDto.cs @@ -4,91 +4,97 @@ using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms { - [TableName(Constants.DatabaseSchema.Tables.PropertyData)] + [TableName(TableName)] [PrimaryKey("id")] [ExplicitColumns] internal class PropertyDataDto { + private const string TableName = Constants.DatabaseSchema.Tables.PropertyData; + public const int VarcharLength = 512; + public const int SegmentLength = 256; + + private decimal? _decimalValue; + [Column("id")] [PrimaryKeyColumn] public int Id { get; set; } - [Column("contentNodeId")] + [Column("nodeId")] [ForeignKey(typeof(NodeDto))] - [Index(IndexTypes.UniqueNonClustered, Name = "IX_cmsPropertyData_1", ForColumns = "contentNodeId,versionId,propertytypeid")] + [Index(IndexTypes.UniqueNonClustered, Name = "IX_" + TableName + "_NodeId", ForColumns = "nodeId,versionId,propertyTypeId")] public int NodeId { get; set; } [Column("versionId")] [NullSetting(NullSetting = NullSettings.Null)] - [Index(IndexTypes.NonClustered, Name = "IX_cmsPropertyData_2")] + [Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_VersionId")] public Guid? VersionId { get; set; } - [Column("propertytypeid")] + [Column("propertyTypeId")] [ForeignKey(typeof(PropertyTypeDto))] - [Index(IndexTypes.NonClustered, Name = "IX_cmsPropertyData_3")] + [Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_PropertyTypeId")] public int PropertyTypeId { get; set; } - [Column("dataInt")] + [Column("languageId")] + [ForeignKey(typeof(LanguageDto))] + [Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_LanguageId")] [NullSetting(NullSetting = NullSettings.Null)] - public int? Integer { get; set; } + public int LanguageId { get; set; } - private decimal? _decimalValue; - - [Column("dataDecimal")] + [Column("segment")] + [Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_Segment")] [NullSetting(NullSetting = NullSettings.Null)] - public decimal? Decimal + [Length(SegmentLength)] + public string Segment { get; set; } + + [Column("intValue")] + [NullSetting(NullSetting = NullSettings.Null)] + public int? IntegerValue { get; set; } + + [Column("decimalValue")] + [NullSetting(NullSetting = NullSettings.Null)] + public decimal? DecimalValue { get => _decimalValue; set => _decimalValue = value?.Normalize(); } - [Column("dataDate")] + [Column("dateValue")] [NullSetting(NullSetting = NullSettings.Null)] - public DateTime? Date { get; set; } + public DateTime? DateValue { get; set; } - [Column("dataNvarchar")] + [Column("varcharValue")] [NullSetting(NullSetting = NullSettings.Null)] - [Length(500)] - public string VarChar { get; set; } + [Length(VarcharLength)] + public string VarcharValue { get; set; } - [Column("dataNtext")] + [Column("textValue")] [NullSetting(NullSetting = NullSettings.Null)] [SpecialDbType(SpecialDbTypes.NTEXT)] - public string Text { get; set; } + public string TextValue { get; set; } [ResultColumn] [Reference(ReferenceType.OneToOne, ColumnName = "PropertyTypeId")] public PropertyTypeDto PropertyTypeDto { get; set; } [Ignore] - public object GetValue + public object Value { get { - if (Integer.HasValue) - { - return Integer.Value; - } + if (IntegerValue.HasValue) + return IntegerValue.Value; - if (Decimal.HasValue) - { - return Decimal.Value; - } + if (DecimalValue.HasValue) + return DecimalValue.Value; - if (Date.HasValue) - { - return Date.Value; - } + if (DateValue.HasValue) + return DateValue.Value; - if (string.IsNullOrEmpty(VarChar) == false) - { - return VarChar; - } + if (!string.IsNullOrEmpty(VarcharValue)) + return VarcharValue; - if (string.IsNullOrEmpty(Text) == false) - { - return Text; - } + if (!string.IsNullOrEmpty(TextValue)) + return TextValue; return null; } @@ -103,12 +109,13 @@ namespace Umbraco.Core.Models.Rdbms { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; + if (obj.GetType() != GetType()) return false; return Equals((PropertyDataDto) obj); } public override int GetHashCode() { + // ReSharper disable once NonReadonlyMemberInGetHashCode return Id; } } diff --git a/src/Umbraco.Core/Persistence/Constants-DatabaseSchema.cs b/src/Umbraco.Core/Persistence/Constants-DatabaseSchema.cs index 5acf0ece76..3acd45cf58 100644 --- a/src/Umbraco.Core/Persistence/Constants-DatabaseSchema.cs +++ b/src/Umbraco.Core/Persistence/Constants-DatabaseSchema.cs @@ -15,19 +15,19 @@ namespace Umbraco.Core public const string Node = /*TableNamePrefix*/ "umbraco" + "Node"; public const string NodeData = /*TableNamePrefix*/ "cms" + "ContentNu"; public const string NodeXml = /*TableNamePrefix*/ "cms" + "ContentXml"; - public const string NodePreviewXml = /*TableNamePrefix*/ "cms" + "PreviewXml"; // fixme kill merge with ContentXml + public const string NodePreviewXml = /*TableNamePrefix*/ "cms" + "PreviewXml"; // fixme dbfix kill merge with ContentXml - public const string ContentType = /*TableNamePrefix*/ "cms" + "ContentType"; // fixme rename and split uElementType, uDocumentType + public const string ContentType = /*TableNamePrefix*/ "cms" + "ContentType"; // fixme dbfixrename and split uElementType, uDocumentType public const string ContentChildType = /*TableNamePrefix*/ "cms" + "ContentTypeAllowedContentType"; - public const string DocumentType = /*TableNamePrefix*/ "cms" + "DocumentType"; // fixme must rename corresponding DTO - public const string ElementTypeTree = /*TableNamePrefix*/ "cms" + "ContentType2ContentType"; // fixme why can't we just use uNode for this? + public const string DocumentType = /*TableNamePrefix*/ "cms" + "DocumentType"; // fixme dbfixmust rename corresponding DTO + public const string ElementTypeTree = /*TableNamePrefix*/ "cms" + "ContentType2ContentType"; // fixme dbfixwhy can't we just use uNode for this? public const string DataType = /*TableNamePrefix*/ "cms" + "DataType"; - public const string DataTypePreValue = /*TableNamePrefix*/ "cms" + "DataTypePreValues"; // fixme kill merge with uDataType + public const string DataTypePreValue = /*TableNamePrefix*/ "cms" + "DataTypePreValues"; // fixme dbfixkill merge with uDataType public const string Template = /*TableNamePrefix*/ "cms" + "Template"; - public const string Content = /*TableNamePrefix*/ "cms" + "Content"; // fixme merge into uDocument - public const string ContentVersion = /*TableNamePrefix*/ "cms" + "ContentVersion"; // fixme rename uDocumentVersion - public const string Document = /*TableNamePrefix*/ "cms" + "Document"; // fixme merge with others + no more version here + public const string Content = /*TableNamePrefix*/ "cms" + "Content"; // fixme dbfix merge into uDocument + public const string ContentVersion = /*TableNamePrefix*/ "cms" + "ContentVersion"; // fixme dbfix rename uDocumentVersion + public const string Document = /*TableNamePrefix*/ "cms" + "Document"; // fixme dbfix merge with others + no more version here public const string PropertyType = /*TableNamePrefix*/ "cms" + "PropertyType"; public const string PropertyTypeGroup = /*TableNamePrefix*/ "cms" + "PropertyTypeGroup"; diff --git a/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs b/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs index 7af14fd156..013e371252 100644 --- a/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs @@ -39,7 +39,7 @@ namespace Umbraco.Core.Persistence.Factories var propertyDataDto = dtos.LastOrDefault(x => x.PropertyTypeId == propertyType.Id); var property = propertyDataDto == null ? propertyType.CreatePropertyFromValue(null) - : propertyType.CreatePropertyFromRawValue(propertyDataDto.GetValue, + : propertyType.CreatePropertyFromRawValue(propertyDataDto.Value, propertyDataDto.VersionId.Value, propertyDataDto.Id); try @@ -87,7 +87,7 @@ namespace Umbraco.Core.Persistence.Factories { if (property.Value is bool || property.PropertyType.PropertyEditorAlias == Constants.PropertyEditors.TrueFalseAlias) { - dto.Integer = property.Value != null && string.IsNullOrEmpty(property.Value.ToString()) + dto.IntegerValue = property.Value != null && string.IsNullOrEmpty(property.Value.ToString()) ? 0 : Convert.ToInt32(property.Value); } @@ -96,7 +96,7 @@ namespace Umbraco.Core.Persistence.Factories int val; if ((property.Value != null && string.IsNullOrWhiteSpace(property.Value.ToString()) == false) && int.TryParse(property.Value.ToString(), out val)) { - dto.Integer = val; + dto.IntegerValue = val; } } } @@ -105,7 +105,7 @@ namespace Umbraco.Core.Persistence.Factories decimal val; if (decimal.TryParse(property.Value.ToString(), out val)) { - dto.Decimal = val; // property value should be normalized already + dto.DecimalValue = val; // property value should be normalized already } } else if (property.DataTypeDatabaseType == DataTypeDatabaseType.Date && property.Value != null && string.IsNullOrWhiteSpace(property.Value.ToString()) == false) @@ -113,16 +113,16 @@ namespace Umbraco.Core.Persistence.Factories DateTime date; if (DateTime.TryParse(property.Value.ToString(), out date)) { - dto.Date = date; + dto.DateValue = date; } } else if (property.DataTypeDatabaseType == DataTypeDatabaseType.Ntext && property.Value != null) { - dto.Text = property.Value.ToString(); + dto.TextValue = property.Value.ToString(); } else if (property.DataTypeDatabaseType == DataTypeDatabaseType.Nvarchar && property.Value != null) { - dto.VarChar = property.Value.ToString(); + dto.VarcharValue = property.Value.ToString(); } propertyDataDtos.Add(dto); diff --git a/src/Umbraco.Core/Persistence/Mappers/MemberMapper.cs b/src/Umbraco.Core/Persistence/Mappers/MemberMapper.cs index ae7f54de41..3d87e99e47 100644 --- a/src/Umbraco.Core/Persistence/Mappers/MemberMapper.cs +++ b/src/Umbraco.Core/Persistence/Mappers/MemberMapper.cs @@ -38,22 +38,22 @@ namespace Umbraco.Core.Persistence.Mappers CacheMap(src => src.Username, dto => dto.LoginName); CacheMap(src => src.RawPasswordValue, dto => dto.Password); - CacheMap(src => src.IsApproved, dto => dto.Integer); - CacheMap(src => src.IsLockedOut, dto => dto.Integer); - CacheMap(src => src.Comments, dto => dto.Text); - CacheMap(src => src.RawPasswordAnswerValue, dto => dto.VarChar); - CacheMap(src => src.PasswordQuestion, dto => dto.VarChar); - CacheMap(src => src.FailedPasswordAttempts, dto => dto.Integer); - CacheMap(src => src.LastLockoutDate, dto => dto.Date); - CacheMap(src => src.LastLoginDate, dto => dto.Date); - CacheMap(src => src.LastPasswordChangeDate, dto => dto.Date); + CacheMap(src => src.IsApproved, dto => dto.IntegerValue); + CacheMap(src => src.IsLockedOut, dto => dto.IntegerValue); + CacheMap(src => src.Comments, dto => dto.TextValue); + CacheMap(src => src.RawPasswordAnswerValue, dto => dto.VarcharValue); + CacheMap(src => src.PasswordQuestion, dto => dto.VarcharValue); + CacheMap(src => src.FailedPasswordAttempts, dto => dto.IntegerValue); + CacheMap(src => src.LastLockoutDate, dto => dto.DateValue); + CacheMap(src => src.LastLoginDate, dto => dto.DateValue); + CacheMap(src => src.LastPasswordChangeDate, dto => dto.DateValue); /* Internal experiment */ - CacheMap(src => src.DateTimePropertyValue, dto => dto.Date); - CacheMap(src => src.IntegerPropertyValue, dto => dto.Integer); - CacheMap(src => src.BoolPropertyValue, dto => dto.Integer); - CacheMap(src => src.LongStringPropertyValue, dto => dto.Text); - CacheMap(src => src.ShortStringPropertyValue, dto => dto.VarChar); + CacheMap(src => src.DateTimePropertyValue, dto => dto.DateValue); + CacheMap(src => src.IntegerPropertyValue, dto => dto.IntegerValue); + CacheMap(src => src.BoolPropertyValue, dto => dto.IntegerValue); + CacheMap(src => src.LongStringPropertyValue, dto => dto.TextValue); + CacheMap(src => src.ShortStringPropertyValue, dto => dto.VarcharValue); CacheMap(src => src.PropertyTypeAlias, dto => dto.Alias); } } diff --git a/src/Umbraco.Core/Persistence/Migrations/IMigrationExpression.cs b/src/Umbraco.Core/Persistence/Migrations/IMigrationExpression.cs index 8955ff318c..30c1df4e75 100644 --- a/src/Umbraco.Core/Persistence/Migrations/IMigrationExpression.cs +++ b/src/Umbraco.Core/Persistence/Migrations/IMigrationExpression.cs @@ -1,12 +1,10 @@ -using NPoco; - -namespace Umbraco.Core.Persistence.Migrations +namespace Umbraco.Core.Persistence.Migrations { /// /// Marker interface for migration expressions /// public interface IMigrationExpression { - string Process(IUmbracoDatabase database); + string Process(IMigrationContext context); } } diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs index 000d80b957..61d7f6d7a8 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/DatabaseSchemaCreation.cs @@ -35,7 +35,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial #region All Ordered Tables - private static readonly Dictionary OrderedTables = new Dictionary + public static readonly Dictionary OrderedTables = new Dictionary { {0, typeof (NodeDto)}, {1, typeof (ContentTypeDto)}, diff --git a/src/Umbraco.Core/Persistence/Migrations/LocalMigration.cs b/src/Umbraco.Core/Persistence/Migrations/LocalMigration.cs index a3e34e0ed1..0e15b02160 100644 --- a/src/Umbraco.Core/Persistence/Migrations/LocalMigration.cs +++ b/src/Umbraco.Core/Persistence/Migrations/LocalMigration.cs @@ -28,7 +28,7 @@ namespace Umbraco.Core.Persistence.Migrations public string GetSql() { var sb = new StringBuilder(); - foreach (var sql in Expressions.Select(x => x.Process(Database))) + foreach (var sql in Expressions.Select(x => x.Process(this))) { sb.Append(sql); sb.AppendLine(); diff --git a/src/Umbraco.Core/Persistence/Migrations/MigrationExpressionBase.cs b/src/Umbraco.Core/Persistence/Migrations/MigrationExpressionBase.cs index 1f195be126..32b4b8c87e 100644 --- a/src/Umbraco.Core/Persistence/Migrations/MigrationExpressionBase.cs +++ b/src/Umbraco.Core/Persistence/Migrations/MigrationExpressionBase.cs @@ -36,7 +36,7 @@ namespace Umbraco.Core.Persistence.Migrations || SupportedDatabaseTypes.Any(x => CurrentDatabaseType.GetType().Inherits(x.GetType())); } - public virtual string Process(IUmbracoDatabase database) + public virtual string Process(IMigrationContext context) { return ToString(); } diff --git a/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs b/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs index a43f212ab1..94e0dec22c 100644 --- a/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs +++ b/src/Umbraco.Core/Persistence/Migrations/MigrationRunner.cs @@ -186,7 +186,7 @@ namespace Umbraco.Core.Persistence.Migrations int i = 1; foreach (var expression in context.Expressions) { - var sql = expression.Process(context.Database); + var sql = expression.Process(context); if (string.IsNullOrEmpty(sql)) { i++; @@ -211,6 +211,7 @@ namespace Umbraco.Core.Persistence.Migrations //Execute the SQL up to the point of a GO statement var exeSql = sb.ToString(); _logger.Info("Executing sql statement " + i + ": " + exeSql); + Console.WriteLine("EXEC: " + exeSql); context.Database.Execute(exeSql); //restart the string builder @@ -226,6 +227,7 @@ namespace Umbraco.Core.Persistence.Migrations { var exeSql = sb.ToString(); _logger.Info("Executing sql statement " + i + ": " + exeSql); + Console.WriteLine("EXEC: " + exeSql); context.Database.Execute(exeSql); } } diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Create/CreateBuilder.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Create/CreateBuilder.cs index 15f7ee43f2..b29c8c8884 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Create/CreateBuilder.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Create/CreateBuilder.cs @@ -38,6 +38,28 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create AddSql(sql); } + public void KeysAndIndexes() + { + var tableDefinition = DefinitionFactory.GetTableDefinition(typeof(T), SqlSyntax); + + AddSql(SqlSyntax.FormatPrimaryKey(tableDefinition)); + foreach (var sql in SqlSyntax.Format(tableDefinition.ForeignKeys)) + AddSql(sql); + foreach (var sql in SqlSyntax.Format(tableDefinition.Indexes)) + AddSql(sql); + } + + public void KeysAndIndexes(Type typeOfDto) + { + var tableDefinition = DefinitionFactory.GetTableDefinition(typeOfDto, SqlSyntax); + + AddSql(SqlSyntax.FormatPrimaryKey(tableDefinition)); + foreach (var sql in SqlSyntax.Format(tableDefinition.ForeignKeys)) + AddSql(sql); + foreach (var sql in SqlSyntax.Format(tableDefinition.Indexes)) + AddSql(sql); + } + private void AddSql(string sql) { var expression = new ExecuteSqlStatementExpression(_context, _supportedDatabaseTypes) { SqlStatement = sql }; diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Create/ICreateBuilder.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Create/ICreateBuilder.cs index 48eaccd3b2..4ada8439cc 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Create/ICreateBuilder.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Create/ICreateBuilder.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Persistence.Migrations.Syntax.Create.Column; +using System; +using Umbraco.Core.Persistence.Migrations.Syntax.Create.Column; using Umbraco.Core.Persistence.Migrations.Syntax.Create.Constraint; using Umbraco.Core.Persistence.Migrations.Syntax.Create.ForeignKey; using Umbraco.Core.Persistence.Migrations.Syntax.Create.Index; @@ -9,6 +10,8 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create public interface ICreateBuilder : IFluentSyntax { void Table(); + void KeysAndIndexes(); + void KeysAndIndexes(Type typeOfDto); ICreateTableWithColumnSyntax Table(string tableName); ICreateColumnOnTableSyntax Column(string columnName); diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Delete/DeleteBuilder.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Delete/DeleteBuilder.cs index c23d88eb43..150e9b7155 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Delete/DeleteBuilder.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Delete/DeleteBuilder.cs @@ -1,4 +1,5 @@ -using NPoco; +using System; +using NPoco; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Migrations.Syntax.Delete.Column; using Umbraco.Core.Persistence.Migrations.Syntax.Delete.Constraint; diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/ExecuteBuilder.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/ExecuteBuilder.cs index e8c11f2966..858e261ff7 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/ExecuteBuilder.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/ExecuteBuilder.cs @@ -22,7 +22,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Execute _context.Expressions.Add(expression); } - public void Code(Func codeStatement) + public void Code(Func codeStatement) { var expression = new ExecuteCodeStatementExpression(_context, _supportedDatabaseTypes) { CodeStatement = codeStatement }; _context.Expressions.Add(expression); diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/ExecuteBuilderExtensions.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/ExecuteBuilderExtensions.cs new file mode 100644 index 0000000000..a015ad3c7e --- /dev/null +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/ExecuteBuilderExtensions.cs @@ -0,0 +1,56 @@ +using System.Linq; +using Umbraco.Core.Persistence.SqlSyntax; + +namespace Umbraco.Core.Persistence.Migrations.Syntax.Execute +{ + public static class ExecuteBuilderExtensions + { + public static void DropKeysAndIndexes(this IExecuteBuilder execute, string tableName) + { + execute.Code(context => DropKeysAndIndexes(context, tableName)); + } + + public static void DropKeysAndIndexes(this IExecuteBuilder execute) + { + execute.Code(DropKeysAndIndexes); + } + + private static string DropKeysAndIndexes(IMigrationContext context, string tableName) + { + var local = context.GetLocalMigration(); + + // drop indexes + var indexes = context.SqlContext.SqlSyntax.GetDefinedIndexesDefinitions(context.Database).ToArray(); + foreach (var index in indexes.Where(x => x.TableName == tableName)) + local.Delete.Index(index.IndexName).OnTable(index.TableName); + + // drop keys + var keys = context.SqlContext.SqlSyntax.GetConstraintsPerTable(context.Database).ToArray(); + foreach (var key in keys.Where(x => x.Item1 == tableName && x.Item2.StartsWith("FK_"))) + local.Delete.ForeignKey(key.Item2).OnTable(key.Item1); + foreach (var key in keys.Where(x => x.Item1 == tableName && x.Item2.StartsWith("PK_"))) + local.Delete.PrimaryKey(key.Item2).FromTable(key.Item1); + + return local.GetSql(); + } + + private static string DropKeysAndIndexes(IMigrationContext context) + { + var local = context.GetLocalMigration(); + + // drop indexes + var indexes = context.SqlContext.SqlSyntax.GetDefinedIndexesDefinitions(context.Database).ToArray(); + foreach (var index in indexes) + local.Delete.Index(index.IndexName).OnTable(index.TableName); + + // drop keys + var keys = context.SqlContext.SqlSyntax.GetConstraintsPerTable(context.Database).ToArray(); + foreach (var key in keys.Where(x => x.Item2.StartsWith("FK_"))) + local.Delete.ForeignKey(key.Item2).OnTable(key.Item1); + foreach (var key in keys.Where(x => x.Item2.StartsWith("PK_"))) + local.Delete.PrimaryKey(key.Item2).FromTable(key.Item1); + + return local.GetSql(); + } + } +} diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/Expressions/ExecuteCodeStatementExpression.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/Expressions/ExecuteCodeStatementExpression.cs index e7cd02c9f3..ca589af16a 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/Expressions/ExecuteCodeStatementExpression.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/Expressions/ExecuteCodeStatementExpression.cs @@ -9,14 +9,11 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Execute.Expressions : base(context, supportedDatabaseTypes) { } - public virtual Func CodeStatement { get; set; } + public virtual Func CodeStatement { get; set; } - public override string Process(IUmbracoDatabase database) + public override string Process(IMigrationContext context) { - if(CodeStatement != null) - return CodeStatement(database); - - return base.Process(database); + return CodeStatement != null ? CodeStatement(context) : base.Process(context); } } } diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/IExecuteBuilder.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/IExecuteBuilder.cs index 66d30d0b17..7c18e3cf4e 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/IExecuteBuilder.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Execute/IExecuteBuilder.cs @@ -5,6 +5,6 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Execute public interface IExecuteBuilder : IFluentSyntax { void Sql(string sqlStatement); - void Code(Func codeStatement); + void Code(Func codeStatement); } } diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Rename/Expressions/RenameColumnExpression.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Rename/Expressions/RenameColumnExpression.cs index 5bebe98dd7..1042a60402 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Rename/Expressions/RenameColumnExpression.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Rename/Expressions/RenameColumnExpression.cs @@ -13,7 +13,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Rename.Expressions public virtual string OldName { get; set; } public virtual string NewName { get; set; } - public override string Process(IUmbracoDatabase database) + public override string Process(IMigrationContext context) { if (CurrentDatabaseType.IsMySql()) { @@ -35,7 +35,7 @@ SELECT CONCAT( FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '{0}' AND COLUMN_NAME = '{1}'", TableName, OldName); - var columnDefinition = database.ExecuteScalar(columnDefinitionSql); + var columnDefinition = context.Database.ExecuteScalar(columnDefinitionSql); return this.ToString() + " " + columnDefinition; } diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionEight/AddLockObjects.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionEight/AddLockObjects.cs index 18fec935c9..4c9955bb07 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionEight/AddLockObjects.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionEight/AddLockObjects.cs @@ -32,8 +32,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionEight private void EnsureLockObject(int id, string name) { - Execute.Code(db => + Execute.Code(context => { + var db = context.Database; var exists = db.Exists(id); if (exists) return string.Empty; // be safe: delete old umbracoNode lock objects if any diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionEight/AddRedirectUrlTable.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionEight/AddRedirectUrlTable.cs index f917c38bf6..0bd0080606 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionEight/AddRedirectUrlTable.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionEight/AddRedirectUrlTable.cs @@ -16,8 +16,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionEight Execute.Code(MigrationCode); } - private string MigrationCode(IUmbracoDatabase database) + private string MigrationCode(IMigrationContext context) { + var database = context.Database; var umbracoRedirectUrlTableName = "umbracoRedirectUrl"; var local = Context.GetLocalMigration(); diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionEight/VariantsMigration.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionEight/VariantsMigration.cs new file mode 100644 index 0000000000..4a70e2bdbb --- /dev/null +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionEight/VariantsMigration.cs @@ -0,0 +1,71 @@ +using System.Linq; +using Umbraco.Core.Models.Rdbms; +using Umbraco.Core.Persistence.Migrations.Syntax.Execute; + +namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionEight +{ + [Migration("8.0.0", 400, Constants.System.UmbracoMigrationName)] + public class VariantsMigration : MigrationBase + { + public VariantsMigration(IMigrationContext context) + : base(context) + { } + + public override void Up() + { + // delete keys and indexes + Execute.DropKeysAndIndexes(Constants.DatabaseSchema.Tables.PropertyData); + + // fixme is this enough or shall we drop *all* keys and indexes? + + MigratePropertyData(); + + // re-create keys and indexes + Create.KeysAndIndexes(); + } + + private void MigrateContentDocumentAndVersion() + { + // todo + // add a varyBy field that's an enum (invariant, culture, segment) + } + + private void MigratePropertyData() + { + // add column propertyData.languageId + if (!ColumnExists(Constants.DatabaseSchema.Tables.PropertyData, "languageId")) + Alter.Table(Constants.DatabaseSchema.Tables.PropertyData).AddColumn("languageId").AsInt32().Nullable(); + + // add column propertyData.segment + if (!ColumnExists(Constants.DatabaseSchema.Tables.PropertyData, "segment")) + Alter.Table(Constants.DatabaseSchema.Tables.PropertyData).AddColumn("segment").AsString(256).Nullable(); + + // rename column propertyData.contentNodeId to nodeId + if (ColumnExists(Constants.DatabaseSchema.Tables.PropertyData, "contentNodeId")) + Rename.Column("contentNodeId").OnTable(Constants.DatabaseSchema.Tables.PropertyData).To("nodeId"); + + // rename column propertyData.dataNtext to textValue + // rename column propertyData.dataNvarchar to varcharValue + // rename column propertyData.dataDecimal to decimalValue + // rename column propertyData.dataInt to intValue + // rename column propertyData.dataDate to dateValue + if (ColumnExists(Constants.DatabaseSchema.Tables.PropertyData, "dataNtext")) + Rename.Column("dataNtext").OnTable(Constants.DatabaseSchema.Tables.PropertyData).To("textValue"); + if (ColumnExists(Constants.DatabaseSchema.Tables.PropertyData, "dataNvarchar")) + Rename.Column("dataNtext").OnTable(Constants.DatabaseSchema.Tables.PropertyData).To("varcharValue"); + if (ColumnExists(Constants.DatabaseSchema.Tables.PropertyData, "dataDecimal")) + Rename.Column("dataDecimal").OnTable(Constants.DatabaseSchema.Tables.PropertyData).To("decimalValue"); + if (ColumnExists(Constants.DatabaseSchema.Tables.PropertyData, "dataInt")) + Rename.Column("dataInt").OnTable(Constants.DatabaseSchema.Tables.PropertyData).To("intValue"); + if (ColumnExists(Constants.DatabaseSchema.Tables.PropertyData, "dataDate")) + Rename.Column("dataDate").OnTable(Constants.DatabaseSchema.Tables.PropertyData).To("dateValue"); + } + + private bool ColumnExists(string tableName, string columnName) + { + // that's ok even on MySql + var columns = SqlSyntax.GetColumnsInSchema(Context.Database).Distinct().ToArray(); + return columns.Any(x => x.TableName.InvariantEquals(tableName) && x.ColumnName.InvariantEquals(columnName)); + } + } +} diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/UpdateRelatedLinksData.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/UpdateRelatedLinksData.cs index ebf825c4bd..096abb9e6a 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/UpdateRelatedLinksData.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSeven/UpdateRelatedLinksData.cs @@ -30,8 +30,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven Execute.Code(UpdateRelatedLinksDataDo); } - public string UpdateRelatedLinksDataDo(IDatabase database) + public string UpdateRelatedLinksDataDo(IMigrationContext context) { + var database = context?.Database; if (database != null) { var dtSql = Sql().Select("nodeId").From() @@ -45,7 +46,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven + " WHERE propertyTypeId in (SELECT id from cmsPropertyType where dataTypeID IN (@dataTypeIds))", new { /*dataTypeIds =*/ dataTypeIds }); if (propertyData.Any() == false) return string.Empty; - var nodesIdsWithProperty = propertyData.Select(x => (int) x.contentNodeId).Distinct().ToArray(); + var nodesIdsWithProperty = propertyData.Select(x => (int) x.nodeId).Distinct().ToArray(); var cmsContentXmlEntries = new List(); //We're doing an "IN" query here but SQL server only supports 2100 query parameters so we're going to split on that @@ -65,25 +66,25 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven foreach (var data in propertyData) { - if (string.IsNullOrEmpty(data.dataNtext) == false) + if (string.IsNullOrEmpty(data.textValue) == false) { XmlDocument xml; //fetch the current data (that's in xml format) try { xml = new XmlDocument(); - xml.LoadXml(data.dataNtext); + xml.LoadXml(data.textValue); } catch (Exception ex) { int dataId = data.id; - int dataNodeId = data.contentNodeId; - string dataText = data.dataNtext; + int dataNodeId = data.nodeId; + string dataText = data.textValue; Logger.Error("The data stored for property id " + dataId + " on document " + dataNodeId + " is not valid XML, the data will be removed because it cannot be converted to the new format. The value was: " + dataText, ex); - data.dataNtext = ""; - database.Update("cmsPropertyData", "id", data, new[] { "dataNText" }); + data.textValue = ""; + database.Update("cmsPropertyData", "id", data, new[] { "textValue" }); UpdateXmlTable(propertyTypes, data, cmsContentXmlEntries, database); @@ -116,9 +117,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven } //store the serialized data - data.dataNtext = JsonConvert.SerializeObject(links); + data.textValue = JsonConvert.SerializeObject(links); - database.Update("cmsPropertyData", "id", data, new[] { "dataNText" }); + database.Update("cmsPropertyData", "id", data, new[] { "textValue" }); UpdateXmlTable(propertyTypes, data, cmsContentXmlEntries, database); @@ -139,14 +140,14 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven var propertyType = propertyTypes.SingleOrDefault(x => x.Id == data.propertytypeid); if (propertyType != null) { - var xmlItem = cmsContentXmlEntries.SingleOrDefault(x => x.NodeId == data.contentNodeId); + var xmlItem = cmsContentXmlEntries.SingleOrDefault(x => x.NodeId == data.nodeId); if (xmlItem != null) { var x = XElement.Parse(xmlItem.Xml); var prop = x.Element(propertyType.Alias); if (prop != null) { - prop.ReplaceAll(new XCData(data.dataNtext)); + prop.ReplaceAll(new XCData(data.textValue)); database.Update(xmlItem); } } diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveFive/AddLockObjects.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveFive/AddLockObjects.cs index 9240e2e86e..cded8d5fc4 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveFive/AddLockObjects.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveFive/AddLockObjects.cs @@ -22,8 +22,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFiveFiv private void EnsureLockObject(int id, string name) { - Execute.Code(db => + Execute.Code(context => { + var db = context.Database; var exists = db.Exists(id); if (exists) return string.Empty; // be safe: delete old umbracoNode lock objects if any diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveZero/RemoveStylesheetDataAndTablesAgain.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveZero/RemoveStylesheetDataAndTablesAgain.cs index 9b2afb52a1..e6a5e7886d 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveZero/RemoveStylesheetDataAndTablesAgain.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveZero/RemoveStylesheetDataAndTablesAgain.cs @@ -23,7 +23,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFiveZer Execute.Code(MigrationCode); } - private string MigrationCode(IUmbracoDatabase database) + private string MigrationCode(IMigrationContext context) { var local = Context.GetLocalMigration(); diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveZero/UpdateUniqueIndexOnCmsPropertyData.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveZero/UpdateUniqueIndexOnCmsPropertyData.cs index 9e444e87f3..fb0c78ebce 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveZero/UpdateUniqueIndexOnCmsPropertyData.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFiveZero/UpdateUniqueIndexOnCmsPropertyData.cs @@ -41,7 +41,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFiveZer var delPropQry = SqlSyntax.GetDeleteSubquery( "cmsPropertyData", "id", - Sql("SELECT MIN(id) FROM cmsPropertyData GROUP BY contentNodeId, versionId, propertytypeid HAVING MIN(id) IS NOT NULL"), + Sql("SELECT MIN(id) FROM cmsPropertyData GROUP BY nodeId, versionId, propertytypeid HAVING MIN(id) IS NOT NULL"), WhereInType.NotIn); Execute.Sql(delPropQry.SQL); } @@ -50,13 +50,13 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFiveZer //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)"); + Execute.Sql("DELETE FROM cmsPropertyData WHERE id NOT IN (SELECT MIN(id) FROM cmsPropertyData GROUP BY nodeId, 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("nodeId").Ascending() .OnColumn("versionId").Ascending() .OnColumn("propertytypeid").Ascending() .WithOptions().NonClustered() diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourZero/AddUniqueIdPropertyTypeGroupColumn.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourZero/AddUniqueIdPropertyTypeGroupColumn.cs index 2cb8459e1d..395057c397 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourZero/AddUniqueIdPropertyTypeGroupColumn.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenFourZero/AddUniqueIdPropertyTypeGroupColumn.cs @@ -39,8 +39,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFourZer } } - private static string UpdateGuids(IDatabase database) + private static string UpdateGuids(IMigrationContext context) { + var database = context.Database; var updates = new List>(); foreach (var data in database.Query(@" diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSevenZero/AddIndexToDictionaryKeyColumn.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSevenZero/AddIndexToDictionaryKeyColumn.cs index 3ada30ace9..109e6de5ea 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSevenZero/AddIndexToDictionaryKeyColumn.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSevenZero/AddIndexToDictionaryKeyColumn.cs @@ -13,8 +13,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSevenZe public override void Up() { - Execute.Code(database => + Execute.Code(context => { + var database = context.Database; //Now we need to check if we can actually do this because we won't be able to if there's data in there that is too long var colLen = (SqlSyntax is MySqlSyntaxProvider) ? database.ExecuteScalar(string.Format("select max(LENGTH({0})) from cmsDictionary", SqlSyntax.GetQuotedColumnName("key"))) diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSevenZero/EnsureContentTemplatePermissions.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSevenZero/EnsureContentTemplatePermissions.cs index 504384338a..632fa578b1 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSevenZero/EnsureContentTemplatePermissions.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSevenZero/EnsureContentTemplatePermissions.cs @@ -16,8 +16,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSevenZe public override void Up() { - Execute.Code(database => + Execute.Code(context => { + var database = context.Database; var userGroups = database.Fetch( Context.SqlContext.Sql().Select("*") .From() diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSevenZero/ReduceDictionaryKeyColumnsSize.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSevenZero/ReduceDictionaryKeyColumnsSize.cs index aade0500d8..433a8f60fe 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSevenZero/ReduceDictionaryKeyColumnsSize.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSevenZero/ReduceDictionaryKeyColumnsSize.cs @@ -15,8 +15,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSevenZe { //Now we need to check if we can actually do this because we won't be able to if there's data in there that is too long - Execute.Code(database => + Execute.Code(context => { + var database = context.Database; var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(database); var colLen = SqlSyntax is MySqlSyntaxProvider diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddIndexToCmsMemberLoginName.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddIndexToCmsMemberLoginName.cs index d96dd82823..b1231e1375 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddIndexToCmsMemberLoginName.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddIndexToCmsMemberLoginName.cs @@ -13,8 +13,10 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero public override void Up() { - Execute.Code(database => + Execute.Code(context => { + var database = context.Database; + //Now we need to check if we can actually d6 this because we won't be able to if there's data in there that is too long //http://issues.umbraco.org/issue/U4-9758 diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddIndexesToUmbracoRelationTables.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddIndexesToUmbracoRelationTables.cs index 5c08b32616..f6e453ae52 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddIndexesToUmbracoRelationTables.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddIndexesToUmbracoRelationTables.cs @@ -21,8 +21,10 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero { //This will remove any corrupt/duplicate data in the relation table before the index is applied //Ensure this executes in a defered block which will be done inside of the migration transaction - this.Execute.Code(database => + this.Execute.Code(context => { + var database = context.Database; + //We need to check if this index has corrupted data and then clear that data var duplicates = database.Fetch("SELECT parentId,childId,relType FROM umbracoRelation GROUP BY parentId,childId,relType HAVING COUNT(*) > 1"); if (duplicates.Count > 0) diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddLockObjects.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddLockObjects.cs index 2dfe0d5dea..3b45230f59 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddLockObjects.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddLockObjects.cs @@ -23,8 +23,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero private void EnsureLockObject(int id, string name) { - Execute.Code(db => + Execute.Code(context => { + var db = context.Database; var exists = db.Exists(id); if (exists) return string.Empty; // be safe: delete old umbracoNode lock objects if any diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddMacroUniqueIdColumn.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddMacroUniqueIdColumn.cs index 6e34d002de..896c083e4b 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddMacroUniqueIdColumn.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddMacroUniqueIdColumn.cs @@ -40,8 +40,10 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero } } - private static string UpdateMacroGuids(IUmbracoDatabase database) + private static string UpdateMacroGuids(IMigrationContext context) { + var database = context.Database; + var updates = database.Query("SELECT id, macroAlias FROM cmsMacro") .Select(macro => Tuple.Create((int) macro.id, ("macro____" + (string) macro.macroAlias).ToGuid())) .ToList(); @@ -52,8 +54,10 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero return string.Empty; } - private static string UpdateMacroPropertyGuids(IUmbracoDatabase database) + private static string UpdateMacroPropertyGuids(IMigrationContext context) { + var database = context.Database; + var updates = database.Query(@"SELECT cmsMacroProperty.id id, macroPropertyAlias propertyAlias, cmsMacro.macroAlias macroAlias FROM cmsMacroProperty JOIN cmsMacro ON cmsMacroProperty.macro=cmsMacro.id") diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddRelationTypeUniqueIdColumn.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddRelationTypeUniqueIdColumn.cs index 9525b4eba8..d877ea8ba3 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddRelationTypeUniqueIdColumn.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/AddRelationTypeUniqueIdColumn.cs @@ -28,8 +28,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero } } - private static string UpdateRelationTypeGuids(IUmbracoDatabase database) + private static string UpdateRelationTypeGuids(IMigrationContext context) { + var database = context.Database; var updates = database.Query("SELECT id, alias, name FROM umbracoRelationType") .Select(relationType => Tuple.Create((int) relationType.id, ("relationType____" + (string) relationType.alias + "____" + (string) relationType.name).ToGuid())) .ToList(); diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/NormalizeTemplateGuids.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/NormalizeTemplateGuids.cs index fbe014ebe6..9c6b6179fa 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/NormalizeTemplateGuids.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/NormalizeTemplateGuids.cs @@ -16,8 +16,10 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero Execute.Code(UpdateTemplateGuids); } - private static string UpdateTemplateGuids(IUmbracoDatabase database) + private static string UpdateTemplateGuids(IMigrationContext context) { + var database = context.Database; + // we need this migration because ppl running pre-7.6 on Cloud and Courier have templates in different // environments having different GUIDs (Courier does not sync template GUIDs) and we need to normalize // these GUIDs so templates with the same alias on different environments have the same GUID. diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/ReduceLoginNameColumnsSize.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/ReduceLoginNameColumnsSize.cs index 4f6d0de714..b18287c529 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/ReduceLoginNameColumnsSize.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenSixZero/ReduceLoginNameColumnsSize.cs @@ -17,8 +17,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero //Now we need to check if we can actually d6 this because we won't be able to if there's data in there that is too long //http://issues.umbraco.org/issue/U4-9758 - Execute.Code(database => + Execute.Code(context => { + var database = context.Database; var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(database); var colLen = (SqlSyntax is MySqlSyntaxProvider) diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeTwo/EnsureMigrationsTableIdentityIsCorrect.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeTwo/EnsureMigrationsTableIdentityIsCorrect.cs index fee75ed8a2..29c961c9be 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeTwo/EnsureMigrationsTableIdentityIsCorrect.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeTwo/EnsureMigrationsTableIdentityIsCorrect.cs @@ -29,8 +29,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeTw return string.Empty; }); Delete.FromTable("umbracoMigration").AllRows(); - Execute.Code(database => + Execute.Code(context => { + var database = context.Database; if (migrations != null) { foreach (var migration in migrations) diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MigrateAndRemoveTemplateMasterColumn.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MigrateAndRemoveTemplateMasterColumn.cs index 9b445fd06f..7d1d8baeaa 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MigrateAndRemoveTemplateMasterColumn.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/MigrateAndRemoveTemplateMasterColumn.cs @@ -54,8 +54,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe //FROM umbracoNode t1 //INNER JOIN cmsTemplate t2 //ON t1.id = t2.nodeId"); - Execute.Code(database => + Execute.Code(context => { + var database = context.Database; var templateData = database.Fetch("SELECT * FROM cmsTemplate"); foreach (var template in templateData) @@ -72,8 +73,10 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe }); //Now we can update the path, but this needs to be done in a delegate callback so that the query runs after the updates just completed - Execute.Code(database => + Execute.Code(context => { + var database = context.Database; + //NOTE: we are using dynamic because we need to get the data in a column that no longer exists in the schema var templates = database.Fetch(Sql().SelectAll().From()); foreach (var template in templates) diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/AddMissingForeignKeyForContentType.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/AddMissingForeignKeyForContentType.cs index aed682e0be..79260b344c 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/AddMissingForeignKeyForContentType.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenTwoZero/AddMissingForeignKeyForContentType.cs @@ -35,7 +35,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwoZero Delete.FromTable("cmsTagRelationship").Row(new { nodeId = orphanedId }); Delete.FromTable("umbracoDomains").Row(new { domainRootStructureID = orphanedId }); Delete.FromTable("cmsDocument").Row(new { nodeId = orphanedId }); - Delete.FromTable("cmsPropertyData").Row(new { contentNodeId = orphanedId }); + Delete.FromTable("cmsPropertyData").Row(new { nodeId = orphanedId }); Delete.FromTable("cmsMember2MemberGroup").Row(new { Member = orphanedId }); Delete.FromTable("cmsMember").Row(new { nodeId = orphanedId }); Delete.FromTable("cmsPreviewXml").Row(new { nodeId = orphanedId }); diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs index a6bd19e708..2352e010e7 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs @@ -194,7 +194,7 @@ namespace Umbraco.Core.Persistence.Repositories "DELETE FROM cmsTagRelationship WHERE nodeId = @Id", "DELETE FROM umbracoDomains WHERE domainRootStructureID = @Id", "DELETE FROM cmsDocument WHERE nodeId = @Id", - "DELETE FROM cmsPropertyData WHERE contentNodeId = @Id", + "DELETE FROM cmsPropertyData WHERE nodeId = @Id", "DELETE FROM cmsPreviewXml WHERE nodeId = @Id", "DELETE FROM cmsContentVersion WHERE ContentId = @Id", "DELETE FROM cmsContentXml WHERE nodeId = @Id", @@ -274,7 +274,7 @@ namespace Umbraco.Core.Persistence.Repositories // raise event first else potential FK issues OnUowRemovingVersion(new UnitOfWorkVersionEventArgs(UnitOfWork, id, versionId)); - Database.Delete("WHERE contentNodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId }); + Database.Delete("WHERE nodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId }); Database.Delete("WHERE ContentId = @Id AND VersionId = @VersionId", new { Id = id, VersionId = versionId }); Database.Delete("WHERE nodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId }); } diff --git a/src/Umbraco.Core/Persistence/Repositories/EntityRepository.cs b/src/Umbraco.Core/Persistence/Repositories/EntityRepository.cs index acfaee8f95..75a32a448e 100644 --- a/src/Umbraco.Core/Persistence/Repositories/EntityRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/EntityRepository.cs @@ -71,8 +71,8 @@ namespace Umbraco.Core.Persistence.Repositories foreach (var idGroup in ids) { var propSql = GetPropertySql(Constants.ObjectTypes.Media) - .Where("contentNodeId IN (@ids)", new { ids = idGroup }) - .OrderBy("contentNodeId"); + .Where("nodeId IN (@ids)", new { ids = idGroup }) + .OrderBy("nodeId"); //This does NOT fetch all data into memory in a list, this will read // over the records as a data reader, this is much better for performance and memory, @@ -94,7 +94,7 @@ namespace Umbraco.Core.Persistence.Repositories // use the available enumerator.Current if any else move to next while (hasCurrent || propertyDataSetEnumerator.MoveNext()) { - if (propertyDataSetEnumerator.Current.contentNodeId == entity.Id) + if (propertyDataSetEnumerator.Current.nodeId == entity.Id) { hasCurrent = false; // enumerator.Current is not available @@ -102,9 +102,9 @@ namespace Umbraco.Core.Persistence.Repositories entity.AdditionalData[propertyDataSetEnumerator.Current.propertyTypeAlias] = new UmbracoEntity.EntityProperty { PropertyEditorAlias = propertyDataSetEnumerator.Current.propertyEditorAlias, - Value = StringExtensions.IsNullOrWhiteSpace(propertyDataSetEnumerator.Current.dataNtext) - ? propertyDataSetEnumerator.Current.dataNvarchar - : StringExtensions.ConvertToJsonIfPossible(propertyDataSetEnumerator.Current.dataNtext) + Value = StringExtensions.IsNullOrWhiteSpace(propertyDataSetEnumerator.Current.textValue) + ? propertyDataSetEnumerator.Current.varcharValue + : StringExtensions.ConvertToJsonIfPossible(propertyDataSetEnumerator.Current.textValue) }; } else @@ -418,7 +418,7 @@ namespace Umbraco.Core.Persistence.Repositories private Sql GetPropertySql(Guid nodeObjectType) { var sql = Sql() - .Select("contentNodeId, versionId, dataNvarchar, dataNtext, propertyEditorAlias, alias as propertyTypeAlias") + .Select("nodeId, versionId, varcharValue, textValue, propertyEditorAlias, alias as propertyTypeAlias") .From() .InnerJoin() .On(dto => dto.NodeId, dto => dto.NodeId) @@ -433,7 +433,7 @@ namespace Umbraco.Core.Persistence.Repositories private Sql GetFullSqlForMedia(Sql entitySql, Action> filter = null) { - //this will add any dataNvarchar property to the output which can be added to the additional properties + //this will add any varcharValue property to the output which can be added to the additional properties var sql = GetPropertySql(Constants.ObjectTypes.Media); @@ -448,7 +448,7 @@ namespace Umbraco.Core.Persistence.Repositories .Append(entitySql) .Append(") tmpTbl LEFT JOIN (") .Append(sql) - .Append(") as property ON id = property.contentNodeId") + .Append(") as property ON id = property.nodeId") .OrderBy("sortOrder, id"); return wrappedSql; @@ -661,11 +661,11 @@ namespace Umbraco.Core.Persistence.Repositories [Column("propertyTypeAlias")] public string PropertyAlias { get; set; } - [Column("dataNvarchar")] - public string NVarcharValue { get; set; } + [Column("varcharValue")] + public string VarcharValue { get; set; } - [Column("dataNtext")] - public string NTextValue { get; set; } + [Column("textValue")] + public string TextValue { get; set; } } /// @@ -707,8 +707,8 @@ namespace Umbraco.Core.Persistence.Repositories string pPropertyEditorAlias = a.propertyEditorAlias; var pExists = pPropertyEditorAlias != null; string pPropertyAlias = a.propertyTypeAlias; - string pNTextValue = a.dataNtext; - string pNVarcharValue = a.dataNvarchar; + string pTextValue = a.textValue; + string pNVarcharValue = a.varcharValue; // Is this the same UmbracoEntity as the current one we're processing if (Current != null && Current.Key == a.uniqueID) @@ -719,9 +719,9 @@ namespace Umbraco.Core.Persistence.Repositories Current.AdditionalData[pPropertyAlias] = new UmbracoEntity.EntityProperty { PropertyEditorAlias = pPropertyEditorAlias, - Value = pNTextValue.IsNullOrWhiteSpace() + Value = pTextValue.IsNullOrWhiteSpace() ? pNVarcharValue - : pNTextValue.ConvertToJsonIfPossible() + : pTextValue.ConvertToJsonIfPossible() }; } @@ -745,9 +745,9 @@ namespace Umbraco.Core.Persistence.Repositories Current.AdditionalData[pPropertyAlias] = new UmbracoEntity.EntityProperty { PropertyEditorAlias = pPropertyEditorAlias, - Value = pNTextValue.IsNullOrWhiteSpace() + Value = pTextValue.IsNullOrWhiteSpace() ? pNVarcharValue - : pNTextValue.ConvertToJsonIfPossible() + : pTextValue.ConvertToJsonIfPossible() }; } diff --git a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs index c5885056d9..b771a0846c 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs @@ -136,7 +136,7 @@ namespace Umbraco.Core.Persistence.Repositories "DELETE FROM umbracoRelation WHERE childId = @Id", "DELETE FROM cmsTagRelationship WHERE nodeId = @Id", "DELETE FROM cmsDocument WHERE nodeId = @Id", - "DELETE FROM cmsPropertyData WHERE contentNodeId = @Id", + "DELETE FROM cmsPropertyData WHERE nodeId = @Id", "DELETE FROM cmsContentVersion WHERE ContentId = @Id", "DELETE FROM cmsContent WHERE nodeId = @Id", "DELETE FROM umbracoNode WHERE id = @Id" @@ -189,12 +189,12 @@ namespace Umbraco.Core.Persistence.Repositories // If the stripped-down url returns null, we try again with the original url. // Previously, the function would fail on e.g. "my_x_image.jpg" - var nodeId = GetMediaNodeIdByPath(Sql().Where(x => x.VarChar== umbracoFileValue)); - if (nodeId < 0) nodeId = GetMediaNodeIdByPath(Sql().Where(x => x.VarChar == mediaPath)); + var nodeId = GetMediaNodeIdByPath(Sql().Where(x => x.VarcharValue== umbracoFileValue)); + if (nodeId < 0) nodeId = GetMediaNodeIdByPath(Sql().Where(x => x.VarcharValue == mediaPath)); // If no result so far, try getting from a json value stored in the ntext / nvarchar column - if (nodeId < 0) nodeId = GetMediaNodeIdByPath(Sql().Where("dataNtext LIKE @0", "%" + umbracoFileValue + "%")); - if (nodeId < 0) nodeId = GetMediaNodeIdByPath(Sql().Where("dataNvarchar LIKE @0", "%" + umbracoFileValue + "%")); + if (nodeId < 0) nodeId = GetMediaNodeIdByPath(Sql().Where("textValue LIKE @0", "%" + umbracoFileValue + "%")); + if (nodeId < 0) nodeId = GetMediaNodeIdByPath(Sql().Where("varcharValue LIKE @0", "%" + umbracoFileValue + "%")); return nodeId < 0 ? null : Get(nodeId); } @@ -217,7 +217,7 @@ namespace Umbraco.Core.Persistence.Repositories // raise event first else potential FK issues OnUowRemovingVersion(new UnitOfWorkVersionEventArgs(UnitOfWork, id, versionId)); - Database.Delete("WHERE contentNodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId }); + Database.Delete("WHERE nodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId }); Database.Delete("WHERE ContentId = @Id AND VersionId = @VersionId", new { Id = id, VersionId = versionId }); } diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs index 016aa14d0a..1b343e8577 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs @@ -175,7 +175,7 @@ namespace Umbraco.Core.Persistence.Repositories "DELETE FROM umbracoRelation WHERE parentId = @Id", "DELETE FROM umbracoRelation WHERE childId = @Id", "DELETE FROM cmsTagRelationship WHERE nodeId = @Id", - "DELETE FROM cmsPropertyData WHERE contentNodeId = @Id", + "DELETE FROM cmsPropertyData WHERE nodeId = @Id", "DELETE FROM cmsMember2MemberGroup WHERE Member = @Id", "DELETE FROM cmsMember WHERE nodeId = @Id", "DELETE FROM cmsContentVersion WHERE ContentId = @Id", @@ -450,7 +450,7 @@ namespace Umbraco.Core.Persistence.Repositories // raise event first else potential FK issues OnUowRemovingVersion(new UnitOfWorkVersionEventArgs(UnitOfWork, id, versionId)); - Database.Delete("WHERE contentNodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId }); + Database.Delete("WHERE nodeId = @Id AND versionId = @VersionId", new { Id = id, VersionId = versionId }); Database.Delete("WHERE ContentId = @Id AND VersionId = @VersionId", new { Id = id, VersionId = versionId }); } diff --git a/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs index 3174e8af3a..24f6dcdd2b 100644 --- a/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs @@ -322,10 +322,10 @@ namespace Umbraco.Core.Persistence.Repositories { // Sorting by a custom field, so set-up sub-query for ORDER BY clause to pull through value // from most recent content version for the given order by field - var sortedInt = string.Format(SqlContext.SqlSyntax.ConvertIntegerToOrderableString, "dataInt"); - var sortedDate = string.Format(SqlContext.SqlSyntax.ConvertDateToOrderableString, "dataDate"); - var sortedString = "COALESCE(dataNvarchar,'')"; // assuming COALESCE is ok for all syntaxes - var sortedDecimal = string.Format(SqlContext.SqlSyntax.ConvertDecimalToOrderableString, "dataDecimal"); + var sortedInt = string.Format(SqlContext.SqlSyntax.ConvertIntegerToOrderableString, "intValue"); + var sortedDate = string.Format(SqlContext.SqlSyntax.ConvertDateToOrderableString, "dateValue"); + var sortedString = "COALESCE(varcharValue,'')"; // assuming COALESCE is ok for all syntaxes + var sortedDecimal = string.Format(SqlContext.SqlSyntax.ConvertDecimalToOrderableString, "decimalValue"); // variable query fragments that depend on what we are querying string andVersion, andNewest, idField; @@ -353,14 +353,14 @@ namespace Umbraco.Core.Persistence.Repositories // needs to be an outer join since there's no guarantee that any of the nodes have values for this property var outerJoinTempTable = $@"LEFT OUTER JOIN ( SELECT CASE - WHEN dataInt IS NOT NULL THEN {sortedInt} - WHEN dataDecimal IS NOT NULL THEN {sortedDecimal} - WHEN dataDate IS NOT NULL THEN {sortedDate} + WHEN intValue IS NOT NULL THEN {sortedInt} + WHEN decimalValue IS NOT NULL THEN {sortedDecimal} + WHEN dateValue IS NOT NULL THEN {sortedDate} ELSE {sortedString} END AS CustomPropVal, cd.{idField} AS CustomPropValContentId FROM {table} cd - INNER JOIN cmsPropertyData cpd ON cpd.contentNodeId = cd.{idField}{andVersion} + INNER JOIN cmsPropertyData cpd ON cpd.nodeId = cd.{idField}{andVersion} INNER JOIN cmsPropertyType cpt ON cpt.Id = cpd.propertytypeId WHERE cpt.Alias = @{sql.Arguments.Length}{andNewest}) AS CustomPropData ON CustomPropData.CustomPropValContentId = umbracoNode.id "; // trailing space is important! @@ -731,8 +731,8 @@ INNER JOIN cmsPropertyType ON cmsPropertyData.propertytypeid = cmsPropertyType.id INNER JOIN (" + string.Format(parsedOriginalSql, "cmsContent.nodeId, cmsContentVersion.VersionId") + @") as docData -ON cmsPropertyData.versionId = docData.VersionId AND cmsPropertyData.contentNodeId = docData.nodeId -ORDER BY contentNodeId, versionId, propertytypeid +ON cmsPropertyData.versionId = docData.VersionId AND cmsPropertyData.nodeId = docData.nodeId +ORDER BY nodeId, versionId, propertytypeid ", docSql.Arguments); //This does NOT fetch all data into memory in a list, this will read diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 9011e69fff..f49c239de7 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -975,6 +975,7 @@ + @@ -1013,6 +1014,7 @@ + diff --git a/src/Umbraco.Tests/Migrations/AdvancedMigrationTests.cs b/src/Umbraco.Tests/Migrations/AdvancedMigrationTests.cs new file mode 100644 index 0000000000..5e930d8d09 --- /dev/null +++ b/src/Umbraco.Tests/Migrations/AdvancedMigrationTests.cs @@ -0,0 +1,216 @@ +using System.Linq; +using Moq; +using NUnit.Framework; +using Semver; +using Umbraco.Core.Logging; +using Umbraco.Core.Models.Rdbms; +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.Migrations; +using Umbraco.Core.Persistence.Migrations.Initial; +using Umbraco.Core.Persistence.Migrations.Syntax.Execute; +using Umbraco.Core.Persistence.SqlSyntax; +using Umbraco.Core.Services; +using Umbraco.Tests.TestHelpers; +using Umbraco.Tests.Testing; + +namespace Umbraco.Tests.Migrations +{ + [TestFixture] + [UmbracoTest(Database = UmbracoTestOptions.Database.NewEmptyPerTest)] + public class AdvancedMigrationTests : TestWithDatabaseBase + { + [Test] + public void CreateTableOfTDto() + { + var logger = new DebugDiagnosticsLogger(); + + using (var scope = ScopeProvider.CreateScope()) + { + var database = scope.Database; + + var context = new MigrationContext(database, logger); + + var runner = new MigrationRunner( + Mock.Of(), + Mock.Of(), + logger, + new SemVersion(0), // 0.0.0 + new SemVersion(1), // 1.0.0 + "Test", + + // explicit migrations + new CreateTableOfTDtoMigration(context) + ); + + var upgraded = runner.Execute(context); + Assert.IsTrue(upgraded); + + var helper = new DatabaseSchemaHelper(database, logger); + var exists = helper.TableExist("umbracoNode"); + Assert.IsTrue(exists); + + scope.Complete(); + } + } + + [Test] + public void DeleteKeysAndIndexesOfTDto() + { + var logger = new DebugDiagnosticsLogger(); + + using (var scope = ScopeProvider.CreateScope()) + { + var database = scope.Database; + + var context = new MigrationContext(database, logger); + + var runner = new MigrationRunner( + Mock.Of(), + Mock.Of(), + logger, + new SemVersion(0), // 0.0.0 + new SemVersion(1), // 1.0.0 + "Test", + + // explicit migrations + new CreateTableOfTDtoMigration(context), + new DeleteKeysAndIndexesMigration(context) + ); + + var upgraded = runner.Execute(context); + Assert.IsTrue(upgraded); + + scope.Complete(); + } + } + + [Test] + public void CreateKeysAndIndexesOfTDto() + { + var logger = new DebugDiagnosticsLogger(); + + using (var scope = ScopeProvider.CreateScope()) + { + var database = scope.Database; + + var context = new MigrationContext(database, logger); + + var runner = new MigrationRunner( + Mock.Of(), + Mock.Of(), + logger, + new SemVersion(0), // 0.0.0 + new SemVersion(1), // 1.0.0 + "Test", + + // explicit migrations + new CreateTableOfTDtoMigration(context), + new DeleteKeysAndIndexesMigration(context), + new CreateKeysAndIndexesOfTDtoMigration(context) + ); + + var upgraded = runner.Execute(context); + Assert.IsTrue(upgraded); + + scope.Complete(); + } + } + + [Test] + public void CreateKeysAndIndexes() + { + var logger = new DebugDiagnosticsLogger(); + + using (var scope = ScopeProvider.CreateScope()) + { + var database = scope.Database; + + var context = new MigrationContext(database, logger); + + var runner = new MigrationRunner( + Mock.Of(), + Mock.Of(), + logger, + new SemVersion(0), // 0.0.0 + new SemVersion(1), // 1.0.0 + "Test", + + // explicit migrations + new CreateTableOfTDtoMigration(context), + new DeleteKeysAndIndexesMigration(context), + new CreateKeysAndIndexesMigration(context) + ); + + var upgraded = runner.Execute(context); + Assert.IsTrue(upgraded); + + scope.Complete(); + } + } + + [Migration("1.0.0", 0, "Test")] + public class CreateTableOfTDtoMigration : MigrationBase + { + public CreateTableOfTDtoMigration(IMigrationContext context) + : base(context) + { } + + public override void Up() + { + // creates Node table with keys, indexes, etc + Create.Table(); + } + } + + [Migration("1.0.0", 1, "Test")] + public class DeleteKeysAndIndexesMigration : MigrationBase + { + public DeleteKeysAndIndexesMigration(IMigrationContext context) + : base(context) + { } + + public override void Up() + { + // drops Node table keys and indexes + //Execute.DropKeysAndIndexes("umbracoNode"); + + // drops *all* tables keys and indexes + Execute.DropKeysAndIndexes(); + } + } + + [Migration("1.0.0", 2, "Test")] + public class CreateKeysAndIndexesOfTDtoMigration : MigrationBase + { + public CreateKeysAndIndexesOfTDtoMigration(IMigrationContext context) + : base(context) + { } + + public override void Up() + { + // creates Node table keys and indexes + Create.KeysAndIndexes(); + } + } + + [Migration("1.0.0", 3, "Test")] + public class CreateKeysAndIndexesMigration : MigrationBase + { + public CreateKeysAndIndexesMigration(IMigrationContext context) + : base(context) + { } + + public override void Up() + { + // creates *all* tables keys and indexes + foreach (var x in DatabaseSchemaCreation.OrderedTables) + { + // ok - for tests, restrict to Node + if (x.Value != typeof(NodeDto)) continue; + + Create.KeysAndIndexes(x.Value); + } + } + } + } +} diff --git a/src/Umbraco.Tests/Migrations/CreateTableMigrationTests.cs b/src/Umbraco.Tests/Migrations/CreateTableMigrationTests.cs deleted file mode 100644 index d6e00218a3..0000000000 --- a/src/Umbraco.Tests/Migrations/CreateTableMigrationTests.cs +++ /dev/null @@ -1,71 +0,0 @@ -using Moq; -using NUnit.Framework; -using Semver; -using Umbraco.Core.Exceptions; -using Umbraco.Core.Logging; -using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Migrations; -using Umbraco.Core.Services; -using Umbraco.Tests.TestHelpers; -using Umbraco.Tests.Testing; - -namespace Umbraco.Tests.Migrations -{ - [TestFixture] - [UmbracoTest(Database = UmbracoTestOptions.Database.NewEmptyPerTest)] - public class CreateTableMigrationTests : TestWithDatabaseBase - { - [Test] - public void CreateTableOfTDto() - { - var logger = new DebugDiagnosticsLogger(); - - using (var scope = ScopeProvider.CreateScope()) - { - var database = scope.Database; - - var context = new MigrationContext(database, logger); - - var runner = new MigrationRunner( - Mock.Of(), - Mock.Of(), - logger, - new SemVersion(0), // 0.0.0 - new SemVersion(1), // 1.0.0 - "Test", - - // explicit migrations - new CreateTableOfTDtoMigration(context) - ); - - var upgraded = runner.Execute(context); - Assert.IsTrue(upgraded); - - var helper = new DatabaseSchemaHelper(database, logger); - var exists = helper.TableExist("umbracoNode"); - Assert.IsTrue(exists); - - scope.Complete(); - } - } - - [Migration("1.0.0", 0, "Test")] - public class CreateTableOfTDtoMigration : MigrationBase - { - public CreateTableOfTDtoMigration(IMigrationContext context) - : base(context) - { } - - public override void Up() - { - Create.Table(); - } - - public override void Down() - { - throw new WontImplementException(); - } - } - } -} diff --git a/src/Umbraco.Tests/Migrations/MigrationIssuesTests.cs b/src/Umbraco.Tests/Migrations/MigrationIssuesTests.cs index 870e658f56..fafe0bf4c5 100644 --- a/src/Umbraco.Tests/Migrations/MigrationIssuesTests.cs +++ b/src/Umbraco.Tests/Migrations/MigrationIssuesTests.cs @@ -83,7 +83,7 @@ namespace Umbraco.Tests.Migrations { NodeId = n.NodeId, PropertyTypeId = pt.Id, - Text = "text", + TextValue = "text", VersionId = Guid.NewGuid() }; database.Insert(data); @@ -91,20 +91,20 @@ namespace Umbraco.Tests.Migrations { NodeId = n.NodeId, PropertyTypeId = pt.Id, - Text = "", + TextValue = "", VersionId = Guid.NewGuid() }; database.Insert(data); var migrationContext = new MigrationContext(database, Logger); var migration = new UpdateRelatedLinksData(migrationContext); - migration.UpdateRelatedLinksDataDo(database); + migration.UpdateRelatedLinksDataDo(migrationContext); data = database.Fetch("SELECT * FROM cmsPropertyData WHERE id=" + data.Id).FirstOrDefault(); Assert.IsNotNull(data); - Debug.Print(data.Text); + Debug.Print(data.TextValue); Assert.AreEqual("[{\"title\":\"\",\"caption\":\"\",\"link\":\"\",\"newWindow\":false,\"type\":\"external\",\"internal\":null,\"edit\":false,\"isInternal\":false}]", - data.Text); + data.TextValue); } } diff --git a/src/Umbraco.Tests/Persistence/Querying/ContentRepositorySqlClausesTest.cs b/src/Umbraco.Tests/Persistence/Querying/ContentRepositorySqlClausesTest.cs index 418349d52c..d3230536ac 100644 --- a/src/Umbraco.Tests/Persistence/Querying/ContentRepositorySqlClausesTest.cs +++ b/src/Umbraco.Tests/Persistence/Querying/ContentRepositorySqlClausesTest.cs @@ -135,7 +135,7 @@ namespace Umbraco.Tests.Persistence.Querying expected.Select("*"); expected.From("[cmsPropertyData]"); expected.InnerJoin("[cmsPropertyType]").On("[cmsPropertyData].[propertytypeid] = [cmsPropertyType].[id]"); - expected.Where("([cmsPropertyData].[contentNodeId] = @0)", 1050); + expected.Where("([cmsPropertyData].[nodeId] = @0)", 1050); expected.Where("([cmsPropertyData].[versionId] = @0)", new Guid("2b543516-a944-4ee6-88c6-8813da7aaa07")); var sql = Sql(); diff --git a/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs index dc08296e22..913980bd83 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs @@ -327,7 +327,7 @@ namespace Umbraco.Tests.Persistence.Repositories sql.Select("umbracoNode.*", "cmsContent.contentType", "cmsContentType.alias AS ContentTypeAlias", "cmsContentVersion.VersionId", "cmsContentVersion.VersionDate", "cmsMember.Email", "cmsMember.LoginName", "cmsMember.Password", "cmsPropertyData.id AS PropertyDataId", "cmsPropertyData.propertytypeid", - "cmsPropertyData.dataDate", "cmsPropertyData.dataInt", "cmsPropertyData.dataNtext", "cmsPropertyData.dataNvarchar", + "cmsPropertyData.dateValue", "cmsPropertyData.intValue", "cmsPropertyData.textValue", "cmsPropertyData.varcharValue", "cmsPropertyType.id", "cmsPropertyType.Alias", "cmsPropertyType.Description", "cmsPropertyType.Name", "cmsPropertyType.mandatory", "cmsPropertyType.validationRegExp", "cmsPropertyType.sortOrder AS PropertyTypeSortOrder", "cmsPropertyType.propertyTypeGroupId", diff --git a/src/Umbraco.Tests/Services/MemberServiceTests.cs b/src/Umbraco.Tests/Services/MemberServiceTests.cs index af867e7b3f..6a27e98446 100644 --- a/src/Umbraco.Tests/Services/MemberServiceTests.cs +++ b/src/Umbraco.Tests/Services/MemberServiceTests.cs @@ -1150,10 +1150,10 @@ namespace Umbraco.Tests.Services } Assert.AreEqual(1, colResult.Count); - Assert.IsTrue(colResult.First().Date.HasValue); - Assert.IsFalse(colResult.First().Integer.HasValue); - Assert.IsNull(colResult.First().Text); - Assert.IsNull(colResult.First().VarChar); + Assert.IsTrue(colResult.First().DateValue.HasValue); + Assert.IsFalse(colResult.First().IntegerValue.HasValue); + Assert.IsNull(colResult.First().TextValue); + Assert.IsNull(colResult.First().VarcharValue); } [Test] diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 98159d6a25..eb6b75b54a 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -233,7 +233,7 @@ - +