GCC Code Coverage Report
Directory: cvmfs/ Exec Total Coverage
File: cvmfs/history_sql.h Lines: 35 36 97.2 %
Date: 2019-02-03 02:48:13 Branches: 25 51 49.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
117
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 { return true; }  // no implementation specific
37
                                                 // database compaction.
38
 protected:
39
  // TODO(rmeusel): C++11 - constructor inheritance
40
  friend class sqlite::Database<HistoryDatabase>;
41
117
  HistoryDatabase(const std::string  &filename,
42
                  const OpenMode      open_mode) :
43
117
    sqlite::Database<HistoryDatabase>(filename, open_mode) {}
44
45
 private:
46
  bool CreateTagsTable();
47
  bool CreateRecycleBinTable();
48
  bool CreateBranchesTable();
49
50
  bool UpgradeSchemaRevision_10_1();
51
  bool UpgradeSchemaRevision_10_2();
52
  bool UpgradeSchemaRevision_10_3();
53
};
54
55
56
//------------------------------------------------------------------------------
57
58
59
3194
class SqlHistory : public sqlite::Sql {};
60
61
62
/**
63
 * A mixin that allows to inject the RetrieveTag() method if it is needed in an
64
 * SQL query subclass.
65
 *
66
 * This allows us to orchestrate specific functionality in those classes as we
67
 * need it, without relying on multiple inheritance. Otherwise one would inherit
68
 * from sqlite::Sql more than once when inheriting from more than one of those
69
 * mixin classes in a query subclass.
70
 * In contrast, the mixins produce a clear (single) inheritance graph for each
71
 * of the derived classes by chaining the functionality as seen below.
72
 *
73
 * Example:
74
 * class SqlListRollbackTags : public SqlRetrieveTag<SqlRollback<SqlHistory>> {}
75
 *
76
 *    ################     Note: both SqlRetrieveTag and SqlRollback need the
77
 *    # sqlite::Sql  #           functionality provided in sqlite::Sql, thus
78
 *    ################           would otherwise be derived from it individually
79
 *          ��|`
80
 *           |
81
 *    ################      ####################      #################
82
 *    #  SqlHistory  # <--- #  SqlRetrieveTag  # <--- #  SqlRollback  #
83
 *    ################      ####################      #################
84
 *                                                           ��|`
85
 *                                                            |
86
 *                                                #########################
87
 *                                                #  SqlListRollbackTags  #
88
 *                                                #########################
89
 *
90
 * Note: MixinT needs to be eventually derived from sqlite::Sql as it uses
91
 *       Sql::Retrieve...() methods to extract information from SQLite rows.
92
 *
93
 * @param MixinT  the class that should gain RetrieveTag()'s functionality
94
 */
95
template <class MixinT>
96

