GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/sql_impl.h
Date: 2024-04-21 02:33:16
Exec Total Coverage
Lines: 220 252 87.3%
Branches: 207 451 45.9%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM file system.
3 */
4
5 #ifndef CVMFS_SQL_IMPL_H_
6 #define CVMFS_SQL_IMPL_H_
7
8 #include <fcntl.h>
9
10 #include <cassert>
11 #include <cerrno>
12 #include <string>
13
14 #include "sqlitemem.h"
15 #include "util/logging.h"
16 #include "util/platform.h"
17
18 namespace sqlite {
19
20 template <class DerivedT>
21 442 Database<DerivedT>::Database(const std::string &filename,
22 const OpenMode open_mode)
23 442 : database_(filename, this)
24 442 , read_write_(kOpenReadWrite == open_mode)
25 442 , schema_version_(0.0f)
26
5/10
✓ Branch 2 taken 442 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 442 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 442 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 442 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 442 times.
✗ Branch 15 not taken.
884 , schema_revision_(0) {}
27
28
29 template <class DerivedT>
30 228 DerivedT* Database<DerivedT>::Create(const std::string &filename) {
31
3/6
✓ Branch 1 taken 228 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 228 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 116 times.
✗ Branch 8 not taken.
228 UniquePtr<DerivedT> database(new DerivedT(filename, kOpenReadWrite));
32
33
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 228 times.
228 if (!database.IsValid()) {
34 LogCvmfs(kLogSql, kLogDebug, "Failed to create new database object");
35 return NULL;
36 }
37
38 228 database->set_schema_version(DerivedT::kLatestSchema);
39 228 database->set_schema_revision(DerivedT::kLatestSchemaRevision);
40
41 228 const int open_flags = SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_READWRITE |
42 SQLITE_OPEN_CREATE;
43
2/4
✓ Branch 2 taken 228 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 228 times.
228 if (!database->OpenDatabase(open_flags)) {
44 LogCvmfs(kLogSql, kLogDebug, "Failed to create new database file");
45 return NULL;
46 }
47
48
2/4
✓ Branch 2 taken 228 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 228 times.
228 if (!database->CreatePropertiesTable()) {
49 database->PrintSqlError("Failed to create common properties table");
50 return NULL;
51 }
52
53
2/4
✓ Branch 2 taken 228 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 228 times.
228 if (!database->CreateEmptyDatabase()) {
54 database->PrintSqlError("Failed to create empty database");
55 return NULL;
56 }
57
58
2/4
✓ Branch 2 taken 228 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 228 times.
228 if (!database->PrepareCommonQueries()) {
59 database->PrintSqlError("Failed to initialize properties queries");
60 return NULL;
61 }
62
63
2/4
✓ Branch 2 taken 228 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 228 times.
228 if (!database->StoreSchemaRevision()) {
64 database->PrintSqlError("Failed to store initial schema revision");
65 return NULL;
66 }
67
68 228 return database.Release();
69 228 }
70
71
72 template <class DerivedT>
73 214 DerivedT* Database<DerivedT>::Open(const std::string &filename,
74 const OpenMode open_mode) {
75
3/6
✓ Branch 1 taken 214 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 214 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 176 times.
✗ Branch 8 not taken.
214 UniquePtr<DerivedT> database(new DerivedT(filename, open_mode));
76
77
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 214 times.
214 if (!database.IsValid()) {
78 LogCvmfs(kLogSql, kLogDebug,
79 "Failed to open database file '%s' - errno: %d",
80 filename.c_str(), errno);
81 return NULL;
82 }
83
84
3/4
✓ Branch 2 taken 214 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 210 times.
214 if (!database->Initialize()) {
85 4 return NULL;
86 }
87
88 210 return database.Release();
89 214 }
90
91
92 template <class DerivedT>
93 214 bool Database<DerivedT>::Initialize() {
94
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 88 times.
214 const int flags = (read_write_) ? SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_READWRITE
95 : SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_READONLY;
96
97
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
214 bool successful = OpenDatabase(flags) &&
98
1/2
✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
212 Configure() &&
99
3/4
✓ Branch 0 taken 212 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 212 times.
✗ Branch 4 not taken.
638 FileReadAhead() &&
100
1/2
✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
212 PrepareCommonQueries();
101
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 212 times.
214 if (!successful) {
102 2 LogCvmfs(kLogSql, kLogDebug, "failed to open database file '%s'",
103 2 filename().c_str());
104 2 return false;
105 }
106
107 212 ReadSchemaRevision();
108 212 LogCvmfs(kLogSql, kLogDebug, "opened database with schema version %f "
109 "and revision %u",
110 212 schema_version_, schema_revision_);
111
112
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 211 times.
212 if (!static_cast<DerivedT*>(this)->CheckSchemaCompatibility()) {
113 2 LogCvmfs(kLogSql, kLogDebug, "schema version %f not supported (%s)",
114 1 schema_version_, filename().c_str());
115 1 return false;
116 }
117
118
4/4
✓ Branch 0 taken 125 times.
✓ Branch 1 taken 86 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 210 times.
336 if (read_write_ &&
119
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 124 times.
125 !static_cast<DerivedT*>(this)->LiveSchemaUpgradeIfNecessary()) {
120 1 LogCvmfs(kLogSql, kLogDebug, "failed tp upgrade schema revision");
121 1 return false;
122 }
123
124 210 return true;
125 }
126
127
128 template <class DerivedT>
129 442 bool Database<DerivedT>::OpenDatabase(const int flags) {
130 // Open database file (depending on the flags read-only or read-write)
131 442 LogCvmfs(kLogSql, kLogDebug, "opening database file %s",
132 442 filename().c_str());
133 442 int retval = sqlite3_open_v2(filename().c_str(),
134 &database_.sqlite_db,
135 flags | SQLITE_OPEN_EXRESCODE,
136 NULL);
137
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 440 times.
442 if (retval != SQLITE_OK) {
138 2 LogCvmfs(kLogSql, kLogDebug, "cannot open database file %s (%d - %d)",
139 2 filename().c_str(), retval, errno);
140 2 return false;
141 }
142
143 440 return true;
144 }
145
146
147 template <class DerivedT>
148 475 Database<DerivedT>::DatabaseRaiiWrapper::~DatabaseRaiiWrapper() {
149
1/2
✓ Branch 0 taken 439 times.
✗ Branch 1 not taken.
475 if (NULL != sqlite_db) {
150 475 const bool close_successful = Close();
151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 439 times.
475 assert(close_successful);
152 }
153 475 }
154
155
156 template <class DerivedT>
157 475 bool Database<DerivedT>::DatabaseRaiiWrapper::Close() {
158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 439 times.
475 assert(NULL != sqlite_db);
159
160
2/2
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 337 times.
950 LogCvmfs(kLogSql, kLogDebug, "closing SQLite database '%s' (unlink: %s)",
161 475 filename().c_str(),
162 475 (db_file_guard.IsEnabled() ? "yes" : "no"));
163 475 const int result = sqlite3_close(sqlite_db);
164
165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 439 times.
475 if (result != SQLITE_OK) {
166 LogCvmfs(kLogSql, kLogDebug,
167 "failed to close SQLite database '%s' (%d - %s)",
168 filename().c_str(), result,
169 delegate_->GetLastErrorMsg().c_str());
170 return false;
171 }
172
173 475 sqlite_db = NULL;
174
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 405 times.
475 if (lookaside_buffer != NULL) {
175 34 SqliteMemoryManager::GetInstance()->ReleaseLookasideBuffer(
176 lookaside_buffer);
177 34 lookaside_buffer = NULL;
178 }
179 475 return true;
180 }
181
182
183 template <class DerivedT>
184 212 bool Database<DerivedT>::Configure() {
185 // Read-only databases should store temporary files in memory. This avoids
186 // unexpected open read-write file descriptors in the cache directory like
187 // etilqs_<number>. They also use the optimized memory manager, if it is
188 // available.
189
2/2
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 126 times.
212 if (!read_write_) {
190
2/2
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 52 times.
86 if (SqliteMemoryManager::HasInstance()) {
191 34 database_.lookaside_buffer =
192 34 SqliteMemoryManager::GetInstance()->AssignLookasideBuffer(sqlite_db());
193 }
194
195
7/22
✓ Branch 2 taken 86 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 86 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 86 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 86 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 86 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 86 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 86 times.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
258 return Sql(sqlite_db() , "PRAGMA temp_store=2;").Execute() &&
196
9/24
✓ Branch 2 taken 86 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 86 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 86 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 86 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 86 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 86 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 86 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 86 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 86 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
172 Sql(sqlite_db() , "PRAGMA locking_mode=EXCLUSIVE;").Execute();
197 }
198 126 return true;
199 }
200
201
202 template <class DerivedT>
203 212 bool Database<DerivedT>::FileReadAhead() {
204 // Read-ahead into file system buffers
205 // TODO(jblomer): mmap, re-readahead
206
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 212 times.
212 assert(filename().length() > 1);
207 int fd_readahead;
208
2/2
✓ Branch 2 taken 178 times.
✓ Branch 3 taken 34 times.
212 if (filename()[0] != '@') {
209 178 fd_readahead = open(filename().c_str(), O_RDONLY);
210
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 178 times.
178 if (fd_readahead < 0) {
211 LogCvmfs(kLogSql, kLogDebug, "failed to open %s for read-ahead (%d)",
212 filename().c_str(), errno);
213 return false;
214 }
215 178 const ssize_t retval = platform_readahead(fd_readahead);
216 178 close(fd_readahead);
217
218 // Read-ahead is known to fail on tmpfs with EINVAL
219 // EINVAL = "readahead() cannot be applied to that a file type"
220 // Don't consider it a fatal error.
221
2/4
✓ Branch 0 taken 178 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 178 times.
178 if (retval != 0 && errno != EINVAL) {
222 LogCvmfs(kLogSql, kLogDebug | kLogSyslogWarn,
223 "failed to read-ahead %s: invalid file descrp. or not open for reading",
224 filename().c_str());
225 return false;
226 }
227 }
228
229 212 return true;
230 }
231
232
233 template <class DerivedT>
234 440 bool Database<DerivedT>::PrepareCommonQueries() {
235 440 sqlite3 *db = sqlite_db();
236
4/8
✓ Branch 2 taken 440 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 440 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 440 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 440 times.
✗ Branch 12 not taken.
440 begin_transaction_ = new Sql(db, "BEGIN;");
237
4/8
✓ Branch 2 taken 440 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 440 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 440 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 440 times.
✗ Branch 12 not taken.
440 commit_transaction_ = new Sql(db, "COMMIT;");
238
4/8
✓ Branch 2 taken 440 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 440 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 440 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 440 times.
✗ Branch 12 not taken.
440 has_property_ = new Sql(db, "SELECT count(*) FROM properties "
239 "WHERE key = :key;");
240
4/8
✓ Branch 2 taken 440 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 440 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 440 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 440 times.
✗ Branch 12 not taken.
440 get_property_ = new Sql(db, "SELECT value FROM properties "
241 "WHERE key = :key;");
242
4/8
✓ Branch 2 taken 440 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 440 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 440 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 440 times.
✗ Branch 12 not taken.
440 set_property_ = new Sql(db, "INSERT OR REPLACE INTO properties "
243 "(key, value) VALUES (:key, :value);");
244
1/2
✓ Branch 1 taken 440 times.
✗ Branch 2 not taken.
880 return (begin_transaction_.IsValid() &&
245
1/2
✓ Branch 1 taken 440 times.
✗ Branch 2 not taken.
880 commit_transaction_.IsValid() &&
246
1/2
✓ Branch 1 taken 440 times.
✗ Branch 2 not taken.
880 has_property_.IsValid() &&
247
2/4
✓ Branch 0 taken 440 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 440 times.
✗ Branch 4 not taken.
1320 get_property_.IsValid() &&
248 880 set_property_.IsValid());
249 }
250
251
252 template <class DerivedT>
253 212 void Database<DerivedT>::ReadSchemaRevision() {
254
2/4
✓ Branch 2 taken 212 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 212 times.
✗ Branch 6 not taken.
424 schema_version_ = (this->HasProperty(kSchemaVersionKey))
255
5/15
✓ Branch 0 taken 212 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 212 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 212 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 212 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 212 times.
✗ Branch 13 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
212 ? this->GetProperty<double>(kSchemaVersionKey)
256 : 1.0;
257
2/4
✓ Branch 2 taken 212 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 212 times.
✗ Branch 6 not taken.
424 schema_revision_ = (this->HasProperty(kSchemaRevisionKey))
258
8/15
✓ Branch 0 taken 207 times.
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 207 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 207 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 207 times.
✓ Branch 10 taken 5 times.
✓ Branch 12 taken 207 times.
✓ Branch 13 taken 5 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
212 ? this->GetProperty<int>(kSchemaRevisionKey)
259 : 0;
260 212 }
261
262
263 template <class DerivedT>
264 248 bool Database<DerivedT>::StoreSchemaRevision() {
265
4/14
✓ Branch 2 taken 248 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 248 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 248 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 248 times.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
744 return this->SetProperty(kSchemaVersionKey, schema_version_) &&
266
6/17
✓ Branch 2 taken 248 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 248 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 248 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 248 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 248 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 248 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
744 this->SetProperty(kSchemaRevisionKey, schema_revision_);
267 }
268
269
270 template <class DerivedT>
271 206 bool Database<DerivedT>::BeginTransaction() const {
272
2/4
✓ Branch 2 taken 203 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
409 return begin_transaction_->Execute() &&
273
1/2
✓ Branch 2 taken 203 times.
✗ Branch 3 not taken.
409 begin_transaction_->Reset();
274 }
275
276
277 template <class DerivedT>
278 195 bool Database<DerivedT>::CommitTransaction() const {
279
1/4
✓ Branch 2 taken 195 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
390 return commit_transaction_->Execute() &&
280
1/2
✓ Branch 2 taken 195 times.
✗ Branch 3 not taken.
390 commit_transaction_->Reset();
281 }
282
283
284 template <class DerivedT>
285 228 bool Database<DerivedT>::CreatePropertiesTable() {
286
3/6
✓ Branch 2 taken 228 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 228 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 228 times.
✗ Branch 9 not taken.
456 return Sql(sqlite_db(),
287 "CREATE TABLE properties (key TEXT, value TEXT, "
288
1/2
✓ Branch 1 taken 228 times.
✗ Branch 2 not taken.
456 "CONSTRAINT pk_properties PRIMARY KEY (key));").Execute();
289 }
290
291
292 template <class DerivedT>
293 1043 bool Database<DerivedT>::HasProperty(const std::string &key) const {
294
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1043 times.
1043 assert(has_property_.IsValid());
295
1/4
✓ Branch 2 taken 1043 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2086 const bool retval = has_property_->BindText(1, key) &&
296
1/2
✓ Branch 2 taken 1043 times.
✗ Branch 3 not taken.
1043 has_property_->FetchRow();
297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1043 times.
1043 assert(retval);
298 1043 const bool result = has_property_->RetrieveInt64(0) > 0;
299 1043 has_property_->Reset();
300 1043 return result;
301 }
302
303 template <class DerivedT>
304 template <typename T>
305 1492 T Database<DerivedT>::GetProperty(const std::string &key) const {
306
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 746 times.
1492 assert(get_property_.IsValid());
307
1/4
✓ Branch 2 taken 746 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2984 const bool retval = get_property_->BindText(1, key) &&
308
1/2
✓ Branch 2 taken 746 times.
✗ Branch 3 not taken.
1492 get_property_->FetchRow();
309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 746 times.
1492 assert(retval);
310 1492 const T result = get_property_->Retrieve<T>(0);
311
1/2
✓ Branch 2 taken 126 times.
✗ Branch 3 not taken.
1492 get_property_->Reset();
312 1492 return result;
313 }
314
315 template <class DerivedT>
316 template <typename T>
317 610 T Database<DerivedT>::GetPropertyDefault(const std::string &key,
318 const T default_value) const {
319
2/2
✓ Branch 1 taken 132 times.
✓ Branch 2 taken 168 times.
610 return (HasProperty(key)) ? GetProperty<T>(key)
320
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
610 : default_value;
321 }
322
323 template <class DerivedT>
324 template <typename T>
325 2270 bool Database<DerivedT>::SetProperty(const std::string &key,
326 const T value) {
327
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1149 times.
2270 assert(set_property_.IsValid());
328
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2270 return set_property_->BindText(1, key) &&
329
1/2
✓ Branch 2 taken 1149 times.
✗ Branch 3 not taken.
2270 set_property_->Bind(2, value) &&
330
2/4
✓ Branch 0 taken 1149 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 1149 times.
✗ Branch 5 not taken.
6810 set_property_->Execute() &&
331
1/2
✓ Branch 2 taken 1149 times.
✗ Branch 3 not taken.
4540 set_property_->Reset();
332 }
333
334 template <class DerivedT>
335 std::string Database<DerivedT>::GetLastErrorMsg() const {
336 std::string msg = sqlite3_errmsg(sqlite_db());
337 return msg;
338 }
339
340
341 template <class DerivedT>
342 106 void Database<DerivedT>::TakeFileOwnership() {
343 106 database_.TakeFileOwnership();
344 106 LogCvmfs(kLogSql, kLogDebug, "Database object took ownership of '%s'",
345 106 database_.filename().c_str());
346 106 }
347
348
349 template <class DerivedT>
350 4 void Database<DerivedT>::DropFileOwnership() {
351 4 database_.DropFileOwnership();
352 4 LogCvmfs(kLogSql, kLogDebug, "Database object dropped ownership of '%s'",
353 4 database_.filename().c_str());
354 4 }
355
356
357 template <class DerivedT>
358 11 unsigned Database<DerivedT>::GetModifiedRowCount() const {
359 11 const int modified_rows = sqlite3_total_changes(sqlite_db());
360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 assert(modified_rows >= 0);
361 11 return static_cast<unsigned>(modified_rows);
362 }
363
364 /**
365 * Ask SQlite for per-connection memory statistics
366 */
367 template <class DerivedT>
368 1 void Database<DerivedT>::GetMemStatistics(MemStatistics *stats) const {
369 1 const int reset = 0;
370 int current;
371 int highwater;
372 1 int retval = SQLITE_OK;
373
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 retval |= sqlite3_db_status(sqlite_db(), SQLITE_DBSTATUS_LOOKASIDE_USED,
374 &current, &highwater, reset);
375 1 stats->lookaside_slots_used = current;
376 1 stats->lookaside_slots_max = highwater;
377
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 retval |= sqlite3_db_status(sqlite_db(), SQLITE_DBSTATUS_LOOKASIDE_HIT,
378 &current, &highwater, reset);
379 1 stats->lookaside_hit = highwater;
380
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 retval |= sqlite3_db_status(sqlite_db(), SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
381 &current, &highwater, reset);
382 1 stats->lookaside_miss_size = highwater;
383
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 retval |= sqlite3_db_status(sqlite_db(), SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
384 &current, &highwater, reset);
385 1 stats->lookaside_miss_full = highwater;
386
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 retval |= sqlite3_db_status(sqlite_db(), SQLITE_DBSTATUS_CACHE_USED,
387 &current, &highwater, reset);
388 1 stats->page_cache_used = current;
389
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 retval |= sqlite3_db_status(sqlite_db(), SQLITE_DBSTATUS_CACHE_HIT,
390 &current, &highwater, reset);
391 1 stats->page_cache_hit = current;
392
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 retval |= sqlite3_db_status(sqlite_db(), SQLITE_DBSTATUS_CACHE_MISS,
393 &current, &highwater, reset);
394 1 stats->page_cache_miss = current;
395
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 retval |= sqlite3_db_status(sqlite_db(), SQLITE_DBSTATUS_SCHEMA_USED,
396 &current, &highwater, reset);
397 1 stats->schema_used = current;
398
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 retval |= sqlite3_db_status(sqlite_db(), SQLITE_DBSTATUS_STMT_USED,
399 &current, &highwater, reset);
400 1 stats->stmt_used = current;
401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(retval == SQLITE_OK);
402 1 }
403
404
405 template <class DerivedT>
406 58 double Database<DerivedT>::GetFreePageRatio() const {
407
3/6
✓ Branch 2 taken 58 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 58 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 58 times.
✗ Branch 9 not taken.
116 Sql free_page_count_query(this->sqlite_db(), "PRAGMA freelist_count;");
408
3/6
✓ Branch 2 taken 58 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 58 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 58 times.
✗ Branch 9 not taken.
116 Sql page_count_query(this->sqlite_db(), "PRAGMA page_count;");
409
410
2/4
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 58 times.
✗ Branch 4 not taken.
116 const bool retval = page_count_query.FetchRow() &&
411
2/4
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 58 times.
✗ Branch 4 not taken.
58 free_page_count_query.FetchRow();
412
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 assert(retval);
413
414
1/2
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
58 int64_t pages = page_count_query.RetrieveInt64(0);
415
1/2
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
58 int64_t free_pages = free_page_count_query.RetrieveInt64(0);
416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 assert(pages > 0);
417
418 58 return (static_cast<double>(free_pages) / static_cast<double>(pages));
419 58 }
420
421
422 template <class DerivedT>
423 18 bool Database<DerivedT>::Vacuum() const {
424
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 assert(read_write_);
425
3/4
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
35 return static_cast<const DerivedT*>(this)->CompactDatabase() &&
426
11/22
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 17 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 17 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 17 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 17 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 17 times.
✓ Branch 16 taken 1 times.
✓ Branch 18 taken 17 times.
✓ Branch 19 taken 1 times.
✓ Branch 21 taken 17 times.
✓ Branch 22 taken 1 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
35 Sql(this->sqlite_db(), "VACUUM;").Execute();
427 }
428
429
430 template <class DerivedT>
431 void Database<DerivedT>::PrintSqlError(const std::string &error_msg) {
432 LogCvmfs(kLogSql, kLogStderr, "%s\nSQLite said: '%s'",
433 error_msg.c_str(), this->GetLastErrorMsg().c_str());
434 }
435
436 template <class DerivedT>
437 const float Database<DerivedT>::kSchemaEpsilon = 0.0005;
438 template <class DerivedT>
439 const char *Database<DerivedT>::kSchemaVersionKey = "schema";
440 template <class DerivedT>
441 const char *Database<DerivedT>::kSchemaRevisionKey = "schema_revision";
442
443
444 //
445 // # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
446 //
447
448
449 template <>
450 101 inline bool Sql::Bind(const int index, const int &value) {
451 101 return this->BindInt64(index, value);
452 }
453
454 template <>
455 268 inline bool Sql::Bind(const int index, const unsigned int &value) {
456 268 return this->BindInt64(index, static_cast<int>(value));
457 }
458
459 template <>
460 283 inline bool Sql::Bind(const int index, const uint64_t &value) {
461 283 return this->BindInt64(index, static_cast<int64_t>(value));
462 }
463
464 template <>
465 inline bool Sql::Bind(const int index, const sqlite3_int64 &value) {
466 return this->BindInt64(index, value);
467 }
468
469 template <>
470 245 inline bool Sql::Bind(const int index, const std::string &value) {
471 245 return this->BindTextTransient(index, value);
472 }
473
474 template <>
475 248 inline bool Sql::Bind(const int index, const float &value) {
476 248 return this->BindDouble(index, value);
477 }
478
479 template <>
480 4 inline bool Sql::Bind(const int index, const double &value) {
481 4 return this->BindDouble(index, value);
482 }
483
484
485 template <>
486 273 inline int Sql::Retrieve(const int index) {
487 273 return static_cast<int>(this->RetrieveInt64(index));
488 }
489
490 template <>
491 inline bool Sql::Retrieve(const int index) {
492 return static_cast<bool>(this->RetrieveInt(index));
493 }
494
495 template <>
496 inline sqlite3_int64 Sql::Retrieve(const int index) {
497 return this->RetrieveInt64(index);
498 }
499
500 template <>
501 128 inline uint64_t Sql::Retrieve(const int index) {
502 128 return static_cast<uint64_t>(this->RetrieveInt64(index));
503 }
504
505 template <>
506 156 inline std::string Sql::Retrieve(const int index) {
507 156 return RetrieveString(index);
508 }
509
510 template <>
511 4 inline float Sql::Retrieve(const int index) {
512 4 return static_cast<float>(this->RetrieveDouble(index));
513 }
514
515 template <>
516 216 inline double Sql::Retrieve(const int index) {
517 216 return this->RetrieveDouble(index);
518 }
519
520 } // namespace sqlite
521
522 #endif // CVMFS_SQL_IMPL_H_
523