GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/sql_impl.h
Date: 2025-11-02 02:35:35
Exec Total Coverage
Lines: 209 240 87.1%
Branches: 211 448 47.1%

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