aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/Data
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Server.Implementations/Data')
-rw-r--r--Emby.Server.Implementations/Data/BaseSqliteRepository.cs6
-rw-r--r--Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs2
-rw-r--r--Emby.Server.Implementations/Data/ManagedConnection.cs2
-rw-r--r--Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs2
-rw-r--r--Emby.Server.Implementations/Data/SqliteExtensions.cs2
-rw-r--r--Emby.Server.Implementations/Data/SqliteItemRepository.cs245
-rw-r--r--Emby.Server.Implementations/Data/SqliteUserDataRepository.cs2
-rw-r--r--Emby.Server.Implementations/Data/SqliteUserRepository.cs2
-rw-r--r--Emby.Server.Implementations/Data/TypeMapper.cs11
9 files changed, 247 insertions, 27 deletions
diff --git a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs
index 4e392f6c9c..0654132f41 100644
--- a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs
+++ b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Linq;
@@ -11,6 +13,10 @@ namespace Emby.Server.Implementations.Data
{
private bool _disposed = false;
+ /// <summary>
+ /// Initializes a new instance of the <see cref="BaseSqliteRepository"/> class.
+ /// </summary>
+ /// <param name="logger">The logger.</param>
protected BaseSqliteRepository(ILogger logger)
{
Logger = logger;
diff --git a/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs b/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs
index f7743a3c25..2a8f2d6b33 100644
--- a/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs
+++ b/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Threading;
using System.Threading.Tasks;
diff --git a/Emby.Server.Implementations/Data/ManagedConnection.cs b/Emby.Server.Implementations/Data/ManagedConnection.cs
index 4c34244100..5c094ddd2d 100644
--- a/Emby.Server.Implementations/Data/ManagedConnection.cs
+++ b/Emby.Server.Implementations/Data/ManagedConnection.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Threading;
diff --git a/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs b/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs
index 2f6c1288da..d474f1c6ba 100644
--- a/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Globalization;
diff --git a/Emby.Server.Implementations/Data/SqliteExtensions.cs b/Emby.Server.Implementations/Data/SqliteExtensions.cs
index c76ae0cac0..c87793072e 100644
--- a/Emby.Server.Implementations/Data/SqliteExtensions.cs
+++ b/Emby.Server.Implementations/Data/SqliteExtensions.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Globalization;
diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
index 8d509f6888..c514846e58 100644
--- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
@@ -7,6 +7,7 @@ using System.Text;
using System.Text.Json;
using System.Threading;
using Emby.Server.Implementations.Playlists;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Json;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Channels;
@@ -48,6 +49,21 @@ namespace Emby.Server.Implementations.Data
private readonly TypeMapper _typeMapper;
private readonly JsonSerializerOptions _jsonOptions;
+ static SqliteItemRepository()
+ {
+ var queryPrefixText = new StringBuilder();
+ queryPrefixText.Append("insert into mediaattachments (");
+ foreach (var column in _mediaAttachmentSaveColumns)
+ {
+ queryPrefixText.Append(column)
+ .Append(',');
+ }
+
+ queryPrefixText.Length -= 1;
+ queryPrefixText.Append(") values ");
+ _mediaAttachmentInsertPrefix = queryPrefixText.ToString();
+ }
+
/// <summary>
/// Initializes a new instance of the <see cref="SqliteItemRepository"/> class.
/// </summary>
@@ -91,6 +107,8 @@ namespace Emby.Server.Implementations.Data
{
const string CreateMediaStreamsTableCommand
= "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, IsAvc BIT NULL, Title TEXT NULL, TimeBase TEXT NULL, CodecTimeBase TEXT NULL, ColorPrimaries TEXT NULL, ColorSpace TEXT NULL, ColorTransfer TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))";
+ const string CreateMediaAttachmentsTableCommand
+ = "create table if not exists mediaattachments (ItemId GUID, AttachmentIndex INT, Codec TEXT, CodecTag TEXT NULL, Comment TEXT NULL, Filename TEXT NULL, MIMEType TEXT NULL, PRIMARY KEY (ItemId, AttachmentIndex))";
string[] queries =
{
@@ -113,6 +131,7 @@ namespace Emby.Server.Implementations.Data
"create table if not exists " + ChaptersTableName + " (ItemId GUID, ChapterIndex INT NOT NULL, StartPositionTicks BIGINT NOT NULL, Name TEXT, ImagePath TEXT, PRIMARY KEY (ItemId, ChapterIndex))",
CreateMediaStreamsTableCommand,
+ CreateMediaAttachmentsTableCommand,
"pragma shrink_memory"
};
@@ -420,6 +439,19 @@ namespace Emby.Server.Implementations.Data
"ColorTransfer"
};
+ private static readonly string[] _mediaAttachmentSaveColumns =
+ {
+ "ItemId",
+ "AttachmentIndex",
+ "Codec",
+ "CodecTag",
+ "Comment",
+ "Filename",
+ "MIMEType"
+ };
+
+ private static readonly string _mediaAttachmentInsertPrefix;
+
private static string GetSaveItemCommandText()
{
var saveColumns = new []
@@ -2831,8 +2863,8 @@ namespace Emby.Server.Implementations.Data
BindSimilarParams(query, statement);
BindSearchParams(query, statement);
- // Running this again will bind the params
- GetWhereClauses(query, statement);
+ // Running this again will bind the params
+ GetWhereClauses(query, statement);
var hasEpisodeAttributes = HasEpisodeAttributes(query);
var hasServiceName = HasServiceName(query);
@@ -2881,14 +2913,14 @@ namespace Emby.Server.Implementations.Data
private string GetOrderByText(InternalItemsQuery query)
{
+ var orderBy = query.OrderBy;
if (string.IsNullOrEmpty(query.SearchTerm))
{
- int oldLen = query.OrderBy.Length;
-
- if (query.SimilarTo != null && oldLen == 0)
+ int oldLen = orderBy.Count;
+ if (oldLen == 0 && query.SimilarTo != null)
{
var arr = new (string, SortOrder)[oldLen + 2];
- query.OrderBy.CopyTo(arr, 0);
+ orderBy.CopyTo(arr, 0);
arr[oldLen] = ("SimilarityScore", SortOrder.Descending);
arr[oldLen + 1] = (ItemSortBy.Random, SortOrder.Ascending);
query.OrderBy = arr;
@@ -2896,16 +2928,15 @@ namespace Emby.Server.Implementations.Data
}
else
{
- query.OrderBy = new []
+ query.OrderBy = new[]
{
("SearchScore", SortOrder.Descending),
(ItemSortBy.SortName, SortOrder.Ascending)
};
}
- var orderBy = query.OrderBy;
- if (orderBy.Length == 0)
+ if (orderBy.Count == 0)
{
return string.Empty;
}
@@ -2913,14 +2944,8 @@ namespace Emby.Server.Implementations.Data
return " ORDER BY " + string.Join(",", orderBy.Select(i =>
{
var columnMap = MapOrderByField(i.Item1, query);
- var columnAscending = i.Item2 == SortOrder.Ascending;
- const bool enableOrderInversion = false;
- if (columnMap.Item2 && enableOrderInversion)
- {
- columnAscending = !columnAscending;
- }
- var sortOrder = columnAscending ? "ASC" : "DESC";
+ var sortOrder = i.Item2 == SortOrder.Ascending ? "ASC" : "DESC";
return columnMap.Item1 + " " + sortOrder;
}));
@@ -4599,10 +4624,20 @@ namespace Emby.Server.Implementations.Data
if (query.ExcludeInheritedTags.Length > 0)
{
- var tagValues = query.ExcludeInheritedTags.Select(i => "'" + GetCleanValue(i) + "'");
- var tagValuesList = string.Join(",", tagValues);
-
- whereClauses.Add("((select CleanValue from itemvalues where ItemId=Guid and Type=6 and cleanvalue in (" + tagValuesList + ")) is null)");
+ var paramName = "@ExcludeInheritedTags";
+ if (statement == null)
+ {
+ int index = 0;
+ string excludedTags = string.Join(",", query.ExcludeInheritedTags.Select(t => paramName + index++));
+ whereClauses.Add("((select CleanValue from itemvalues where ItemId=Guid and Type=6 and cleanvalue in (" + excludedTags + ")) is null)");
+ }
+ else
+ {
+ for (int index = 0; index < query.ExcludeInheritedTags.Length; index++)
+ {
+ statement.TryBind(paramName + index, GetCleanValue(query.ExcludeInheritedTags[index]));
+ }
+ }
}
if (query.SeriesStatuses.Length > 0)
@@ -6132,5 +6167,175 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
return item;
}
+
+ public List<MediaAttachment> GetMediaAttachments(MediaAttachmentQuery query)
+ {
+ CheckDisposed();
+
+ if (query == null)
+ {
+ throw new ArgumentNullException(nameof(query));
+ }
+
+ var cmdText = "select "
+ + string.Join(",", _mediaAttachmentSaveColumns)
+ + " from mediaattachments where"
+ + " ItemId=@ItemId";
+
+ if (query.Index.HasValue)
+ {
+ cmdText += " AND AttachmentIndex=@AttachmentIndex";
+ }
+
+ cmdText += " order by AttachmentIndex ASC";
+
+ var list = new List<MediaAttachment>();
+ using (var connection = GetConnection(true))
+ using (var statement = PrepareStatement(connection, cmdText))
+ {
+ statement.TryBind("@ItemId", query.ItemId.ToByteArray());
+
+ if (query.Index.HasValue)
+ {
+ statement.TryBind("@AttachmentIndex", query.Index.Value);
+ }
+
+ foreach (var row in statement.ExecuteQuery())
+ {
+ list.Add(GetMediaAttachment(row));
+ }
+ }
+
+ return list;
+ }
+
+ public void SaveMediaAttachments(
+ Guid id,
+ IReadOnlyList<MediaAttachment> attachments,
+ CancellationToken cancellationToken)
+ {
+ CheckDisposed();
+ if (id == Guid.Empty)
+ {
+ throw new ArgumentException(nameof(id));
+ }
+
+ if (attachments == null)
+ {
+ throw new ArgumentNullException(nameof(attachments));
+ }
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ using (var connection = GetConnection())
+ {
+ connection.RunInTransaction(db =>
+ {
+ var itemIdBlob = id.ToByteArray();
+
+ db.Execute("delete from mediaattachments where ItemId=@ItemId", itemIdBlob);
+
+ InsertMediaAttachments(itemIdBlob, attachments, db, cancellationToken);
+
+ }, TransactionMode);
+ }
+ }
+
+ private void InsertMediaAttachments(
+ byte[] idBlob,
+ IReadOnlyList<MediaAttachment> attachments,
+ IDatabaseConnection db,
+ CancellationToken cancellationToken)
+ {
+ const int InsertAtOnce = 10;
+
+ for (var startIndex = 0; startIndex < attachments.Count; startIndex += InsertAtOnce)
+ {
+ var insertText = new StringBuilder(_mediaAttachmentInsertPrefix);
+
+ var endIndex = Math.Min(attachments.Count, startIndex + InsertAtOnce);
+
+ for (var i = startIndex; i < endIndex; i++)
+ {
+ var index = i.ToString(CultureInfo.InvariantCulture);
+ insertText.Append("(@ItemId, ");
+
+ foreach (var column in _mediaAttachmentSaveColumns.Skip(1))
+ {
+ insertText.Append("@" + column + index + ",");
+ }
+
+ insertText.Length -= 1;
+
+ insertText.Append("),");
+ }
+
+ insertText.Length--;
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ using (var statement = PrepareStatement(db, insertText.ToString()))
+ {
+ statement.TryBind("@ItemId", idBlob);
+
+ for (var i = startIndex; i < endIndex; i++)
+ {
+ var index = i.ToString(CultureInfo.InvariantCulture);
+
+ var attachment = attachments[i];
+
+ statement.TryBind("@AttachmentIndex" + index, attachment.Index);
+ statement.TryBind("@Codec" + index, attachment.Codec);
+ statement.TryBind("@CodecTag" + index, attachment.CodecTag);
+ statement.TryBind("@Comment" + index, attachment.Comment);
+ statement.TryBind("@FileName" + index, attachment.FileName);
+ statement.TryBind("@MimeType" + index, attachment.MimeType);
+ }
+
+ statement.Reset();
+ statement.MoveNext();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets the attachment.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ /// <returns>MediaAttachment</returns>
+ private MediaAttachment GetMediaAttachment(IReadOnlyList<IResultSetValue> reader)
+ {
+ var item = new MediaAttachment
+ {
+ Index = reader[1].ToInt()
+ };
+
+ if (reader[2].SQLiteType != SQLiteType.Null)
+ {
+ item.Codec = reader[2].ToString();
+ }
+
+ if (reader[2].SQLiteType != SQLiteType.Null)
+ {
+ item.CodecTag = reader[3].ToString();
+ }
+
+ if (reader[4].SQLiteType != SQLiteType.Null)
+ {
+ item.Comment = reader[4].ToString();
+ }
+
+ if (reader[6].SQLiteType != SQLiteType.Null)
+ {
+ item.FileName = reader[5].ToString();
+ }
+
+ if (reader[6].SQLiteType != SQLiteType.Null)
+ {
+ item.MimeType = reader[6].ToString();
+ }
+
+ return item;
+ }
}
}
diff --git a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs
index 26ac17bdc2..22955850ab 100644
--- a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.IO;
diff --git a/Emby.Server.Implementations/Data/SqliteUserRepository.cs b/Emby.Server.Implementations/Data/SqliteUserRepository.cs
index 26798993b4..a042320c91 100644
--- a/Emby.Server.Implementations/Data/SqliteUserRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteUserRepository.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.IO;
diff --git a/Emby.Server.Implementations/Data/TypeMapper.cs b/Emby.Server.Implementations/Data/TypeMapper.cs
index 0e67affbfc..7044b1d194 100644
--- a/Emby.Server.Implementations/Data/TypeMapper.cs
+++ b/Emby.Server.Implementations/Data/TypeMapper.cs
@@ -5,25 +5,22 @@ using System.Linq;
namespace Emby.Server.Implementations.Data
{
/// <summary>
- /// Class TypeMapper
+ /// Class TypeMapper.
/// </summary>
public class TypeMapper
{
/// <summary>
- /// This holds all the types in the running assemblies so that we can de-serialize properly when we don't have strong types
+ /// This holds all the types in the running assemblies
+ /// so that we can de-serialize properly when we don't have strong types.
/// </summary>
private readonly ConcurrentDictionary<string, Type> _typeMap = new ConcurrentDictionary<string, Type>();
- public TypeMapper()
- {
- }
-
/// <summary>
/// Gets the type.
/// </summary>
/// <param name="typeName">Name of the type.</param>
/// <returns>Type.</returns>
- /// <exception cref="ArgumentNullException"></exception>
+ /// <exception cref="ArgumentNullException"><c>typeName</c> is null.</exception>
public Type GetType(string typeName)
{
if (string.IsNullOrEmpty(typeName))