loading works

This commit is contained in:
cvium
2023-08-21 12:13:32 +02:00
parent d3f8874a3e
commit 613f4296e3
14 changed files with 706 additions and 612 deletions

View File

@@ -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))