GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/history_sql.h
Date: 2025-07-06 02:35:01
Exec Total Coverage
Lines: 15 17 88.2%
Branches: 10 20 50.0%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #ifndef CVMFS_HISTORY_SQL_H_
6 #define CVMFS_HISTORY_SQL_H_
7
8 #include <string>
9
10 #include "history.h"
11 #include "sql.h"
12
13 namespace history {
14
15 /**
16 * This class wraps the database structure of the History SQLite database files.
17 * For that it inherits from sqlite::Database<>, please look there for further
18 * details.
19 */
20 class HistoryDatabase : public sqlite::Database<HistoryDatabase> {
21 public:
22 static const float kLatestSchema;
23 static const float kLatestSupportedSchema;
24 // backwards-compatible schema changes
25 static const unsigned kLatestSchemaRevision;
26
27 static const std::string kFqrnKey;
28
29 bool CreateEmptyDatabase();
30 bool InsertInitialValues(const std::string &repository_name);
31
32 bool ContainsRecycleBin() const;
33
34 bool CheckSchemaCompatibility();
35 bool LiveSchemaUpgradeIfNecessary();
36 bool CompactDatabase() const {
37 return true;
38 } // no implementation specific
39 // database compaction.
40 protected:
41 // TODO(rmeusel): C++11 - constructor inheritance
42 friend class sqlite::Database<HistoryDatabase>;
43 2712 HistoryDatabase(const std::string &filename, const OpenMode open_mode)
44 2712 : sqlite::Database<HistoryDatabase>(filename, open_mode) { }
45
46 private:
47 bool CreateTagsTable();
48 bool CreateRecycleBinTable();
49 bool CreateBranchesTable();
50
51 bool UpgradeSchemaRevision_10_1();
52 bool UpgradeSchemaRevision_10_2();
53 bool UpgradeSchemaRevision_10_3();
54 };
55
56
57 //------------------------------------------------------------------------------
58
59
60 class SqlHistory : public sqlite::Sql { };
61
62
63 /**
64 * A mixin that allows to inject the RetrieveTag() method if it is needed in an
65 * SQL query subclass.
66 *
67 * This allows us to orchestrate specific functionality in those classes as we
68 * need it, without relying on multiple inheritance. Otherwise one would inherit
69 * from sqlite::Sql more than once when inheriting from more than one of those
70 * mixin classes in a query subclass.
71 * In contrast, the mixins produce a clear (single) inheritance graph for each
72 * of the derived classes by chaining the functionality as seen below.
73 *
74 * Example:
75 * class SqlListRollbackTags : public SqlRetrieveTag<SqlRollback<SqlHistory>> {}
76 *
77 * ################ Note: both SqlRetrieveTag and SqlRollback need the
78 * # sqlite::Sql # functionality provided in sqlite::Sql, thus
79 * ################ would otherwise be derived from it individually
80 * ´|`
81 * |
82 * ################ #################### #################
83 * # SqlHistory # <--- # SqlRetrieveTag # <--- # SqlRollback #
84 * ################ #################### #################
85 * ´|`
86 * |
87 * #########################
88 * # SqlListRollbackTags #
89 * #########################
90 *
91 * Note: MixinT needs to be eventually derived from sqlite::Sql as it uses
92 * Sql::Retrieve...() methods to extract information from SQLite rows.
93 *
94 * @param MixinT the class that should gain RetrieveTag()'s functionality
95 */
96 template<class MixinT>
97 class SqlRetrieveTag : public MixinT {
98 public:
99 /**
100 * Retrieves a tag from a database row
101 * See SqlHistory::db_fields for a listing of the used SQLite data fields
102 *
103 * @return a tag retrieved from the SQLite database row
104 */
105 7452 History::Tag RetrieveTag() const {
106 7452 History::Tag result;
107
1/2
✓ Branch 1 taken 3726 times.
✗ Branch 2 not taken.
7452 result.name = MixinT::RetrieveString(0);
108
2/4
✓ Branch 1 taken 3726 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 3726 times.
✗ Branch 6 not taken.
7452 result.root_hash = shash::MkFromHexPtr(
109 shash::HexPtr(MixinT::RetrieveString(1)), shash::kSuffixCatalog);
110
1/2
✓ Branch 1 taken 3726 times.
✗ Branch 2 not taken.
7452 result.revision = MixinT::RetrieveInt64(2);
111
1/2
✓ Branch 1 taken 3726 times.
✗ Branch 2 not taken.
7452 result.timestamp = MixinT::RetrieveInt64(3);
112
1/2
✓ Branch 1 taken 3726 times.
✗ Branch 2 not taken.
7452 result.description = MixinT::RetrieveString(5);
113
1/2
✓ Branch 1 taken 3726 times.
✗ Branch 2 not taken.
7452 result.size = MixinT::RetrieveInt64(6);
114
1/2
✓ Branch 1 taken 3726 times.
✗ Branch 2 not taken.
7452 result.branch = MixinT::RetrieveString(7);
115 7452 return result;
116 }
117 };
118
119
120 class SqlInsertTag : public SqlHistory {
121 private:
122 static const std::string db_placeholders;
123
124 public:
125 explicit SqlInsertTag(const HistoryDatabase *database);
126 bool BindTag(const History::Tag &tag);
127 };
128
129
130 class SqlRemoveTag : public SqlHistory {
131 public:
132 explicit SqlRemoveTag(const HistoryDatabase *database);
133 bool BindName(const std::string &name);
134 };
135
136
137 class SqlFindTag : public SqlRetrieveTag<SqlHistory> {
138 public:
139 explicit SqlFindTag(const HistoryDatabase *database);
140 bool BindName(const std::string &name);
141 };
142
143
144 class SqlFindTagByDate : public SqlRetrieveTag<SqlHistory> {
145 public:
146 explicit SqlFindTagByDate(const HistoryDatabase *database);
147 bool BindTimestamp(const time_t timestamp);
148 };
149
150
151 class SqlFindBranchHead : public SqlRetrieveTag<SqlHistory> {
152 public:
153 explicit SqlFindBranchHead(const HistoryDatabase *database);
154 bool BindBranchName(const std::string &branch_name);
155 };
156
157
158 class SqlCountTags : public SqlHistory {
159 public:
160 explicit SqlCountTags(const HistoryDatabase *database);
161 unsigned RetrieveCount() const;
162 };
163
164
165 class SqlListTags : public SqlRetrieveTag<SqlHistory> {
166 public:
167 explicit SqlListTags(const HistoryDatabase *database);
168 };
169
170
171 class SqlGetHashes : public SqlHistory {
172 public:
173 explicit SqlGetHashes(const HistoryDatabase *database);
174 shash::Any RetrieveHash() const;
175 };
176
177
178 class SqlListBranches : public SqlHistory {
179 public:
180 explicit SqlListBranches(const HistoryDatabase *database);
181 History::Branch RetrieveBranch() const;
182 };
183
184
185 class SqlInsertBranch : public SqlHistory {
186 public:
187 explicit SqlInsertBranch(const HistoryDatabase *database);
188 bool BindBranch(const History::Branch &branch);
189 };
190
191
192 /**
193 * Mixin to inject the rollback condition definition and the BindTargetTag()
194 * method into other subclasses.
195 *
196 * Note: See documentation of the SqlRetrieveTag<> for further details.
197 *
198 * @param MixinT the class that should gain BindTargetTags()'s functionality
199 * @param offset offset for SQLite placeholders, if used inside other complex
200 * SQL queries with preceding placeholders
201 */
202 template<class MixinT, int offset = 0>
203 class SqlRollback : public MixinT {
204 public:
205 15 bool BindTargetTag(const History::Tag &target_tag) {
206 15 return MixinT::BindInt64(offset + 1, target_tag.revision)
207
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
15 && MixinT::BindText(offset + 2, target_tag.name);
208 }
209 };
210
211
212 class SqlRollbackTag : public SqlRollback<SqlHistory> {
213 public:
214 explicit SqlRollbackTag(const HistoryDatabase *database);
215 };
216
217
218 class SqlListRollbackTags : public SqlRetrieveTag<SqlRollback<SqlHistory> > {
219 public:
220 explicit SqlListRollbackTags(const HistoryDatabase *database);
221 };
222
223
224 class SqlRecycleBin : public SqlHistory {
225 protected:
226 static const unsigned int kFlagCatalog = 1;
227
228 bool CheckSchema(const HistoryDatabase *database) const;
229 };
230
231
232 class SqlRecycleBinList : public SqlRecycleBin {
233 public:
234 explicit SqlRecycleBinList(const HistoryDatabase *database);
235 shash::Any RetrieveHash();
236 };
237
238
239 class SqlRecycleBinFlush : public SqlRecycleBin {
240 public:
241 explicit SqlRecycleBinFlush(const HistoryDatabase *database);
242 };
243
244 } // namespace history
245
246 #endif // CVMFS_HISTORY_SQL_H_
247