1 /*
2  *  Copyright (C) 2012-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #pragma once
10 
11 #include "dbwrappers/Database.h"
12 #include "threads/CriticalSection.h"
13 
14 #include <memory>
15 #include <vector>
16 
17 class CDateTime;
18 
19 namespace PVR
20 {
21   class CPVREpg;
22   class CPVREpgInfoTag;
23 
24   struct PVREpgSearchData;
25 
26   /** The EPG database */
27 
28   static constexpr int EPG_COMMIT_QUERY_COUNT_LIMIT = 10000;
29 
30   class CPVREpgDatabase : public CDatabase, public std::enable_shared_from_this<CPVREpgDatabase>
31   {
32   public:
33     /*!
34      * @brief Create a new instance of the EPG database.
35      */
36     CPVREpgDatabase() = default;
37 
38     /*!
39      * @brief Destroy this instance.
40      */
41     ~CPVREpgDatabase() override = default;
42 
43     /*!
44      * @brief Open the database.
45      * @return True if it was opened successfully, false otherwise.
46      */
47     bool Open() override;
48 
49     /*!
50      * @brief Close the database.
51      */
52     void Close() override;
53 
54     /*!
55      * @brief Lock the database.
56      */
57     void Lock();
58 
59     /*!
60      * @brief Unlock the database.
61      */
62     void Unlock();
63 
64     /*!
65      * @brief Get the minimal database version that is required to operate correctly.
66      * @return The minimal database version.
67      */
GetSchemaVersion()68     int GetSchemaVersion() const override { return 13; }
69 
70     /*!
71      * @brief Get the default sqlite database filename.
72      * @return The default filename.
73      */
GetBaseDBName()74     const char* GetBaseDBName() const override { return "Epg"; }
75 
76     /*! @name EPG methods */
77     //@{
78 
79     /*!
80      * @brief Remove all EPG information from the database
81      * @return True if the EPG information was erased, false otherwise.
82      */
83     bool DeleteEpg();
84 
85     /*!
86      * @brief Queue deletionof an EPG table.
87      * @param tag The table to queue for deletion.
88      * @return True on success, false otherwise.
89      */
90     bool QueueDeleteEpgQuery(const CPVREpg& table);
91 
92     /*!
93      * @brief Write the query to delete the given EPG tag to db query queue.
94      * @param tag The EPG tag to remove.
95      * @return True on success, false otherwise.
96      */
97     bool QueueDeleteTagQuery(const CPVREpgInfoTag& tag);
98 
99     /*!
100      * @brief Get all EPG tables from the database. Does not get the EPG tables' entries.
101      * @return The entries.
102      */
103     std::vector<std::shared_ptr<CPVREpg>> GetAll();
104 
105     /*!
106      * @brief Get all tags for a given EPG id.
107      * @param iEpgID The ID of the EPG.
108      * @return The entries.
109      */
110     std::vector<std::shared_ptr<CPVREpgInfoTag>> GetAllEpgTags(int iEpgID);
111 
112     /*!
113      * @brief Get the start time of the first tag in this EPG.
114      * @param iEpgID The ID of the EPG.
115      * @return The time.
116      */
117     CDateTime GetFirstStartTime(int iEpgID);
118 
119     /*!
120      * @brief Get the end time of the last tag in this EPG.
121      * @param iEpgID The ID of the EPG.
122      * @return The time.
123      */
124     CDateTime GetLastEndTime(int iEpgID);
125 
126     /*!
127      * @brief Get the start time of the first tag with a start time greater than the given min time.
128      * @param iEpgID The ID of the EPG.
129      * @param minStart The min start time.
130      * @return The time.
131      */
132     CDateTime GetMinStartTime(int iEpgID, const CDateTime& minStart);
133 
134     /*!
135      * @brief Get the end time of the first tag with an end time less than the given max time.
136      * @param iEpgID The ID of the EPG.
137      * @param maxEnd The mx end time.
138      * @return The time.
139      */
140     CDateTime GetMaxEndTime(int iEpgID, const CDateTime& maxEnd);
141 
142     /*!
143      * @brief Get all EPG tags matching the given search criteria.
144      * @param searchData The search criteria.
145      * @return The matching tags.
146      */
147     std::vector<std::shared_ptr<CPVREpgInfoTag>> GetEpgTags(const PVREpgSearchData& searchData);
148 
149     /*!
150      * @brief Get an EPG tag given its EPG id and unique broadcast ID.
151      * @param iEpgID The ID of the EPG for the tag to get.
152      * @param iUniqueBroadcastId The unique broadcast ID for the tag to get.
153      * @return The tag or nullptr, if not found.
154      */
155     std::shared_ptr<CPVREpgInfoTag> GetEpgTagByUniqueBroadcastID(int iEpgID,
156                                                                  unsigned int iUniqueBroadcastId);
157 
158     /*!
159      * @brief Get an EPG tag given its EPG id and database ID.
160      * @param iEpgID The ID of the EPG for the tag to get.
161      * @param iDatabaseId The database ID for the tag to get.
162      * @return The tag or nullptr, if not found.
163      */
164     std::shared_ptr<CPVREpgInfoTag> GetEpgTagByDatabaseID(int iEpgID, int iDatabaseId);
165 
166     /*!
167      * @brief Get an EPG tag given its EPG ID and start time.
168      * @param iEpgID The ID of the EPG for the tag to get.
169      * @param startTime The start time for the tag to get.
170      * @return The tag or nullptr, if not found.
171      */
172     std::shared_ptr<CPVREpgInfoTag> GetEpgTagByStartTime(int iEpgID, const CDateTime& startTime);
173 
174     /*!
175      * @brief Get the next EPG tag matching the given EPG id and min start time.
176      * @param iEpgID The ID of the EPG for the tag to get.
177      * @param minStartTime The min start time for the tag to get.
178      * @return The tag or nullptr, if not found.
179      */
180     std::shared_ptr<CPVREpgInfoTag> GetEpgTagByMinStartTime(int iEpgID,
181                                                             const CDateTime& minStartTime);
182 
183     /*!
184      * @brief Get the next EPG tag matching the given EPG id and max end time.
185      * @param iEpgID The ID of the EPG for the tag to get.
186      * @param maxEndTime The max end time for the tag to get.
187      * @return The tag or nullptr, if not found.
188      */
189     std::shared_ptr<CPVREpgInfoTag> GetEpgTagByMaxEndTime(int iEpgID, const CDateTime& maxEndTime);
190 
191     /*!
192      * @brief Get all EPG tags matching the given EPG id, min start time and max end time.
193      * @param iEpgID The ID of the EPG for the tags to get.
194      * @param minStartTime The min start time for the tags to get.
195      * @param maxEndTime The max end time for the tags to get.
196      * @return The tags or empty vector, if no tags were found.
197      */
198     std::vector<std::shared_ptr<CPVREpgInfoTag>> GetEpgTagsByMinStartMaxEndTime(
199         int iEpgID, const CDateTime& minStartTime, const CDateTime& maxEndTime);
200 
201     /*!
202      * @brief Get all EPG tags matching the given EPG id, min end time and max start time.
203      * @param iEpgID The ID of the EPG for the tags to get.
204      * @param minEndTime The min end time for the tags to get.
205      * @param maxStartTime The max start time for the tags to get.
206      * @return The tags or empty vector, if no tags were found.
207      */
208     std::vector<std::shared_ptr<CPVREpgInfoTag>> GetEpgTagsByMinEndMaxStartTime(
209         int iEpgID, const CDateTime& minEndTime, const CDateTime& maxStartTime);
210 
211     /*!
212      * @brief Write the query to delete all EPG tags in range of given EPG id, min end time and max
213      * start time to db query queue. .
214      * @param iEpgID The ID of the EPG for the tags to delete.
215      * @param minEndTime The min end time for the tags to delete.
216      * @param maxStartTime The max start time for the tags to delete.
217      * @return True if it was removed or queued successfully, false otherwise.
218      */
219     bool QueueDeleteEpgTagsByMinEndMaxStartTimeQuery(int iEpgID,
220                                                      const CDateTime& minEndTime,
221                                                      const CDateTime& maxStartTime);
222 
223     /*!
224      * @brief Get the last stored EPG scan time.
225      * @param iEpgId The table to update the time for. Use 0 for a global value.
226      * @param lastScan The last scan time or -1 if it wasn't found.
227      * @return True if the time was fetched successfully, false otherwise.
228      */
229     bool GetLastEpgScanTime(int iEpgId, CDateTime* lastScan);
230 
231     /*!
232      * @brief Write the query to update the last scan time for the given EPG to db query queue.
233      * @param iEpgId The table to update the time for.
234      * @param lastScanTime The time to write to the database.
235      * @return True on success, false otherwise.
236      */
237     bool QueuePersistLastEpgScanTimeQuery(int iEpgId, const CDateTime& lastScanTime);
238 
239     /*!
240      * @brief Write the query to delete the last scan time for the given EPG to db query queue.
241      * @param iEpgId The table to delete the time for.
242      * @return True on success, false otherwise.
243      */
244     bool QueueDeleteLastEpgScanTimeQuery(const CPVREpg& table);
245 
246     /*!
247      * @brief Persist an EPG table. It's entries are not persisted.
248      * @param epg The table to persist.
249      * @param bQueueWrite If true, don't execute the query immediately but queue it.
250      * @return The database ID of this entry or 0 if bQueueWrite is false and the query was queued.
251      */
252     int Persist(const CPVREpg& epg, bool bQueueWrite);
253 
254     /*!
255      * @brief Erase all EPG tags with the given epg ID and an end time less than the given time.
256      * @param iEpgId The ID of the EPG.
257      * @param maxEndTime The maximum allowed end time.
258      * @return True if the entries were removed successfully, false otherwise.
259      */
260     bool DeleteEpgTags(int iEpgId, const CDateTime& maxEndTime);
261 
262     /*!
263      * @brief Erase all EPG tags with the given epg ID.
264      * @param iEpgId The ID of the EPG.
265      * @return True if the entries were removed successfully, false otherwise.
266      */
267     bool DeleteEpgTags(int iEpgId);
268 
269     /*!
270      * @brief Queue the erase all EPG tags with the given epg ID.
271      * @param iEpgId The ID of the EPG.
272      * @return True if the entries were queued successfully, false otherwise.
273      */
274     bool QueueDeleteEpgTags(int iEpgId);
275 
276     /*!
277      * @brief Write the query to persist the given EPG tag to db query queue.
278      * @param tag The tag to persist.
279      * @return True on success, false otherwise.
280      */
281     bool QueuePersistQuery(const CPVREpgInfoTag& tag);
282 
283     /*!
284      * @return Last EPG id in the database
285      */
286     int GetLastEPGId();
287 
288     //@}
289 
290   private:
291     /*!
292      * @brief Create the EPG database tables.
293      */
294     void CreateTables() override;
295 
296     /*!
297      * @brief Create the EPG database analytics.
298      */
299     void CreateAnalytics() override;
300 
301     /*!
302      * @brief Update an old version of the database.
303      * @param version The version to update the database from.
304      */
305     void UpdateTables(int version) override;
306 
GetMinSchemaVersion()307     int GetMinSchemaVersion() const override { return 4; }
308 
309     std::shared_ptr<CPVREpgInfoTag> CreateEpgTag(const std::unique_ptr<dbiplus::Dataset>& pDS);
310 
311     CCriticalSection m_critSection;
312   };
313 }
314