GCC Code Coverage Report


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