|
@@ -35,9 +35,9 @@ using MediaBrowser.Model.Entities;
|
|
|
using MediaBrowser.Model.Globalization;
|
|
|
using MediaBrowser.Model.LiveTv;
|
|
|
using MediaBrowser.Model.Querying;
|
|
|
+using Microsoft.Data.Sqlite;
|
|
|
using Microsoft.Extensions.Configuration;
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
-using SQLitePCL.pretty;
|
|
|
|
|
|
namespace Emby.Server.Implementations.Data
|
|
|
{
|
|
@@ -555,8 +555,7 @@ namespace Emby.Server.Implementations.Data
|
|
|
AddColumn(db, "MediaStreams", "DvBlSignalCompatibilityId", "INT", existingColumnNames);
|
|
|
|
|
|
AddColumn(db, "MediaStreams", "IsHearingImpaired", "BIT", existingColumnNames);
|
|
|
- },
|
|
|
- TransactionMode);
|
|
|
+ });
|
|
|
|
|
|
connection.RunQueries(postQueries);
|
|
|
}
|
|
@@ -580,8 +579,7 @@ namespace Emby.Server.Implementations.Data
|
|
|
|
|
|
saveImagesStatement.MoveNext();
|
|
|
}
|
|
|
- },
|
|
|
- TransactionMode);
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -624,12 +622,11 @@ namespace Emby.Server.Implementations.Data
|
|
|
db =>
|
|
|
{
|
|
|
SaveItemsInTransaction(db, tuples);
|
|
|
- },
|
|
|
- TransactionMode);
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void SaveItemsInTransaction(IDatabaseConnection db, IEnumerable<(BaseItem Item, List<Guid> AncestorIds, BaseItem TopParent, string UserDataKey, List<string> InheritedTags)> tuples)
|
|
|
+ private void SaveItemsInTransaction(SqliteConnection db, IEnumerable<(BaseItem Item, List<Guid> AncestorIds, BaseItem TopParent, string UserDataKey, List<string> InheritedTags)> tuples)
|
|
|
{
|
|
|
using (var saveItemStatement = PrepareStatement(db, SaveItemCommandText))
|
|
|
using (var deleteAncestorsStatement = PrepareStatement(db, "delete from AncestorIds where ItemId=@ItemId"))
|
|
@@ -639,7 +636,7 @@ namespace Emby.Server.Implementations.Data
|
|
|
{
|
|
|
if (requiresReset)
|
|
|
{
|
|
|
- saveItemStatement.Reset();
|
|
|
+ // TODO saveItemStatement.Parameters.Clear();
|
|
|
}
|
|
|
|
|
|
var item = tuple.Item;
|
|
@@ -677,7 +674,7 @@ namespace Emby.Server.Implementations.Data
|
|
|
return _appHost.ExpandVirtualPath(path);
|
|
|
}
|
|
|
|
|
|
- private void SaveItem(BaseItem item, BaseItem topParent, string userDataKey, IStatement saveItemStatement)
|
|
|
+ private void SaveItem(BaseItem item, BaseItem topParent, string userDataKey, SqliteCommand saveItemStatement)
|
|
|
{
|
|
|
Type type = item.GetType();
|
|
|
|
|
@@ -1389,12 +1386,12 @@ namespace Emby.Server.Implementations.Data
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- private BaseItem GetItem(IReadOnlyList<ResultSetValue> reader, InternalItemsQuery query)
|
|
|
+ private BaseItem GetItem(SqliteDataReader reader, InternalItemsQuery query)
|
|
|
{
|
|
|
return GetItem(reader, query, HasProgramAttributes(query), HasEpisodeAttributes(query), HasServiceName(query), HasStartDate(query), HasTrailerTypes(query), HasArtistFields(query), HasSeriesFields(query));
|
|
|
}
|
|
|
|
|
|
- private BaseItem GetItem(IReadOnlyList<ResultSetValue> reader, InternalItemsQuery query, bool enableProgramAttributes, bool hasEpisodeAttributes, bool hasServiceName, bool queryHasStartDate, bool hasTrailerTypes, bool hasArtistFields, bool hasSeriesFields)
|
|
|
+ private BaseItem GetItem(SqliteDataReader reader, InternalItemsQuery query, bool enableProgramAttributes, bool hasEpisodeAttributes, bool hasServiceName, bool queryHasStartDate, bool hasTrailerTypes, bool hasArtistFields, bool hasSeriesFields)
|
|
|
{
|
|
|
var typeString = reader.GetString(0);
|
|
|
|
|
@@ -1411,7 +1408,7 @@ namespace Emby.Server.Implementations.Data
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
- item = JsonSerializer.Deserialize(reader[1].ToBlob(), type, _jsonOptions) as BaseItem;
|
|
|
+ item = JsonSerializer.Deserialize(reader.GetStream(1), type, _jsonOptions) as BaseItem;
|
|
|
}
|
|
|
catch (JsonException ex)
|
|
|
{
|
|
@@ -1452,17 +1449,9 @@ namespace Emby.Server.Implementations.Data
|
|
|
item.EndDate = endDate;
|
|
|
}
|
|
|
|
|
|
- var channelId = reader[index];
|
|
|
- if (!channelId.IsDbNull())
|
|
|
+ if (reader.TryGetGuid(index, out var guid))
|
|
|
{
|
|
|
- if (!Utf8Parser.TryParse(channelId.ToBlob(), out Guid value, out _, standardFormat: 'N'))
|
|
|
- {
|
|
|
- var str = reader.GetString(index);
|
|
|
- Logger.LogWarning("{ChannelId} isn't in the expected format", str);
|
|
|
- value = new Guid(str);
|
|
|
- }
|
|
|
-
|
|
|
- item.ChannelId = value;
|
|
|
+ item.ChannelId = guid;
|
|
|
}
|
|
|
|
|
|
index++;
|
|
@@ -2018,7 +2007,7 @@ namespace Emby.Server.Implementations.Data
|
|
|
/// <param name="reader">The reader.</param>
|
|
|
/// <param name="item">The item.</param>
|
|
|
/// <returns>ChapterInfo.</returns>
|
|
|
- private ChapterInfo GetChapter(IReadOnlyList<ResultSetValue> reader, BaseItem item)
|
|
|
+ private ChapterInfo GetChapter(SqliteDataReader reader, BaseItem item)
|
|
|
{
|
|
|
var chapter = new ChapterInfo
|
|
|
{
|
|
@@ -2071,23 +2060,22 @@ namespace Emby.Server.Implementations.Data
|
|
|
|
|
|
ArgumentNullException.ThrowIfNull(chapters);
|
|
|
|
|
|
- var idBlob = id.ToByteArray();
|
|
|
-
|
|
|
using (var connection = GetConnection())
|
|
|
{
|
|
|
connection.RunInTransaction(
|
|
|
db =>
|
|
|
{
|
|
|
// First delete chapters
|
|
|
- db.Execute("delete from " + ChaptersTableName + " where ItemId=@ItemId", idBlob);
|
|
|
+ var command = db.PrepareStatement($"delete from {ChaptersTableName} where ItemId=@ItemId");
|
|
|
+ command.TryBind("@ItemId", id);
|
|
|
+ command.ExecuteNonQuery();
|
|
|
|
|
|
- InsertChapters(idBlob, chapters, db);
|
|
|
- },
|
|
|
- TransactionMode);
|
|
|
+ InsertChapters(id, chapters, db);
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void InsertChapters(byte[] idBlob, IReadOnlyList<ChapterInfo> chapters, IDatabaseConnection db)
|
|
|
+ private void InsertChapters(Guid idBlob, IReadOnlyList<ChapterInfo> chapters, SqliteConnection db)
|
|
|
{
|
|
|
var startIndex = 0;
|
|
|
var limit = 100;
|
|
@@ -2126,7 +2114,7 @@ namespace Emby.Server.Implementations.Data
|
|
|
chapterIndex++;
|
|
|
}
|
|
|
|
|
|
- statement.Reset();
|
|
|
+ // TODO statement.Parameters.Clear();
|
|
|
statement.MoveNext();
|
|
|
}
|
|
|
|
|
@@ -2463,7 +2451,7 @@ namespace Emby.Server.Implementations.Data
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void BindSearchParams(InternalItemsQuery query, IStatement statement)
|
|
|
+ private void BindSearchParams(InternalItemsQuery query, SqliteCommand statement)
|
|
|
{
|
|
|
var searchTerm = query.SearchTerm;
|
|
|
|
|
@@ -2475,7 +2463,7 @@ namespace Emby.Server.Implementations.Data
|
|
|
searchTerm = FixUnicodeChars(searchTerm);
|
|
|
searchTerm = GetCleanValue(searchTerm);
|
|
|
|
|
|
- var commandText = statement.SQL;
|
|
|
+ var commandText = statement.CommandText;
|
|
|
if (commandText.Contains("@SearchTermStartsWith", StringComparison.OrdinalIgnoreCase))
|
|
|
{
|
|
|
statement.TryBind("@SearchTermStartsWith", searchTerm + "%");
|
|
@@ -2492,7 +2480,7 @@ namespace Emby.Server.Implementations.Data
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void BindSimilarParams(InternalItemsQuery query, IStatement statement)
|
|
|
+ private void BindSimilarParams(InternalItemsQuery query, SqliteCommand statement)
|
|
|
{
|
|
|
var item = query.SimilarTo;
|
|
|
|
|
@@ -2501,7 +2489,7 @@ namespace Emby.Server.Implementations.Data
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- var commandText = statement.SQL;
|
|
|
+ var commandText = statement.CommandText;
|
|
|
|
|
|
if (commandText.Contains("@ItemOfficialRating", StringComparison.OrdinalIgnoreCase))
|
|
|
{
|
|
@@ -2598,7 +2586,7 @@ namespace Emby.Server.Implementations.Data
|
|
|
// Running this again will bind the params
|
|
|
GetWhereClauses(query, statement);
|
|
|
|
|
|
- return statement.ExecuteQuery().SelectScalarInt().First();
|
|
|
+ return statement.SelectScalarInt();
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -2916,11 +2904,10 @@ namespace Emby.Server.Implementations.Data
|
|
|
// Running this again will bind the params
|
|
|
GetWhereClauses(query, statement);
|
|
|
|
|
|
- result.TotalRecordCount = statement.ExecuteQuery().SelectScalarInt().First();
|
|
|
+ result.TotalRecordCount = statement.SelectScalarInt();
|
|
|
}
|
|
|
}
|
|
|
- },
|
|
|
- ReadTransactionMode);
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
result.StartIndex = query.StartIndex ?? 0;
|
|
@@ -3188,7 +3175,7 @@ namespace Emby.Server.Implementations.Data
|
|
|
|
|
|
foreach (var row in statement.ExecuteQuery())
|
|
|
{
|
|
|
- list.Add(row[0].ReadGuidFromBlob());
|
|
|
+ list.Add(row.GetGuid(0));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -3224,7 +3211,7 @@ namespace Emby.Server.Implementations.Data
|
|
|
}
|
|
|
|
|
|
#nullable enable
|
|
|
- private List<string> GetWhereClauses(InternalItemsQuery query, IStatement? statement)
|
|
|
+ private List<string> GetWhereClauses(InternalItemsQuery query, SqliteCommand? statement)
|
|
|
{
|
|
|
if (query.IsResumable ?? false)
|
|
|
{
|
|
@@ -3647,8 +3634,7 @@ namespace Emby.Server.Implementations.Data
|
|
|
|
|
|
if (statement is not null)
|
|
|
{
|
|
|
- query.PersonIds[i].TryWriteBytes(idBytes);
|
|
|
- statement.TryBind(paramName, idBytes);
|
|
|
+ statement.TryBind(paramName, query.PersonIds[i]);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -4696,8 +4682,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
|
|
db =>
|
|
|
{
|
|
|
connection.ExecuteAll(sql);
|
|
|
- },
|
|
|
- TransactionMode);
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -4735,16 +4720,15 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
|
|
|
|
|
// Delete the item
|
|
|
ExecuteWithSingleParam(db, "delete from TypedBaseItems where guid=@Id", idBlob);
|
|
|
- },
|
|
|
- TransactionMode);
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void ExecuteWithSingleParam(IDatabaseConnection db, string query, ReadOnlySpan<byte> value)
|
|
|
+ private void ExecuteWithSingleParam(SqliteConnection db, string query, ReadOnlySpan<byte> value)
|
|
|
{
|
|
|
using (var statement = PrepareStatement(db, query))
|
|
|
{
|
|
|
- statement.TryBind("@Id", value);
|
|
|
+ statement.TryBind("@Id", value.ToArray());
|
|
|
|
|
|
statement.MoveNext();
|
|
|
}
|
|
@@ -4826,7 +4810,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
|
|
return list;
|
|
|
}
|
|
|
|
|
|
- private List<string> GetPeopleWhereClauses(InternalPeopleQuery query, IStatement statement)
|
|
|
+ private List<string> GetPeopleWhereClauses(InternalPeopleQuery query, SqliteCommand statement)
|
|
|
{
|
|
|
var whereClauses = new List<string>();
|
|
|
|
|
@@ -4896,7 +4880,7 @@ AND Type = @InternalPersonType)");
|
|
|
return whereClauses;
|
|
|
}
|
|
|
|
|
|
- private void UpdateAncestors(Guid itemId, List<Guid> ancestorIds, IDatabaseConnection db, IStatement deleteAncestorsStatement)
|
|
|
+ private void UpdateAncestors(Guid itemId, List<Guid> ancestorIds, SqliteConnection db, SqliteCommand deleteAncestorsStatement)
|
|
|
{
|
|
|
if (itemId.Equals(default))
|
|
|
{
|
|
@@ -4907,12 +4891,14 @@ AND Type = @InternalPersonType)");
|
|
|
|
|
|
CheckDisposed();
|
|
|
|
|
|
- Span<byte> itemIdBlob = stackalloc byte[16];
|
|
|
- itemId.TryWriteBytes(itemIdBlob);
|
|
|
+ // TODO how to handle span?
|
|
|
+ Span<byte> itemIdBlob2 = stackalloc byte[16];
|
|
|
+ itemId.TryWriteBytes(itemIdBlob2);
|
|
|
+ var itemIdBlob = Encoding.ASCII.GetBytes(itemId.ToString());
|
|
|
|
|
|
// First delete
|
|
|
- deleteAncestorsStatement.Reset();
|
|
|
- deleteAncestorsStatement.TryBind("@ItemId", itemIdBlob);
|
|
|
+ // TODO deleteAncestorsStatement.Parameters.Clear();
|
|
|
+ deleteAncestorsStatement.TryBind("@ItemId", itemId);
|
|
|
deleteAncestorsStatement.MoveNext();
|
|
|
|
|
|
if (ancestorIds.Count == 0)
|
|
@@ -4942,13 +4928,13 @@ AND Type = @InternalPersonType)");
|
|
|
var index = i.ToString(CultureInfo.InvariantCulture);
|
|
|
|
|
|
var ancestorId = ancestorIds[i];
|
|
|
- ancestorId.TryWriteBytes(itemIdBlob);
|
|
|
+ itemIdBlob = Encoding.ASCII.GetBytes(itemId.ToString());
|
|
|
|
|
|
- statement.TryBind("@AncestorId" + index, itemIdBlob);
|
|
|
+ statement.TryBind("@AncestorId" + index, ancestorId);
|
|
|
statement.TryBind("@AncestorIdText" + index, ancestorId.ToString("N", CultureInfo.InvariantCulture));
|
|
|
}
|
|
|
|
|
|
- statement.Reset();
|
|
|
+ // TODO statement.Parameters.Clear();
|
|
|
statement.MoveNext();
|
|
|
}
|
|
|
}
|
|
@@ -5323,11 +5309,10 @@ AND Type = @InternalPersonType)");
|
|
|
GetWhereClauses(innerQuery, statement);
|
|
|
GetWhereClauses(outerQuery, statement);
|
|
|
|
|
|
- result.TotalRecordCount = statement.ExecuteQuery().SelectScalarInt().First();
|
|
|
+ result.TotalRecordCount = statement.SelectScalarInt();
|
|
|
}
|
|
|
}
|
|
|
- },
|
|
|
- ReadTransactionMode);
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
if (result.TotalRecordCount == 0)
|
|
@@ -5341,7 +5326,7 @@ AND Type = @InternalPersonType)");
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
- private static ItemCounts GetItemCounts(IReadOnlyList<ResultSetValue> reader, int countStartColumn, BaseItemKind[] typesToCount)
|
|
|
+ private static ItemCounts GetItemCounts(SqliteDataReader reader, int countStartColumn, BaseItemKind[] typesToCount)
|
|
|
{
|
|
|
var counts = new ItemCounts();
|
|
|
|
|
@@ -5420,7 +5405,7 @@ AND Type = @InternalPersonType)");
|
|
|
return list;
|
|
|
}
|
|
|
|
|
|
- private void UpdateItemValues(Guid itemId, List<(int MagicNumber, string Value)> values, IDatabaseConnection db)
|
|
|
+ private void UpdateItemValues(Guid itemId, List<(int MagicNumber, string Value)> values, SqliteConnection db)
|
|
|
{
|
|
|
if (itemId.Equals(default))
|
|
|
{
|
|
@@ -5434,12 +5419,14 @@ AND Type = @InternalPersonType)");
|
|
|
var guidBlob = itemId.ToByteArray();
|
|
|
|
|
|
// First delete
|
|
|
- db.Execute("delete from ItemValues where ItemId=@Id", guidBlob);
|
|
|
+ using var command = db.PrepareStatement("delete from ItemValues where ItemId=@Id");
|
|
|
+ command.TryBind("@Id", guidBlob);
|
|
|
+ command.ExecuteNonQuery();
|
|
|
|
|
|
InsertItemValues(guidBlob, values, db);
|
|
|
}
|
|
|
|
|
|
- private void InsertItemValues(byte[] idBlob, List<(int MagicNumber, string Value)> values, IDatabaseConnection db)
|
|
|
+ private void InsertItemValues(byte[] idBlob, List<(int MagicNumber, string Value)> values, SqliteConnection db)
|
|
|
{
|
|
|
const int Limit = 100;
|
|
|
var startIndex = 0;
|
|
@@ -5484,7 +5471,7 @@ AND Type = @InternalPersonType)");
|
|
|
statement.TryBind("@CleanValue" + index, GetCleanValue(itemValue));
|
|
|
}
|
|
|
|
|
|
- statement.Reset();
|
|
|
+ // TODO statement.Parameters.Clear();
|
|
|
statement.MoveNext();
|
|
|
}
|
|
|
|
|
@@ -5512,15 +5499,17 @@ AND Type = @InternalPersonType)");
|
|
|
var itemIdBlob = itemId.ToByteArray();
|
|
|
|
|
|
// First delete chapters
|
|
|
- db.Execute("delete from People where ItemId=@ItemId", itemIdBlob);
|
|
|
+ using var command = db.CreateCommand();
|
|
|
+ command.CommandText = "delete from People where ItemId=@ItemId";
|
|
|
+ command.TryBind("@ItemId", itemIdBlob);
|
|
|
+ command.ExecuteNonQuery();
|
|
|
|
|
|
InsertPeople(itemIdBlob, people, db);
|
|
|
- },
|
|
|
- TransactionMode);
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void InsertPeople(byte[] idBlob, List<PersonInfo> people, IDatabaseConnection db)
|
|
|
+ private void InsertPeople(byte[] idBlob, List<PersonInfo> people, SqliteConnection db)
|
|
|
{
|
|
|
const int Limit = 100;
|
|
|
var startIndex = 0;
|
|
@@ -5561,7 +5550,6 @@ AND Type = @InternalPersonType)");
|
|
|
listIndex++;
|
|
|
}
|
|
|
|
|
|
- statement.Reset();
|
|
|
statement.MoveNext();
|
|
|
}
|
|
|
|
|
@@ -5570,7 +5558,7 @@ AND Type = @InternalPersonType)");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private PersonInfo GetPerson(IReadOnlyList<ResultSetValue> reader)
|
|
|
+ private PersonInfo GetPerson(SqliteDataReader reader)
|
|
|
{
|
|
|
var item = new PersonInfo
|
|
|
{
|
|
@@ -5666,15 +5654,16 @@ AND Type = @InternalPersonType)");
|
|
|
var itemIdBlob = id.ToByteArray();
|
|
|
|
|
|
// Delete existing mediastreams
|
|
|
- db.Execute("delete from mediastreams where ItemId=@ItemId", itemIdBlob);
|
|
|
+ using var command = db.PrepareStatement("delete from mediastreams where ItemId=@ItemId");
|
|
|
+ command.TryBind("@ItemId", itemIdBlob);
|
|
|
+ command.ExecuteNonQuery();
|
|
|
|
|
|
InsertMediaStreams(itemIdBlob, streams, db);
|
|
|
- },
|
|
|
- TransactionMode);
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void InsertMediaStreams(byte[] idBlob, IReadOnlyList<MediaStream> streams, IDatabaseConnection db)
|
|
|
+ private void InsertMediaStreams(byte[] idBlob, IReadOnlyList<MediaStream> streams, SqliteConnection db)
|
|
|
{
|
|
|
const int Limit = 10;
|
|
|
var startIndex = 0;
|
|
@@ -5770,7 +5759,7 @@ AND Type = @InternalPersonType)");
|
|
|
statement.TryBind("@IsHearingImpaired" + index, stream.IsHearingImpaired);
|
|
|
}
|
|
|
|
|
|
- statement.Reset();
|
|
|
+ // TODO statement.Parameters.Clear();
|
|
|
statement.MoveNext();
|
|
|
}
|
|
|
|
|
@@ -5784,15 +5773,14 @@ AND Type = @InternalPersonType)");
|
|
|
/// </summary>
|
|
|
/// <param name="reader">The reader.</param>
|
|
|
/// <returns>MediaStream.</returns>
|
|
|
- private MediaStream GetMediaStream(IReadOnlyList<ResultSetValue> reader)
|
|
|
+ private MediaStream GetMediaStream(SqliteDataReader reader)
|
|
|
{
|
|
|
var item = new MediaStream
|
|
|
{
|
|
|
- Index = reader[1].ToInt()
|
|
|
+ Index = reader.GetInt32(1),
|
|
|
+ Type = Enum.Parse<MediaStreamType>(reader.GetString(2), true)
|
|
|
};
|
|
|
|
|
|
- item.Type = Enum.Parse<MediaStreamType>(reader[2].ToString(), true);
|
|
|
-
|
|
|
if (reader.TryGetString(3, out var codec))
|
|
|
{
|
|
|
item.Codec = codec;
|
|
@@ -6050,18 +6038,19 @@ AND Type = @InternalPersonType)");
|
|
|
{
|
|
|
var itemIdBlob = id.ToByteArray();
|
|
|
|
|
|
- db.Execute("delete from mediaattachments where ItemId=@ItemId", itemIdBlob);
|
|
|
+ using var command = db.PrepareStatement("delete from mediaattachments where ItemId=@ItemId");
|
|
|
+ command.TryBind("@ItemId", itemIdBlob);
|
|
|
+ command.ExecuteNonQuery();
|
|
|
|
|
|
InsertMediaAttachments(itemIdBlob, attachments, db, cancellationToken);
|
|
|
- },
|
|
|
- TransactionMode);
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void InsertMediaAttachments(
|
|
|
byte[] idBlob,
|
|
|
IReadOnlyList<MediaAttachment> attachments,
|
|
|
- IDatabaseConnection db,
|
|
|
+ SqliteConnection db,
|
|
|
CancellationToken cancellationToken)
|
|
|
{
|
|
|
const int InsertAtOnce = 10;
|
|
@@ -6111,7 +6100,7 @@ AND Type = @InternalPersonType)");
|
|
|
statement.TryBind("@MIMEType" + index, attachment.MimeType);
|
|
|
}
|
|
|
|
|
|
- statement.Reset();
|
|
|
+ // TODO statement.Parameters.Clear();
|
|
|
statement.MoveNext();
|
|
|
}
|
|
|
|
|
@@ -6124,11 +6113,11 @@ AND Type = @InternalPersonType)");
|
|
|
/// </summary>
|
|
|
/// <param name="reader">The reader.</param>
|
|
|
/// <returns>MediaAttachment.</returns>
|
|
|
- private MediaAttachment GetMediaAttachment(IReadOnlyList<ResultSetValue> reader)
|
|
|
+ private MediaAttachment GetMediaAttachment(SqliteDataReader reader)
|
|
|
{
|
|
|
var item = new MediaAttachment
|
|
|
{
|
|
|
- Index = reader[1].ToInt()
|
|
|
+ Index = reader.GetInt32(1)
|
|
|
};
|
|
|
|
|
|
if (reader.TryGetString(2, out var codec))
|