|
@@ -219,7 +219,8 @@ namespace Emby.Server.Implementations.Data
|
|
{
|
|
{
|
|
connection.RunQueries(queries);
|
|
connection.RunQueries(queries);
|
|
|
|
|
|
- connection.RunInTransaction(db =>
|
|
|
|
|
|
+ connection.RunInTransaction(
|
|
|
|
+ db =>
|
|
{
|
|
{
|
|
var existingColumnNames = GetColumnNames(db, "AncestorIds");
|
|
var existingColumnNames = GetColumnNames(db, "AncestorIds");
|
|
AddColumn(db, "AncestorIds", "AncestorIdText", "Text", existingColumnNames);
|
|
AddColumn(db, "AncestorIds", "AncestorIdText", "Text", existingColumnNames);
|
|
@@ -495,7 +496,8 @@ namespace Emby.Server.Implementations.Data
|
|
|
|
|
|
using (var connection = GetConnection())
|
|
using (var connection = GetConnection())
|
|
{
|
|
{
|
|
- connection.RunInTransaction(db =>
|
|
|
|
|
|
+ connection.RunInTransaction(
|
|
|
|
+ db =>
|
|
{
|
|
{
|
|
using (var saveImagesStatement = base.PrepareStatement(db, "Update TypedBaseItems set Images=@Images where guid=@Id"))
|
|
using (var saveImagesStatement = base.PrepareStatement(db, "Update TypedBaseItems set Images=@Images where guid=@Id"))
|
|
{
|
|
{
|
|
@@ -546,7 +548,8 @@ namespace Emby.Server.Implementations.Data
|
|
|
|
|
|
using (var connection = GetConnection())
|
|
using (var connection = GetConnection())
|
|
{
|
|
{
|
|
- connection.RunInTransaction(db =>
|
|
|
|
|
|
+ connection.RunInTransaction(
|
|
|
|
+ db =>
|
|
{
|
|
{
|
|
SaveItemsInTranscation(db, tuples);
|
|
SaveItemsInTranscation(db, tuples);
|
|
}, TransactionMode);
|
|
}, TransactionMode);
|
|
@@ -2032,7 +2035,8 @@ namespace Emby.Server.Implementations.Data
|
|
|
|
|
|
using (var connection = GetConnection())
|
|
using (var connection = GetConnection())
|
|
{
|
|
{
|
|
- connection.RunInTransaction(db =>
|
|
|
|
|
|
+ connection.RunInTransaction(
|
|
|
|
+ db =>
|
|
{
|
|
{
|
|
// First delete chapters
|
|
// First delete chapters
|
|
db.Execute("delete from " + ChaptersTableName + " where ItemId=@ItemId", idBlob);
|
|
db.Execute("delete from " + ChaptersTableName + " where ItemId=@ItemId", idBlob);
|
|
@@ -2399,11 +2403,11 @@ namespace Emby.Server.Implementations.Data
|
|
|
|
|
|
if (string.IsNullOrEmpty(item.OfficialRating))
|
|
if (string.IsNullOrEmpty(item.OfficialRating))
|
|
{
|
|
{
|
|
- builder.Append("((OfficialRating is null) * 10)");
|
|
|
|
|
|
+ builder.Append("(OfficialRating is null * 10)");
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
- builder.Append("((OfficialRating=@ItemOfficialRating) * 10)");
|
|
|
|
|
|
+ builder.Append("(OfficialRating=@ItemOfficialRating * 10)");
|
|
}
|
|
}
|
|
|
|
|
|
if (item.ProductionYear.HasValue)
|
|
if (item.ProductionYear.HasValue)
|
|
@@ -2412,8 +2416,26 @@ namespace Emby.Server.Implementations.Data
|
|
builder.Append("+(Select Case When Abs(COALESCE(ProductionYear, 0) - @ItemProductionYear) < 5 Then 5 Else 0 End )");
|
|
builder.Append("+(Select Case When Abs(COALESCE(ProductionYear, 0) - @ItemProductionYear) < 5 Then 5 Else 0 End )");
|
|
}
|
|
}
|
|
|
|
|
|
- //// genres, tags
|
|
|
|
- builder.Append("+ ((Select count(CleanValue) from ItemValues where ItemId=Guid and CleanValue in (select CleanValue from itemvalues where ItemId=@SimilarItemId)) * 10)");
|
|
|
|
|
|
+ // genres, tags, studios, person, year?
|
|
|
|
+ builder.Append("+ (Select count(1) * 10 from ItemValues where ItemId=Guid and CleanValue in (select CleanValue from itemvalues where ItemId=@SimilarItemId))");
|
|
|
|
+
|
|
|
|
+ if (item is MusicArtist)
|
|
|
|
+ {
|
|
|
|
+ // Match albums where the artist is AlbumArtist against other albums.
|
|
|
|
+ // It is assumed that similar albums => similar artists.
|
|
|
|
+ builder.Append(
|
|
|
|
+ @"+ (WITH artistValues AS (
|
|
|
|
+ SELECT DISTINCT albumValues.CleanValue
|
|
|
|
+ FROM ItemValues albumValues
|
|
|
|
+ INNER JOIN ItemValues artistAlbums ON albumValues.ItemId = artistAlbums.ItemId
|
|
|
|
+ INNER JOIN TypedBaseItems artistItem ON artistAlbums.CleanValue = artistItem.CleanName AND artistAlbums.TYPE = 1 AND artistItem.Guid = @SimilarItemId
|
|
|
|
+ ), similarArtist AS (
|
|
|
|
+ SELECT albumValues.ItemId
|
|
|
|
+ FROM ItemValues albumValues
|
|
|
|
+ INNER JOIN ItemValues artistAlbums ON albumValues.ItemId = artistAlbums.ItemId
|
|
|
|
+ INNER JOIN TypedBaseItems artistItem ON artistAlbums.CleanValue = artistItem.CleanName AND artistAlbums.TYPE = 1 AND artistItem.Guid = A.Guid
|
|
|
|
+ ) SELECT COUNT(DISTINCT(CleanValue)) * 10 FROM ItemValues WHERE ItemId IN (SELECT ItemId FROM similarArtist) AND CleanValue IN (SELECT CleanValue FROM artistValues))");
|
|
|
|
+ }
|
|
|
|
|
|
builder.Append(") as SimilarityScore");
|
|
builder.Append(") as SimilarityScore");
|
|
|
|
|
|
@@ -2921,7 +2943,8 @@ namespace Emby.Server.Implementations.Data
|
|
var result = new QueryResult<BaseItem>();
|
|
var result = new QueryResult<BaseItem>();
|
|
using (var connection = GetConnection(true))
|
|
using (var connection = GetConnection(true))
|
|
{
|
|
{
|
|
- connection.RunInTransaction(db =>
|
|
|
|
|
|
+ connection.RunInTransaction(
|
|
|
|
+ db =>
|
|
{
|
|
{
|
|
var statements = PrepareAll(db, statementTexts);
|
|
var statements = PrepareAll(db, statementTexts);
|
|
|
|
|
|
@@ -3324,7 +3347,8 @@ namespace Emby.Server.Implementations.Data
|
|
var result = new QueryResult<Guid>();
|
|
var result = new QueryResult<Guid>();
|
|
using (var connection = GetConnection(true))
|
|
using (var connection = GetConnection(true))
|
|
{
|
|
{
|
|
- connection.RunInTransaction(db =>
|
|
|
|
|
|
+ connection.RunInTransaction(
|
|
|
|
+ db =>
|
|
{
|
|
{
|
|
var statements = PrepareAll(db, statementTexts);
|
|
var statements = PrepareAll(db, statementTexts);
|
|
|
|
|
|
@@ -3908,7 +3932,7 @@ namespace Emby.Server.Implementations.Data
|
|
if (query.IsPlayed.HasValue)
|
|
if (query.IsPlayed.HasValue)
|
|
{
|
|
{
|
|
// We should probably figure this out for all folders, but for right now, this is the only place where we need it
|
|
// We should probably figure this out for all folders, but for right now, this is the only place where we need it
|
|
- if (query.IncludeItemTypes.Length == 1 && string.Equals(query.IncludeItemTypes[0], typeof(Series).Name, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
|
+ if (query.IncludeItemTypes.Length == 1 && string.Equals(query.IncludeItemTypes[0], nameof(Series), StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
{
|
|
if (query.IsPlayed.Value)
|
|
if (query.IsPlayed.Value)
|
|
{
|
|
{
|
|
@@ -4749,29 +4773,29 @@ namespace Emby.Server.Implementations.Data
|
|
{
|
|
{
|
|
var list = new List<string>();
|
|
var list = new List<string>();
|
|
|
|
|
|
- if (IsTypeInQuery(typeof(Person).Name, query))
|
|
|
|
|
|
+ if (IsTypeInQuery(nameof(Person), query))
|
|
{
|
|
{
|
|
- list.Add(typeof(Person).Name);
|
|
|
|
|
|
+ list.Add(nameof(Person));
|
|
}
|
|
}
|
|
|
|
|
|
- if (IsTypeInQuery(typeof(Genre).Name, query))
|
|
|
|
|
|
+ if (IsTypeInQuery(nameof(Genre), query))
|
|
{
|
|
{
|
|
- list.Add(typeof(Genre).Name);
|
|
|
|
|
|
+ list.Add(nameof(Genre));
|
|
}
|
|
}
|
|
|
|
|
|
- if (IsTypeInQuery(typeof(MusicGenre).Name, query))
|
|
|
|
|
|
+ if (IsTypeInQuery(nameof(MusicGenre), query))
|
|
{
|
|
{
|
|
- list.Add(typeof(MusicGenre).Name);
|
|
|
|
|
|
+ list.Add(nameof(MusicGenre));
|
|
}
|
|
}
|
|
|
|
|
|
- if (IsTypeInQuery(typeof(MusicArtist).Name, query))
|
|
|
|
|
|
+ if (IsTypeInQuery(nameof(MusicArtist), query))
|
|
{
|
|
{
|
|
- list.Add(typeof(MusicArtist).Name);
|
|
|
|
|
|
+ list.Add(nameof(MusicArtist));
|
|
}
|
|
}
|
|
|
|
|
|
- if (IsTypeInQuery(typeof(Studio).Name, query))
|
|
|
|
|
|
+ if (IsTypeInQuery(nameof(Studio), query))
|
|
{
|
|
{
|
|
- list.Add(typeof(Studio).Name);
|
|
|
|
|
|
+ list.Add(nameof(Studio));
|
|
}
|
|
}
|
|
|
|
|
|
return list;
|
|
return list;
|
|
@@ -4826,12 +4850,12 @@ namespace Emby.Server.Implementations.Data
|
|
|
|
|
|
var types = new[]
|
|
var types = new[]
|
|
{
|
|
{
|
|
- typeof(Episode).Name,
|
|
|
|
- typeof(Video).Name,
|
|
|
|
- typeof(Movie).Name,
|
|
|
|
- typeof(MusicVideo).Name,
|
|
|
|
- typeof(Series).Name,
|
|
|
|
- typeof(Season).Name
|
|
|
|
|
|
+ nameof(Episode),
|
|
|
|
+ nameof(Video),
|
|
|
|
+ nameof(Movie),
|
|
|
|
+ nameof(MusicVideo),
|
|
|
|
+ nameof(Series),
|
|
|
|
+ nameof(Season)
|
|
};
|
|
};
|
|
|
|
|
|
if (types.Any(i => query.IncludeItemTypes.Contains(i, StringComparer.OrdinalIgnoreCase)))
|
|
if (types.Any(i => query.IncludeItemTypes.Contains(i, StringComparer.OrdinalIgnoreCase)))
|
|
@@ -4899,7 +4923,8 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
|
|
|
|
|
using (var connection = GetConnection())
|
|
using (var connection = GetConnection())
|
|
{
|
|
{
|
|
- connection.RunInTransaction(db =>
|
|
|
|
|
|
+ connection.RunInTransaction(
|
|
|
|
+ db =>
|
|
{
|
|
{
|
|
connection.ExecuteAll(sql);
|
|
connection.ExecuteAll(sql);
|
|
}, TransactionMode);
|
|
}, TransactionMode);
|
|
@@ -4950,7 +4975,8 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
|
|
|
|
|
using (var connection = GetConnection())
|
|
using (var connection = GetConnection())
|
|
{
|
|
{
|
|
- connection.RunInTransaction(db =>
|
|
|
|
|
|
+ connection.RunInTransaction(
|
|
|
|
+ db =>
|
|
{
|
|
{
|
|
var idBlob = id.ToByteArray();
|
|
var idBlob = id.ToByteArray();
|
|
|
|
|
|
@@ -4994,26 +5020,33 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
|
|
|
|
|
CheckDisposed();
|
|
CheckDisposed();
|
|
|
|
|
|
- var commandText = "select Distinct Name from People";
|
|
|
|
|
|
+ var commandText = new StringBuilder("select Distinct p.Name from People p");
|
|
|
|
+
|
|
|
|
+ if (query.User != null && query.IsFavorite.HasValue)
|
|
|
|
+ {
|
|
|
|
+ commandText.Append(" LEFT JOIN TypedBaseItems tbi ON tbi.Name=p.Name AND tbi.Type='");
|
|
|
|
+ commandText.Append(typeof(Person).FullName);
|
|
|
|
+ commandText.Append("' LEFT JOIN UserDatas ON tbi.UserDataKey=key AND userId=@UserId");
|
|
|
|
+ }
|
|
|
|
|
|
var whereClauses = GetPeopleWhereClauses(query, null);
|
|
var whereClauses = GetPeopleWhereClauses(query, null);
|
|
|
|
|
|
if (whereClauses.Count != 0)
|
|
if (whereClauses.Count != 0)
|
|
{
|
|
{
|
|
- commandText += " where " + string.Join(" AND ", whereClauses);
|
|
|
|
|
|
+ commandText.Append(" where ").Append(string.Join(" AND ", whereClauses));
|
|
}
|
|
}
|
|
|
|
|
|
- commandText += " order by ListOrder";
|
|
|
|
|
|
+ commandText.Append(" order by ListOrder");
|
|
|
|
|
|
if (query.Limit > 0)
|
|
if (query.Limit > 0)
|
|
{
|
|
{
|
|
- commandText += " LIMIT " + query.Limit;
|
|
|
|
|
|
+ commandText.Append(" LIMIT ").Append(query.Limit);
|
|
}
|
|
}
|
|
|
|
|
|
using (var connection = GetConnection(true))
|
|
using (var connection = GetConnection(true))
|
|
{
|
|
{
|
|
var list = new List<string>();
|
|
var list = new List<string>();
|
|
- using (var statement = PrepareStatement(connection, commandText))
|
|
|
|
|
|
+ using (var statement = PrepareStatement(connection, commandText.ToString()))
|
|
{
|
|
{
|
|
// Run this again to bind the params
|
|
// Run this again to bind the params
|
|
GetPeopleWhereClauses(query, statement);
|
|
GetPeopleWhereClauses(query, statement);
|
|
@@ -5037,7 +5070,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
|
|
|
|
|
CheckDisposed();
|
|
CheckDisposed();
|
|
|
|
|
|
- var commandText = "select ItemId, Name, Role, PersonType, SortOrder from People";
|
|
|
|
|
|
+ var commandText = "select ItemId, Name, Role, PersonType, SortOrder from People p";
|
|
|
|
|
|
var whereClauses = GetPeopleWhereClauses(query, null);
|
|
var whereClauses = GetPeopleWhereClauses(query, null);
|
|
|
|
|
|
@@ -5079,19 +5112,13 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
|
if (!query.ItemId.Equals(Guid.Empty))
|
|
if (!query.ItemId.Equals(Guid.Empty))
|
|
{
|
|
{
|
|
whereClauses.Add("ItemId=@ItemId");
|
|
whereClauses.Add("ItemId=@ItemId");
|
|
- if (statement != null)
|
|
|
|
- {
|
|
|
|
- statement.TryBind("@ItemId", query.ItemId.ToByteArray());
|
|
|
|
- }
|
|
|
|
|
|
+ statement?.TryBind("@ItemId", query.ItemId.ToByteArray());
|
|
}
|
|
}
|
|
|
|
|
|
if (!query.AppearsInItemId.Equals(Guid.Empty))
|
|
if (!query.AppearsInItemId.Equals(Guid.Empty))
|
|
{
|
|
{
|
|
- whereClauses.Add("Name in (Select Name from People where ItemId=@AppearsInItemId)");
|
|
|
|
- if (statement != null)
|
|
|
|
- {
|
|
|
|
- statement.TryBind("@AppearsInItemId", query.AppearsInItemId.ToByteArray());
|
|
|
|
- }
|
|
|
|
|
|
+ whereClauses.Add("p.Name in (Select Name from People where ItemId=@AppearsInItemId)");
|
|
|
|
+ statement?.TryBind("@AppearsInItemId", query.AppearsInItemId.ToByteArray());
|
|
}
|
|
}
|
|
|
|
|
|
var queryPersonTypes = query.PersonTypes.Where(IsValidPersonType).ToList();
|
|
var queryPersonTypes = query.PersonTypes.Where(IsValidPersonType).ToList();
|
|
@@ -5099,10 +5126,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
|
if (queryPersonTypes.Count == 1)
|
|
if (queryPersonTypes.Count == 1)
|
|
{
|
|
{
|
|
whereClauses.Add("PersonType=@PersonType");
|
|
whereClauses.Add("PersonType=@PersonType");
|
|
- if (statement != null)
|
|
|
|
- {
|
|
|
|
- statement.TryBind("@PersonType", queryPersonTypes[0]);
|
|
|
|
- }
|
|
|
|
|
|
+ statement?.TryBind("@PersonType", queryPersonTypes[0]);
|
|
}
|
|
}
|
|
else if (queryPersonTypes.Count > 1)
|
|
else if (queryPersonTypes.Count > 1)
|
|
{
|
|
{
|
|
@@ -5116,10 +5140,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
|
if (queryExcludePersonTypes.Count == 1)
|
|
if (queryExcludePersonTypes.Count == 1)
|
|
{
|
|
{
|
|
whereClauses.Add("PersonType<>@PersonType");
|
|
whereClauses.Add("PersonType<>@PersonType");
|
|
- if (statement != null)
|
|
|
|
- {
|
|
|
|
- statement.TryBind("@PersonType", queryExcludePersonTypes[0]);
|
|
|
|
- }
|
|
|
|
|
|
+ statement?.TryBind("@PersonType", queryExcludePersonTypes[0]);
|
|
}
|
|
}
|
|
else if (queryExcludePersonTypes.Count > 1)
|
|
else if (queryExcludePersonTypes.Count > 1)
|
|
{
|
|
{
|
|
@@ -5131,19 +5152,24 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
|
if (query.MaxListOrder.HasValue)
|
|
if (query.MaxListOrder.HasValue)
|
|
{
|
|
{
|
|
whereClauses.Add("ListOrder<=@MaxListOrder");
|
|
whereClauses.Add("ListOrder<=@MaxListOrder");
|
|
- if (statement != null)
|
|
|
|
- {
|
|
|
|
- statement.TryBind("@MaxListOrder", query.MaxListOrder.Value);
|
|
|
|
- }
|
|
|
|
|
|
+ statement?.TryBind("@MaxListOrder", query.MaxListOrder.Value);
|
|
}
|
|
}
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(query.NameContains))
|
|
if (!string.IsNullOrWhiteSpace(query.NameContains))
|
|
{
|
|
{
|
|
- whereClauses.Add("Name like @NameContains");
|
|
|
|
- if (statement != null)
|
|
|
|
- {
|
|
|
|
- statement.TryBind("@NameContains", "%" + query.NameContains + "%");
|
|
|
|
- }
|
|
|
|
|
|
+ whereClauses.Add("p.Name like @NameContains");
|
|
|
|
+ statement?.TryBind("@NameContains", "%" + query.NameContains + "%");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (query.IsFavorite.HasValue)
|
|
|
|
+ {
|
|
|
|
+ whereClauses.Add("isFavorite=@IsFavorite");
|
|
|
|
+ statement?.TryBind("@IsFavorite", query.IsFavorite.Value);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (query.User != null)
|
|
|
|
+ {
|
|
|
|
+ statement?.TryBind("@UserId", query.User.InternalId);
|
|
}
|
|
}
|
|
|
|
|
|
return whereClauses;
|
|
return whereClauses;
|
|
@@ -5357,7 +5383,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
|
|
|
|
|
itemCountColumns = new Dictionary<string, string>()
|
|
itemCountColumns = new Dictionary<string, string>()
|
|
{
|
|
{
|
|
- { "itemTypes", "(" + itemCountColumnQuery + ") as itemTypes"}
|
|
|
|
|
|
+ { "itemTypes", "(" + itemCountColumnQuery + ") as itemTypes" }
|
|
};
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
@@ -5412,6 +5438,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
|
NameStartsWithOrGreater = query.NameStartsWithOrGreater,
|
|
NameStartsWithOrGreater = query.NameStartsWithOrGreater,
|
|
Tags = query.Tags,
|
|
Tags = query.Tags,
|
|
OfficialRatings = query.OfficialRatings,
|
|
OfficialRatings = query.OfficialRatings,
|
|
|
|
+ StudioIds = query.StudioIds,
|
|
GenreIds = query.GenreIds,
|
|
GenreIds = query.GenreIds,
|
|
Genres = query.Genres,
|
|
Genres = query.Genres,
|
|
Years = query.Years,
|
|
Years = query.Years,
|
|
@@ -5744,7 +5771,8 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
|
|
|
|
|
using (var connection = GetConnection())
|
|
using (var connection = GetConnection())
|
|
{
|
|
{
|
|
- connection.RunInTransaction(db =>
|
|
|
|
|
|
+ connection.RunInTransaction(
|
|
|
|
+ db =>
|
|
{
|
|
{
|
|
var itemIdBlob = itemId.ToByteArray();
|
|
var itemIdBlob = itemId.ToByteArray();
|
|
|
|
|
|
@@ -5898,7 +5926,8 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
|
|
|
|
|
using (var connection = GetConnection())
|
|
using (var connection = GetConnection())
|
|
{
|
|
{
|
|
- connection.RunInTransaction(db =>
|
|
|
|
|
|
+ connection.RunInTransaction(
|
|
|
|
+ db =>
|
|
{
|
|
{
|
|
var itemIdBlob = id.ToByteArray();
|
|
var itemIdBlob = id.ToByteArray();
|
|
|
|
|
|
@@ -6232,7 +6261,8 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
|
|
|
|
|
using (var connection = GetConnection())
|
|
using (var connection = GetConnection())
|
|
{
|
|
{
|
|
- connection.RunInTransaction(db =>
|
|
|
|
|
|
+ connection.RunInTransaction(
|
|
|
|
+ db =>
|
|
{
|
|
{
|
|
var itemIdBlob = id.ToByteArray();
|
|
var itemIdBlob = id.ToByteArray();
|
|
|
|
|