Merge pull request #2339 from MediaBrowser/dev

Dev
This commit is contained in:
Luke 2016-12-12 14:40:54 -05:00 committed by GitHub
commit acf71527b5
9 changed files with 179 additions and 69 deletions

View File

@ -85,7 +85,7 @@ namespace Emby.Server.Implementations.Activity
using (var connection = CreateConnection(true)) using (var connection = CreateConnection(true))
{ {
var list = new List<ActivityLogEntry>(); var list = new List<ActivityLogEntry>();
int totalRecordCount = 0; var result = new QueryResult<ActivityLogEntry>();
var commandText = BaseActivitySelectText; var commandText = BaseActivitySelectText;
var whereClauses = new List<string>(); var whereClauses = new List<string>();
@ -151,15 +151,12 @@ namespace Emby.Server.Implementations.Activity
statement.TryBind("@DateCreated", minDate.Value.ToDateTimeParamValue()); statement.TryBind("@DateCreated", minDate.Value.ToDateTimeParamValue());
} }
totalRecordCount = statement.ExecuteQuery().SelectScalarInt().First(); result.TotalRecordCount = statement.ExecuteQuery().SelectScalarInt().First();
} }
}, ReadTransactionMode); }, ReadTransactionMode);
return new QueryResult<ActivityLogEntry>() result.Items = list.ToArray();
{ return result;
Items = list.ToArray(),
TotalRecordCount = totalRecordCount
};
} }
} }
} }

View File

