Data migration schema API

--HG--
branch : dev
This commit is contained in:
Sebastien Ros
2010-06-24 16:05:08 -07:00
parent 360332fbb9
commit 0d30307fce
28 changed files with 775 additions and 204 deletions

View File

@@ -1,38 +0,0 @@
using System.Data;
using NUnit.Framework;
using Orchard.DataMigration.Schema;
namespace Orchard.Tests.DataMigration {
[TestFixture]
public class DataMigrationCommandsTests {
[Test]
public void AllMethodsShouldBeCalledSuccessfully() {
var schemaBuilder = new SchemaBuilder("TEST_");
schemaBuilder
.CreateTable("User", table => table
.ContentPartRecord()
.Column("Id", DbType.Int32, column => column.PrimaryKey())
.Column("Firstname", DbType.String, column => column.Length(255))
.Column("Lastname", DbType.String, column => column.Precision(0).Scale(1))
.ForeignKey("User_Address", fk => fk.On("Id", "Address", "UserId")))
.CreateTable("Address", table => table
.VersionedContentPartRecord()
.Column("City", DbType.String)
.Column("ZIP", DbType.Int32, column => column.Unique())
.Column("UserId", DbType.Int32, column => column.NotNull()))
.AlterTable("User", table => table
.AddColumn("Age", DbType.Int32)
.AlterColumn("Lastname", column => column.Default("John"))
.AlterColumn("Lastname", column => column.Rename("John"))
.DropColumn("Lastname")
.CreateIndex("IDX_XYZ", "NickName")
.DropIndex("IDX_XYZ")
.AddForeignKey("FKL", fk => fk.On("Id", "A", "Id").On("Id", "B", "Id") )
.DropForeignKey("FKL"))
.DropTable("Address")
.ExecuteSql("DROP DATABASE", statement => statement.ForDialect("SQLite").ForDialect("MsSqlServer2008"));
}
}
}

View File

