Fix migrations for SqlServer
This commit is contained in:
@@ -34,6 +34,16 @@ namespace Umbraco.Core.Migrations.Expressions.Create.KeysAndIndexes
|
||||
ExecuteSql(sql);
|
||||
foreach (var sql in syntax.Format(tableDefinition.ForeignKeys))
|
||||
ExecuteSql(sql);
|
||||
|
||||
// note: we do *not* create the DF_ default constraints
|
||||
/*
|
||||
foreach (var column in tableDefinition.Columns)
|
||||
{
|
||||
var sql = syntax.FormatDefaultConstraint(column);
|
||||
if (!sql.IsNullOrWhiteSpace())
|
||||
ExecuteSql(sql);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
private void ExecuteSql(string sql)
|
||||
|
||||
@@ -10,9 +10,13 @@ namespace Umbraco.Core.Migrations.Expressions.Delete.DefaultConstraint
|
||||
IDeleteDefaultConstraintOnTableBuilder,
|
||||
IDeleteDefaultConstraintOnColumnBuilder
|
||||
{
|
||||
public DeleteDefaultConstraintBuilder(DeleteDefaultConstraintExpression expression)
|
||||
private readonly IMigrationContext _context;
|
||||
|
||||
public DeleteDefaultConstraintBuilder(IMigrationContext context, DeleteDefaultConstraintExpression expression)
|
||||
: base(expression)
|
||||
{ }
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IDeleteDefaultConstraintOnColumnBuilder OnTable(string tableName)
|
||||
@@ -24,6 +28,8 @@ namespace Umbraco.Core.Migrations.Expressions.Delete.DefaultConstraint
|
||||
/// <inheritdoc />
|
||||
public IExecutableBuilder OnColumn(string columnName)
|
||||
{
|
||||
var defaultConstraint = _context.SqlContext.SqlSyntax.GetDefaultConstraint(_context.Database, Expression.TableName, columnName);
|
||||
Expression.ConstraintName = defaultConstraint ?? string.Empty;
|
||||
Expression.ColumnName = columnName;
|
||||
return new ExecutableBuilder(Expression);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using NPoco;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Migrations.Expressions.Common;
|
||||
using Umbraco.Core.Migrations.Expressions.Delete.Column;
|
||||
using Umbraco.Core.Migrations.Expressions.Delete.Constraint;
|
||||
@@ -30,19 +29,19 @@ namespace Umbraco.Core.Migrations.Expressions.Delete
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IExecutableBuilder KeysAndIndexes<TDto>(bool pk = true, bool fk = true, bool ix = true)
|
||||
public IExecutableBuilder KeysAndIndexes<TDto>(bool local = true, bool foreign = true)
|
||||
{
|
||||
var syntax = _context.SqlContext.SqlSyntax;
|
||||
var tableDefinition = DefinitionFactory.GetTableDefinition(typeof(TDto), syntax);
|
||||
return KeysAndIndexes(tableDefinition.Name, pk, fk, ix);
|
||||
return KeysAndIndexes(tableDefinition.Name, local, foreign);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IExecutableBuilder KeysAndIndexes(string tableName, bool pk = true, bool fk = true, bool ix = true)
|
||||
public IExecutableBuilder KeysAndIndexes(string tableName, bool local = true, bool foreign = true)
|
||||
{
|
||||
if (tableName.IsNullOrWhiteSpace())
|
||||
throw new ArgumentNullOrEmptyException(nameof(tableName));
|
||||
return new DeleteKeysAndIndexesBuilder(_context) { TableName = tableName, DeletePrimaryKey = pk, DeleteForeignKeys = fk, DeleteIndexes = ix};
|
||||
return new DeleteKeysAndIndexesBuilder(_context) { TableName = tableName, DeleteLocal = local, DeleteForeign = foreign };
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -111,7 +110,7 @@ namespace Umbraco.Core.Migrations.Expressions.Delete
|
||||
public IDeleteDefaultConstraintOnTableBuilder DefaultConstraint()
|
||||
{
|
||||
var expression = new DeleteDefaultConstraintExpression(_context);
|
||||
return new DeleteDefaultConstraintBuilder(expression);
|
||||
return new DeleteDefaultConstraintBuilder(_context, expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,12 +10,16 @@ namespace Umbraco.Core.Migrations.Expressions.Delete.Expressions
|
||||
|
||||
public virtual string TableName { get; set; }
|
||||
public virtual string ColumnName { get; set; }
|
||||
public virtual string ConstraintName { get; set; }
|
||||
|
||||
protected override string GetSql()
|
||||
{
|
||||
return string.Format(SqlSyntax.DeleteDefaultConstraint,
|
||||
SqlSyntax.GetQuotedTableName(TableName),
|
||||
SqlSyntax.GetQuotedColumnName(ColumnName));
|
||||
return ConstraintName.IsNullOrWhiteSpace()
|
||||
? string.Empty
|
||||
: string.Format(SqlSyntax.DeleteDefaultConstraint,
|
||||
SqlSyntax.GetQuotedTableName(TableName),
|
||||
SqlSyntax.GetQuotedColumnName(ColumnName),
|
||||
SqlSyntax.GetQuotedName(ConstraintName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,12 +21,12 @@ namespace Umbraco.Core.Migrations.Expressions.Delete
|
||||
/// <summary>
|
||||
/// Builds a Delete Keys and Indexes expression, and executes.
|
||||
/// </summary>
|
||||
IExecutableBuilder KeysAndIndexes<TDto>(bool pk = true, bool fk = true, bool ix = true);
|
||||
IExecutableBuilder KeysAndIndexes<TDto>(bool local = true, bool foreign = true);
|
||||
|
||||
/// <summary>
|
||||
/// Builds a Delete Keys and Indexes expression, and executes.
|
||||
/// </summary>
|
||||
IExecutableBuilder KeysAndIndexes(string tableName, bool pk = true, bool fk = true, bool ix = true);
|
||||
IExecutableBuilder KeysAndIndexes(string tableName, bool local = true, bool foreign = true);
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the column to delete.
|
||||
|
||||
@@ -18,11 +18,9 @@ namespace Umbraco.Core.Migrations.Expressions.Delete.KeysAndIndexes
|
||||
|
||||
public string TableName { get; set; }
|
||||
|
||||
public bool DeletePrimaryKey { get; set; }
|
||||
public bool DeleteLocal { get; set; }
|
||||
|
||||
public bool DeleteForeignKeys { get; set; }
|
||||
|
||||
public bool DeleteIndexes { get; set; }
|
||||
public bool DeleteForeign { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Do()
|
||||
@@ -30,19 +28,26 @@ namespace Umbraco.Core.Migrations.Expressions.Delete.KeysAndIndexes
|
||||
_context.BuildingExpression = false;
|
||||
|
||||
// drop keys
|
||||
if (DeleteForeignKeys || DeletePrimaryKey)
|
||||
if (DeleteLocal || DeleteForeign)
|
||||
{
|
||||
var keys = _context.SqlContext.SqlSyntax.GetConstraintsPerTable(_context.Database).DistinctBy(x => x.Item2).ToList();
|
||||
if (DeleteForeignKeys)
|
||||
foreach (var key in keys.Where(x => x.Item1 == TableName && x.Item2.StartsWith("FK_")))
|
||||
// table, constraint
|
||||
var tableKeys = _context.SqlContext.SqlSyntax.GetConstraintsPerTable(_context.Database).DistinctBy(x => x.Item2).ToList();
|
||||
if (DeleteForeign)
|
||||
{
|
||||
foreach (var key in tableKeys.Where(x => x.Item1 == TableName && x.Item2.StartsWith("FK_")))
|
||||
Delete.ForeignKey(key.Item2).OnTable(key.Item1).Do();
|
||||
if (DeletePrimaryKey)
|
||||
foreach (var key in keys.Where(x => x.Item1 == TableName && x.Item2.StartsWith("PK_")))
|
||||
}
|
||||
if (DeleteLocal)
|
||||
{
|
||||
foreach (var key in tableKeys.Where(x => x.Item1 == TableName && x.Item2.StartsWith("PK_")))
|
||||
Delete.PrimaryKey(key.Item2).FromTable(key.Item1).Do();
|
||||
|
||||
// note: we do *not* delete the DEFAULT constraints
|
||||
}
|
||||
}
|
||||
|
||||
// drop indexes
|
||||
if (DeleteIndexes)
|
||||
if (DeleteLocal)
|
||||
{
|
||||
var indexes = _context.SqlContext.SqlSyntax.GetDefinedIndexesDefinitions(_context.Database).DistinctBy(x => x.IndexName).ToList();
|
||||
foreach (var index in indexes.Where(x => x.TableName == TableName))
|
||||
|
||||
@@ -67,9 +67,9 @@
|
||||
// delete *all* keys and indexes - because of FKs
|
||||
// on known v7 tables only
|
||||
foreach (var table in tables)
|
||||
Delete.KeysAndIndexes(table, false, true, false).Do();
|
||||
Delete.KeysAndIndexes(table, false, true).Do();
|
||||
foreach (var table in tables)
|
||||
Delete.KeysAndIndexes(table, true, false, true).Do();
|
||||
Delete.KeysAndIndexes(table, true, false).Do();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,12 @@
|
||||
|
||||
Database.Execute("set identity_insert umbracoUser on;");
|
||||
Database.Execute(@"
|
||||
insert into umbracoUser select
|
||||
insert into umbracoUser (id,
|
||||
userDisabled, userNoConsole, userName, userLogin, userPassword, passwordConfig,
|
||||
userEmail, userLanguage, securityStampToken, failedLoginAttempts, lastLockoutDate,
|
||||
lastPasswordChangeDate, lastLoginDate, emailConfirmedDate, invitedDate,
|
||||
createDate, updateDate, avatar, tourData)
|
||||
select
|
||||
-1 id,
|
||||
userDisabled, userNoConsole, userName, substring(userLogin, 1, len(userLogin) - 2) userLogin, userPassword, passwordConfig,
|
||||
userEmail, userLanguage, securityStampToken, failedLoginAttempts, lastLockoutDate,
|
||||
|
||||
@@ -213,8 +213,10 @@ WHERE versionId NOT IN (SELECT (versionId) FROM {PreTables.ContentVersion} WHERE
|
||||
Delete.Column("text").FromTable(PreTables.Document).Do();
|
||||
Delete.Column("templateId").FromTable(PreTables.Document).Do();
|
||||
Delete.Column("documentUser").FromTable(PreTables.Document).Do();
|
||||
Delete.DefaultConstraint().OnTable(PreTables.Document).OnColumn("updateDate").Do();
|
||||
Delete.Column("updateDate").FromTable(PreTables.Document).Do();
|
||||
Delete.Column("versionId").FromTable(PreTables.Document).Do();
|
||||
Delete.DefaultConstraint().OnTable(PreTables.Document).OnColumn("newest").Do();
|
||||
Delete.Column("newest").FromTable(PreTables.Document).Do();
|
||||
|
||||
// add and populate edited column
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
string TruncateTable { get; }
|
||||
string CreateConstraint { get; }
|
||||
string DeleteConstraint { get; }
|
||||
|
||||
|
||||
string DeleteDefaultConstraint { get; }
|
||||
string FormatDateTime(DateTime date, bool includeTime = true);
|
||||
string Format(TableDefinition table);
|
||||
@@ -106,5 +106,14 @@ namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
/// A Tuple containing: TableName, IndexName, ColumnName, IsUnique
|
||||
/// </returns>
|
||||
IEnumerable<Tuple<string, string, string, bool>> GetDefinedIndexes(IDatabase db);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the default constraint on a column.
|
||||
/// </summary>
|
||||
/// <param name="db">The database.</param>
|
||||
/// <param name="tableName">The table name.</param>
|
||||
/// <param name="columnName">The column name.</param>
|
||||
/// <returns>The name of the default constraint, or the empty string if there is no default constraint.</returns>
|
||||
string GetDefaultConstraint(IDatabase db, string tableName, string columnName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,6 +132,16 @@ ORDER BY TABLE_NAME, INDEX_NAME");
|
||||
item => new Tuple<string, string, string, bool>(item.TABLE_NAME, item.INDEX_NAME, item.COLUMN_NAME, item.UNIQUE));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetDefaultConstraint(IDatabase db, string tableName, string columnName)
|
||||
{
|
||||
// cannot return a true default constraint name (does not exist on SqlCe)
|
||||
// but we won't really need it anyways - just check whether there is a constraint
|
||||
var hasDefault = db.Fetch<bool>(@"select column_hasdefault from information_schema.columns
|
||||
where table_name=@0 and column_name=@1", tableName, columnName).FirstOrDefault();
|
||||
return hasDefault ? "XXXXX" : string.Empty;
|
||||
}
|
||||
|
||||
public override bool DoesTableExist(IDatabase db, string tableName)
|
||||
{
|
||||
var result =
|
||||
@@ -175,7 +185,7 @@ ORDER BY TABLE_NAME, INDEX_NAME");
|
||||
{
|
||||
get
|
||||
{
|
||||
return "ALTER TABLE [{0}] ALTER COLUMN [{1}] DROP DEFAULT";
|
||||
return "ALTER TABLE {0} ALTER COLUMN {1} DROP DEFAULT";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -225,6 +225,17 @@ order by T.name, I.name");
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetDefaultConstraint(IDatabase db, string tableName, string columnName)
|
||||
{
|
||||
return db.Fetch<string>(@"select con.[name] as [constraintName]
|
||||
from sys.default_constraints con
|
||||
join sys.columns col on con.object_id=col.default_object_id
|
||||
join sys.tables tbl on col.object_id=tbl.object_id
|
||||
where tbl.[name]=@0 and col.[name]=@1;", tableName, columnName)
|
||||
.FirstOrDefault() ?? string.Empty;
|
||||
}
|
||||
|
||||
public override bool DoesTableExist(IDatabase db, string tableName)
|
||||
{
|
||||
var result =
|
||||
@@ -276,7 +287,7 @@ order by T.name, I.name");
|
||||
return null;
|
||||
}
|
||||
|
||||
public override string DeleteDefaultConstraint => "ALTER TABLE [{0}] DROP CONSTRAINT [DF_{0}_{1}]";
|
||||
public override string DeleteDefaultConstraint => "ALTER TABLE {0} DROP CONSTRAINT {2}";
|
||||
|
||||
public override string DropIndex => "DROP INDEX {0} ON {1}";
|
||||
|
||||
|
||||
@@ -223,6 +223,8 @@ namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
|
||||
public abstract IEnumerable<Tuple<string, string, string, bool>> GetDefinedIndexes(IDatabase db);
|
||||
|
||||
public abstract string GetDefaultConstraint(IDatabase db, string tableName, string columnName);
|
||||
|
||||
public virtual bool DoesTableExist(IDatabase db, string tableName)
|
||||
{
|
||||
return false;
|
||||
@@ -552,6 +554,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
public virtual string CreateConstraint => "ALTER TABLE {0} ADD CONSTRAINT {1} {2} ({3})";
|
||||
public virtual string DeleteConstraint => "ALTER TABLE {0} DROP CONSTRAINT {1}";
|
||||
public virtual string CreateForeignKeyConstraint => "ALTER TABLE {0} ADD CONSTRAINT {1} FOREIGN KEY ({2}) REFERENCES {3} ({4}){5}{6}";
|
||||
public virtual string CreateDefaultConstraint => "ALTER TABLE {0} ADD CONSTRAINT {1} DEFAULT ({2}) FOR {3}";
|
||||
|
||||
public virtual string ConvertIntegerToOrderableString => "REPLACE(STR({0}, 8), SPACE(1), '0')";
|
||||
public virtual string ConvertDateToOrderableString => "CONVERT(nvarchar, {0}, 102)";
|
||||
|
||||
@@ -219,9 +219,9 @@ namespace Umbraco.Tests.Migrations
|
||||
// drops *all* tables keys and indexes
|
||||
var tables = SqlSyntax.GetTablesInSchema(Context.Database).ToList();
|
||||
foreach (var table in tables)
|
||||
Delete.KeysAndIndexes(table, false).Do();
|
||||
Delete.KeysAndIndexes(table, false, true).Do();
|
||||
foreach (var table in tables)
|
||||
Delete.KeysAndIndexes(table, true, false, false).Do();
|
||||
Delete.KeysAndIndexes(table, true, false).Do();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user