@ -343,6 +343,9 @@ namespace Emby.Server.Implementations.Data
// series // series
"create index if not exists idx_TypeSeriesPresentationUniqueKey1 on TypedBaseItems(Type,SeriesPresentationUniqueKey,PresentationUniqueKey,SortName)", "create index if not exists idx_TypeSeriesPresentationUniqueKey1 on TypedBaseItems(Type,SeriesPresentationUniqueKey,PresentationUniqueKey,SortName)",
// series next up
"create index if not exists idx_SeriesPresentationUniqueKey on TypedBaseItems(SeriesPresentationUniqueKey)",
// live tv programs // live tv programs
"create index if not exists idx_TypeTopParentIdStartDate on TypedBaseItems(Type,TopParentId,StartDate)", "create index if not exists idx_TypeTopParentIdStartDate on TypedBaseItems(Type,TopParentId,StartDate)",
@ -2263,6 +2266,10 @@ namespace Emby.Server.Implementations.Data
{ {
return true; return true;
} }
if (sortingFields.Contains(ItemSortBy.SeriesDatePlayed, StringComparer.OrdinalIgnoreCase))
{
return true;
}
if (query.IsFavoriteOrLiked.HasValue) if (query.IsFavoriteOrLiked.HasValue)
{ {
@ -2436,6 +2443,66 @@ namespace Emby.Server.Implementations.Data
return " from TypedBaseItems " + alias; return " from TypedBaseItems " + alias;
} }
public int GetCount(InternalItemsQuery query)
{
if (query == null)
{
throw new ArgumentNullException("query");
}
CheckDisposed();
//Logger.Info("GetItemList: " + _environmentInfo.StackTrace);
var now = DateTime.UtcNow;
// Hack for right now since we currently don't support filtering out these duplicates within a query
if (query.Limit.HasValue && query.EnableGroupByMetadataKey)
{
query.Limit = query.Limit.Value + 4;
}
var commandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new [] { "count(distinct PresentationUniqueKey)" })) + GetFromText();
commandText += GetJoinUserDataText(query);
var whereClauses = GetWhereClauses(query, null);
var whereText = whereClauses.Count == 0 ?
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
commandText += whereText;
//commandText += GetGroupBy(query);
int count = 0;
using (WriteLock.Read())
{
using (var connection = CreateConnection(true))
{
using (var statement = PrepareStatementSafe(connection, commandText))
{
if (EnableJoinUserData(query))
{
statement.TryBind("@UserId", query.User.Id);
}
BindSimilarParams(query, statement);
// Running this again will bind the params
GetWhereClauses(query, statement);
count = statement.ExecuteQuery().SelectScalarInt().First();
}
}
LogQueryTime("GetCount", commandText, now);
}
return count;
}
public List<BaseItem> GetItemList(InternalItemsQuery query) public List<BaseItem> GetItemList(InternalItemsQuery query)
{ {
if (query == null) if (query == null)
@ -2656,7 +2723,7 @@ namespace Emby.Server.Implementations.Data
} }
} }
var totalRecordCount = 0; var result = new QueryResult<BaseItem>();
var isReturningZeroItems = query.Limit.HasValue && query.Limit <= 0; var isReturningZeroItems = query.Limit.HasValue && query.Limit <= 0;
var statementTexts = new List<string>(); var statementTexts = new List<string>();
@ -2714,23 +2781,23 @@ namespace Emby.Server.Implementations.Data
} }
} }
} }
}
if (query.EnableTotalRecordCount) if (query.EnableTotalRecordCount)
{
using (var statement = statements[statements.Count - 1])
{ {
using (var statement = statements[statements.Count - 1]) if (EnableJoinUserData(query))
{ {
if (EnableJoinUserData(query)) statement.TryBind("@UserId", query.User.Id);
{
statement.TryBind("@UserId", query.User.Id);
}
BindSimilarParams(query, statement);
// Running this again will bind the params
GetWhereClauses(query, statement);
totalRecordCount = statement.ExecuteQuery().SelectScalarInt().First();
} }
BindSimilarParams(query, statement);
// Running this again will bind the params
GetWhereClauses(query, statement);
result.TotalRecordCount = statement.ExecuteQuery().SelectScalarInt().First();
} }
} }
@ -2738,11 +2805,8 @@ namespace Emby.Server.Implementations.Data
LogQueryTime("GetItems", commandText, now); LogQueryTime("GetItems", commandText, now);
return new QueryResult<BaseItem>() result.Items = list.ToArray();
{ return result;
Items = list.ToArray(),
TotalRecordCount = totalRecordCount
};
} }
} }
} }
@ -2855,7 +2919,7 @@ namespace Emby.Server.Implementations.Data
} }
if (string.Equals(name, ItemSortBy.SeriesDatePlayed, StringComparison.OrdinalIgnoreCase)) if (string.Equals(name, ItemSortBy.SeriesDatePlayed, StringComparison.OrdinalIgnoreCase))
{ {
return new Tuple<string, bool>("(Select MAX(LastPlayedDate) from TypedBaseItems B" + GetJoinUserDataText(query) + " where B.Guid in (Select ItemId from AncestorIds where AncestorId in (select guid from typedbaseitems c where C.Type = 'MediaBrowser.Controller.Entities.TV.Series' And C.Guid in (Select AncestorId from AncestorIds where ItemId=A.Guid))))", false); return new Tuple<string, bool>("(Select MAX(LastPlayedDate) from TypedBaseItems B" + GetJoinUserDataText(query) + " where Played=1 and B.SeriesPresentationUniqueKey=A.PresentationUniqueKey)", false);
} }
return new Tuple<string, bool>(name, false); return new Tuple<string, bool>(name, false);
@ -3094,7 +3158,7 @@ namespace Emby.Server.Implementations.Data
{ {
using (var connection = CreateConnection(true)) using (var connection = CreateConnection(true))
{ {
var totalRecordCount = 0; var result = new QueryResult<Guid>();
connection.RunInTransaction(db => connection.RunInTransaction(db =>
{ {
@ -3136,7 +3200,7 @@ namespace Emby.Server.Implementations.Data
// Running this again will bind the params // Running this again will bind the params
GetWhereClauses(query, statement); GetWhereClauses(query, statement);
totalRecordCount = statement.ExecuteQuery().SelectScalarInt().First(); result.TotalRecordCount = statement.ExecuteQuery().SelectScalarInt().First();
} }
} }
@ -3144,11 +3208,8 @@ namespace Emby.Server.Implementations.Data
LogQueryTime("GetItemIds", commandText, now); LogQueryTime("GetItemIds", commandText, now);
return new QueryResult<Guid>() result.Items = list.ToArray();
{ return result;
Items = list.ToArray(),
TotalRecordCount = totalRecordCount
};
} }
} }
} }
@ -5026,7 +5087,7 @@ namespace Emby.Server.Implementations.Data
var isReturningZeroItems = query.Limit.HasValue && query.Limit <= 0; var isReturningZeroItems = query.Limit.HasValue && query.Limit <= 0;
var list = new List<Tuple<BaseItem, ItemCounts>>(); var list = new List<Tuple<BaseItem, ItemCounts>>();
var count = 0; var result = new QueryResult<Tuple<BaseItem, ItemCounts>>();
var statementTexts = new List<string>(); var statementTexts = new List<string>();
if (!isReturningZeroItems) if (!isReturningZeroItems)
@ -5106,7 +5167,7 @@ namespace Emby.Server.Implementations.Data
GetWhereClauses(innerQuery, statement); GetWhereClauses(innerQuery, statement);
GetWhereClauses(outerQuery, statement); GetWhereClauses(outerQuery, statement);
count = statement.ExecuteQuery().SelectScalarInt().First(); result.TotalRecordCount = statement.ExecuteQuery().SelectScalarInt().First();
LogQueryTime("GetItemValues", commandText, now); LogQueryTime("GetItemValues", commandText, now);
} }
@ -5115,16 +5176,13 @@ namespace Emby.Server.Implementations.Data
} }
} }
if (count == 0) if (result.TotalRecordCount == 0)
{ {
count = list.Count; result.TotalRecordCount = list.Count;
} }
result.Items = list.ToArray();
return new QueryResult<Tuple<BaseItem, ItemCounts>> return result;
{
Items = list.ToArray(),
TotalRecordCount = count
};
} }
private ItemCounts GetItemCounts(IReadOnlyList<IResultSetValue> reader, int countStartColumn, List<string> typesToCount) private ItemCounts GetItemCounts(IReadOnlyList<IResultSetValue> reader, int countStartColumn, List<string> typesToCount)

