Complete PropertyData table migration

This commit is contained in:
Stephan
2017-11-01 15:35:37 +01:00
parent 8157daaf23
commit b66412e2d6
5 changed files with 123 additions and 26 deletions

View File

@@ -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")]

View File

@@ -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)

View File

@@ -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();
}
}

View File

@@ -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);

View File

@@ -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);
}
}
}
}