mirror of
https://github.com/Radarr/Radarr.git
synced 2024-11-04 10:02:40 +01:00
added support for removing columns
This commit is contained in:
parent
38c3faf53c
commit
99daa47f89
@ -1,49 +0,0 @@
|
|||||||
using System.Linq;
|
|
||||||
using FluentAssertions;
|
|
||||||
using NUnit.Framework;
|
|
||||||
using NzbDrone.Core.Datastore;
|
|
||||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
|
||||||
using NzbDrone.Core.Test.Framework;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.Datastore
|
|
||||||
{
|
|
||||||
[TestFixture]
|
|
||||||
public class SQLiteAlterFixture : DbTest
|
|
||||||
{
|
|
||||||
private SQLiteAlter Subject;
|
|
||||||
|
|
||||||
[SetUp]
|
|
||||||
public void SetUp()
|
|
||||||
{
|
|
||||||
var connection = Mocker.Resolve<IDatabase>().DataMapper.ConnectionString;
|
|
||||||
Subject = new SQLiteAlter(connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void should_parse_existing_columns()
|
|
||||||
{
|
|
||||||
var columns = Subject.GetColumns("Series");
|
|
||||||
|
|
||||||
columns.Should().NotBeEmpty();
|
|
||||||
|
|
||||||
columns.Values.Should().NotContain(c => string.IsNullOrWhiteSpace(c.Name));
|
|
||||||
columns.Values.Should().NotContain(c => string.IsNullOrWhiteSpace(c.Schema));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void should_create_table_from_column_list()
|
|
||||||
{
|
|
||||||
var columns = Subject.GetColumns("Series");
|
|
||||||
columns.Remove("Title");
|
|
||||||
|
|
||||||
Subject.CreateTable("Series_New", columns.Values);
|
|
||||||
|
|
||||||
var newColumns = Subject.GetColumns("Series_New");
|
|
||||||
|
|
||||||
newColumns.Values.Should().HaveSameCount(columns.Values);
|
|
||||||
newColumns.Should().NotContainKey("Title");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
84
NzbDrone.Core.Test/Datastore/SQLiteMigrationHelperFixture.cs
Normal file
84
NzbDrone.Core.Test/Datastore/SQLiteMigrationHelperFixture.cs
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
using FizzWare.NBuilder;
|
||||||
|
using FluentAssertions;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.Datastore
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class SQLiteMigrationHelperFixture : DbTest
|
||||||
|
{
|
||||||
|
private SQLiteMigrationHelper _subject;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp()
|
||||||
|
{
|
||||||
|
_subject = Mocker.Resolve<SQLiteMigrationHelper>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_parse_existing_columns()
|
||||||
|
{
|
||||||
|
var columns = _subject.GetColumns("Series");
|
||||||
|
|
||||||
|
columns.Should().NotBeEmpty();
|
||||||
|
|
||||||
|
columns.Values.Should().NotContain(c => string.IsNullOrWhiteSpace(c.Name));
|
||||||
|
columns.Values.Should().NotContain(c => string.IsNullOrWhiteSpace(c.Schema));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_create_table_from_column_list()
|
||||||
|
{
|
||||||
|
var columns = _subject.GetColumns("Series");
|
||||||
|
columns.Remove("Title");
|
||||||
|
|
||||||
|
_subject.CreateTable("Series_New", columns.Values);
|
||||||
|
|
||||||
|
var newColumns = _subject.GetColumns("Series_New");
|
||||||
|
|
||||||
|
newColumns.Values.Should().HaveSameCount(columns.Values);
|
||||||
|
newColumns.Should().NotContainKey("Title");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_get_zero_count_on_empty_table()
|
||||||
|
{
|
||||||
|
_subject.GetRowCount("Series").Should().Be(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_be_able_to_transfer_empty_tables()
|
||||||
|
{
|
||||||
|
var columns = _subject.GetColumns("Series");
|
||||||
|
columns.Remove("Title");
|
||||||
|
|
||||||
|
_subject.CreateTable("Series_New", columns.Values);
|
||||||
|
|
||||||
|
|
||||||
|
_subject.CopyData("Series", "Series_New", columns.Values);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_transfer_table_with_data()
|
||||||
|
{
|
||||||
|
var originalEpisodes = Builder<Episode>.CreateListOfSize(10).BuildListOfNew();
|
||||||
|
|
||||||
|
Mocker.Resolve<EpisodeRepository>().InsertMany(originalEpisodes);
|
||||||
|
|
||||||
|
var columns = _subject.GetColumns("Episodes");
|
||||||
|
columns.Remove("Title");
|
||||||
|
|
||||||
|
_subject.CreateTable("Episodes_New", columns.Values);
|
||||||
|
|
||||||
|
_subject.CopyData("Episodes", "Episodes_New", columns.Values);
|
||||||
|
|
||||||
|
_subject.GetRowCount("Episodes_New").Should().Be(originalEpisodes.Count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using FluentMigrator.Runner;
|
||||||
using Marr.Data;
|
using Marr.Data;
|
||||||
using Moq;
|
using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
@ -93,10 +94,16 @@ private void WithTestDb()
|
|||||||
WithTempAsAppPath();
|
WithTempAsAppPath();
|
||||||
|
|
||||||
|
|
||||||
|
Mocker.SetConstant<IAnnouncer>(Mocker.Resolve<MigrationLogger>());
|
||||||
|
Mocker.SetConstant<IConnectionStringFactory>(Mocker.Resolve<ConnectionStringFactory>());
|
||||||
|
Mocker.SetConstant<ISQLiteMigrationHelper>(Mocker.Resolve<SQLiteMigrationHelper>());
|
||||||
|
Mocker.SetConstant<ISQLiteAlter>(Mocker.Resolve<SQLiteAlter>());
|
||||||
|
Mocker.SetConstant<IMigrationController>(Mocker.Resolve<MigrationController>());
|
||||||
|
|
||||||
MapRepository.Instance.EnableTraceLogging = true;
|
MapRepository.Instance.EnableTraceLogging = true;
|
||||||
|
|
||||||
var factory = new DbFactory(new MigrationController(new MigrationLogger(TestLogger)), Mocker.GetMock<IAppDirectoryInfo>().Object);
|
var factory = Mocker.Resolve<DbFactory>();
|
||||||
_database = factory.Create(MigrationType);
|
var _database = factory.Create(MigrationType);
|
||||||
_db = new TestDatabase(_database);
|
_db = new TestDatabase(_database);
|
||||||
Mocker.SetConstant(_database);
|
Mocker.SetConstant(_database);
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@
|
|||||||
<Compile Include="Datastore\PagingSpecExtenstionsTests\ToSortDirectionFixture.cs" />
|
<Compile Include="Datastore\PagingSpecExtenstionsTests\ToSortDirectionFixture.cs" />
|
||||||
<Compile Include="Datastore\PagingSpecExtenstionsTests\PagingOffsetFixture.cs" />
|
<Compile Include="Datastore\PagingSpecExtenstionsTests\PagingOffsetFixture.cs" />
|
||||||
<Compile Include="Datastore\ReflectionStrategyFixture\Benchmarks.cs" />
|
<Compile Include="Datastore\ReflectionStrategyFixture\Benchmarks.cs" />
|
||||||
<Compile Include="Datastore\SQLiteAlterFixture.cs" />
|
<Compile Include="Datastore\SQLiteMigrationHelperFixture.cs" />
|
||||||
<Compile Include="DecisionEngineTests\NotRestrictedNzbSpecificationFixture.cs" />
|
<Compile Include="DecisionEngineTests\NotRestrictedNzbSpecificationFixture.cs" />
|
||||||
<Compile Include="Download\DownloadApprovedReportsTests\DownloadApprovedFixture.cs" />
|
<Compile Include="Download\DownloadApprovedReportsTests\DownloadApprovedFixture.cs" />
|
||||||
<Compile Include="Download\DownloadApprovedReportsTests\GetQualifiedReportsFixture.cs" />
|
<Compile Include="Download\DownloadApprovedReportsTests\GetQualifiedReportsFixture.cs" />
|
||||||
|
37
NzbDrone.Core/Datastore/ConnectionStringFactory.cs
Normal file
37
NzbDrone.Core/Datastore/ConnectionStringFactory.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using System.Data.SQLite;
|
||||||
|
using NzbDrone.Common;
|
||||||
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore
|
||||||
|
{
|
||||||
|
public interface IConnectionStringFactory
|
||||||
|
{
|
||||||
|
string MainDbConnectionString { get; }
|
||||||
|
string LogDbConnectionString { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ConnectionStringFactory : IConnectionStringFactory
|
||||||
|
{
|
||||||
|
public ConnectionStringFactory(IAppDirectoryInfo appDirectoryInfo)
|
||||||
|
{
|
||||||
|
MainDbConnectionString = GetConnectionString(appDirectoryInfo.GetNzbDroneDatabase());
|
||||||
|
LogDbConnectionString = GetConnectionString(appDirectoryInfo.GetLogDatabase());
|
||||||
|
}
|
||||||
|
|
||||||
|
public string MainDbConnectionString { get; private set; }
|
||||||
|
public string LogDbConnectionString { get; private set; }
|
||||||
|
|
||||||
|
private static string GetConnectionString(string dbPath)
|
||||||
|
{
|
||||||
|
var connectionBuilder = new SQLiteConnectionStringBuilder();
|
||||||
|
|
||||||
|
connectionBuilder.DataSource = dbPath;
|
||||||
|
connectionBuilder.CacheSize = (int)-10.Megabytes();
|
||||||
|
connectionBuilder.DateTimeKind = DateTimeKind.Utc;
|
||||||
|
connectionBuilder.JournalMode = SQLiteJournalModeEnum.Wal;
|
||||||
|
|
||||||
|
return connectionBuilder.ConnectionString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,10 +3,8 @@
|
|||||||
using Marr.Data;
|
using Marr.Data;
|
||||||
using Marr.Data.Reflection;
|
using Marr.Data.Reflection;
|
||||||
using NzbDrone.Common.Composition;
|
using NzbDrone.Common.Composition;
|
||||||
using NzbDrone.Common.EnvironmentInfo;
|
|
||||||
using NzbDrone.Common.Messaging;
|
using NzbDrone.Common.Messaging;
|
||||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
using NzbDrone.Common;
|
|
||||||
using NzbDrone.Core.Instrumentation;
|
using NzbDrone.Core.Instrumentation;
|
||||||
|
|
||||||
|
|
||||||
@ -17,10 +15,11 @@ public interface IDbFactory
|
|||||||
IDatabase Create(MigrationType migrationType = MigrationType.Main);
|
IDatabase Create(MigrationType migrationType = MigrationType.Main);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public class DbFactory : IDbFactory
|
public class DbFactory : IDbFactory
|
||||||
{
|
{
|
||||||
private readonly IMigrationController _migrationController;
|
private readonly IMigrationController _migrationController;
|
||||||
private readonly IAppDirectoryInfo _appDirectoryInfo;
|
private readonly IConnectionStringFactory _connectionStringFactory;
|
||||||
|
|
||||||
static DbFactory()
|
static DbFactory()
|
||||||
{
|
{
|
||||||
@ -39,26 +38,27 @@ public static void RegisterDatabase(IContainer container)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public DbFactory(IMigrationController migrationController, IAppDirectoryInfo appDirectoryInfo)
|
public DbFactory(IMigrationController migrationController, IConnectionStringFactory connectionStringFactory)
|
||||||
{
|
{
|
||||||
_migrationController = migrationController;
|
_migrationController = migrationController;
|
||||||
_appDirectoryInfo = appDirectoryInfo;
|
_connectionStringFactory = connectionStringFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDatabase Create(MigrationType migrationType = MigrationType.Main)
|
public IDatabase Create(MigrationType migrationType = MigrationType.Main)
|
||||||
{
|
{
|
||||||
string dbPath;
|
string connectionString;
|
||||||
|
|
||||||
|
|
||||||
switch (migrationType)
|
switch (migrationType)
|
||||||
{
|
{
|
||||||
case MigrationType.Main:
|
case MigrationType.Main:
|
||||||
{
|
{
|
||||||
dbPath = _appDirectoryInfo.GetNzbDroneDatabase();
|
connectionString = _connectionStringFactory.MainDbConnectionString;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MigrationType.Log:
|
case MigrationType.Log:
|
||||||
{
|
{
|
||||||
dbPath = _appDirectoryInfo.GetLogDatabase();
|
connectionString = _connectionStringFactory.LogDbConnectionString;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -68,7 +68,6 @@ public IDatabase Create(MigrationType migrationType = MigrationType.Main)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var connectionString = GetConnectionString(dbPath);
|
|
||||||
|
|
||||||
_migrationController.MigrateToLatest(connectionString, migrationType);
|
_migrationController.MigrateToLatest(connectionString, migrationType);
|
||||||
|
|
||||||
@ -82,17 +81,5 @@ public IDatabase Create(MigrationType migrationType = MigrationType.Main)
|
|||||||
return dataMapper;
|
return dataMapper;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetConnectionString(string dbPath)
|
|
||||||
{
|
|
||||||
var connectionBuilder = new SQLiteConnectionStringBuilder();
|
|
||||||
|
|
||||||
connectionBuilder.DataSource = dbPath;
|
|
||||||
connectionBuilder.CacheSize = (int)-10.Megabytes();
|
|
||||||
connectionBuilder.DateTimeKind = DateTimeKind.Utc;
|
|
||||||
connectionBuilder.JournalMode = SQLiteJournalModeEnum.Wal;
|
|
||||||
|
|
||||||
return connectionBuilder.ConnectionString;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,24 +3,13 @@
|
|||||||
|
|
||||||
namespace NzbDrone.Core.Datastore.Migration
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
{
|
{
|
||||||
/* [Tags("")]
|
[Tags("")]
|
||||||
[Migration(7)]
|
[Migration(7)]
|
||||||
public class remove_backlog : NzbDroneMigrationBase
|
public class remove_backlog : NzbDroneMigrationBase
|
||||||
{
|
{
|
||||||
protected override void MainDbUpgrade()
|
protected override void MainDbUpgrade()
|
||||||
{
|
{
|
||||||
var newSeriesTable = "CREATE TABLE [Series_new] ([Id] integer NOT NULL PRIMARY KEY AUTOINCREMENT, [TvdbId] integer NOT NULL, " +
|
SQLiteAlter.DropColumns("Series", new[] { "BacklogSetting" });
|
||||||
"[TvRageId] integer NOT NULL, [ImdbId] text NOT NULL, [Title] text NOT NULL, [TitleSlug] text NOT NULL, " +
|
|
||||||
"[CleanTitle] text NOT NULL, [Status] integer NOT NULL, [Overview] text, [AirTime] text, " +
|
|
||||||
"[Images] text NOT NULL, [Path] text NOT NULL, [Monitored] integer NOT NULL, [QualityProfileId] integer NOT NULL, " +
|
|
||||||
"[SeasonFolder] integer NOT NULL, [LastInfoSync] datetime, [LastDiskSync] datetime, [Runtime] integer NOT NULL, " +
|
|
||||||
"[SeriesType] integer NOT NULL, [Network] text, [CustomStartDate] datetime, " +
|
|
||||||
"[UseSceneNumbering] integer NOT NULL, [FirstAired] datetime)";
|
|
||||||
|
|
||||||
Execute.Sql(newSeriesTable);
|
|
||||||
|
|
||||||
|
|
||||||
Execute.Sql("INSERT INTO Series_new SELECT * FROM Series");
|
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
namespace NzbDrone.Core.Datastore.Migration.Framework
|
||||||
|
{
|
||||||
|
public class MigrationContext
|
||||||
|
{
|
||||||
|
public MigrationType MigrationType { get; set; }
|
||||||
|
public ISQLiteAlter SQLiteAlter { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -14,12 +14,14 @@ public interface IMigrationController
|
|||||||
public class MigrationController : IMigrationController
|
public class MigrationController : IMigrationController
|
||||||
{
|
{
|
||||||
private readonly IAnnouncer _announcer;
|
private readonly IAnnouncer _announcer;
|
||||||
|
private readonly ISQLiteAlter _sqLiteAlter;
|
||||||
|
|
||||||
private static readonly HashSet<string> MigrationCache = new HashSet<string>();
|
private static readonly HashSet<string> MigrationCache = new HashSet<string>();
|
||||||
|
|
||||||
public MigrationController(IAnnouncer announcer)
|
public MigrationController(IAnnouncer announcer, ISQLiteAlter sqLiteAlter)
|
||||||
{
|
{
|
||||||
_announcer = announcer;
|
_announcer = announcer;
|
||||||
|
_sqLiteAlter = sqLiteAlter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MigrateToLatest(string connectionString, MigrationType migrationType)
|
public void MigrateToLatest(string connectionString, MigrationType migrationType)
|
||||||
@ -35,7 +37,11 @@ public void MigrateToLatest(string connectionString, MigrationType migrationType
|
|||||||
var migrationContext = new RunnerContext(_announcer)
|
var migrationContext = new RunnerContext(_announcer)
|
||||||
{
|
{
|
||||||
Namespace = "NzbDrone.Core.Datastore.Migration",
|
Namespace = "NzbDrone.Core.Datastore.Migration",
|
||||||
ApplicationContext = migrationType
|
ApplicationContext = new MigrationContext
|
||||||
|
{
|
||||||
|
MigrationType = migrationType,
|
||||||
|
SQLiteAlter = _sqLiteAlter
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var options = new MigrationOptions { PreviewOnly = false, Timeout = 60 };
|
var options = new MigrationOptions { PreviewOnly = false, Timeout = 60 };
|
||||||
|
@ -14,7 +14,11 @@ protected virtual void LogDbUpgrade()
|
|||||||
|
|
||||||
public override void Up()
|
public override void Up()
|
||||||
{
|
{
|
||||||
switch ((MigrationType)ApplicationContext)
|
var context = (MigrationContext)ApplicationContext;
|
||||||
|
|
||||||
|
SQLiteAlter = context.SQLiteAlter;
|
||||||
|
|
||||||
|
switch (context.MigrationType)
|
||||||
{
|
{
|
||||||
case MigrationType.Main:
|
case MigrationType.Main:
|
||||||
MainDbUpgrade();
|
MainDbUpgrade();
|
||||||
@ -29,6 +33,7 @@ public override void Up()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ISQLiteAlter SQLiteAlter { get; private set; }
|
||||||
|
|
||||||
public override void Down()
|
public override void Down()
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,134 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data.SQLite;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration.Framework
|
||||||
|
{
|
||||||
|
public interface ISQLiteMigrationHelper
|
||||||
|
{
|
||||||
|
Dictionary<String, SQLiteMigrationHelper.SQLiteColumn> GetColumns(string tableName);
|
||||||
|
void CreateTable(string tableName, IEnumerable<SQLiteMigrationHelper.SQLiteColumn> values);
|
||||||
|
void CopyData(string sourceTable, string destinationTable, IEnumerable<SQLiteMigrationHelper.SQLiteColumn> columns);
|
||||||
|
int GetRowCount(string tableName);
|
||||||
|
void DropTable(string tableName);
|
||||||
|
void RenameTable(string tableName, string newName);
|
||||||
|
SQLiteTransaction BeginTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SQLiteMigrationHelper : ISQLiteMigrationHelper
|
||||||
|
{
|
||||||
|
private readonly SQLiteConnection _connection;
|
||||||
|
|
||||||
|
private static readonly Regex SchemaRegex = new Regex(@"['\""\[](?<name>\w+)['\""\]]\s(?<schema>[\w-\s]+)",
|
||||||
|
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Multiline);
|
||||||
|
|
||||||
|
public SQLiteMigrationHelper(IConnectionStringFactory connectionStringFactory)
|
||||||
|
{
|
||||||
|
_connection = new SQLiteConnection(connectionStringFactory.MainDbConnectionString);
|
||||||
|
_connection.Open();
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetOriginalSql(string tableName)
|
||||||
|
{
|
||||||
|
var command =
|
||||||
|
new SQLiteCommand(string.Format("SELECT sql FROM sqlite_master WHERE type='table' AND name ='{0}'",
|
||||||
|
tableName));
|
||||||
|
|
||||||
|
command.Connection = _connection;
|
||||||
|
return (string)command.ExecuteScalar();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<String, SQLiteColumn> GetColumns(string tableName)
|
||||||
|
{
|
||||||
|
var originalSql = GetOriginalSql(tableName);
|
||||||
|
|
||||||
|
var matches = SchemaRegex.Matches(originalSql);
|
||||||
|
|
||||||
|
return matches.Cast<Match>().ToDictionary(
|
||||||
|
match => match.Groups["name"].Value.Trim(),
|
||||||
|
match => new SQLiteColumn
|
||||||
|
{
|
||||||
|
Name = match.Groups["name"].Value.Trim(),
|
||||||
|
Schema = match.Groups["schema"].Value.Trim()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateTable(string tableName, IEnumerable<SQLiteColumn> values)
|
||||||
|
{
|
||||||
|
var columns = String.Join(",", values.Select(c => c.ToString()));
|
||||||
|
|
||||||
|
var command = new SQLiteCommand(string.Format("CREATE TABLE [{0}] ({1})", tableName, columns));
|
||||||
|
command.Connection = _connection;
|
||||||
|
|
||||||
|
command.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CopyData(string sourceTable, string destinationTable, IEnumerable<SQLiteColumn> columns)
|
||||||
|
{
|
||||||
|
var originalCount = GetRowCount(sourceTable);
|
||||||
|
|
||||||
|
var columnsToTransfer = String.Join(",", columns.Select(c => c.Name));
|
||||||
|
|
||||||
|
var transferCommand = BuildCommand("INSERT INTO {0} SELECT {1} FROM {2};", destinationTable, columnsToTransfer, sourceTable);
|
||||||
|
|
||||||
|
transferCommand.ExecuteNonQuery();
|
||||||
|
|
||||||
|
var transferredRows = GetRowCount(destinationTable);
|
||||||
|
|
||||||
|
|
||||||
|
if (transferredRows != originalCount)
|
||||||
|
{
|
||||||
|
throw new ApplicationException(string.Format("Expected {0} rows to be copied from [{1}] to [{2}]. But only copied {3}", originalCount, sourceTable, destinationTable, transferredRows));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void DropTable(string tableName)
|
||||||
|
{
|
||||||
|
var dropCommand = BuildCommand("DROP TABLE {0};", tableName);
|
||||||
|
dropCommand.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void RenameTable(string tableName, string newName)
|
||||||
|
{
|
||||||
|
var renameCommand = BuildCommand("ALTER TABLE {0} RENAME TO {1};", tableName, newName);
|
||||||
|
renameCommand.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetRowCount(string tableName)
|
||||||
|
{
|
||||||
|
var countCommand = BuildCommand("SELECT COUNT(*) FROM {0};", tableName);
|
||||||
|
return Convert.ToInt32(countCommand.ExecuteScalar());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public SQLiteTransaction BeginTransaction()
|
||||||
|
{
|
||||||
|
return _connection.BeginTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
private SQLiteCommand BuildCommand(string format, params string[] args)
|
||||||
|
{
|
||||||
|
var command = new SQLiteCommand(string.Format(format, args));
|
||||||
|
command.Connection = _connection;
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class SQLiteColumn
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Schema { get; set; }
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return string.Format("[{0}] {1}", Name, Schema);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,69 +1,42 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Data.SQLite;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using FluentMigrator.Builders.Execute;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Datastore.Migration.Framework
|
namespace NzbDrone.Core.Datastore.Migration.Framework
|
||||||
{
|
{
|
||||||
public class SQLiteAlter
|
public interface ISQLiteAlter
|
||||||
{
|
{
|
||||||
private readonly SQLiteConnection _connection;
|
void DropColumns(string tableName, IEnumerable<string> columns);
|
||||||
|
|
||||||
private static readonly Regex SchemaRegex = new Regex(@"[\""\[](?<name>\w+)[\""\]]\s(?<schema>[\w-\s]+)",
|
|
||||||
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Multiline);
|
|
||||||
|
|
||||||
public SQLiteAlter(string connectionString)
|
|
||||||
{
|
|
||||||
_connection = new SQLiteConnection(connectionString);
|
|
||||||
_connection.Open();
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetOriginalSql(string tableName)
|
|
||||||
{
|
|
||||||
var command =
|
|
||||||
new SQLiteCommand(string.Format("SELECT sql FROM sqlite_master WHERE type='table' AND name ='{0}'",
|
|
||||||
tableName));
|
|
||||||
|
|
||||||
command.Connection = _connection;
|
|
||||||
return (string)command.ExecuteScalar();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dictionary<String, SQLiteColumn> GetColumns(string tableName)
|
|
||||||
{
|
|
||||||
var originalSql = GetOriginalSql(tableName);
|
|
||||||
|
|
||||||
var matches = SchemaRegex.Matches(originalSql);
|
|
||||||
|
|
||||||
return matches.Cast<Match>().ToDictionary(
|
|
||||||
match => match.Groups["name"].Value.Trim(),
|
|
||||||
match => new SQLiteColumn
|
|
||||||
{
|
|
||||||
Name = match.Groups["name"].Value.Trim(),
|
|
||||||
Schema = match.Groups["schema"].Value.Trim()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CreateTable(string tableName, Dictionary<string, SQLiteColumn>.ValueCollection values)
|
|
||||||
{
|
|
||||||
var columns = String.Join(",", values.Select(c => c.ToString()));
|
|
||||||
|
|
||||||
var command = new SQLiteCommand(string.Format("CREATE TABLE [{0}] ({1})", tableName, columns));
|
|
||||||
command.Connection = _connection;
|
|
||||||
|
|
||||||
command.ExecuteNonQuery();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SQLiteColumn
|
public class SQLiteAlter : ISQLiteAlter
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
private readonly ISQLiteMigrationHelper _sqLiteMigrationHelper;
|
||||||
public string Schema { get; set; }
|
|
||||||
|
|
||||||
public override string ToString()
|
public SQLiteAlter(ISQLiteMigrationHelper sqLiteMigrationHelper)
|
||||||
{
|
{
|
||||||
return string.Format("[{0}] {1}", Name, Schema);
|
_sqLiteMigrationHelper = sqLiteMigrationHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DropColumns(string tableName, IEnumerable<string> columns)
|
||||||
|
{
|
||||||
|
using (var transaction = _sqLiteMigrationHelper.BeginTransaction())
|
||||||
|
{
|
||||||
|
var originalColumns = _sqLiteMigrationHelper.GetColumns(tableName);
|
||||||
|
|
||||||
|
var newColumns = originalColumns.Where(c => !columns.Contains(c.Key)).Select(c => c.Value).ToList();
|
||||||
|
|
||||||
|
var tempTableName = tableName + "_temp";
|
||||||
|
|
||||||
|
_sqLiteMigrationHelper.CreateTable(tempTableName, newColumns);
|
||||||
|
|
||||||
|
_sqLiteMigrationHelper.CopyData(tableName, tempTableName, newColumns);
|
||||||
|
|
||||||
|
_sqLiteMigrationHelper.DropTable(tableName);
|
||||||
|
|
||||||
|
_sqLiteMigrationHelper.RenameTable(tempTableName, tableName);
|
||||||
|
|
||||||
|
transaction.Commit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -194,6 +194,7 @@
|
|||||||
<Compile Include="DataAugmentation\Scene\SceneMappingRepository.cs" />
|
<Compile Include="DataAugmentation\Scene\SceneMappingRepository.cs" />
|
||||||
<Compile Include="DataAugmentation\Scene\UpdateSceneMappingCommand.cs" />
|
<Compile Include="DataAugmentation\Scene\UpdateSceneMappingCommand.cs" />
|
||||||
<Compile Include="Datastore\CachedBasicRepository.cs" />
|
<Compile Include="Datastore\CachedBasicRepository.cs" />
|
||||||
|
<Compile Include="Datastore\ConnectionStringFactory.cs" />
|
||||||
<Compile Include="Datastore\Converters\BooleanIntConverter.cs" />
|
<Compile Include="Datastore\Converters\BooleanIntConverter.cs" />
|
||||||
<Compile Include="Datastore\Converters\QualityIntConverter.cs" />
|
<Compile Include="Datastore\Converters\QualityIntConverter.cs" />
|
||||||
<Compile Include="Datastore\Converters\Int32Converter.cs" />
|
<Compile Include="Datastore\Converters\Int32Converter.cs" />
|
||||||
@ -213,6 +214,7 @@
|
|||||||
<Compile Include="Datastore\Migration\006_add_index_to_log_time.cs" />
|
<Compile Include="Datastore\Migration\006_add_index_to_log_time.cs" />
|
||||||
<Compile Include="Datastore\Migration\007_add_renameEpisodes_to_naming.cs" />
|
<Compile Include="Datastore\Migration\007_add_renameEpisodes_to_naming.cs" />
|
||||||
<Compile Include="Datastore\Migration\007_remove_backlog.cs" />
|
<Compile Include="Datastore\Migration\007_remove_backlog.cs" />
|
||||||
|
<Compile Include="Datastore\Migration\Framework\MigrationContext.cs" />
|
||||||
<Compile Include="Datastore\Migration\Framework\MigrationController.cs" />
|
<Compile Include="Datastore\Migration\Framework\MigrationController.cs" />
|
||||||
<Compile Include="Datastore\Migration\Framework\MigrationExtension.cs" />
|
<Compile Include="Datastore\Migration\Framework\MigrationExtension.cs" />
|
||||||
<Compile Include="Datastore\Migration\Framework\MigrationOptions.cs" />
|
<Compile Include="Datastore\Migration\Framework\MigrationOptions.cs" />
|
||||||
@ -220,7 +222,8 @@
|
|||||||
<Compile Include="Datastore\Migration\001_initialSetup.cs" />
|
<Compile Include="Datastore\Migration\001_initialSetup.cs" />
|
||||||
<Compile Include="Datastore\Migration\Framework\NzbDroneMigrationBase.cs" />
|
<Compile Include="Datastore\Migration\Framework\NzbDroneMigrationBase.cs" />
|
||||||
<Compile Include="Datastore\MigrationType.cs" />
|
<Compile Include="Datastore\MigrationType.cs" />
|
||||||
<Compile Include="Datastore\Migration\Framework\SqliteAlter.cs" />
|
<Compile Include="Datastore\Migration\Framework\SQLiteAlter.cs" />
|
||||||
|
<Compile Include="Datastore\Migration\Framework\SQLiteMigrationHelper.cs" />
|
||||||
<Compile Include="Datastore\ModelBase.cs" />
|
<Compile Include="Datastore\ModelBase.cs" />
|
||||||
<Compile Include="Datastore\BasicRepository.cs" />
|
<Compile Include="Datastore\BasicRepository.cs" />
|
||||||
<Compile Include="Datastore\PagingSpec.cs" />
|
<Compile Include="Datastore\PagingSpec.cs" />
|
||||||
|
Loading…
Reference in New Issue
Block a user