View File

@ -1279,6 +1279,26 @@ namespace Emby.Server.Implementations.Library
return ItemRepository.GetItemList(query); return ItemRepository.GetItemList(query);
} }
public int GetCount(InternalItemsQuery query)
{
if (query.Recursive && query.ParentId.HasValue)
{
var parent = GetItemById(query.ParentId.Value);
if (parent != null)
{
SetTopParentIdsOrAncestors(query, new List<BaseItem> { parent });
query.ParentId = null;
}
}
if (query.User != null)
{
AddUserToQuery(query, query.User);
}
return ItemRepository.GetCount(query);
}
public IEnumerable<BaseItem> GetItemList(InternalItemsQuery query, List<BaseItem> parents) public IEnumerable<BaseItem> GetItemList(InternalItemsQuery query, List<BaseItem> parents)
{ {
SetTopParentIdsOrAncestors(query, parents); SetTopParentIdsOrAncestors(query, parents);

View File

@ -201,12 +201,13 @@ namespace Emby.Server.Implementations.Security
} }
var list = new List<AuthenticationInfo>(); var list = new List<AuthenticationInfo>();
int totalRecordCount = 0;
using (WriteLock.Read()) using (WriteLock.Read())
{ {
using (var connection = CreateConnection(true)) using (var connection = CreateConnection(true))
{ {
var result = new QueryResult<AuthenticationInfo>();
connection.RunInTransaction(db => connection.RunInTransaction(db =>
{ {
var statementTexts = new List<string>(); var statementTexts = new List<string>();
@ -229,7 +230,7 @@ namespace Emby.Server.Implementations.Security
{ {
BindAuthenticationQueryParams(query, totalCountStatement); BindAuthenticationQueryParams(query, totalCountStatement);
totalRecordCount = totalCountStatement.ExecuteQuery() result.TotalRecordCount = totalCountStatement.ExecuteQuery()
.SelectScalarInt() .SelectScalarInt()
.First(); .First();
} }
@ -237,11 +238,8 @@ namespace Emby.Server.Implementations.Security
}, ReadTransactionMode); }, ReadTransactionMode);
return new QueryResult<AuthenticationInfo>() result.Items = list.ToArray();
{ return result;
Items = list.ToArray(),
TotalRecordCount = totalRecordCount
};
} }
} }
} }

View File

