aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs')
-rw-r--r--MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs353
1 files changed, 341 insertions, 12 deletions
diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
index dcf94f737..4d86330e5 100644
--- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
@@ -19,6 +19,7 @@ using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Channels;
+using MediaBrowser.Model.LiveTv;
namespace MediaBrowser.Server.Implementations.Persistence
{
@@ -76,7 +77,10 @@ namespace MediaBrowser.Server.Implementations.Persistence
private IDbCommand _deleteStreamsCommand;
private IDbCommand _saveStreamCommand;
- private const int LatestSchemaVersion = 13;
+ private IDbCommand _deleteAncestorsCommand;
+ private IDbCommand _saveAncestorCommand;
+
+ private const int LatestSchemaVersion = 19;
/// <summary>
/// Initializes a new instance of the <see cref="SqliteItemRepository"/> class.
@@ -121,13 +125,17 @@ namespace MediaBrowser.Server.Implementations.Persistence
_connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false);
var 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, IsCabac BIT NULL, KeyFrames TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))";
+ = "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, IsCabac BIT NULL, KeyFrames TEXT NULL, CodecTag TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))";
string[] queries = {
- "create table if not exists TypedBaseItems (guid GUID primary key, type TEXT, data BLOB)",
+ "create table if not exists TypedBaseItems (guid GUID primary key, type TEXT, data BLOB, ParentId GUID)",
"create index if not exists idx_TypedBaseItems on TypedBaseItems(guid)",
+ "create index if not exists idx_ParentIdTypedBaseItems on TypedBaseItems(ParentId)",
+ "create table if not exists AncestorIds (ItemId GUID, AncestorId GUID, PRIMARY KEY (ItemId, AncestorId))",
+ "create index if not exists idx_AncestorIds on AncestorIds(ItemId,AncestorId)",
+
"create table if not exists ChildrenIds (ParentId GUID, ItemId GUID, PRIMARY KEY (ParentId, ItemId))",
"create index if not exists idx_ChildrenIds on ChildrenIds(ParentId,ItemId)",
@@ -198,6 +206,15 @@ namespace MediaBrowser.Server.Implementations.Persistence
_connection.AddColumn(_logger, "TypedBaseItems", "ExternalEtag", "Text");
_connection.AddColumn(_logger, "TypedBaseItems", "DateLastRefreshed", "DATETIME");
+ _connection.AddColumn(_logger, "TypedBaseItems", "DateLastSaved", "DATETIME");
+ _connection.AddColumn(_logger, "TypedBaseItems", "IsInMixedFolder", "BIT");
+ _connection.AddColumn(_logger, "TypedBaseItems", "LockedFields", "Text");
+ _connection.AddColumn(_logger, "TypedBaseItems", "Studios", "Text");
+ _connection.AddColumn(_logger, "TypedBaseItems", "Audio", "Text");
+ _connection.AddColumn(_logger, "TypedBaseItems", "ExternalServiceId", "Text");
+ _connection.AddColumn(_logger, "TypedBaseItems", "Tags", "Text");
+ _connection.AddColumn(_logger, "TypedBaseItems", "IsFolder", "BIT");
+
PrepareStatements();
new MediaStreamColumns(_connection, _logger).AddColumns();
@@ -307,7 +324,27 @@ namespace MediaBrowser.Server.Implementations.Persistence
"PreferredMetadataCountryCode",
"IsHD",
"ExternalEtag",
- "DateLastRefreshed"
+ "DateLastRefreshed",
+ "Name",
+ "Path",
+ "PremiereDate",
+ "Overview",
+ "ParentIndexNumber",
+ "ProductionYear",
+ "OfficialRating",
+ "OfficialRatingDescription",
+ "HomePageUrl",
+ "DisplayMediaType",
+ "ForcedSortName",
+ "RunTimeTicks",
+ "VoteCount",
+ "DateCreated",
+ "DateModified",
+ "guid",
+ "Genres",
+ "ParentId",
+ "Audio",
+ "ExternalServiceId"
};
private readonly string[] _mediaStreamSaveColumns =
@@ -338,7 +375,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
"IsAnamorphic",
"RefFrames",
"IsCabac",
- "KeyFrames"
+ "KeyFrames",
+ "CodecTag"
};
/// <summary>
@@ -394,7 +432,15 @@ namespace MediaBrowser.Server.Implementations.Persistence
"PreferredMetadataCountryCode",
"IsHD",
"ExternalEtag",
- "DateLastRefreshed"
+ "DateLastRefreshed",
+ "DateLastSaved",
+ "IsInMixedFolder",
+ "LockedFields",
+ "Studios",
+ "Audio",
+ "ExternalServiceId",
+ "Tags",
+ "IsFolder"
};
_saveItemCommand = _connection.CreateCommand();
_saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values (";
@@ -437,6 +483,16 @@ namespace MediaBrowser.Server.Implementations.Persistence
_savePersonCommand.Parameters.Add(_savePersonCommand, "@PersonType");
_savePersonCommand.Parameters.Add(_savePersonCommand, "@SortOrder");
_savePersonCommand.Parameters.Add(_savePersonCommand, "@ListOrder");
+
+ // Ancestors
+ _deleteAncestorsCommand = _connection.CreateCommand();
+ _deleteAncestorsCommand.CommandText = "delete from AncestorIds where ItemId=@Id";
+ _deleteAncestorsCommand.Parameters.Add(_deleteAncestorsCommand, "@Id");
+
+ _saveAncestorCommand = _connection.CreateCommand();
+ _saveAncestorCommand.CommandText = "insert into AncestorIds (ItemId, AncestorId) values (@ItemId, @AncestorId)";
+ _saveAncestorCommand.Parameters.Add(_saveAncestorCommand, "@ItemId");
+ _saveAncestorCommand.Parameters.Add(_saveAncestorCommand, "@AncestorId");
// Chapters
_deleteChaptersCommand = _connection.CreateCommand();
@@ -623,9 +679,41 @@ namespace MediaBrowser.Server.Implementations.Persistence
_saveItemCommand.GetParameter(index++).Value = item.DateLastRefreshed;
}
+ _saveItemCommand.GetParameter(index++).Value = item.DateLastSaved;
+ _saveItemCommand.GetParameter(index++).Value = item.IsInMixedFolder;
+ _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.LockedFields.Select(i => i.ToString()).ToArray());
+ _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Studios.ToArray());
+
+ if (item.Audio.HasValue)
+ {
+ _saveItemCommand.GetParameter(index++).Value = item.Audio.Value.ToString();
+ }
+ else
+ {
+ _saveItemCommand.GetParameter(index++).Value = null;
+ }
+
+ var tvItem = item as ILiveTvItem;
+ if (tvItem != null)
+ {
+ _saveItemCommand.GetParameter(index++).Value = tvItem.ServiceName;
+ }
+ else
+ {
+ _saveItemCommand.GetParameter(index++).Value = null;
+ }
+
+ _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Tags.ToArray());
+ _saveItemCommand.GetParameter(index++).Value = item.IsFolder;
+
_saveItemCommand.Transaction = transaction;
_saveItemCommand.ExecuteNonQuery();
+
+ if (item.SupportsAncestors)
+ {
+ UpdateAncestors(item.Id, item.GetAncestorIds().Distinct().ToList(), transaction);
+ }
}
transaction.Commit();
@@ -706,22 +794,32 @@ namespace MediaBrowser.Server.Implementations.Persistence
return null;
}
- BaseItem item;
+ BaseItem item = null;
using (var stream = reader.GetMemoryStream(1))
{
try
{
item = _jsonSerializer.DeserializeFromStream(stream, type) as BaseItem;
+ }
+ catch (SerializationException ex)
+ {
+ _logger.ErrorException("Error deserializing item", ex);
+ }
- if (item == null)
+ if (item == null)
+ {
+ try
+ {
+ item = Activator.CreateInstance(type) as BaseItem;
+ }
+ catch
{
- return null;
}
}
- catch (SerializationException ex)
+
+ if (item == null)
{
- _logger.ErrorException("Error deserializing item", ex);
return null;
}
}
@@ -844,6 +942,107 @@ namespace MediaBrowser.Server.Implementations.Persistence
item.DateLastRefreshed = reader.GetDateTime(23).ToUniversalTime();
}
+ if (!reader.IsDBNull(24))
+ {
+ item.Name = reader.GetString(24);
+ }
+
+ if (!reader.IsDBNull(25))
+ {
+ item.Path = reader.GetString(25);
+ }
+
+ if (!reader.IsDBNull(26))
+ {
+ item.PremiereDate = reader.GetDateTime(26).ToUniversalTime();
+ }
+
+ if (!reader.IsDBNull(27))
+ {
+ item.Overview = reader.GetString(27);
+ }
+
+ if (!reader.IsDBNull(28))
+ {
+ item.ParentIndexNumber = reader.GetInt32(28);
+ }
+
+ if (!reader.IsDBNull(29))
+ {
+ item.ProductionYear = reader.GetInt32(29);
+ }
+
+ if (!reader.IsDBNull(30))
+ {
+ item.OfficialRating = reader.GetString(30);
+ }
+
+ if (!reader.IsDBNull(31))
+ {
+ item.OfficialRating = reader.GetString(31);
+ }
+
+ if (!reader.IsDBNull(32))
+ {
+ item.HomePageUrl = reader.GetString(32);
+ }
+
+ if (!reader.IsDBNull(33))
+ {
+ item.DisplayMediaType = reader.GetString(33);
+ }
+
+ if (!reader.IsDBNull(34))
+ {
+ item.ForcedSortName = reader.GetString(34);
+ }
+
+ if (!reader.IsDBNull(35))
+ {
+ item.RunTimeTicks = reader.GetInt64(35);
+ }
+
+ if (!reader.IsDBNull(36))
+ {
+ item.VoteCount = reader.GetInt32(36);
+ }
+
+ if (!reader.IsDBNull(37))
+ {
+ item.DateCreated = reader.GetDateTime(37).ToUniversalTime();
+ }
+
+ if (!reader.IsDBNull(38))
+ {
+ item.DateModified = reader.GetDateTime(38).ToUniversalTime();
+ }
+
+ item.Id = reader.GetGuid(39);
+
+ if (!reader.IsDBNull(40))
+ {
+ item.Genres = reader.GetString(40).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
+ }
+
+ if (!reader.IsDBNull(41))
+ {
+ item.ParentId = reader.GetGuid(41);
+ }
+
+ if (!reader.IsDBNull(42))
+ {
+ item.Audio = (ProgramAudio)Enum.Parse(typeof(ProgramAudio), reader.GetString(42), true);
+ }
+
+ if (!reader.IsDBNull(43))
+ {
+ var tvItem = item as ILiveTvItem;
+ if (tvItem != null)
+ {
+ item.ForcedSortName = reader.GetString(43);
+ }
+ }
+
return item;
}
@@ -1168,6 +1367,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.Parameters.Add(cmd, "@ParentId", DbType.Guid).Value = parentId;
+ //_logger.Debug(cmd.CommandText);
+
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{
while (reader.Read())
@@ -1213,6 +1414,50 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
}
+ public IEnumerable<BaseItem> GetItemList(InternalItemsQuery query)
+ {
+ if (query == null)
+ {
+ throw new ArgumentNullException("query");
+ }
+
+ CheckDisposed();
+
+ using (var cmd = _connection.CreateCommand())
+ {
+ cmd.CommandText = "select " + string.Join(",", _retriveItemColumns) + " from TypedBaseItems";
+
+ var whereClauses = GetWhereClauses(query, cmd, true);
+
+ var whereText = whereClauses.Count == 0 ?
+ string.Empty :
+ " where " + string.Join(" AND ", whereClauses.ToArray());
+
+ cmd.CommandText += whereText;
+
+ cmd.CommandText += GetOrderByText(query);
+
+ if (query.Limit.HasValue)
+ {
+ cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(CultureInfo.InvariantCulture);
+ }
+
+ //_logger.Debug(cmd.CommandText);
+
+ using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
+ {
+ while (reader.Read())
+ {
+ var item = GetItem(reader);
+ if (item != null)
+ {
+ yield return item;
+ }
+ }
+ }
+ }
+ }
+
public QueryResult<BaseItem> GetItems(InternalItemsQuery query)
{
if (query == null)
@@ -1293,6 +1538,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
private string MapOrderByField(string name)
{
+ if (string.Equals(name, "airtime", StringComparison.OrdinalIgnoreCase))
+ {
+ // TODO
+ return "SortName";
+ }
+
return name;
}
@@ -1328,7 +1579,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
_logger.Debug(cmd.CommandText);
- using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
+ using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{
while (reader.Read())
{
@@ -1512,6 +1763,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
whereClauses.Add("IsSports=@IsSports");
cmd.Parameters.Add(cmd, "@IsSports", DbType.Boolean).Value = query.IsSports;
}
+ if (query.IsFolder.HasValue)
+ {
+ whereClauses.Add("IsFolder=@IsFolder");
+ cmd.Parameters.Add(cmd, "@IsFolder", DbType.Boolean).Value = query.IsFolder;
+ }
var includeTypes = query.IncludeItemTypes.SelectMany(MapIncludeItemTypes).ToArray();
if (includeTypes.Length == 1)
@@ -1572,6 +1828,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
cmd.Parameters.Add(cmd, "@MinStartDate", DbType.Date).Value = query.MinStartDate.Value;
}
+ if (query.MinPremiereDate.HasValue)
+ {
+ whereClauses.Add("PremiereDate>=@MinPremiereDate");
+ cmd.Parameters.Add(cmd, "@MinPremiereDate", DbType.Date).Value = query.MinPremiereDate.Value;
+ }
+
if (query.MaxStartDate.HasValue)
{
whereClauses.Add("StartDate<=@MaxStartDate");
@@ -1647,6 +1909,28 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
}
+ if (query.AncestorIds.Length == 1)
+ {
+ whereClauses.Add("Guid in (select itemId from AncestorIds where AncestorId=@AncestorId)");
+ cmd.Parameters.Add(cmd, "@AncestorId", DbType.Guid).Value = new Guid(query.AncestorIds[0]);
+ }
+ if (query.AncestorIds.Length > 1)
+ {
+ var inClause = string.Join(",", query.AncestorIds.Select(i => "'" + i + "'").ToArray());
+ whereClauses.Add(string.Format("Guid in (select itemId from AncestorIds where AncestorId in ({0}))", inClause));
+ }
+ if (query.ExcludeLocationTypes.Length == 1)
+ {
+ whereClauses.Add("LocationType<>@LocationType");
+ cmd.Parameters.Add(cmd, "@LocationType", DbType.String).Value = query.ExcludeLocationTypes[0].ToString();
+ }
+ if (query.ExcludeLocationTypes.Length > 1)
+ {
+ var val = string.Join(",", query.ExcludeLocationTypes.Select(i => "'" + i + "'").ToArray());
+
+ whereClauses.Add("LocationType not in (" + val + ")");
+ }
+
if (addPaging)
{
if (query.StartIndex.HasValue && query.StartIndex.Value > 0)
@@ -1681,6 +1965,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
typeof(Movie),
typeof(BoxSet),
typeof(Episode),
+ typeof(ChannelVideoItem),
typeof(Season),
typeof(Series),
typeof(Book),
@@ -1710,6 +1995,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
dict[t.Name] = new[] { t.FullName };
}
+ dict["ChannelItem"] = new[] { typeof(ChannelVideoItem).FullName, typeof(ChannelAudioItem).FullName, typeof(ChannelFolderItem).FullName };
dict["Recording"] = new[] { typeof(LiveTvAudioRecording).FullName, typeof(LiveTvVideoRecording).FullName };
dict["Program"] = new[] { typeof(LiveTvProgram).FullName };
dict["TvChannel"] = new[] { typeof(LiveTvChannel).FullName };
@@ -1767,6 +2053,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
_deleteStreamsCommand.GetParameter(0).Value = id;
_deleteStreamsCommand.Transaction = transaction;
_deleteStreamsCommand.ExecuteNonQuery();
+
+ // Delete ancestors
+ _deleteAncestorsCommand.GetParameter(0).Value = id;
+ _deleteAncestorsCommand.Transaction = transaction;
+ _deleteAncestorsCommand.ExecuteNonQuery();
// Delete the item
_deleteItemCommand.GetParameter(0).Value = id;
@@ -2001,6 +2292,37 @@ namespace MediaBrowser.Server.Implementations.Persistence
return whereClauses;
}
+ private void UpdateAncestors(Guid itemId, List<Guid> ancestorIds, IDbTransaction transaction)
+ {
+ if (itemId == Guid.Empty)
+ {
+ throw new ArgumentNullException("itemId");
+ }
+
+ if (ancestorIds == null)
+ {
+ throw new ArgumentNullException("ancestorIds");
+ }
+
+ CheckDisposed();
+
+ // First delete
+ _deleteAncestorsCommand.GetParameter(0).Value = itemId;
+ _deleteAncestorsCommand.Transaction = transaction;
+
+ _deleteAncestorsCommand.ExecuteNonQuery();
+
+ foreach (var ancestorId in ancestorIds)
+ {
+ _saveAncestorCommand.GetParameter(0).Value = itemId;
+ _saveAncestorCommand.GetParameter(1).Value = ancestorId;
+
+ _saveAncestorCommand.Transaction = transaction;
+
+ _saveAncestorCommand.ExecuteNonQuery();
+ }
+ }
+
public async Task UpdatePeople(Guid itemId, List<PersonInfo> people)
{
if (itemId == Guid.Empty)
@@ -2227,6 +2549,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
_saveStreamCommand.GetParameter(index++).Value = string.Join(",", stream.KeyFrames.Select(i => i.ToString(CultureInfo.InvariantCulture)).ToArray());
}
+ _saveStreamCommand.GetParameter(index++).Value = stream.CodecTag;
+
_saveStreamCommand.Transaction = transaction;
_saveStreamCommand.ExecuteNonQuery();
}
@@ -2388,6 +2712,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
}
+ if (!reader.IsDBNull(27))
+ {
+ item.CodecTag = reader.GetString(27);
+ }
+
return item;
}