1352
class SqlRetrieveTag : public MixinT {
97
 public:
98
  /**
99
   * Retrieves a tag from a database row
100
   * See SqlHistory::db_fields for a listing of the used SQLite data fields
101
   *
102
   * @return  a tag retrieved from the SQLite database row
103
   */
104
1248
  History::Tag RetrieveTag() const {
105
1248
    History::Tag result;
106
1248
    result.name        = MixinT::RetrieveString(0);
107

1248
    result.root_hash   = shash::MkFromHexPtr(
108
                           shash::HexPtr(MixinT::RetrieveString(1)),
109
                           shash::kSuffixCatalog);
110
1248
    result.revision    = MixinT::RetrieveInt64(2);
111
1248
    result.timestamp   = MixinT::RetrieveInt64(3);
112
1248
    result.channel     = static_cast<History::UpdateChannel>(
113
                           MixinT::RetrieveInt64(4));
114
1248
    result.description = MixinT::RetrieveString(5);
115
1248
    result.size        = MixinT::RetrieveInt64(6);
116
1248
    result.branch      = MixinT::RetrieveString(7);
117
1248
    return result;
118
  }
119
};
120
121
122
182
class SqlInsertTag : public SqlHistory {
123
 private:
124
  static const std::string db_placeholders;
125
126
 public:
127
  explicit SqlInsertTag(const HistoryDatabase *database);
128
  bool BindTag(const History::Tag &tag);
129
};
130
131
132
182
class SqlRemoveTag : public SqlHistory {
133
 public:
134
  explicit SqlRemoveTag(const HistoryDatabase *database);
135
  bool BindName(const std::string &name);
136
};
137
138
139
234
class SqlFindTag : public SqlRetrieveTag<SqlHistory> {
140
 public:
141
  explicit SqlFindTag(const HistoryDatabase *database);
142
  bool BindName(const std::string &name);
143
};
144
145
146
234
class SqlFindTagByDate : public SqlRetrieveTag<SqlHistory> {
147
 public:
148
  explicit SqlFindTagByDate(const HistoryDatabase *database);
149
  bool BindTimestamp(const time_t timestamp);
150
};
151
152
153
182
class SqlFindBranchHead : public SqlRetrieveTag<SqlHistory> {
154
 public:
155
  explicit SqlFindBranchHead(const HistoryDatabase *database);
156
  bool BindBranchName(const std::string &branch_name);
157
};
158
159
160
234
class SqlCountTags : public SqlHistory {
161
 public:
162
  explicit SqlCountTags(const HistoryDatabase *database);
163
  unsigned RetrieveCount() const;
164
};
165
166
167
234
class SqlListTags : public SqlRetrieveTag<SqlHistory> {
168
 public:
169
  explicit SqlListTags(const HistoryDatabase *database);
170
};
171
172
173
234
class SqlGetChannelTips : public SqlRetrieveTag<SqlHistory> {
174
 public:
175
  explicit SqlGetChannelTips(const HistoryDatabase *database);
176
};
177
178
179
234
class SqlGetHashes : public SqlHistory {
180
 public:
181
  explicit SqlGetHashes(const HistoryDatabase *database);
182
  shash::Any RetrieveHash() const;
183
};
184
185
186
234
class SqlListBranches : public SqlHistory {
187
 public:
188
  explicit SqlListBranches(const HistoryDatabase *database);
189
  History::Branch RetrieveBranch() const;
190
};
191
192
193
182
class SqlInsertBranch : public SqlHistory {
194
 public:
195
  explicit SqlInsertBranch(const HistoryDatabase *database);
196
  bool BindBranch(const History::Branch &branch);
197
};
198
199
200
/**
201
 * Mixin to inject the rollback condition definition and the BindTargetTag()
202
 * method into other subclasses.
203
 *
204
 * Note: See documentation of the SqlRetrieveTag<> for further details.
205
 *
206
 * @param MixinT  the class that should gain BindTargetTags()'s functionality
207
 * @param offset  offset for SQLite placeholders, if used inside other complex
208
 *                SQL queries with preceeding placeholders
209
 */
210
template <class MixinT, int offset = 0>
211
416
class SqlRollback : public MixinT {
212
 protected:
213
  static const std::string rollback_condition;
214
215
 public:
216
7
  bool BindTargetTag(const History::Tag &target_tag) {
217
    return MixinT::BindInt64(offset + 1, target_tag.revision) &&
218
           MixinT::BindText(offset + 2, target_tag.name) &&
219

7
           MixinT::BindInt64(offset + 3, target_tag.channel);
220
  }
221
};
222
223
template <class MixinT, int offset>
224
const std::string SqlRollback<MixinT, offset>::rollback_condition =
225
                                             "(revision > :target_rev  OR "
226
                                             " name     = :target_name)   "
227
                                             "AND channel  = :target_chan ";
228
229
230
182
class SqlRollbackTag : public SqlRollback<SqlHistory> {
231
 public:
232
  explicit SqlRollbackTag(const HistoryDatabase *database);
233
};
234
235
236
234
class SqlListRollbackTags : public SqlRetrieveTag<SqlRollback<SqlHistory> > {
237
 public:
238
  explicit SqlListRollbackTags(const HistoryDatabase *database);
239
};
240
241
242
412
class SqlRecycleBin : public SqlHistory {
243
 protected:
244
  static const unsigned int kFlagCatalog = 1;
245
246
  bool CheckSchema(const HistoryDatabase *database) const;
247
};
248
249
250
230
class SqlRecycleBinList : public SqlRecycleBin {
251
 public:
252
  explicit SqlRecycleBinList(const HistoryDatabase *database);
253
  shash::Any RetrieveHash();
254
};
255
256
257
182
class SqlRecycleBinFlush : public SqlRecycleBin {
258
 public:
259
  explicit SqlRecycleBinFlush(const HistoryDatabase *database);
260
};
261
262
}  // namespace history
263
264
#endif  // CVMFS_HISTORY_SQL_H_