@ -58,7 +58,8 @@ namespace Emby.Server.Implementations.TV
var items = _libraryManager.GetItemList(new InternalItemsQuery(user) var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
{ {
IncludeItemTypes = new[] { typeof(Series).Name }, IncludeItemTypes = new[] { typeof(Series).Name },
SortOrder = SortOrder.Ascending, SortBy = new[] { ItemSortBy.SeriesDatePlayed },
SortOrder = SortOrder.Descending,
PresentationUniqueKey = presentationUniqueKey, PresentationUniqueKey = presentationUniqueKey,
Limit = limit, Limit = limit,
ParentId = parentIdGuid, ParentId = parentIdGuid,
@ -71,7 +72,7 @@ namespace Emby.Server.Implementations.TV
} }
} }
}).Cast<Series>(); }).Cast<Series>().Select(GetUniqueSeriesKey);
// Avoid implicitly captured closure // Avoid implicitly captured closure
var episodes = GetNextUpEpisodes(request, user, items); var episodes = GetNextUpEpisodes(request, user, items);
@ -109,7 +110,8 @@ namespace Emby.Server.Implementations.TV
var items = _libraryManager.GetItemList(new InternalItemsQuery(user) var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
{ {
IncludeItemTypes = new[] { typeof(Series).Name }, IncludeItemTypes = new[] { typeof(Series).Name },
SortOrder = SortOrder.Ascending, SortBy = new[] { ItemSortBy.SeriesDatePlayed },
SortOrder = SortOrder.Descending,
PresentationUniqueKey = presentationUniqueKey, PresentationUniqueKey = presentationUniqueKey,
Limit = limit, Limit = limit,
DtoOptions = new MediaBrowser.Controller.Dto.DtoOptions DtoOptions = new MediaBrowser.Controller.Dto.DtoOptions
@ -121,7 +123,7 @@ namespace Emby.Server.Implementations.TV
EnableImages = false EnableImages = false
} }
}, parentsFolders.Cast<BaseItem>().ToList()).Cast<Series>(); }, parentsFolders.Cast<BaseItem>().ToList()).Cast<Series>().Select(GetUniqueSeriesKey);
// Avoid implicitly captured closure // Avoid implicitly captured closure
var episodes = GetNextUpEpisodes(request, user, items); var episodes = GetNextUpEpisodes(request, user, items);
@ -129,15 +131,15 @@ namespace Emby.Server.Implementations.TV
return GetResult(episodes, null, request); return GetResult(episodes, null, request);
} }
public IEnumerable<Episode> GetNextUpEpisodes(NextUpQuery request, User user, IEnumerable<Series> series) public IEnumerable<Episode> GetNextUpEpisodes(NextUpQuery request, User user, IEnumerable<string> seriesKeys)
{ {
// Avoid implicitly captured closure // Avoid implicitly captured closure
var currentUser = user; var currentUser = user;
var allNextUp = series var allNextUp = seriesKeys
.Select(i => GetNextUp(GetUniqueSeriesKey(i), currentUser)) .Select(i => GetNextUp(i, currentUser));
// Include if an episode was found, and either the series is not unwatched or the specific series was requested
.OrderByDescending(i => i.Item1); //allNextUp = allNextUp.OrderByDescending(i => i.Item1);
// If viewing all next up for all series, remove first episodes // If viewing all next up for all series, remove first episodes
// But if that returns empty, keep those first episodes (avoid completely empty view) // But if that returns empty, keep those first episodes (avoid completely empty view)
@ -160,7 +162,6 @@ namespace Emby.Server.Implementations.TV
return true; return true;
}) })
.Take(request.Limit.HasValue ? (request.Limit.Value * 2) : int.MaxValue)
.Select(i => i.Item2()) .Select(i => i.Item2())
.Where(i => i != null) .Where(i => i != null)
.Take(request.Limit ?? int.MaxValue); .Take(request.Limit ?? int.MaxValue);

View File

