Directory: | cvmfs/ |
---|---|
File: | cvmfs/sql.cc |
Date: | 2025-06-22 02:36:02 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 46 | 87 | 52.9% |
Branches: | 12 | 86 | 14.0% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | /** | ||
2 | * This file is part of the CernVM file system. | ||
3 | */ | ||
4 | |||
5 | |||
6 | #include "sql.h" | ||
7 | |||
8 | #include "util/logging.h" | ||
9 | #include "util/string.h" | ||
10 | |||
11 | using namespace std; // NOLINT | ||
12 | |||
13 | namespace sqlite { | ||
14 | |||
15 | 104390 | Sql::Sql(sqlite3 *sqlite_db, const std::string &statement) | |
16 | 104390 | : database_(NULL) | |
17 | 104390 | , statement_(NULL) | |
18 | 104390 | , query_string_(NULL) | |
19 | 104390 | , last_error_code_(0) { | |
20 | 104390 | const bool success = Init(sqlite_db, statement); | |
21 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 104390 times.
|
104390 | assert(success); |
22 | 104390 | } | |
23 | |||
24 | |||
25 | 678902 | Sql::~Sql() { | |
26 | 545872 | last_error_code_ = sqlite3_finalize(statement_); | |
27 | |||
28 |
2/2✓ Branch 1 taken 288 times.
✓ Branch 2 taken 272648 times.
|
545872 | if (!Successful()) { |
29 | 576 | LogCvmfs(kLogSql, kLogDebug, | |
30 | "failed to finalize statement - error code: %d", last_error_code_); | ||
31 | } | ||
32 | 545872 | LogCvmfs(kLogSql, kLogDebug, "successfully finalized statement"); | |
33 | 678902 | } | |
34 | |||
35 | |||
36 | /** | ||
37 | * Executes the prepared statement. | ||
38 | * (this method should be used for modifying statements like DELETE or INSERT) | ||
39 | * @return true on success otherwise false | ||
40 | */ | ||
41 | 2570024 | bool Sql::Execute() { | |
42 | 2570024 | LazyInit(); | |
43 | 2570024 | last_error_code_ = sqlite3_step(statement_); | |
44 | #ifdef DEBUGMSG | ||
45 |
2/2✓ Branch 1 taken 288 times.
✓ Branch 2 taken 2569736 times.
|
2570024 | if (!Successful()) { |
46 |
1/2✓ Branch 3 taken 288 times.
✗ Branch 4 not taken.
|
288 | LogCvmfs(kLogSql, kLogDebug, "SQL query failed - SQLite: %d - %s", |
47 | 576 | GetLastError(), GetLastErrorMsg().c_str()); | |
48 | } | ||
49 | #endif | ||
50 | 2570024 | return Successful(); | |
51 | } | ||
52 | |||
53 | |||
54 | /** | ||
55 | * Execute the prepared statement or fetch its next row. | ||
56 | * This method is intended to step through the result set. | ||
57 | * If it returns false this does not necessarily mean, that the actual | ||
58 | * statement execution failed, but that no row was fetched. | ||
59 | * @return true if a new row was fetched otherwise false | ||
60 | */ | ||
61 | 442873 | bool Sql::FetchRow() { | |
62 | 442873 | LazyInit(); | |
63 | 442873 | last_error_code_ = sqlite3_step(statement_); | |
64 | 442873 | return SQLITE_ROW == last_error_code_; | |
65 | } | ||
66 | |||
67 | |||
68 | ✗ | std::string Sql::DebugResultTable() { | |
69 | ✗ | std::string line; | |
70 | ✗ | std::string result; | |
71 | ✗ | unsigned int rows = 0; | |
72 | |||
73 | // go through all data rows | ||
74 | ✗ | while (FetchRow()) { | |
75 | // retrieve the table header (once) | ||
76 | ✗ | const unsigned int cols = sqlite3_column_count(statement_); | |
77 | ✗ | if (rows == 0) { | |
78 | ✗ | for (unsigned int col = 0; col < cols; ++col) { | |
79 | ✗ | const char *name = sqlite3_column_name(statement_, col); | |
80 | ✗ | line += name; | |
81 | ✗ | if (col + 1 < cols) | |
82 | ✗ | line += " | "; | |
83 | } | ||
84 | ✗ | result += line + "\n"; | |
85 | ✗ | line.clear(); | |
86 | } | ||
87 | |||
88 | // retrieve the data fields for each row | ||
89 | ✗ | for (unsigned int col = 0; col < cols; ++col) { | |
90 | ✗ | const int type = sqlite3_column_type(statement_, col); | |
91 | ✗ | switch (type) { | |
92 | ✗ | case SQLITE_INTEGER: | |
93 | ✗ | line += StringifyInt(RetrieveInt64(col)); | |
94 | ✗ | break; | |
95 | ✗ | case SQLITE_FLOAT: | |
96 | ✗ | line += StringifyDouble(RetrieveDouble(col)); | |
97 | ✗ | break; | |
98 | ✗ | case SQLITE_TEXT: | |
99 | ✗ | line += reinterpret_cast<const char *>(RetrieveText(col)); | |
100 | ✗ | break; | |
101 | ✗ | case SQLITE_BLOB: | |
102 | ✗ | line += "[BLOB data]"; | |
103 | ✗ | break; | |
104 | ✗ | case SQLITE_NULL: | |
105 | ✗ | line += "[NULL]"; | |
106 | ✗ | break; | |
107 | } | ||
108 | ✗ | if (col + 1 < cols) | |
109 | ✗ | line += " | "; | |
110 | } | ||
111 | |||
112 | ✗ | result += line + "\n"; | |
113 | ✗ | line.clear(); | |
114 | ✗ | ++rows; | |
115 | } | ||
116 | |||
117 | // print the result | ||
118 | ✗ | result += "Retrieved Rows: " + StringifyInt(rows); | |
119 | ✗ | return result; | |
120 | } | ||
121 | |||
122 | |||
123 | /** | ||
124 | * Reset a prepared statement to make it reusable. | ||
125 | * @return true on success otherwise false | ||
126 | */ | ||
127 | 2779594 | bool Sql::Reset() { | |
128 | 2779594 | last_error_code_ = sqlite3_reset(statement_); | |
129 | 2779594 | return Successful(); | |
130 | } | ||
131 | |||
132 | |||
133 | 140017 | bool Sql::Init(const sqlite3 *database, const std::string &statement) { | |
134 | 140017 | database_ = const_cast<sqlite3 *>(database); | |
135 | 140017 | return Init(statement.c_str()); | |
136 | } | ||
137 | |||
138 | 175118 | bool Sql::Init(const char *statement) { | |
139 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 175118 times.
|
175118 | assert(NULL == statement_); |
140 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 175118 times.
|
175118 | assert(NULL != database_); |
141 | |||
142 | 175118 | last_error_code_ = sqlite3_prepare_v2(database_, | |
143 | statement, | ||
144 | -1, // parse until null termination | ||
145 | &statement_, | ||
146 | NULL); | ||
147 | |||
148 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 175118 times.
|
175118 | if (!Successful()) { |
149 | ✗ | LogCvmfs(kLogSql, kLogDebug, "failed to prepare statement '%s' (%d: %s)", | |
150 | statement, GetLastError(), sqlite3_errmsg(database_)); | ||
151 | ✗ | return false; | |
152 | } | ||
153 | |||
154 | 175118 | LogCvmfs(kLogSql, kLogDebug, "successfully prepared statement '%s'", | |
155 | statement); | ||
156 | 175118 | return true; | |
157 | } | ||
158 | |||
159 | 133304 | void Sql::DeferredInit(const sqlite3 *database, const char *statement) { | |
160 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 133304 times.
|
133304 | assert(NULL == database_); |
161 | 133304 | database_ = const_cast<sqlite3 *>(database); | |
162 | 133304 | query_string_ = statement; | |
163 | 133304 | } | |
164 | |||
165 | 288 | std::string Sql::GetLastErrorMsg() const { | |
166 |
2/4✓ Branch 2 taken 288 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 288 times.
✗ Branch 6 not taken.
|
288 | std::string msg = sqlite3_errmsg(database_); |
167 | 288 | return msg; | |
168 | } | ||
169 | |||
170 | } // namespace sqlite | ||
171 |