Complete PropertyData table migration
This commit is contained in:
@@ -38,7 +38,7 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
[ForeignKey(typeof(LanguageDto))]
|
||||
[Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_LanguageId")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public int LanguageId { get; set; }
|
||||
public int? LanguageId { get; set; }
|
||||
|
||||
[Column("segment")]
|
||||
[Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_Segment")]
|
||||
|
||||
@@ -43,10 +43,10 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create
|
||||
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);
|
||||
foreach (var sql in SqlSyntax.Format(tableDefinition.ForeignKeys))
|
||||
AddSql(sql);
|
||||
}
|
||||
|
||||
public void KeysAndIndexes(Type typeOfDto)
|
||||
@@ -54,10 +54,10 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create
|
||||
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);
|
||||
foreach (var sql in SqlSyntax.Format(tableDefinition.ForeignKeys))
|
||||
AddSql(sql);
|
||||
}
|
||||
|
||||
private void AddSql(string sql)
|
||||
|
||||
@@ -19,18 +19,18 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Execute
|
||||
{
|
||||
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();
|
||||
var keys = context.SqlContext.SqlSyntax.GetConstraintsPerTable(context.Database).DistinctBy(x => x.Item2).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);
|
||||
|
||||
// drop indexes
|
||||
var indexes = context.SqlContext.SqlSyntax.GetDefinedIndexesDefinitions(context.Database).DistinctBy(x => x.IndexName).ToArray();
|
||||
foreach (var index in indexes.Where(x => x.TableName == tableName))
|
||||
local.Delete.Index(index.IndexName).OnTable(index.TableName);
|
||||
|
||||
return local.GetSql();
|
||||
}
|
||||
|
||||
@@ -38,18 +38,18 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Execute
|
||||
{
|
||||
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();
|
||||
var keys = context.SqlContext.SqlSyntax.GetConstraintsPerTable(context.Database).DistinctBy(x => x.Item2).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);
|
||||
|
||||
// drop indexes
|
||||
var indexes = context.SqlContext.SqlSyntax.GetDefinedIndexesDefinitions(context.Database).DistinctBy(x => x.IndexName).ToArray();
|
||||
foreach (var index in indexes)
|
||||
local.Delete.Index(index.IndexName).OnTable(index.TableName);
|
||||
|
||||
return local.GetSql();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Migrations.Initial;
|
||||
using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Column;
|
||||
using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Table;
|
||||
using Umbraco.Core.Persistence.Migrations.Syntax.Execute;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionEight
|
||||
@@ -33,15 +38,17 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionEight
|
||||
|
||||
// add column propertyData.languageId
|
||||
if (!ColumnExists(PreTables.PropertyData, "languageId"))
|
||||
Alter.Table(PreTables.PropertyData).AddColumn("languageId").AsInt32().Nullable();
|
||||
AddColumn<PropertyDataDto>(PreTables.PropertyData, "languageId");
|
||||
|
||||
// add column propertyData.segment
|
||||
if (!ColumnExists(PreTables.PropertyData, "segment"))
|
||||
Alter.Table(PreTables.PropertyData).AddColumn("segment").AsString(256).Nullable();
|
||||
AddColumn<PropertyDataDto>(PreTables.PropertyData, "segment");
|
||||
|
||||
// do NOT use Rename.Column as it's borked on SQLCE - use ReplaceColumn instead
|
||||
|
||||
// rename column propertyData.contentNodeId to nodeId
|
||||
if (ColumnExists(PreTables.PropertyData, "contentNodeId"))
|
||||
Rename.Column("contentNodeId").OnTable(PreTables.PropertyData).To("nodeId");
|
||||
ReplaceColumn<PropertyDataDto>(PreTables.PropertyData, "contentNodeId", "nodeId");
|
||||
|
||||
// rename column propertyData.dataNtext to textValue
|
||||
// rename column propertyData.dataNvarchar to varcharValue
|
||||
@@ -49,15 +56,15 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionEight
|
||||
// rename column propertyData.dataInt to intValue
|
||||
// rename column propertyData.dataDate to dateValue
|
||||
if (ColumnExists(PreTables.PropertyData, "dataNtext"))
|
||||
Rename.Column("dataNtext").OnTable(PreTables.PropertyData).To("textValue");
|
||||
ReplaceColumn<PropertyDataDto>(PreTables.PropertyData, "dataNtext", "textValue");
|
||||
if (ColumnExists(PreTables.PropertyData, "dataNvarchar"))
|
||||
Rename.Column("dataNtext").OnTable(PreTables.PropertyData).To("varcharValue");
|
||||
ReplaceColumn<PropertyDataDto>(PreTables.PropertyData, "dataNvarchar", "varcharValue");
|
||||
if (ColumnExists(PreTables.PropertyData, "dataDecimal"))
|
||||
Rename.Column("dataDecimal").OnTable(PreTables.PropertyData).To("decimalValue");
|
||||
ReplaceColumn<PropertyDataDto>(PreTables.PropertyData, "dataDecimal", "decimalValue");
|
||||
if (ColumnExists(PreTables.PropertyData, "dataInt"))
|
||||
Rename.Column("dataInt").OnTable(PreTables.PropertyData).To("intValue");
|
||||
ReplaceColumn<PropertyDataDto>(PreTables.PropertyData, "dataInt", "intValue");
|
||||
if (ColumnExists(PreTables.PropertyData, "dataDate"))
|
||||
Rename.Column("dataDate").OnTable(PreTables.PropertyData).To("dateValue");
|
||||
ReplaceColumn<PropertyDataDto>(PreTables.PropertyData, "dataDate", "dateValue");
|
||||
|
||||
// rename table
|
||||
Rename.Table(PreTables.PropertyData).To(Constants.DatabaseSchema.Tables.PropertyData);
|
||||
@@ -128,6 +135,41 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionEight
|
||||
public const string TaskType = "cmsTaskType";
|
||||
}
|
||||
|
||||
private void AddColumn<T>(string tableName, string columnName)
|
||||
{
|
||||
AddColumn<T>(tableName, columnName, out var notNull);
|
||||
if (notNull != null) Execute.Sql(notNull);
|
||||
}
|
||||
|
||||
private void AddColumn<T>(string tableName, string columnName, out string notNull)
|
||||
{
|
||||
if (ColumnExists(tableName, columnName))
|
||||
throw new InvalidOperationException($"Column {tableName}.{columnName} already exists.");
|
||||
|
||||
var table = DefinitionFactory.GetTableDefinition(typeof(T), SqlSyntax);
|
||||
var column = table.Columns.First(x => x.Name == columnName);
|
||||
var create = SqlSyntax.Format(column);
|
||||
// some db cannot add a NOT NULL column, so change it into NULL
|
||||
if (create.Contains("NOT NULL"))
|
||||
{
|
||||
notNull = string.Format(SqlSyntax.AlterColumn, SqlSyntax.GetQuotedTableName(tableName), create);
|
||||
create = create.Replace("NOT NULL", "NULL");
|
||||
}
|
||||
else
|
||||
{
|
||||
notNull = null;
|
||||
}
|
||||
Execute.Sql($"ALTER TABLE {SqlSyntax.GetQuotedTableName(tableName)} ADD COLUMN " + create);
|
||||
}
|
||||
|
||||
private void ReplaceColumn<T>(string tableName, string currentName, string newName)
|
||||
{
|
||||
AddColumn<T>(tableName, newName, out var notNull);
|
||||
Execute.Sql($"UPDATE {SqlSyntax.GetQuotedTableName(tableName)} SET {SqlSyntax.GetQuotedColumnName(newName)}={SqlSyntax.GetQuotedColumnName(currentName)}");
|
||||
if (notNull != null) Execute.Sql(notNull);
|
||||
Delete.Column(currentName).FromTable(tableName);
|
||||
}
|
||||
|
||||
private bool TableExists(string tableName)
|
||||
{
|
||||
var tables = SqlSyntax.GetTablesInSchema(Context.Database);
|
||||
|
||||
@@ -5,9 +5,11 @@ using Semver;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Migrations;
|
||||
using Umbraco.Core.Persistence.Migrations.Initial;
|
||||
using Umbraco.Core.Persistence.Migrations.Syntax.Execute;
|
||||
using Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionEight;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
@@ -148,6 +150,38 @@ namespace Umbraco.Tests.Migrations
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateColumn()
|
||||
{
|
||||
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<IMigrationCollectionBuilder>(),
|
||||
Mock.Of<IMigrationEntryService>(),
|
||||
logger,
|
||||
new SemVersion(0), // 0.0.0
|
||||
new SemVersion(1), // 1.0.0
|
||||
"Test",
|
||||
|
||||
// explicit migrations
|
||||
new CreateTableOfTDtoMigration(context),
|
||||
new CreateColumnMigration(context)
|
||||
);
|
||||
|
||||
var upgraded = runner.Execute(context);
|
||||
Assert.IsTrue(upgraded);
|
||||
|
||||
scope.Complete();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Migration("1.0.0", 0, "Test")]
|
||||
public class CreateTableOfTDtoMigration : MigrationBase
|
||||
{
|
||||
@@ -212,5 +246,26 @@ namespace Umbraco.Tests.Migrations
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Migration("1.0.0", 2, "Test")]
|
||||
public class CreateColumnMigration : MigrationBase
|
||||
{
|
||||
public CreateColumnMigration(IMigrationContext context)
|
||||
: base(context)
|
||||
{ }
|
||||
|
||||
public override void Up()
|
||||
{
|
||||
// cannot delete the column without this, of course
|
||||
Execute.DropKeysAndIndexes();
|
||||
|
||||
Delete.Column("id").FromTable("umbracoNode");
|
||||
|
||||
var table = DefinitionFactory.GetTableDefinition(typeof(NodeDto), SqlSyntax);
|
||||
var column = table.Columns.First(x => x.Name == "id");
|
||||
var create = SqlSyntax.Format(column); // returns [id] INTEGER NOT NULL IDENTITY(1060,1)
|
||||
Execute.Sql($"ALTER TABLE {SqlSyntax.GetQuotedTableName("umbracoNode")} ADD COLUMN " + create);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user