1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2024-12-12 11:15:43 +02:00

Merge branch 'master' of git://github.com/kayone/NzbDrone

This commit is contained in:
Mark McDowall 2011-06-16 20:46:22 -07:00
commit 114f0675e0
2 changed files with 137 additions and 27 deletions

View File

@ -1,4 +1,6 @@
using System; using System;
using System.Data;
using System.Data.Common;
using System.Data.SQLite; using System.Data.SQLite;
using System.IO; using System.IO;
using MvcMiniProfiler.Data; using MvcMiniProfiler.Data;
@ -58,9 +60,12 @@ public static IRepository CreateSimpleRepository(string connectionString)
public static IDatabase GetPetaPocoDb(string connectionString) public static IDatabase GetPetaPocoDb(string connectionString)
{ {
var profileConnection = ProfiledDbConnection.Get(new SQLiteConnection(connectionString)); var profileConnection = ProfiledDbConnection.Get(new SQLiteConnection(connectionString));
PetaPoco.Database.Mapper = new CustomeMapper();
var db = new PetaPoco.Database(profileConnection); Database.Mapper = new CustomeMapper();
db.OpenSharedConnection(); var db = new Database(profileConnection);
if (profileConnection.State != ConnectionState.Open)
profileConnection.Open();
return db; return db;
} }

View File

