Directory: | cvmfs/ |
---|---|
File: | cvmfs/sql.cc |
Date: | 2025-02-09 02:34:19 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 46 | 85 | 54.1% |
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 | 3357 | Sql::Sql(sqlite3 *sqlite_db, const std::string &statement) | |
16 | 3357 | : database_(NULL) | |
17 | 3357 | , statement_(NULL) | |
18 | 3357 | , query_string_(NULL) | |
19 | 3357 | , last_error_code_(0) | |
20 | { | ||
21 | 3357 | const bool success = Init(sqlite_db, statement); | |
22 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3357 times.
|
3357 | assert(success); |
23 | 3357 | } | |
24 | |||
25 | |||
26 | 21174 | Sql::~Sql() { | |
27 | 16794 | last_error_code_ = sqlite3_finalize(statement_); | |
28 | |||
29 |
2/2✓ Branch 1 taken 6 times.
✓ Branch 2 taken 8391 times.
|
16794 | if (!Successful()) { |
30 | 12 | LogCvmfs(kLogSql, kLogDebug, | |
31 | "failed to finalize statement - error code: %d", last_error_code_); | ||
32 | } | ||
33 | 16794 | LogCvmfs(kLogSql, kLogDebug, "successfully finalized statement"); | |
34 | 21174 | } | |
35 | |||
36 | |||
37 | /** | ||
38 | * Executes the prepared statement. | ||
39 | * (this method should be used for modifying statements like DELETE or INSERT) | ||
40 | * @return true on success otherwise false | ||
41 | */ | ||
42 | 162571 | bool Sql::Execute() { | |
43 | 162571 | LazyInit(); | |
44 | 162571 | last_error_code_ = sqlite3_step(statement_); | |
45 | #ifdef DEBUGMSG | ||
46 |
2/2✓ Branch 1 taken 6 times.
✓ Branch 2 taken 162565 times.
|
162571 | if (!Successful()) { |
47 |
1/2✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
|
6 | LogCvmfs(kLogSql, kLogDebug, "SQL query failed - SQLite: %d - %s", |
48 | 12 | GetLastError(), GetLastErrorMsg().c_str()); | |
49 | } | ||
50 | #endif | ||
51 | 162571 | return Successful(); | |
52 | } | ||
53 | |||
54 | |||
55 | /** | ||
56 | * Execute the prepared statement or fetch its next row. | ||
57 | * This method is intended to step through the result set. | ||
58 | * If it returns false this does not necessarily mean, that the actual | ||
59 | * statement execution failed, but that no row was fetched. | ||
60 | * @return true if a new row was fetched otherwise false | ||
61 | */ | ||
62 | 11884 | bool Sql::FetchRow() { | |
63 | 11884 | LazyInit(); | |
64 | 11884 | last_error_code_ = sqlite3_step(statement_); | |
65 | 11884 | return SQLITE_ROW == last_error_code_; | |
66 | } | ||
67 | |||
68 | |||
69 | ✗ | std::string Sql::DebugResultTable() { | |
70 | ✗ | std::string line; | |
71 | ✗ | std::string result; | |
72 | ✗ | unsigned int rows = 0; | |
73 | |||
74 | // go through all data rows | ||
75 | ✗ | while (FetchRow()) { | |
76 | // retrieve the table header (once) | ||
77 | ✗ | const unsigned int cols = sqlite3_column_count(statement_); | |
78 | ✗ | if (rows == 0) { | |
79 | ✗ | for (unsigned int col = 0; col < cols; ++col) { | |
80 | ✗ | const char *name = sqlite3_column_name(statement_, col); | |
81 | ✗ | line += name; | |
82 | ✗ | if (col + 1 < cols) 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) line += " | "; | |
109 | } | ||
110 | |||
111 | ✗ | result += line + "\n"; | |
112 | ✗ | line.clear(); | |
113 | ✗ | ++rows; | |
114 | } | ||
115 | |||
116 | // print the result | ||
117 | ✗ | result += "Retrieved Rows: " + StringifyInt(rows); | |
118 | ✗ | return result; | |
119 | } | ||
120 | |||
121 | |||
122 | /** | ||
123 | * Reset a prepared statement to make it reusable. | ||
124 | * @return true on success otherwise false | ||
125 | */ | ||
126 | 168722 | bool Sql::Reset() { | |
127 | 168722 | last_error_code_ = sqlite3_reset(statement_); | |
128 | 168722 | return Successful(); | |
129 | } | ||
130 | |||
131 | |||
132 | 4508 | bool Sql::Init(const sqlite3 *database, const std::string &statement) { | |
133 | 4508 | database_ = const_cast<sqlite3 *>(database); | |
134 | 4508 | return Init(statement.c_str()); | |
135 | } | ||
136 | |||
137 | 5513 | bool Sql::Init(const char *statement) { | |
138 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5513 times.
|
5513 | assert(NULL == statement_); |
139 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5513 times.
|
5513 | assert(NULL != database_); |
140 | |||
141 | 5513 | last_error_code_ = sqlite3_prepare_v2(database_, | |
142 | statement, | ||
143 | -1, // parse until null termination | ||
144 | &statement_, | ||
145 | NULL); | ||
146 | |||
147 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 5513 times.
|
5513 | if (!Successful()) { |
148 | ✗ | LogCvmfs(kLogSql, kLogDebug, "failed to prepare statement '%s' (%d: %s)", | |
149 | statement, GetLastError(), sqlite3_errmsg(database_)); | ||
150 | ✗ | return false; | |
151 | } | ||
152 | |||
153 | 5513 | LogCvmfs(kLogSql, kLogDebug, "successfully prepared statement '%s'", | |
154 | statement); | ||
155 | 5513 | return true; | |
156 | } | ||
157 | |||
158 | 3944 | void Sql::DeferredInit(const sqlite3 *database, const char *statement) { | |
159 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3944 times.
|
3944 | assert(NULL == database_); |
160 | 3944 | database_ = const_cast<sqlite3 *>(database); | |
161 | 3944 | query_string_ = statement; | |
162 | 3944 | } | |
163 | |||
164 | 6 | std::string Sql::GetLastErrorMsg() const { | |
165 |
2/4✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
|
6 | std::string msg = sqlite3_errmsg(database_); |
166 | 6 | return msg; | |
167 | } | ||
168 | |||
169 | } // namespace sqlite | ||
170 |