|
|
|
@ -79,10 +79,13 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
private IDbCommand _deleteAncestorsCommand;
|
|
|
|
|
private IDbCommand _saveAncestorCommand;
|
|
|
|
|
|
|
|
|
|
private IDbCommand _deleteUserDataKeysCommand;
|
|
|
|
|
private IDbCommand _saveUserDataKeysCommand;
|
|
|
|
|
|
|
|
|
|
private IDbCommand _updateInheritedRatingCommand;
|
|
|
|
|
private IDbCommand _updateInheritedTagsCommand;
|
|
|
|
|
|
|
|
|
|
public const int LatestSchemaVersion = 73;
|
|
|
|
|
public const int LatestSchemaVersion = 76;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Initializes a new instance of the <see cref="SqliteItemRepository"/> class.
|
|
|
|
@ -135,15 +138,18 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
"create index if not exists idx_AncestorIds1 on AncestorIds(AncestorId)",
|
|
|
|
|
"create index if not exists idx_AncestorIds2 on AncestorIds(AncestorIdText)",
|
|
|
|
|
|
|
|
|
|
"create table if not exists UserDataKeys (ItemId GUID, UserDataKey TEXT, PRIMARY KEY (ItemId, UserDataKey))",
|
|
|
|
|
"create index if not exists idx_UserDataKeys1 on UserDataKeys(ItemId)",
|
|
|
|
|
|
|
|
|
|
"create table if not exists People (ItemId GUID, Name TEXT NOT NULL, Role TEXT, PersonType TEXT, SortOrder int, ListOrder int)",
|
|
|
|
|
"create index if not exists idxPeopleItemId on People(ItemId)",
|
|
|
|
|
"create index if not exists idxPeopleName on People(Name)",
|
|
|
|
|
|
|
|
|
|
"create table if not exists "+ChaptersTableName+" (ItemId GUID, ChapterIndex INT, StartPositionTicks BIGINT, Name TEXT, ImagePath TEXT, PRIMARY KEY (ItemId, ChapterIndex))",
|
|
|
|
|
"create index if not exists idx_"+ChaptersTableName+" on "+ChaptersTableName+"(ItemId, ChapterIndex)",
|
|
|
|
|
"create index if not exists idx_"+ChaptersTableName+"1 on "+ChaptersTableName+"(ItemId)",
|
|
|
|
|
|
|
|
|
|
createMediaStreamsTableCommand,
|
|
|
|
|
"create index if not exists idx_mediastreams on mediastreams(ItemId, StreamIndex)",
|
|
|
|
|
"create index if not exists idx_mediastreams1 on mediastreams(ItemId)",
|
|
|
|
|
|
|
|
|
|
//pragmas
|
|
|
|
|
"pragma temp_store = memory",
|
|
|
|
@ -229,6 +235,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
_connection.AddColumn(Logger, "TypedBaseItems", "SlugName", "Text");
|
|
|
|
|
_connection.AddColumn(Logger, "TypedBaseItems", "OriginalTitle", "Text");
|
|
|
|
|
_connection.AddColumn(Logger, "TypedBaseItems", "PrimaryVersionId", "Text");
|
|
|
|
|
_connection.AddColumn(Logger, "UserDataKeys", "Priority", "INT");
|
|
|
|
|
|
|
|
|
|
string[] postQueries =
|
|
|
|
|
{
|
|
|
|
@ -242,17 +249,13 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
|
|
|
|
|
new MediaStreamColumns(_connection, Logger).AddColumns();
|
|
|
|
|
|
|
|
|
|
var chapterDbFile = Path.Combine(_config.ApplicationPaths.DataPath, "chapters.db");
|
|
|
|
|
if (File.Exists(chapterDbFile))
|
|
|
|
|
{
|
|
|
|
|
MigrateChapters(chapterDbFile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var mediaStreamsDbFile = Path.Combine(_config.ApplicationPaths.DataPath, "mediainfo.db");
|
|
|
|
|
if (File.Exists(mediaStreamsDbFile))
|
|
|
|
|
{
|
|
|
|
|
MigrateMediaStreams(mediaStreamsDbFile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DataExtensions.Attach(_connection, Path.Combine(_config.ApplicationPaths.DataPath, "userdata_v2.db"), "UserDataDb");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void MigrateMediaStreams(string file)
|
|
|
|
@ -281,30 +284,6 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void MigrateChapters(string file)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var backupFile = file + ".bak";
|
|
|
|
|
File.Copy(file, backupFile, true);
|
|
|
|
|
DataExtensions.Attach(_connection, backupFile, "ChaptersOld");
|
|
|
|
|
|
|
|
|
|
string[] queries = {
|
|
|
|
|
"REPLACE INTO "+ChaptersTableName+"(ItemId, ChapterIndex, StartPositionTicks, Name, ImagePath) SELECT ItemId, ChapterIndex, StartPositionTicks, Name, ImagePath FROM ChaptersOld.Chapters;"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
_connection.RunQueries(queries, Logger);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Logger.ErrorException("Error migrating chapter database", ex);
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
TryDeleteFile(file);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void TryDeleteFile(string file)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
@ -569,6 +548,18 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
_updateInheritedTagsCommand.CommandText = "Update TypedBaseItems set InheritedTags=@InheritedTags where Guid=@Guid";
|
|
|
|
|
_updateInheritedTagsCommand.Parameters.Add(_updateInheritedTagsCommand, "@Guid");
|
|
|
|
|
_updateInheritedTagsCommand.Parameters.Add(_updateInheritedTagsCommand, "@InheritedTags");
|
|
|
|
|
|
|
|
|
|
// user data
|
|
|
|
|
_deleteUserDataKeysCommand = _connection.CreateCommand();
|
|
|
|
|
_deleteUserDataKeysCommand.CommandText = "delete from UserDataKeys where ItemId=@Id";
|
|
|
|
|
_deleteUserDataKeysCommand.Parameters.Add(_deleteUserDataKeysCommand, "@Id");
|
|
|
|
|
|
|
|
|
|
_saveUserDataKeysCommand = _connection.CreateCommand();
|
|
|
|
|
_saveUserDataKeysCommand.CommandText = "insert into UserDataKeys (ItemId, UserDataKey, Priority) values (@ItemId, @UserDataKey, @Priority)";
|
|
|
|
|
_saveUserDataKeysCommand.Parameters.Add(_saveUserDataKeysCommand, "@ItemId");
|
|
|
|
|
_saveUserDataKeysCommand.Parameters.Add(_saveUserDataKeysCommand, "@UserDataKey");
|
|
|
|
|
_saveUserDataKeysCommand.Parameters.Add(_saveUserDataKeysCommand, "@Priority");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@ -841,6 +832,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
{
|
|
|
|
|
UpdateAncestors(item.Id, item.GetAncestorIds().Distinct().ToList(), transaction);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UpdateUserDataKeys(item.Id, item.GetUserDataKeys(), transaction);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
transaction.Commit();
|
|
|
|
@ -1467,34 +1460,96 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IEnumerable<BaseItem> GetItemsOfType(Type type)
|
|
|
|
|
private bool EnableJoinUserData(InternalItemsQuery query)
|
|
|
|
|
{
|
|
|
|
|
if (type == null)
|
|
|
|
|
if (_config.Configuration.SchemaVersion < 76)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentNullException("type");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CheckDisposed();
|
|
|
|
|
if (query.User == null)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
using (var cmd = _connection.CreateCommand())
|
|
|
|
|
if (query.SortBy != null && query.SortBy.Length > 0)
|
|
|
|
|
{
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.IsFavoriteOrLiked, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.IsPlayed, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.IsUnplayed, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.PlayCount, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (query.SortBy.Contains(ItemSortBy.DatePlayed, StringComparer.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.IsFavoriteOrLiked.HasValue)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.IsFavorite.HasValue)
|
|
|
|
|
{
|
|
|
|
|
cmd.CommandText = "select " + string.Join(",", _retriveItemColumns) + " from TypedBaseItems where type = @type";
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cmd.Parameters.Add(cmd, "@type", DbType.String).Value = type.FullName;
|
|
|
|
|
if (query.IsResumable.HasValue)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
|
|
|
|
|
{
|
|
|
|
|
while (reader.Read())
|
|
|
|
|
{
|
|
|
|
|
var item = GetItem(reader);
|
|
|
|
|
if (query.IsPlayed.HasValue)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (item != null)
|
|
|
|
|
{
|
|
|
|
|
yield return item;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (query.IsLiked.HasValue)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private string[] GetFinalColumnsToSelect(InternalItemsQuery query, string[] startColumns)
|
|
|
|
|
{
|
|
|
|
|
var list = startColumns.ToList();
|
|
|
|
|
|
|
|
|
|
if (EnableJoinUserData(query))
|
|
|
|
|
{
|
|
|
|
|
list.Add("UserDataDb.UserData.UserId");
|
|
|
|
|
list.Add("UserDataDb.UserData.lastPlayedDate");
|
|
|
|
|
list.Add("UserDataDb.UserData.playbackPositionTicks");
|
|
|
|
|
list.Add("UserDataDb.UserData.playcount");
|
|
|
|
|
list.Add("UserDataDb.UserData.isFavorite");
|
|
|
|
|
list.Add("UserDataDb.UserData.played");
|
|
|
|
|
list.Add("UserDataDb.UserData.rating");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return list.ToArray();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private string GetJoinUserDataText(InternalItemsQuery query)
|
|
|
|
|
{
|
|
|
|
|
if (!EnableJoinUserData(query))
|
|
|
|
|
{
|
|
|
|
|
return string.Empty;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return " left join UserDataDb.UserData on (select UserDataKey from UserDataKeys where ItemId=Guid order by Priority LIMIT 1)=UserDataDb.UserData.Key";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IEnumerable<BaseItem> GetItemList(InternalItemsQuery query)
|
|
|
|
@ -1510,9 +1565,15 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
|
|
|
|
|
using (var cmd = _connection.CreateCommand())
|
|
|
|
|
{
|
|
|
|
|
cmd.CommandText = "select " + string.Join(",", _retriveItemColumns) + " from TypedBaseItems";
|
|
|
|
|
cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns)) + " from TypedBaseItems";
|
|
|
|
|
cmd.CommandText += GetJoinUserDataText(query);
|
|
|
|
|
|
|
|
|
|
if (EnableJoinUserData(query))
|
|
|
|
|
{
|
|
|
|
|
cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var whereClauses = GetWhereClauses(query, cmd, true);
|
|
|
|
|
var whereClauses = GetWhereClauses(query, cmd);
|
|
|
|
|
|
|
|
|
|
var whereText = whereClauses.Count == 0 ?
|
|
|
|
|
string.Empty :
|
|
|
|
@ -1527,14 +1588,21 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
|
|
|
|
|
cmd.CommandText += GetOrderByText(query);
|
|
|
|
|
|
|
|
|
|
if (query.Limit.HasValue)
|
|
|
|
|
if (query.Limit.HasValue || query.StartIndex.HasValue)
|
|
|
|
|
{
|
|
|
|
|
cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(CultureInfo.InvariantCulture);
|
|
|
|
|
var limit = query.Limit ?? int.MaxValue;
|
|
|
|
|
|
|
|
|
|
cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture);
|
|
|
|
|
|
|
|
|
|
if (query.StartIndex.HasValue)
|
|
|
|
|
{
|
|
|
|
|
cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
|
|
|
|
|
{
|
|
|
|
|
Logger.Debug("GetItemList query time: {0}ms. Query: {1}",
|
|
|
|
|
Logger.Debug("GetItemList query time: {0}ms. Query: {1}",
|
|
|
|
|
Convert.ToInt32((DateTime.UtcNow - now).TotalMilliseconds),
|
|
|
|
|
cmd.CommandText);
|
|
|
|
|
|
|
|
|
@ -1563,16 +1631,20 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
|
|
|
|
|
using (var cmd = _connection.CreateCommand())
|
|
|
|
|
{
|
|
|
|
|
cmd.CommandText = "select " + string.Join(",", _retriveItemColumns) + " from TypedBaseItems";
|
|
|
|
|
cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns)) + " from TypedBaseItems";
|
|
|
|
|
cmd.CommandText += GetJoinUserDataText(query);
|
|
|
|
|
|
|
|
|
|
if (EnableJoinUserData(query))
|
|
|
|
|
{
|
|
|
|
|
cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var whereClauses = GetWhereClauses(query, cmd, false);
|
|
|
|
|
var whereClauses = GetWhereClauses(query, cmd);
|
|
|
|
|
|
|
|
|
|
var whereTextWithoutPaging = whereClauses.Count == 0 ?
|
|
|
|
|
string.Empty :
|
|
|
|
|
" where " + string.Join(" AND ", whereClauses.ToArray());
|
|
|
|
|
|
|
|
|
|
whereClauses = GetWhereClauses(query, cmd, true);
|
|
|
|
|
|
|
|
|
|
var whereText = whereClauses.Count == 0 ?
|
|
|
|
|
string.Empty :
|
|
|
|
|
" where " + string.Join(" AND ", whereClauses.ToArray());
|
|
|
|
@ -1586,20 +1658,30 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
|
|
|
|
|
cmd.CommandText += GetOrderByText(query);
|
|
|
|
|
|
|
|
|
|
if (query.Limit.HasValue)
|
|
|
|
|
if (query.Limit.HasValue || query.StartIndex.HasValue)
|
|
|
|
|
{
|
|
|
|
|
cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(CultureInfo.InvariantCulture);
|
|
|
|
|
var limit = query.Limit ?? int.MaxValue;
|
|
|
|
|
|
|
|
|
|
cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture);
|
|
|
|
|
|
|
|
|
|
if (query.StartIndex.HasValue)
|
|
|
|
|
{
|
|
|
|
|
cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_config.Configuration.SchemaVersion >= 66)
|
|
|
|
|
if (EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66)
|
|
|
|
|
{
|
|
|
|
|
cmd.CommandText += "; select count (distinct PresentationUniqueKey) from TypedBaseItems" + whereTextWithoutPaging;
|
|
|
|
|
cmd.CommandText += "; select count (distinct PresentationUniqueKey) from TypedBaseItems";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
cmd.CommandText += "; select count (guid) from TypedBaseItems" + whereTextWithoutPaging;
|
|
|
|
|
cmd.CommandText += "; select count (guid) from TypedBaseItems";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cmd.CommandText += GetJoinUserDataText(query);
|
|
|
|
|
cmd.CommandText += whereTextWithoutPaging;
|
|
|
|
|
|
|
|
|
|
var list = new List<BaseItem>();
|
|
|
|
|
var count = 0;
|
|
|
|
|
|
|
|
|
@ -1639,32 +1721,64 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
return string.Empty;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var sortOrder = query.SortOrder == SortOrder.Descending ? "DESC" : "ASC";
|
|
|
|
|
var isAscending = query.SortOrder != SortOrder.Descending;
|
|
|
|
|
|
|
|
|
|
return " ORDER BY " + string.Join(",", query.SortBy.Select(i => MapOrderByField(i) + " " + sortOrder).ToArray());
|
|
|
|
|
return " ORDER BY " + string.Join(",", query.SortBy.Select(i =>
|
|
|
|
|
{
|
|
|
|
|
var columnMap = MapOrderByField(i);
|
|
|
|
|
var columnAscending = isAscending;
|
|
|
|
|
if (columnMap.Item2)
|
|
|
|
|
{
|
|
|
|
|
columnAscending = !columnAscending;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var sortOrder = columnAscending ? "ASC" : "DESC";
|
|
|
|
|
|
|
|
|
|
return columnMap.Item1 + " " + sortOrder;
|
|
|
|
|
}).ToArray());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private string MapOrderByField(string name)
|
|
|
|
|
private Tuple<string,bool> MapOrderByField(string name)
|
|
|
|
|
{
|
|
|
|
|
if (string.Equals(name, ItemSortBy.AirTime, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
// TODO
|
|
|
|
|
return "SortName";
|
|
|
|
|
return new Tuple<string, bool>("SortName", false);
|
|
|
|
|
}
|
|
|
|
|
if (string.Equals(name, ItemSortBy.Runtime, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
return "RuntimeTicks";
|
|
|
|
|
return new Tuple<string, bool>("RuntimeTicks", false);
|
|
|
|
|
}
|
|
|
|
|
if (string.Equals(name, ItemSortBy.Random, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
return new Tuple<string, bool>("RANDOM()", false);
|
|
|
|
|
}
|
|
|
|
|
if (string.Equals(name, ItemSortBy.DatePlayed, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
return new Tuple<string, bool>("LastPlayedDate", false);
|
|
|
|
|
}
|
|
|
|
|
if (string.Equals(name, ItemSortBy.PlayCount, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
return new Tuple<string, bool>("PlayCount", false);
|
|
|
|
|
}
|
|
|
|
|
if (string.Equals(name, ItemSortBy.IsFavoriteOrLiked, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
return new Tuple<string, bool>("IsFavorite", true);
|
|
|
|
|
}
|
|
|
|
|
if (string.Equals(name, ItemSortBy.IsFolder, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
return "IsFolder";
|
|
|
|
|
return new Tuple<string, bool>("IsFolder", true);
|
|
|
|
|
}
|
|
|
|
|
if (string.Equals(name, ItemSortBy.Random, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
if (string.Equals(name, ItemSortBy.IsPlayed, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
return new Tuple<string, bool>("played", true);
|
|
|
|
|
}
|
|
|
|
|
if (string.Equals(name, ItemSortBy.IsUnplayed, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
return "RANDOM()";
|
|
|
|
|
return new Tuple<string, bool>("played", false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return name;
|
|
|
|
|
return new Tuple<string, bool>(name, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public List<Guid> GetItemIdsList(InternalItemsQuery query)
|
|
|
|
@ -1680,9 +1794,15 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
|
|
|
|
|
using (var cmd = _connection.CreateCommand())
|
|
|
|
|
{
|
|
|
|
|
cmd.CommandText = "select guid from TypedBaseItems";
|
|
|
|
|
cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" })) + " from TypedBaseItems";
|
|
|
|
|
cmd.CommandText += GetJoinUserDataText(query);
|
|
|
|
|
|
|
|
|
|
if (EnableJoinUserData(query))
|
|
|
|
|
{
|
|
|
|
|
cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var whereClauses = GetWhereClauses(query, cmd, true);
|
|
|
|
|
var whereClauses = GetWhereClauses(query, cmd);
|
|
|
|
|
|
|
|
|
|
var whereText = whereClauses.Count == 0 ?
|
|
|
|
|
string.Empty :
|
|
|
|
@ -1697,9 +1817,16 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
|
|
|
|
|
cmd.CommandText += GetOrderByText(query);
|
|
|
|
|
|
|
|
|
|
if (query.Limit.HasValue)
|
|
|
|
|
if (query.Limit.HasValue || query.StartIndex.HasValue)
|
|
|
|
|
{
|
|
|
|
|
cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(CultureInfo.InvariantCulture);
|
|
|
|
|
var limit = query.Limit ?? int.MaxValue;
|
|
|
|
|
|
|
|
|
|
cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture);
|
|
|
|
|
|
|
|
|
|
if (query.StartIndex.HasValue)
|
|
|
|
|
{
|
|
|
|
|
cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var list = new List<Guid>();
|
|
|
|
@ -1733,14 +1860,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
{
|
|
|
|
|
cmd.CommandText = "select guid,path from TypedBaseItems";
|
|
|
|
|
|
|
|
|
|
var whereClauses = GetWhereClauses(query, cmd, false);
|
|
|
|
|
var whereClauses = GetWhereClauses(query, cmd);
|
|
|
|
|
|
|
|
|
|
var whereTextWithoutPaging = whereClauses.Count == 0 ?
|
|
|
|
|
string.Empty :
|
|
|
|
|
" where " + string.Join(" AND ", whereClauses.ToArray());
|
|
|
|
|
|
|
|
|
|
whereClauses = GetWhereClauses(query, cmd, true, false);
|
|
|
|
|
|
|
|
|
|
var whereText = whereClauses.Count == 0 ?
|
|
|
|
|
string.Empty :
|
|
|
|
|
" where " + string.Join(" AND ", whereClauses.ToArray());
|
|
|
|
@ -1754,9 +1879,16 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
|
|
|
|
|
cmd.CommandText += GetOrderByText(query);
|
|
|
|
|
|
|
|
|
|
if (query.Limit.HasValue)
|
|
|
|
|
if (query.Limit.HasValue || query.StartIndex.HasValue)
|
|
|
|
|
{
|
|
|
|
|
cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(CultureInfo.InvariantCulture);
|
|
|
|
|
var limit = query.Limit ?? int.MaxValue;
|
|
|
|
|
|
|
|
|
|
cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture);
|
|
|
|
|
|
|
|
|
|
if (query.StartIndex.HasValue)
|
|
|
|
|
{
|
|
|
|
|
cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cmd.CommandText += "; select count (guid) from TypedBaseItems" + whereTextWithoutPaging;
|
|
|
|
@ -1807,16 +1939,20 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
|
|
|
|
|
using (var cmd = _connection.CreateCommand())
|
|
|
|
|
{
|
|
|
|
|
cmd.CommandText = "select guid from TypedBaseItems";
|
|
|
|
|
cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" })) + " from TypedBaseItems";
|
|
|
|
|
|
|
|
|
|
var whereClauses = GetWhereClauses(query, cmd);
|
|
|
|
|
cmd.CommandText += GetJoinUserDataText(query);
|
|
|
|
|
|
|
|
|
|
var whereClauses = GetWhereClauses(query, cmd, false);
|
|
|
|
|
if (EnableJoinUserData(query))
|
|
|
|
|
{
|
|
|
|
|
cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var whereTextWithoutPaging = whereClauses.Count == 0 ?
|
|
|
|
|
string.Empty :
|
|
|
|
|
" where " + string.Join(" AND ", whereClauses.ToArray());
|
|
|
|
|
|
|
|
|
|
whereClauses = GetWhereClauses(query, cmd, true);
|
|
|
|
|
|
|
|
|
|
var whereText = whereClauses.Count == 0 ?
|
|
|
|
|
string.Empty :
|
|
|
|
|
" where " + string.Join(" AND ", whereClauses.ToArray());
|
|
|
|
@ -1830,20 +1966,30 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
|
|
|
|
|
cmd.CommandText += GetOrderByText(query);
|
|
|
|
|
|
|
|
|
|
if (query.Limit.HasValue)
|
|
|
|
|
if (query.Limit.HasValue || query.StartIndex.HasValue)
|
|
|
|
|
{
|
|
|
|
|
cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(CultureInfo.InvariantCulture);
|
|
|
|
|
var limit = query.Limit ?? int.MaxValue;
|
|
|
|
|
|
|
|
|
|
cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture);
|
|
|
|
|
|
|
|
|
|
if (query.StartIndex.HasValue)
|
|
|
|
|
{
|
|
|
|
|
cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66)
|
|
|
|
|
{
|
|
|
|
|
cmd.CommandText += "; select count (distinct PresentationUniqueKey) from TypedBaseItems" + whereTextWithoutPaging;
|
|
|
|
|
cmd.CommandText += "; select count (distinct PresentationUniqueKey) from TypedBaseItems";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
cmd.CommandText += "; select count (guid) from TypedBaseItems" + whereTextWithoutPaging;
|
|
|
|
|
cmd.CommandText += "; select count (guid) from TypedBaseItems";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cmd.CommandText += GetJoinUserDataText(query);
|
|
|
|
|
cmd.CommandText += whereTextWithoutPaging;
|
|
|
|
|
|
|
|
|
|
var list = new List<Guid>();
|
|
|
|
|
var count = 0;
|
|
|
|
|
|
|
|
|
@ -1872,7 +2018,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private List<string> GetWhereClauses(InternalItemsQuery query, IDbCommand cmd, bool addPaging, bool enablePresentationUniqueKey = true)
|
|
|
|
|
private List<string> GetWhereClauses(InternalItemsQuery query, IDbCommand cmd)
|
|
|
|
|
{
|
|
|
|
|
var whereClauses = new List<string>();
|
|
|
|
|
|
|
|
|
@ -2161,6 +2307,60 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
cmd.Parameters.Add(cmd, "@NameLessThan", DbType.String).Value = query.NameLessThan.ToLower();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.IsLiked.HasValue)
|
|
|
|
|
{
|
|
|
|
|
if (query.IsLiked.Value)
|
|
|
|
|
{
|
|
|
|
|
whereClauses.Add("rating>=@UserRating");
|
|
|
|
|
cmd.Parameters.Add(cmd, "@UserRating", DbType.Double).Value = UserItemData.MinLikeValue;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
whereClauses.Add("(rating is null or rating<@UserRating)");
|
|
|
|
|
cmd.Parameters.Add(cmd, "@UserRating", DbType.Double).Value = UserItemData.MinLikeValue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.IsFavoriteOrLiked.HasValue)
|
|
|
|
|
{
|
|
|
|
|
if (query.IsFavoriteOrLiked.Value)
|
|
|
|
|
{
|
|
|
|
|
whereClauses.Add("(IsFavorite=@IsFavoriteOrLiked or rating>=@UserRatingIsFavoriteOrLiked)");
|
|
|
|
|
cmd.Parameters.Add(cmd, "@IsFavoriteOrLiked", DbType.Boolean).Value = true;
|
|
|
|
|
cmd.Parameters.Add(cmd, "@UserRatingIsFavoriteOrLiked", DbType.Double).Value = UserItemData.MinLikeValue;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
whereClauses.Add("(IsFavorite=@IsFavoriteOrLiked or rating is null or rating<@UserRatingIsFavoriteOrLiked)");
|
|
|
|
|
cmd.Parameters.Add(cmd, "@IsFavoriteOrLiked", DbType.Boolean).Value = false;
|
|
|
|
|
cmd.Parameters.Add(cmd, "@UserRatingIsFavoriteOrLiked", DbType.Double).Value = UserItemData.MinLikeValue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.IsFavorite.HasValue)
|
|
|
|
|
{
|
|
|
|
|
whereClauses.Add("IsFavorite=@IsFavorite");
|
|
|
|
|
cmd.Parameters.Add(cmd, "@IsFavorite", DbType.Boolean).Value = query.IsFavorite.Value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.IsPlayed.HasValue)
|
|
|
|
|
{
|
|
|
|
|
whereClauses.Add("played=@IsPlayed");
|
|
|
|
|
cmd.Parameters.Add(cmd, "@IsPlayed", DbType.Boolean).Value = query.IsPlayed.Value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.IsResumable.HasValue)
|
|
|
|
|
{
|
|
|
|
|
if (query.IsResumable.Value)
|
|
|
|
|
{
|
|
|
|
|
whereClauses.Add("playbackPositionTicks > 0");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
whereClauses.Add("(playbackPositionTicks is null or playbackPositionTicks = 0)");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (query.Genres.Length > 0)
|
|
|
|
|
{
|
|
|
|
|
var clauses = new List<string>();
|
|
|
|
@ -2368,27 +2568,6 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
excludeTagIndex++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (addPaging)
|
|
|
|
|
{
|
|
|
|
|
if (query.StartIndex.HasValue && query.StartIndex.Value > 0)
|
|
|
|
|
{
|
|
|
|
|
var pagingWhereText = whereClauses.Count == 0 ?
|
|
|
|
|
string.Empty :
|
|
|
|
|
" where " + string.Join(" AND ", whereClauses.ToArray());
|
|
|
|
|
|
|
|
|
|
if (enablePresentationUniqueKey && EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66)
|
|
|
|
|
{
|
|
|
|
|
pagingWhereText += " Group by PresentationUniqueKey";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var orderBy = GetOrderByText(query);
|
|
|
|
|
|
|
|
|
|
whereClauses.Add(string.Format("guid NOT IN (SELECT guid FROM TypedBaseItems {0}" + orderBy + " LIMIT {1})",
|
|
|
|
|
pagingWhereText,
|
|
|
|
|
query.StartIndex.Value.ToString(CultureInfo.InvariantCulture)));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return whereClauses;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2694,6 +2873,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
_deleteAncestorsCommand.Transaction = transaction;
|
|
|
|
|
_deleteAncestorsCommand.ExecuteNonQuery();
|
|
|
|
|
|
|
|
|
|
// Delete user data keys
|
|
|
|
|
_deleteUserDataKeysCommand.GetParameter(0).Value = id;
|
|
|
|
|
_deleteUserDataKeysCommand.Transaction = transaction;
|
|
|
|
|
_deleteUserDataKeysCommand.ExecuteNonQuery();
|
|
|
|
|
|
|
|
|
|
// Delete the item
|
|
|
|
|
_deleteItemCommand.GetParameter(0).Value = id;
|
|
|
|
|
_deleteItemCommand.Transaction = transaction;
|
|
|
|
@ -2886,6 +3070,39 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void UpdateUserDataKeys(Guid itemId, List<string> keys, IDbTransaction transaction)
|
|
|
|
|
{
|
|
|
|
|
if (itemId == Guid.Empty)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentNullException("itemId");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (keys == null)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentNullException("keys");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CheckDisposed();
|
|
|
|
|
|
|
|
|
|
// First delete
|
|
|
|
|
_deleteUserDataKeysCommand.GetParameter(0).Value = itemId;
|
|
|
|
|
_deleteUserDataKeysCommand.Transaction = transaction;
|
|
|
|
|
|
|
|
|
|
_deleteUserDataKeysCommand.ExecuteNonQuery();
|
|
|
|
|
var index = 0;
|
|
|
|
|
|
|
|
|
|
foreach (var key in keys)
|
|
|
|
|
{
|
|
|
|
|
_saveUserDataKeysCommand.GetParameter(0).Value = itemId;
|
|
|
|
|
_saveUserDataKeysCommand.GetParameter(1).Value = key;
|
|
|
|
|
_saveUserDataKeysCommand.GetParameter(2).Value = index;
|
|
|
|
|
index++;
|
|
|
|
|
_saveUserDataKeysCommand.Transaction = transaction;
|
|
|
|
|
|
|
|
|
|
_saveUserDataKeysCommand.ExecuteNonQuery();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task UpdatePeople(Guid itemId, List<PersonInfo> people)
|
|
|
|
|
{
|
|
|
|
|
if (itemId == Guid.Empty)
|
|
|
|
|