@ -1,5 +1,5 @@
/* PetaPoco v4.0.2 - A Tiny ORMish thing for your POCO's. /* PetaPoco v4.0.2 - A Tiny ORMish thing for your POCO's.
* Copyright © 2011 Topten Software. All Rights Reserved. * Copyright © 2011 Topten Software. All Rights Reserved.
* *
* Apache License 2.0 - http://www.toptensoftware.com/petapoco/license * Apache License 2.0 - http://www.toptensoftware.com/petapoco/license
* *
@ -24,7 +24,6 @@
using System.Linq.Expressions; using System.Linq.Expressions;
// ReSharper disable
namespace PetaPoco namespace PetaPoco
{ {
// Poco's marked [Explicit] require all column properties to be marked // Poco's marked [Explicit] require all column properties to be marked
@ -182,6 +181,8 @@ public interface IDatabaseQuery
List<T> Fetch<T>(long page, long itemsPerPage, Sql sql); List<T> Fetch<T>(long page, long itemsPerPage, Sql sql);
Page<T> Page<T>(long page, long itemsPerPage, string sql, params object[] args); Page<T> Page<T>(long page, long itemsPerPage, string sql, params object[] args);
Page<T> Page<T>(long page, long itemsPerPage, Sql sql); Page<T> Page<T>(long page, long itemsPerPage, Sql sql);
List<T> SkipTake<T>(long skip, long take, string sql, params object[] args);
List<T> SkipTake<T>(long skip, long take, Sql sql);
List<TRet> Fetch<T1, T2, TRet>(Func<T1, T2, TRet> cb, string sql, params object[] args); List<TRet> Fetch<T1, T2, TRet>(Func<T1, T2, TRet> cb, string sql, params object[] args);
List<TRet> Fetch<T1, T2, T3, TRet>(Func<T1, T2, T3, TRet> cb, string sql, params object[] args); List<TRet> Fetch<T1, T2, T3, TRet>(Func<T1, T2, T3, TRet> cb, string sql, params object[] args);
List<TRet> Fetch<T1, T2, T3, T4, TRet>(Func<T1, T2, T3, T4, TRet> cb, string sql, params object[] args); List<TRet> Fetch<T1, T2, T3, T4, TRet>(Func<T1, T2, T3, T4, TRet> cb, string sql, params object[] args);
@ -221,13 +222,14 @@ public interface IDatabaseQuery
T FirstOrDefault<T>(Sql sql); T FirstOrDefault<T>(Sql sql);
bool Exists<T>(object primaryKey); bool Exists<T>(object primaryKey);
int OneTimeCommandTimeout { get; set; } int OneTimeCommandTimeout { get; set; }
bool Exists<T>(string sql, params object[] args);
} }
public interface IDatabase : IDatabaseQuery public interface IDatabase : IDatabaseQuery
{ {
void Dispose(); void Dispose();
IDbConnection Connection { get; } IDbConnection Connection { get; }
Transaction GetTransaction(); ITransaction GetTransaction();
void BeginTransaction(); void BeginTransaction();
void AbortTransaction(); void AbortTransaction();
void CompleteTransaction(); void CompleteTransaction();
@ -240,6 +242,7 @@ public interface IDatabase : IDatabaseQuery
int Update(object poco, object primaryKeyValue); int Update(object poco, object primaryKeyValue);
int Update<T>(string sql, params object[] args); int Update<T>(string sql, params object[] args);
int Update<T>(Sql sql); int Update<T>(Sql sql);
void UpdateMany<T>(IEnumerable<T> pocoList);
int Delete(string tableName, string primaryKeyName, object poco); int Delete(string tableName, string primaryKeyName, object poco);
int Delete(string tableName, string primaryKeyName, object poco, object primaryKeyValue); int Delete(string tableName, string primaryKeyName, object poco, object primaryKeyValue);
int Delete(object poco); int Delete(object poco);
@ -248,6 +251,8 @@ public interface IDatabase : IDatabaseQuery
int Delete<T>(object pocoOrPrimaryKey); int Delete<T>(object pocoOrPrimaryKey);
void Save(string tableName, string primaryKeyName, object poco); void Save(string tableName, string primaryKeyName, object poco);
void Save(object poco); void Save(object poco);
void InsertMany<T>(IEnumerable<T> pocoList);
void SaveMany<T>(IEnumerable<T> pocoList);
} }
// Database class ... this is where most of the action happens // Database class ... this is where most of the action happens
@ -353,19 +358,17 @@ public void OpenSharedConnection()
{ {
_sharedConnection = _factory.CreateConnection(); _sharedConnection = _factory.CreateConnection();
_sharedConnection.ConnectionString = _connectionString; _sharedConnection.ConnectionString = _connectionString;
_sharedConnection.Open();
if (KeepConnectionAlive) if (KeepConnectionAlive)
_sharedConnectionDepth++; // Make sure you call Dispose _sharedConnectionDepth++; // Make sure you call Dispose
} }
if (_sharedConnection.State != ConnectionState.Open)
_sharedConnection.Open();
_sharedConnectionDepth++; _sharedConnectionDepth++;
} }
// Close a previously opened connection /// <summary>
/// Close a previously opened connection
/// </summary>
public void CloseSharedConnection() public void CloseSharedConnection()
{ {
if (_sharedConnectionDepth > 0) if (_sharedConnectionDepth > 0)
@ -386,7 +389,7 @@ public IDbConnection Connection
} }
// Helper to create a transaction scope // Helper to create a transaction scope
public Transaction GetTransaction() public ITransaction GetTransaction()
{ {
return new Transaction(this); return new Transaction(this);
} }
@ -750,7 +753,7 @@ public List<T> Fetch<T>()
static Regex rxColumns = new Regex(@"\A\s*SELECT\s+((?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|.)*?)(?<!,\s+)\bFROM\b", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled); static Regex rxColumns = new Regex(@"\A\s*SELECT\s+((?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|.)*?)(?<!,\s+)\bFROM\b", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
static Regex rxOrderBy = new Regex(@"\bORDER\s+BY\s+(?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\w\(\)\.])+(?:\s+(?:ASC|DESC))?(?:\s*,\s*(?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\w\(\)\.])+(?:\s+(?:ASC|DESC))?)*", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled); static Regex rxOrderBy = new Regex(@"\bORDER\s+BY\s+(?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\w\(\)\.])+(?:\s+(?:ASC|DESC))?(?:\s*,\s*(?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\w\(\)\.])+(?:\s+(?:ASC|DESC))?)*", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
public static bool SplitSqlForPaging(string sql, out string sqlCount, out string sqlSelectRemoved, out string sqlOrderBy) public static bool SplitSqlForPaging<T>(string sql, out string sqlCount, out string sqlSelectRemoved, out string sqlOrderBy)
{ {
sqlSelectRemoved = null; sqlSelectRemoved = null;
sqlCount = null; sqlCount = null;
@ -766,26 +769,32 @@ public static bool SplitSqlForPaging(string sql, out string sqlCount, out string
sqlCount = sql.Substring(0, g.Index) + "COUNT(*) " + sql.Substring(g.Index + g.Length); sqlCount = sql.Substring(0, g.Index) + "COUNT(*) " + sql.Substring(g.Index + g.Length);
sqlSelectRemoved = sql.Substring(g.Index); sqlSelectRemoved = sql.Substring(g.Index);
// Look for an "ORDER BY <whatever>" clause // Look for an "ORDER BY <whatever>" clause or primarykey from pocodata
var data = PocoData.ForType(typeof(T));
m = rxOrderBy.Match(sqlCount); m = rxOrderBy.Match(sqlCount);
if (!m.Success) if (!m.Success
&& (string.IsNullOrEmpty(data.TableInfo.PrimaryKey) ||
(!data.TableInfo.PrimaryKey.Split(',').All(x => data.Columns.Values.Any(y => y.ColumnName.Equals(x, StringComparison.OrdinalIgnoreCase))))))
{
return false; return false;
}
g = m.Groups[0]; g = m.Groups[0];
sqlOrderBy = g.ToString(); sqlOrderBy = m.Success ? g.ToString() : "ORDER BY " + data.TableInfo.PrimaryKey;
sqlCount = sqlCount.Substring(0, g.Index) + sqlCount.Substring(g.Index + g.Length); sqlCount = sqlCount.Substring(0, g.Index) + sqlCount.Substring(g.Index + g.Length);
return true; return true;
} }
public void BuildPageQueries<T>(long page, long itemsPerPage, string sql, ref object[] args, out string sqlCount, out string sqlPage) private void BuildPageQueries<T>(long skip, long take, string sql, ref object[] args, out string sqlCount, out string sqlPage)
{ {
// Add auto select clause // Add auto select clause
sql = AddSelectClause<T>(sql); sql = AddSelectClause<T>(sql);
// Split the SQL into the bits we need // Split the SQL into the bits we need
string sqlSelectRemoved, sqlOrderBy; string sqlSelectRemoved, sqlOrderBy;
if (!SplitSqlForPaging(sql, out sqlCount, out sqlSelectRemoved, out sqlOrderBy)) if (!SplitSqlForPaging<T>(sql, out sqlCount, out sqlSelectRemoved, out sqlOrderBy))
throw new Exception("Unable to parse SQL statement for paged query"); throw new Exception("Unable to parse SQL statement for paged query");
if (_dbType == DBType.Oracle && sqlSelectRemoved.StartsWith("*")) if (_dbType == DBType.Oracle && sqlSelectRemoved.StartsWith("*"))
throw new Exception("Query must alias '*' when performing a paged query.\neg. select t.* from table t order by t.id"); throw new Exception("Query must alias '*' when performing a paged query.\neg. select t.* from table t order by t.id");
@ -793,20 +802,21 @@ public void BuildPageQueries<T>(long page, long itemsPerPage, string sql, ref ob
// Build the SQL for the actual final result // Build the SQL for the actual final result
if (_dbType == DBType.SqlServer || _dbType == DBType.Oracle) if (_dbType == DBType.SqlServer || _dbType == DBType.Oracle)
{ {
var fromIndex = sqlSelectRemoved.IndexOf("from", StringComparison.OrdinalIgnoreCase);
sqlSelectRemoved = rxOrderBy.Replace(sqlSelectRemoved, ""); sqlSelectRemoved = rxOrderBy.Replace(sqlSelectRemoved, "");
sqlPage = string.Format("SELECT * FROM (SELECT ROW_NUMBER() OVER ({0}) peta_rn, {1}) peta_paged WHERE peta_rn>@{2} AND peta_rn<=@{3}", sqlPage = string.Format("SELECT * FROM (SELECT {2}, ROW_NUMBER() OVER ({0}) peta_rn {1}) peta_paged WHERE peta_rn>@{3} AND peta_rn<=@{4}",
sqlOrderBy, sqlSelectRemoved, args.Length, args.Length + 1); sqlOrderBy, sqlSelectRemoved.Substring(fromIndex), sqlSelectRemoved.Substring(0, fromIndex - 1), args.Length, args.Length + 1);
args = args.Concat(new object[] { (page - 1) * itemsPerPage, page * itemsPerPage }).ToArray(); args = args.Concat(new object[] { skip, skip + take }).ToArray();
} }
else if (_dbType == DBType.SqlServerCE) else if (_dbType == DBType.SqlServerCE)
{ {
sqlPage = string.Format("{0}\nOFFSET @{1} ROWS FETCH NEXT @{2} ROWS ONLY", sql, args.Length, args.Length + 1); sqlPage = string.Format("{0}\nOFFSET @{1} ROWS FETCH NEXT @{2} ROWS ONLY", sql, args.Length, args.Length + 1);
args = args.Concat(new object[] { (page - 1) * itemsPerPage, itemsPerPage }).ToArray(); args = args.Concat(new object[] { skip, take }).ToArray();
} }
else else
{ {
sqlPage = string.Format("{0}\nLIMIT @{1} OFFSET @{2}", sql, args.Length, args.Length + 1); sqlPage = string.Format("{0}\nLIMIT @{1} OFFSET @{2}", sql, args.Length, args.Length + 1);
args = args.Concat(new object[] { itemsPerPage, (page - 1) * itemsPerPage }).ToArray(); args = args.Concat(new object[] { take, skip }).ToArray();
} }
} }
@ -815,7 +825,11 @@ public void BuildPageQueries<T>(long page, long itemsPerPage, string sql, ref ob
public Page<T> Page<T>(long page, long itemsPerPage, string sql, params object[] args) public Page<T> Page<T>(long page, long itemsPerPage, string sql, params object[] args)
{ {
string sqlCount, sqlPage; string sqlCount, sqlPage;
BuildPageQueries<T>(page, itemsPerPage, sql, ref args, out sqlCount, out sqlPage);
long skip = (page - 1) * itemsPerPage;
long take = itemsPerPage;
BuildPageQueries<T>(skip, take, sql, ref args, out sqlCount, out sqlPage);
// Save the one-time command time out and use it for both queries // Save the one-time command time out and use it for both queries
int saveTimeout = OneTimeCommandTimeout; int saveTimeout = OneTimeCommandTimeout;
@ -843,6 +857,21 @@ public Page<T> Page<T>(long page, long itemsPerPage, Sql sql)
return Page<T>(page, itemsPerPage, sql.SQL, sql.Arguments); return Page<T>(page, itemsPerPage, sql.SQL, sql.Arguments);
} }
public List<T> SkipTake<T>(long skip, long take, string sql, params object[] args)
{
string sqlCount, sqlPage;
BuildPageQueries<T>(skip, take, sql, ref args, out sqlCount, out sqlPage);
var result = Fetch<T>(sqlPage, args);
return result;
}
public List<T> SkipTake<T>(long skip, long take, Sql sql)
{
return SkipTake<T>(skip, take, sql.SQL, sql.Arguments);
}
// Return an enumerable collection of pocos // Return an enumerable collection of pocos
public IEnumerable<T> Query<T>(string sql, params object[] args) public IEnumerable<T> Query<T>(string sql, params object[] args)
{ {
@ -1213,6 +1242,38 @@ public bool Exists<T>(object primaryKey)
var primaryKeyValuePairs = GetPrimaryKeyValues(PocoData.ForType(typeof(T)).TableInfo.PrimaryKey, primaryKey); var primaryKeyValuePairs = GetPrimaryKeyValues(PocoData.ForType(typeof(T)).TableInfo.PrimaryKey, primaryKey);
return FirstOrDefault<T>(string.Format("WHERE {0}", BuildPrimaryKeySql(primaryKeyValuePairs, ref index)), primaryKeyValuePairs.Select(x => x.Value).ToArray()) != null; return FirstOrDefault<T>(string.Format("WHERE {0}", BuildPrimaryKeySql(primaryKeyValuePairs, ref index)), primaryKeyValuePairs.Select(x => x.Value).ToArray()) != null;
} }
public bool Exists<T>(string sql, params object[] args)
{
var poco = PocoData.ForType(typeof(T)).TableInfo;
string existsTemplate;
switch (_dbType)
{
case DBType.SQLite:
case DBType.MySql:
{
existsTemplate = "SELECT EXISTS (SELECT 1 FROM {0} WHERE {1})";
break;
}
case DBType.SqlServer:
{
existsTemplate = "IF EXISTS (SELECT 1 FROM {0} WHERE {1}) SELECT 1 ELSE SELECT 0";
break;
}
default:
{
existsTemplate = "SELECT COUNT(*) FROM {0} WHERE {1}";
break;
}
}
return ExecuteScalar<int>(string.Format(existsTemplate, poco.TableName, sql), args) != 0;
}
public T Single<T>(object primaryKey) public T Single<T>(object primaryKey)
{ {
var index = 0; var index = 0;
@ -1297,7 +1358,6 @@ public object Insert(string tableName, string primaryKeyName, bool autoIncrement
{ {
using (var cmd = CreateCommand(_sharedConnection, "")) using (var cmd = CreateCommand(_sharedConnection, ""))
{ {
var pd = PocoData.ForObject(poco, primaryKeyName); var pd = PocoData.ForObject(poco, primaryKeyName);
var names = new List<string>(); var names = new List<string>();
var values = new List<string>(); var values = new List<string>();
@ -1466,6 +1526,19 @@ public object Insert(object poco)
return Insert(pd.TableInfo.TableName, pd.TableInfo.PrimaryKey, pd.TableInfo.AutoIncrement, poco); return Insert(pd.TableInfo.TableName, pd.TableInfo.PrimaryKey, pd.TableInfo.AutoIncrement, poco);
} }
public void InsertMany<T>(IEnumerable<T> pocoList)
{
using (var tran = GetTransaction())
{
foreach (var poco in pocoList)
{
Insert(poco);
}
tran.Complete();
}
}
// Update a record with values from a poco. primary key value can be either supplied or read from the poco // Update a record with values from a poco. primary key value can be either supplied or read from the poco
public int Update(string tableName, string primaryKeyName, object poco, object primaryKeyValue) public int Update(string tableName, string primaryKeyName, object poco, object primaryKeyValue)
{ {
@ -1617,6 +1690,20 @@ public int Update<T>(Sql sql)
return Execute(new Sql(string.Format("UPDATE {0}", EscapeTableName(pd.TableInfo.TableName))).Append(sql)); return Execute(new Sql(string.Format("UPDATE {0}", EscapeTableName(pd.TableInfo.TableName))).Append(sql));
} }
public void UpdateMany<T>(IEnumerable<T> pocoList)
{
using (var tran = GetTransaction())
{
foreach (var poco in pocoList)
{
Update(poco);
}
tran.Complete();
}
}
public int Delete(string tableName, string primaryKeyName, object poco) public int Delete(string tableName, string primaryKeyName, object poco)
{ {
return Delete(tableName, primaryKeyName, poco, null); return Delete(tableName, primaryKeyName, poco, null);
@ -1747,6 +1834,19 @@ public void Save(object poco)
Save(pd.TableInfo.TableName, pd.TableInfo.PrimaryKey, poco); Save(pd.TableInfo.TableName, pd.TableInfo.PrimaryKey, poco);
} }
public void SaveMany<T>(IEnumerable<T> pocoList)
{
using (var tran = GetTransaction())
{
foreach (var poco in pocoList)
{
Save(poco);
}
tran.Complete();
}
}
public int CommandTimeout { get; set; } public int CommandTimeout { get; set; }
public int OneTimeCommandTimeout { get; set; } public int OneTimeCommandTimeout { get; set; }
@ -2269,7 +2369,12 @@ private static Func<object, object> GetConverter(bool forceDateTimesToUtc, PocoC
} }
// Transaction object helps maintain transaction depth counts // Transaction object helps maintain transaction depth counts
public class Transaction : IDisposable public interface ITransaction : IDisposable
{
void Complete();
}
public class Transaction : ITransaction
{ {
public Transaction(Database db) public Transaction(Database db)
{ {