@ -7,18 +7,21 @@ using NLog;
namespace NzbDrone.Core.Datastore.Migration.Framework
{
public interface IS Q LiteMigrationHelper
public interface IS q LiteMigrationHelper
{
Dictionary < String , SQLite MigrationHelper. SQLite Column> GetColumns ( string tableName ) ;
void CreateTable ( string tableName , IEnumerable < SQLite MigrationHelper. SQLite Column> values , IEnumerable < SQLiteMigrationHelper . SQLiteIndex > indexes ) ;
void CopyData ( string sourceTable , string destinationTable , IEnumerable < SQLite MigrationHelper. SQLite Column> columns ) ;
Dictionary < String , SQLite Column> GetColumns ( string tableName ) ;
void CreateTable ( string tableName , IEnumerable < SQLite Column> values , IEnumerable < SQLiteIndex > indexes ) ;
void CopyData ( string sourceTable , string destinationTable , IEnumerable < SQLite Column> columns ) ;
void DropTable ( string tableName ) ;
void RenameTable ( string tableName , string newName ) ;
IEnumerable < IGrouping < T , KeyValuePair < int , T > > > GetDuplicates < T > ( string tableName , string columnName ) ;
SQLiteTransaction BeginTransaction ( ) ;
List < SQLiteMigrationHelper . SQLiteIndex > GetIndexes ( string tableName ) ;
List < SQLiteIndex > GetIndexes ( string tableName ) ;
int ExecuteScalar ( string command , params string [ ] args ) ;
void ExecuteNonQuery ( string command , params string [ ] args ) ;
}
public class S QLiteMigrationHelper : ISQ LiteMigrationHelper
public class S qLiteMigrationHelper : ISq LiteMigrationHelper
{
private readonly SQLiteConnection _connection ;
@ -28,7 +31,7 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
private static readonly Regex IndexRegex = new Regex ( @"\(""(?<col>.*)""\s(?<direction>ASC|DESC)\)$" ,
RegexOptions . Compiled | RegexOptions . IgnoreCase | RegexOptions . Multiline ) ;
public S Q LiteMigrationHelper( IConnectionStringFactory connectionStringFactory , Logger logger )
public S q LiteMigrationHelper( IConnectionStringFactory connectionStringFactory , Logger logger )
{
try
{
@ -69,18 +72,22 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
} ) ;
}
private static IEnumerable < T > ReadArray < T > ( SQLiteDataReader reader )
{
while ( reader . Read ( ) )
{
yield return ( T ) Convert . ChangeType ( reader [ 0 ] , typeof ( T ) ) ;
}
}
public List < SQLiteIndex > GetIndexes ( string tableName )
{
var command = new SQLiteCommand ( string . Format ( "SELECT sql FROM sqlite_master WHERE type='index' AND tbl_name ='{0}'" , tableName ) ) ;
command . Connection = _connection ;
var reader = command . ExecuteReader ( ) ;
var sqls = new List < string > ( ) ;
while ( reader . Read ( ) )
{
sqls . Add ( reader [ 0 ] . ToString ( ) ) ;
}
var sqls = ReadArray < string > ( reader ) . ToList ( ) ;
var indexes = new List < SQLiteIndex > ( ) ;
@ -108,7 +115,7 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
foreach ( var index in indexes )
{
ExecuteNonQuery ( "DROP INDEX {0}", index . IndexName ) ;
ExecuteNonQuery ( "DROP INDEX IF EXISTS {0}", index . IndexName ) ;
ExecuteNonQuery ( index . CreateSql ( tableName ) ) ;
}
}
@ -146,6 +153,23 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
renameCommand . ExecuteNonQuery ( ) ;
}
public IEnumerable < IGrouping < T , KeyValuePair < int , T > > > GetDuplicates < T > ( string tableName , string columnName )
{
var getDuplicates = BuildCommand ( "select id, {0} from {1}" , columnName , tableName ) ;
var result = new List < KeyValuePair < int , T > > ( ) ;
using ( var reader = getDuplicates . ExecuteReader ( ) )
{
while ( reader . Read ( ) )
{
result . Add ( new KeyValuePair < int , T > ( reader . GetInt16 ( 0 ) , ( T ) Convert . ChangeType ( reader [ 1 ] , typeof ( T ) ) ) ) ;
}
}
return result . GroupBy ( c = > c . Value ) . Where ( g = > g . Count ( ) > 1 ) ;
}
public int GetRowCount ( string tableName )
{
var countCommand = BuildCommand ( "SELECT COUNT(*) FROM {0};" , tableName ) ;
@ -166,8 +190,7 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
}
private void ExecuteNonQuery ( string command , params string [ ] args )
public void ExecuteNonQuery ( string command , params string [ ] args )
{
var sqLiteCommand = new SQLiteCommand ( string . Format ( command , args ) )
{
@ -177,43 +200,17 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
sqLiteCommand . ExecuteNonQuery ( ) ;
}
public class SQLiteColumn
public int ExecuteScalar ( string command , params string [ ] args )
{
public string Name { get ; set ; }
public string Schema { get ; set ; }
public override string ToString ( )
{
return string . Format ( "[{0}] {1}" , Name , Schema ) ;
}
}
public class SQLiteIndex
{
public string Column { get ; set ; }
public string Table { get ; set ; }
public bool Unique { get ; set ; }
public override string ToString ( )
{
return string . Format ( "[{0}] Unique: {1}" , Column , Unique ) ;
}
public string IndexName
var sqLiteCommand = new SQLiteCommand ( string . Format ( command , args ) )
{
get
{
return string . Format ( "IX_{0}_{1}" , Table , Column ) ;
}
}
Connection = _connection
} ;
public string CreateSql ( string tableName )
{
return string . Format ( @"CREATE UNIQUE INDEX ""{2}"" ON ""{0}"" (""{1}"" ASC)" , tableName , Column , IndexName ) ;
}
return ( int ) sqLiteCommand . ExecuteScalar ( ) ;
}
}
}
}