@ -138,16 +138,24 @@ namespace MediaBrowser.Controller.Entities.TV
var enableSeriesPresentationKey = ConfigurationManager.Configuration.EnableSeriesPresentationUniqueKey; var enableSeriesPresentationKey = ConfigurationManager.Configuration.EnableSeriesPresentationUniqueKey;
var seriesKey = GetUniqueSeriesKey(this); var seriesKey = GetUniqueSeriesKey(this);
var result = LibraryManager.GetItemsResult(new InternalItemsQuery(user) var result = LibraryManager.GetCount(new InternalItemsQuery(user)
{ {
AncestorWithPresentationUniqueKey = enableSeriesPresentationKey ? null : seriesKey, AncestorWithPresentationUniqueKey = enableSeriesPresentationKey ? null : seriesKey,
SeriesPresentationUniqueKey = enableSeriesPresentationKey ? seriesKey : null, SeriesPresentationUniqueKey = enableSeriesPresentationKey ? seriesKey : null,
IncludeItemTypes = new[] { typeof(Season).Name }, IncludeItemTypes = new[] { typeof(Season).Name },
IsVirtualItem = false, IsVirtualItem = false,
Limit = 0 Limit = 0,
DtoOptions = new Dto.DtoOptions
{
Fields = new List<ItemFields>
{
},
EnableImages = false
}
}); });
return result.TotalRecordCount; return result;
} }
public override int GetRecursiveChildCount(User user) public override int GetRecursiveChildCount(User user)
@ -159,19 +167,25 @@ namespace MediaBrowser.Controller.Entities.TV
{ {
AncestorWithPresentationUniqueKey = enableSeriesPresentationKey ? null : seriesKey, AncestorWithPresentationUniqueKey = enableSeriesPresentationKey ? null : seriesKey,
SeriesPresentationUniqueKey = enableSeriesPresentationKey ? seriesKey : null, SeriesPresentationUniqueKey = enableSeriesPresentationKey ? seriesKey : null,
DtoOptions = new Dto.DtoOptions
{
Fields = new List<ItemFields>
{
},
EnableImages = false
}
}; };
if (query.SortBy.Length == 0)
{
query.SortBy = new[] { ItemSortBy.SortName };
}
if (query.IncludeItemTypes.Length == 0) if (query.IncludeItemTypes.Length == 0)
{ {
query.IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name }; query.IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name };
} }
query.IsVirtualItem = false; query.IsVirtualItem = false;
query.Limit = 0; query.Limit = 0;
return LibraryManager.GetItemsResult(query).TotalRecordCount; var totalRecordCount = LibraryManager.GetCount(query);
return totalRecordCount;
} }
/// <summary> /// <summary>

View File

@ -571,5 +571,6 @@ namespace MediaBrowser.Controller.Library
void RegisterIgnoredPath(string path); void RegisterIgnoredPath(string path);
void UnRegisterIgnoredPath(string path); void UnRegisterIgnoredPath(string path);
int GetCount(InternalItemsQuery query);
} }
} }

View File

@ -163,6 +163,8 @@ namespace MediaBrowser.Controller.Persistence
/// <returns>Task.</returns> /// <returns>Task.</returns>
Task UpdateInheritedValues(CancellationToken cancellationToken); Task UpdateInheritedValues(CancellationToken cancellationToken);
int GetCount(InternalItemsQuery query);
QueryResult<Tuple<BaseItem, ItemCounts>> GetGenres(InternalItemsQuery query); QueryResult<Tuple<BaseItem, ItemCounts>> GetGenres(InternalItemsQuery query);
QueryResult<Tuple<BaseItem, ItemCounts>> GetMusicGenres(InternalItemsQuery query); QueryResult<Tuple<BaseItem, ItemCounts>> GetMusicGenres(InternalItemsQuery query);
QueryResult<Tuple<BaseItem, ItemCounts>> GetGameGenres(InternalItemsQuery query); QueryResult<Tuple<BaseItem, ItemCounts>> GetGameGenres(InternalItemsQuery query);

View File

@ -18,6 +18,25 @@
"SQLitePCLRaw.provider.sqlite3.netstandard11": "1.1.1-pre20161109081005" "SQLitePCLRaw.provider.sqlite3.netstandard11": "1.1.1-pre20161109081005"
}, },
"runtimes": {
"win7-x86": {},
"win7-x64": {},
"win8-x86": {},
"win8-x64": {},
"win8-arm": {},
"win81-x86": {},
"win81-x64": {},
"win81-arm": {},
"win10-x86": {},
"win10-x64": {},
"win10-arm": {},
"win10-arm64": {},
"osx.10.10-x64": {},
"osx.10.11-x64": {},
"osx.10.12-x64": {},
"ubuntu.14.04-x64": {}
},
"frameworks": { "frameworks": {
"netcoreapp1.1": { "netcoreapp1.1": {
"imports": "dnxcore50", "imports": "dnxcore50",