@@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using Autofac;
using NHibernate;
using NUnit.Framework;
using Orchard.ContentManagement.Records;
using Orchard.Data;
using Orchard.DataMigration.Interpreters;
using Orchard.Environment.Configuration;
using Orchard.Environment.Extensions;
using Orchard.Environment.Extensions.Folders;
@@ -49,6 +51,7 @@ namespace Orchard.Tests.DataMigration {
builder.RegisterInstance(new ShellSettings { DataTablePrefix = "TEST_"});
builder.RegisterType<NullInterpreter>().As<IDataMigrationInterpreter>();
builder.RegisterInstance(_folders).As<IExtensionFolders>();
builder.RegisterType<ExtensionManager>().As<IExtensionManager>();
builder.RegisterType<DataMigrationManager>().As<IDataMigrationManager>();
@@ -135,7 +138,6 @@ namespace Orchard.Tests.DataMigration {
public int UpdateFrom666() {
return 999;
}
}
public class DataMigrationDependenciesModule1 : IDataMigration {
@@ -165,7 +167,6 @@ namespace Orchard.Tests.DataMigration {
public int Create() {
Assert.That(SchemaBuilder, Is.Not.Null);
Assert.That(SchemaBuilder.TablePrefix, Is.EqualTo("TEST_"));
return 1;
}
}
@@ -176,7 +177,6 @@ namespace Orchard.Tests.DataMigration {
}
}
public class DataMigrationFeatureNeedUpdate2 : IDataMigration {
public string Feature {
get { return "Feature2"; }
@@ -200,6 +200,20 @@ namespace Orchard.Tests.DataMigration {
return 999;
}
}
public class DataMigrationSimpleBuilder : DataMigrationImpl {
public override string Feature {
get { return "Feature1"; }
}
public int Create() {
SchemaBuilder.CreateTable("UserRecord", table =>
table.Column("Id", DbType.Int32, column =>
column.PrimaryKey()));
return 1;
}
}
[Test]
public void DataMigrationShouldDoNothingIfNoDataMigrationIsProvidedForFeature() {
@@ -389,5 +403,23 @@ features:
Assert.That(_dataMigrationManager.GetFeaturesThatNeedUpdate().Contains("Feature3"), Is.False);
}
[Test] public void SchemaBuilderShouldCreateSql() {
Init(new[] { typeof(DataMigrationSimpleBuilder) });
_folders.Manifests.Add("Module1", @"
name: Module1
version: 0.1
orchardversion: 1
features:
Feature1:
Description: Feature
");
_dataMigrationManager.Update("Feature1");
}
}
}

View File

@@ -0,0 +1,135 @@
using System.Data;
using System.Linq;
using Autofac;
using NHibernate;
using NUnit.Framework;
using Orchard.Data;
using Orchard.DataMigration.Interpreters;
using Orchard.DataMigration.Schema;
using Orchard.Environment.Configuration;
using Orchard.Tests.ContentManagement;
using System.IO;
namespace Orchard.Tests.DataMigration {
[TestFixture]
public class SchemaBuilderTests {
private IContainer _container;
private ISessionFactory _sessionFactory;
private string _databaseFileName;
private SchemaBuilder _schemaBuilder;
private DefaultDataMigrationInterpreter _interpreter;
[SetUp]
public void Setup() {
_databaseFileName = Path.GetTempFileName();
_sessionFactory = DataUtility.CreateSessionFactory(
_databaseFileName);
var builder = new ContainerBuilder();
builder.RegisterInstance(new ShellSettings { DataTablePrefix = "TEST_", DataProvider = "SQLite" });
var session = _sessionFactory.OpenSession();
builder.RegisterType<DefaultDataMigrationInterpreter>().As<IDataMigrationInterpreter>();
builder.RegisterInstance(new DefaultContentManagerTests.TestSessionLocator(session)).As<ISessionLocator>();
builder.RegisterInstance(new ShellSettings { DataProvider = "SQLite", DataTablePrefix = "TEST_" }).As<ShellSettings>();
builder.RegisterType<SqLiteCommandInterpreter>().As<ICommandInterpreter>();
_container = builder.Build();
_interpreter = _container.Resolve<IDataMigrationInterpreter>() as DefaultDataMigrationInterpreter;
_schemaBuilder = new SchemaBuilder(_interpreter);
}
[Test]
public void AllMethodsShouldBeCalledSuccessfully() {
_schemaBuilder = new SchemaBuilder(new NullInterpreter());
_schemaBuilder
.CreateTable("User", table => table
.ContentPartRecord()
.Column("Id", DbType.Int32, column => column.PrimaryKey())
.Column("Firstname", DbType.String, column => column.WithLength(255))
.Column("Lastname", DbType.String, column => column.WithPrecision(0).WithScale(1)))
.CreateTable("Address", table => table
.VersionedContentPartRecord()
.Column("City", DbType.String)
.Column("ZIP", DbType.Int32, column => column.Unique())
.Column("UserId", DbType.Int32, column => column.NotNull()))
.CreateForeignKey("User_Address", "User", new[] { "UserId" }, "User", new[] { "Id" })
.AlterTable("User", table => table
.AddColumn("Age", DbType.Int32))
.AlterTable("User", table => table
.DropColumn("Lastname"))
.AlterTable("User", table => table
.CreateIndex("IDX_XYZ", "NickName"))
.AlterTable("User", table => table
.DropIndex("IDX_XYZ"))
.DropForeignKey("Addresse", "User_Address")
.DropTable("Address")
.ExecuteSql("drop database", statement => statement.ForProvider("SQLite"))
.ExecuteSql("DROP DATABASE", statement => statement.ForProvider("SQLServer"));
}
[Test]
public void CreateCommandShouldBeHandled() {
_schemaBuilder
.CreateTable("User", table => table
.Column("Id", DbType.Int32, column => column.PrimaryKey())
.Column("Firstname", DbType.String, column => column.WithLength(255))
.Column("Lastname", DbType.String, column => column.WithLength(100).NotNull())
.Column("SN", DbType.AnsiString, column => column.WithLength(40).Unique())
.Column("Salary", DbType.Decimal, column => column.WithPrecision(9).WithScale(2))
.Column("Gender", DbType.Decimal, column => column.WithDefault("''"))
);
}
[Test]
public void DropTableCommandShouldBeHandled() {
_schemaBuilder
.DropTable("User");
}
[Test]
public void CustomSqlStatementsShouldBeHandled() {
_schemaBuilder
.ExecuteSql("select 1");
}
[Test]
public void AlterTableCommandShouldBeHandled() {
_schemaBuilder
.CreateTable("User", table => table
.Column("Firstname", DbType.String, column => column.WithLength(255))
.Column("Lastname", DbType.String, column => column.WithLength(100).NotNull()))
.AlterTable("User", table => table
.AddColumn("Age", DbType.Int32))
.AlterTable("User", table => table
.AlterColumn("Lastname", column => column.WithDefault("'John'")))
.AlterTable("User", table => table
.DropColumn("Firstname")
);
}
[Test]
public void ForeignKeyShouldBeCreatedAndRemoved() {
_schemaBuilder
.CreateTable("User", table => table
.Column("Id", DbType.Int32, column => column.PrimaryKey())
.Column("Firstname", DbType.String, column => column.WithLength(255))
.Column("Lastname", DbType.String, column => column.WithPrecision(0).WithScale(1)))
.CreateTable("Address", table => table
.Column("City", DbType.String)
.Column("ZIP", DbType.Int32, column => column.Unique())
.Column("UserId", DbType.Int32, column => column.NotNull()))
.CreateForeignKey("User_Address", "User", new[] { "UserId" }, "User", new[] { "Id" })
.DropForeignKey("User", "User_Address");
}
}
}

View File

@@ -0,0 +1,27 @@

using System;
using Orchard.DataMigration.Interpreters;
using Orchard.DataMigration.Schema;
public class NullInterpreter : IDataMigrationInterpreter {
public void Visit(SchemaCommand command) {
}
public void Visit(CreateTableCommand command) {
}
public void Visit(DropTableCommand command) {
}
public void Visit(AlterTableCommand command) {
}
public void Visit(SqlStatementCommand command) {
}
public void Visit(CreateForeignKeyCommand command) {
}
public void Visit(DropForeignKeyCommand command) {
}
}

View File

@@ -180,8 +180,9 @@
<Compile Include="ContentManagement\Records\GammaRecord.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="DataMigration\DataMigrationCommandsTests.cs" />
<Compile Include="DataMigration\SchemaBuilderTests.cs" />
<Compile Include="DataMigration\DataMigrationTests.cs" />
<Compile Include="DataMigration\Utilities\NullInterpreter.cs" />
<Compile Include="DataUtility.cs" />
<Compile Include="Data\Builders\SessionFactoryBuilderTests.cs" />
<Compile Include="Data\RepositoryTests.cs" />

View File

@@ -4,6 +4,7 @@ using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using Orchard.Data;
using Orchard.DataMigration.Interpreters;
using Orchard.DataMigration.Schema;
using Orchard.Environment.Configuration;
using Orchard.Environment.Extensions;
@@ -20,18 +21,21 @@ namespace Orchard.DataMigration {
private readonly IDataMigrationGenerator _dataMigrationGenerator;
private readonly IExtensionManager _extensionManager;
private readonly ShellSettings _shellSettings;
private readonly IDataMigrationInterpreter _interpreter;
public DataMigrationManager(
IEnumerable<IDataMigration> dataMigrations,
IRepository<DataMigrationRecord> dataMigrationRepository,
IDataMigrationGenerator dataMigrationGenerator,
IExtensionManager extensionManager,
ShellSettings shellSettings) {
ShellSettings shellSettings,
IDataMigrationInterpreter interpreter) {
_dataMigrations = dataMigrations;
_dataMigrationRepository = dataMigrationRepository;
_dataMigrationGenerator = dataMigrationGenerator;
_extensionManager = extensionManager;
_shellSettings = shellSettings;
_interpreter = interpreter;
Logger = NullLogger.Instance;
}
@@ -163,7 +167,7 @@ namespace Orchard.DataMigration {
.ToList();
foreach (var migration in migrations.OfType<DataMigrationImpl>()) {
migration.SchemaBuilder = new SchemaBuilder(_shellSettings.DataTablePrefix);
migration.SchemaBuilder = new SchemaBuilder(_interpreter);
}
return migrations;

View File

@@ -0,0 +1,293 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using NHibernate;
using NHibernate.Dialect;
using NHibernate.SqlTypes;
using Orchard.Data;
using Orchard.DataMigration.Schema;
using Orchard.Environment.Configuration;
using Orchard.Logging;
namespace Orchard.DataMigration.Interpreters {
public class DefaultDataMigrationInterpreter : IDataMigrationInterpreter {
private readonly ShellSettings _shellSettings;
private readonly IEnumerable<ICommandInterpreter> _commandInterpreters;
private readonly ISession _session;
private readonly Dialect _dialect;
private readonly List<string> _sqlStatements;
private const char Space = ' ' ;
public DefaultDataMigrationInterpreter(ShellSettings shellSettings, ISessionLocator sessionLocator, IEnumerable<ICommandInterpreter> commandInterpreters) {
_shellSettings = shellSettings;
_commandInterpreters = commandInterpreters;
_session = sessionLocator.For(typeof(DefaultDataMigrationInterpreter));
_sqlStatements = new List<string>();
_dialect = _shellSettings.DataProvider == "SQLite" ? (Dialect) new SQLiteDialect() : new MsSql2008Dialect();
Logger = NullLogger.Instance;
}
public ILogger Logger { get; set; }
public IEnumerable<string> SqlStatements {
get { return _sqlStatements; }
}
public void Visit(SchemaCommand command) {
switch (command.Type) {
case SchemaCommandType.CreateTable:
Visit((CreateTableCommand)command);
break;
case SchemaCommandType.AlterTable:
Visit((AlterTableCommand)command);
break;
case SchemaCommandType.DropTable:
Visit((DropTableCommand)command);
break;
case SchemaCommandType.SqlStatement:
Visit((SqlStatementCommand)command);
break;
case SchemaCommandType.CreateForeignKey:
Visit((CreateForeignKeyCommand)command);
break;
case SchemaCommandType.DropForeignKey:
Visit((DropForeignKeyCommand)command);
break;
}
}
public void Visit(CreateTableCommand command) {
if ( ExecuteCustomInterpreter(command) ) {
return;
}
var builder = new StringBuilder();
builder.Append(_dialect.CreateMultisetTableString)
.Append(' ')
.Append(_dialect.QuoteForTableName(_shellSettings.DataTablePrefix + command.Name))
.Append(" (");
var appendComma = false;
foreach(var createColumn in command.TableCommands.OfType<CreateColumnCommand>()) {
if(appendComma) {
builder.Append(", ");
}
appendComma = true;
Visit(builder, createColumn);
}
builder.Append(" )");
_sqlStatements.Add(builder.ToString());
RunPendingStatements();
}
public void Visit(DropTableCommand command) {
if ( ExecuteCustomInterpreter(command) ) {
return;
}
var builder = new StringBuilder();
builder.Append(_dialect.GetDropTableString(_shellSettings.DataTablePrefix + command.Name));
_sqlStatements.Add(builder.ToString());
RunPendingStatements();
}
public void Visit(AlterTableCommand command) {
if ( ExecuteCustomInterpreter(command) ) {
return;
}
if(command.TableCommands.Count == 0) {
return;
}
// drop columns
foreach ( var dropColumn in command.TableCommands.OfType<DropColumnCommand>() ) {
var builder = new StringBuilder();
Visit(builder, dropColumn);
RunPendingStatements();
}
// add columns
foreach ( var addColumn in command.TableCommands.OfType<AddColumnCommand>() ) {
var builder = new StringBuilder();
Visit(builder, addColumn);
RunPendingStatements();
}
// alter columns
foreach ( var alterColumn in command.TableCommands.OfType<AlterColumnCommand>() ) {
var builder = new StringBuilder();
Visit(builder, alterColumn);
RunPendingStatements();
}
}
public void Visit(StringBuilder builder, AddColumnCommand command) {
if ( ExecuteCustomInterpreter(command) ) {
return;
}
builder.AppendFormat("alter table {0} add column ", _dialect.QuoteForTableName(_shellSettings.DataTablePrefix + command.TableName));
Visit(builder, (CreateColumnCommand)command);
_sqlStatements.Add(builder.ToString());
}
public void Visit(StringBuilder builder, DropColumnCommand command) {
if ( ExecuteCustomInterpreter(command) ) {
return;
}
builder.AppendFormat("alter table {0} drop column {1}",
_dialect.QuoteForTableName(_shellSettings.DataTablePrefix + command.TableName),
_dialect.QuoteForColumnName(command.TableName));
_sqlStatements.Add(builder.ToString());
}
public void Visit(StringBuilder builder, AlterColumnCommand command) {
if ( ExecuteCustomInterpreter(command) ) {
return;
}
builder.AppendFormat("alter table {0} alter column {1} ",
_dialect.QuoteForTableName(_shellSettings.DataTablePrefix + command.TableName),
_dialect.QuoteForColumnName(command.TableName));
// type
if ( command.DbType != DbType.Object ) {
builder.Append(GetTypeName(command.DbType, command.Length, command.Precision, command.Scale));
}
// [default value]
if ( !string.IsNullOrEmpty(command.Default) ) {
builder.Append(" default ").Append(command.Default).Append(Space);
}
_sqlStatements.Add(builder.ToString());
}
public void Visit(SqlStatementCommand command) {
if (command.Providers.Count == 0 || command.Providers.Contains(_shellSettings.DataProvider) ) {
if (ExecuteCustomInterpreter(command)) {
return;
}
_sqlStatements.Add(command.Sql);
RunPendingStatements();
}
}
public void Visit(CreateForeignKeyCommand command) {
if ( ExecuteCustomInterpreter(command) ) {
return;
}
var builder = new StringBuilder();
builder.Append("alter table ")
.Append(_dialect.QuoteForTableName(_shellSettings.DataTablePrefix + command.SrcTable));
builder.Append(_dialect.GetAddForeignKeyConstraintString(command.Name,
command.SrcColumns,
command.DestTable,
command.DestColumns,
false));
_sqlStatements.Add(builder.ToString());
RunPendingStatements();
}
public void Visit(DropForeignKeyCommand command) {
if ( ExecuteCustomInterpreter(command) ) {
return;
}
var builder = new StringBuilder();
builder.AppendFormat("alter table {0} drop constraint {1}", command.SrcTable, command.Name);
_sqlStatements.Add(builder.ToString());
RunPendingStatements();
}
private string GetTypeName(DbType dbType, int? length, byte precision, byte scale) {
return precision > 0
? _dialect.GetTypeName(new SqlType(dbType, precision, scale))
: length.HasValue
? _dialect.GetTypeName(new SqlType(dbType, length.Value))
: _dialect.GetTypeName(new SqlType(dbType));
}
private void Visit(StringBuilder builder, CreateColumnCommand command) {
if ( ExecuteCustomInterpreter(command) ) {
return;
}
// name
builder.Append(_dialect.QuoteForColumnName(command.ColumnName)).Append(Space);
// type
builder.Append(GetTypeName(command.DbType, command.Length, command.Precision, command.Scale));
// [default value]
if ( !string.IsNullOrEmpty(command.Default) ) {
builder.Append(" default ").Append(command.Default).Append(Space);
}
// nullable
builder.Append(command.IsNotNull
? " not null"
: !command.IsPrimaryKey && !command.IsUnique
? _dialect.NullColumnString
: string.Empty);
// append unique if handled, otherwise at the end of the satement
if ( command.IsUnique && _dialect.SupportsUnique ) {
builder.Append(" unique");
}
if ( command.IsPrimaryKey ) {
builder.Append(Space).Append(_dialect.PrimaryKeyString);
}
}
private void RunPendingStatements() {
var connection = _session.Connection;
foreach ( var sqlStatement in _sqlStatements ) {
Logger.Debug(sqlStatement);
using ( var command = connection.CreateCommand() ) {
command.CommandText = sqlStatement;
command.ExecuteNonQuery();
}
}
_sqlStatements.Clear();
}
private bool ExecuteCustomInterpreter<T>(T command) where T : ISchemaBuilderCommand {
var interpreter = _commandInterpreters
.Where(ici => ici.DataProvider == _shellSettings.DataProvider)
.OfType<ICommandInterpreter<T>>()
.FirstOrDefault();
if ( interpreter != null ) {
_sqlStatements.AddRange(interpreter.CreateStatements(command));
RunPendingStatements();
return true;
}
return false;
}
}
}

View File

@@ -0,0 +1,15 @@
using Orchard.DataMigration.Schema;
namespace Orchard.DataMigration.Interpreters {
/// <summary>
/// This interface can be implemented to provide a data migration behavior
/// </summary>
public interface ICommandInterpreter<in T> : ICommandInterpreter
where T : ISchemaBuilderCommand {
string[] CreateStatements(T command);
}
public interface ICommandInterpreter : IDependency {
string DataProvider { get; }
}
}

View File

@@ -0,0 +1,13 @@
using Orchard.DataMigration.Schema;
namespace Orchard.DataMigration.Interpreters {
public interface IDataMigrationInterpreter : IDependency{
void Visit(SchemaCommand command);
void Visit(CreateTableCommand command);
void Visit(DropTableCommand command);
void Visit(AlterTableCommand command);
void Visit(SqlStatementCommand command);
void Visit(CreateForeignKeyCommand command);
void Visit(DropForeignKeyCommand command);
}
}

View File

@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Orchard.DataMigration.Schema;
namespace Orchard.DataMigration.Interpreters {
public class SqLiteCommandInterpreter :
ICommandInterpreter<DropColumnCommand>,
ICommandInterpreter<AlterColumnCommand>,
ICommandInterpreter<CreateForeignKeyCommand>,
ICommandInterpreter<DropForeignKeyCommand> {
public string[] CreateStatements(DropColumnCommand command) {
return new string[0];
}
public string[] CreateStatements(AlterColumnCommand command) {
return new string[0];
}
public string[] CreateStatements(CreateForeignKeyCommand command) {
return new string[0];
}
public string[] CreateStatements(DropForeignKeyCommand command) {
return new string[0];
}
public string DataProvider {
get { return "SQLite"; }
}
}
}

View File

@@ -0,0 +1,8 @@
using System.Data;
namespace Orchard.DataMigration.Schema {
public class AddColumnCommand : CreateColumnCommand {
public AddColumnCommand(string tableName, string name) : base(tableName, name) {
}
}
}

View File

@@ -1,15 +1,27 @@
namespace Orchard.DataMigration.Schema {
public class AlterColumnCommand : ColumnCommand {
private string _newName;
using System.Data;
public AlterColumnCommand(string name)
: base(name) {
namespace Orchard.DataMigration.Schema {
public class AlterColumnCommand : ColumnCommand {
public AlterColumnCommand(string tableName, string columnName)
: base(tableName, columnName) {
}
public AlterColumnCommand Rename(string name) {
_newName = name;
public new AlterColumnCommand WithType(DbType dbType) {
base.WithType(dbType);
return this;
}
public AlterColumnCommand WithType(DbType dbType, int? length) {
base.WithType(dbType).WithLength(length);
return this;
}
public AlterColumnCommand WithType(DbType dbType, byte precision, byte scale) {
base.WithType(dbType);
Precision = precision;
Scale = scale;
return this;
}
}
}

View File

@@ -1,64 +1,47 @@
using System;
using System.Data;
using JetBrains.Annotations;
namespace Orchard.DataMigration.Schema {
public class AlterTableCommand : SchemaCommand {
public AlterTableCommand(string name)
: base(name) {
: base(name, SchemaCommandType.AlterTable) {
}
public AlterTableCommand AddColumn(string name, DbType dbType, Action<CreateColumnCommand> column = null) {
var command = new CreateColumnCommand(name);
command.Type(dbType);
public void AddColumn(string columnName, DbType dbType, Action<AddColumnCommand> column = null) {
var command = new AddColumnCommand(Name, columnName);
command.WithType(dbType);
if(column != null) {
column(command);
}
_tableCommands.Add(command);
return this;
TableCommands.Add(command);
}
public AlterTableCommand DropColumn(string name) {
var command = new DropColumnCommand(name);
_tableCommands.Add(command);
return this;
public void DropColumn(string columnName) {
var command = new DropColumnCommand(Name, columnName);
TableCommands.Add(command);
}
public AlterTableCommand AlterColumn(string name, Action<AlterColumnCommand> column = null) {
var command = new AlterColumnCommand(name);
public void AlterColumn(string columnName, Action<AlterColumnCommand> column = null) {
var command = new AlterColumnCommand(Name, columnName);
if ( column != null ) {
column(command);
}
_tableCommands.Add(command);
return this;
TableCommands.Add(command);
}
public AlterTableCommand CreateIndex(string name, params string[] columnNames) {
public void CreateIndex(string name, params string[] columnNames) {
var command = new CreateIndexCommand(name, columnNames);
_tableCommands.Add(command);
return this;
TableCommands.Add(command);
}
public AlterTableCommand DropIndex(string name) {
public void DropIndex(string name) {
var command = new DropIndexCommand(name);
_tableCommands.Add(command);
return this;
}
public AlterTableCommand AddForeignKey(string name, Action<CreateForeignKeyCommand> fk) {
var command = new CreateForeignKeyCommand(name);
fk(command);
_tableCommands.Add(command);
return this;
}
public AlterTableCommand DropForeignKey(string name) {
var command = new DropForeignKeyCommand(name);
_tableCommands.Add(command);
return this;
TableCommands.Add(command);
}
}
}

View File

@@ -2,22 +2,40 @@
namespace Orchard.DataMigration.Schema {
public class ColumnCommand : TableCommand {
private DbType _dbType;
private object _default;
public ColumnCommand(string name) : base(name) {
_dbType = DbType.Object;
_default = null;
}
public string ColumnName { get; set; }
public ColumnCommand Type(DbType dbType) {
_dbType = dbType;
public ColumnCommand(string tableName, string name)
: base(tableName) {
ColumnName = name;
DbType = DbType.Object;
Default = null;
Length = null;
}
public byte Scale { get; protected set; }
public byte Precision { get; protected set; }
public DbType DbType { get; private set; }
public string Default { get; private set; }
public int? Length { get; private set; }
public ColumnCommand WithType(DbType dbType) {
DbType = dbType;
return this;
}
public ColumnCommand Default(object @default) {
_default = @default;
public ColumnCommand WithDefault(string @default) {
Default = @default;
return this;
}
}
public ColumnCommand WithLength(int? length) {
Length = length;
return this;
}
}
}

View File

@@ -1,59 +1,67 @@
namespace Orchard.DataMigration.Schema {
public class CreateColumnCommand : ColumnCommand {
private bool _primaryKey;
private byte? _precision;
private byte? _scale;
private int? _length;
private bool _notNull;
private bool _unique;
using System.Data;
public CreateColumnCommand(string name) : base(name) {
_precision = null;
_scale = null;
_length = null;
_notNull = false;
_unique = false;
namespace Orchard.DataMigration.Schema {
public class CreateColumnCommand : ColumnCommand {
public CreateColumnCommand(string tableName, string name) : base(tableName, name) {
IsNotNull = false;
IsUnique = false;
}
public bool IsUnique { get; protected set; }
public bool IsNotNull { get; protected set; }
public bool IsPrimaryKey { get; protected set; }
public CreateColumnCommand PrimaryKey() {
_primaryKey = true;
IsPrimaryKey = true;
IsUnique = false;
return this;
}
public CreateColumnCommand Precision(byte? precision) {
_precision = precision;
public CreateColumnCommand WithPrecision(byte precision) {
Precision = precision;
return this;
}
public CreateColumnCommand Scale(byte? scale) {
_scale = scale;
return this;
}
public CreateColumnCommand Length(int? length) {
_length = length;
public CreateColumnCommand WithScale(byte scale) {
Scale = scale;
return this;
}
public CreateColumnCommand NotNull() {
_notNull = true;
IsNotNull = true;
return this;
}
public CreateColumnCommand Nullable() {
_notNull = false;
IsNotNull = false;
return this;
}
public CreateColumnCommand Unique() {
_unique = true;
IsUnique = true;
IsPrimaryKey = false;
return this;
}
public CreateColumnCommand NotUnique() {
_unique = false;
IsUnique = false;
return this;
}
public new CreateColumnCommand WithLength(int? length) {
base.WithLength(length);
return this;
}
public new CreateColumnCommand WithType(DbType dbType) {
base.WithType(dbType);
return this;
}
public new CreateColumnCommand WithDefault(string @default) {
base.WithDefault(@default);
return this;
}
}

View File

@@ -1,31 +1,21 @@
using System.Collections.Generic;
namespace Orchard.DataMigration.Schema {
public class CreateForeignKeyCommand : TableCommand {
protected readonly List<ForeignKeyClause> _foreignKeyClauses;
public class CreateForeignKeyCommand : SchemaCommand {
public CreateForeignKeyCommand(string name)
: base(name) {
_foreignKeyClauses = new List<ForeignKeyClause>();
}
public CreateForeignKeyCommand On(string srcColumn, string destTable, string destColumn) {
_foreignKeyClauses.Add(new ForeignKeyClause(srcColumn, destTable, destColumn));
return this;
}
}
public class ForeignKeyClause {
public ForeignKeyClause(string srcColumn, string destTable, string destColumn) {
SrcColumn = srcColumn;
DestTable = destTable;
DestColumn = destColumn;
}
public string DestColumn { get; private set; }
public string[] DestColumns { get; private set; }
public string DestTable { get; private set; }
public string SrcColumn { get; private set; }
public string[] SrcColumns { get; private set; }
public string SrcTable { get; private set; }
public CreateForeignKeyCommand(string name, string srcTable, string[] srcColumns, string destTable, string[] destColumns) : base(name, SchemaCommandType.CreateForeignKey) {
SrcColumns = srcColumns;
DestTable = destTable;
DestColumns = destColumns;
SrcTable = srcTable;
}
}
}

View File

@@ -1,7 +1,7 @@
namespace Orchard.DataMigration.Schema {
public class CreateIndexCommand : TableCommand {
public CreateIndexCommand(string name, params string[] columnNames)
: base(name) {
public CreateIndexCommand(string indexName, params string[] columnNames)
: base(indexName) {
ColumnNames = columnNames;
}

View File

@@ -4,17 +4,17 @@ using System.Data;
namespace Orchard.DataMigration.Schema {
public class CreateTableCommand : SchemaCommand {
public CreateTableCommand(string name)
: base(name) {
: base(name, SchemaCommandType.CreateTable) {
}
public CreateTableCommand Column(string name, DbType dbType, Action<CreateColumnCommand> column = null) {
var command = new CreateColumnCommand(name);
command.Type(dbType);
public CreateTableCommand Column(string columnName, DbType dbType, Action<CreateColumnCommand> column = null) {
var command = new CreateColumnCommand(Name, columnName);
command.WithType(dbType);
if ( column != null ) {
column(command);
}
_tableCommands.Add(command);
TableCommands.Add(command);
return this;
}
@@ -27,12 +27,5 @@ namespace Orchard.DataMigration.Schema {
/// TODO: Call Column() with necessary information for content part records
return this;
}
public CreateTableCommand ForeignKey(string name, Action<CreateForeignKeyCommand> fk) {
var command = new CreateForeignKeyCommand(name);
fk(command);
_tableCommands.Add(command);
return this;
}
}
}

View File

@@ -1,8 +1,8 @@
namespace Orchard.DataMigration.Schema {
public class DropColumnCommand : ColumnCommand {
public DropColumnCommand(string name)
: base(name) {
public DropColumnCommand(string tableName, string columnName)
: base(tableName, columnName) {
}
}
}

View File

@@ -1,8 +1,10 @@
namespace Orchard.DataMigration.Schema {
public class DropForeignKeyCommand : TableCommand {
public class DropForeignKeyCommand : SchemaCommand {
public string SrcTable { get; private set; }
public DropForeignKeyCommand(string name)
: base(name) {
public DropForeignKeyCommand(string srcTable, string name)
: base(name, SchemaCommandType.DropForeignKey) {
SrcTable = srcTable;
}
}
}

View File

@@ -1,7 +1,7 @@
namespace Orchard.DataMigration.Schema {
public class DropTableCommand : SchemaCommand {
public DropTableCommand(string name)
: base(name) {
: base(name, SchemaCommandType.DropTable) {
}
}
}

View File

@@ -0,0 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Orchard.DataMigration.Schema {
public interface ISchemaBuilderCommand {
}
}

View File

@@ -0,0 +1 @@


View File

@@ -1,44 +1,55 @@
using System;
using System.Collections.Generic;
using Orchard.DataMigration.Interpreters;
namespace Orchard.DataMigration.Schema {
public class SchemaBuilder {
private readonly List<SchemaCommand> _schemaCommands;
public SchemaBuilder() {
_schemaCommands = new List<SchemaCommand>();
private readonly IDataMigrationInterpreter _interpreter;
public SchemaBuilder(IDataMigrationInterpreter interpreter) {
_interpreter = interpreter;
}
public SchemaBuilder(string tablePrefix) : this() {
TablePrefix = tablePrefix;
}
public string TablePrefix { get; private set; }
public SchemaBuilder CreateTable(string name, Action<CreateTableCommand> table) {
var createTable = new CreateTableCommand(name);
table(createTable);
_schemaCommands.Add(createTable);
Run(createTable);
return this;
}
public SchemaBuilder AlterTable(string name, Action<AlterTableCommand> table) {
var alterTable = new AlterTableCommand(name);
table(alterTable);
_schemaCommands.Add(alterTable);
Run(alterTable);
return this;
}
public SchemaBuilder DropTable(string name) {
var deleteTable = new DropTableCommand(name);
_schemaCommands.Add(deleteTable);
Run(deleteTable);
return this;
}
public SchemaBuilder ExecuteSql(string sql, Action<SqlStatementCommand> statement) {
public SchemaBuilder ExecuteSql(string sql, Action<SqlStatementCommand> statement = null) {
var sqlStatmentCommand = new SqlStatementCommand(sql);
statement(sqlStatmentCommand);
if ( statement != null ) {
statement(sqlStatmentCommand);
}
Run(sqlStatmentCommand);
return this;
}
private void Run(SchemaCommand command) {
_interpreter.Visit(command);
}
public SchemaBuilder CreateForeignKey(string name, string srcTable, string[] srcColumns, string destTable, string[] destColumns) {
var command = new CreateForeignKeyCommand(name, srcTable, srcColumns, destTable, destColumns);
Run(command);
return this;
}
public SchemaBuilder DropForeignKey(string srcTable, string name) {
var command = new DropForeignKeyCommand(srcTable, name);
Run(command);
return this;
}

View File

@@ -1,19 +1,31 @@
using System.Collections.Generic;
using JetBrains.Annotations;
namespace Orchard.DataMigration.Schema {
public class SchemaCommand {
protected readonly List<TableCommand> _tableCommands;
public SchemaCommand(string tableName) {
_tableCommands = new List<TableCommand>();
Name(tableName);
public abstract class SchemaCommand : ISchemaBuilderCommand {
protected SchemaCommand(string name, SchemaCommandType type ) {
TableCommands = new List<TableCommand>();
Type = type;
WithName(name);
}
public string TableName { get; private set; }
public string Name { get; private set; }
public List<TableCommand> TableCommands { get; private set; }
public SchemaCommand Name(string name) {
TableName = name;
public SchemaCommandType Type { get; [UsedImplicitly]private set; }
public SchemaCommand WithName(string name) {
Name = name;
return this;
}
}
public enum SchemaCommandType {
CreateTable,
DropTable,
AlterTable,
SqlStatement,
CreateForeignKey,
DropForeignKey
}
}

View File

@@ -2,17 +2,18 @@
namespace Orchard.DataMigration.Schema {
public class SqlStatementCommand : SchemaCommand {
protected readonly List<string> _dialects;
protected readonly List<string> _providers;
public SqlStatementCommand(string sql)
: base("") {
: base(string.Empty, SchemaCommandType.SqlStatement) {
Sql = sql;
_dialects = new List<string>();
_providers = new List<string>();
}
public string Sql { get; private set; }
public List<string> Providers { get { return _providers; } }
public SqlStatementCommand ForDialect(string dialect) {
_dialects.Add(dialect);
public SqlStatementCommand ForProvider(string dataProvider) {
_providers.Add(dataProvider);
return this;
}
}

View File

@@ -1,9 +1,9 @@
namespace Orchard.DataMigration.Schema {
public class TableCommand {
private string _name;
public class TableCommand : ISchemaBuilderCommand{
public string TableName { get; private set; }
public TableCommand(string name) {
_name = name;
public TableCommand(string tableName) {
TableName = tableName;
}
}

View File

@@ -349,6 +349,13 @@
<Compile Include="ContentManagement\ViewModels\TemplateViewModel.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="DataMigration\Interpreters\ICommandInterpreter.cs" />
<Compile Include="DataMigration\Interpreters\DefaultDataMigrationInterpreter.cs" />
<Compile Include="DataMigration\Interpreters\IDataMigrationInterpreter.cs" />
<Compile Include="DataMigration\Interpreters\SqLiteCommandInterpreter.cs" />
<Compile Include="DataMigration\Schema\AddColumnCommand.cs" />
<Compile Include="DataMigration\Schema\ISchemaBuilderCommand.cs" />
<Compile Include="DataMigration\Schema\IShellSettings.cs" />
<Compile Include="DataMigration\Schema\SqlStatementCommand.cs" />
<Compile Include="DataMigration\Schema\CreateColumnCommand.cs" />
<Compile Include="DataMigration\Schema\CreateForeignKeyCommand.cs" />