1 #include "sqlstorage.h"
10 #include "logging/logging.h"
11 #include "sql_utils.h"
12 #include "utilities/utils.h"
18 db.beginTransaction();
20 auto statement = db.prepareStatement<int, int,
int>(
21 "SELECT meta FROM meta WHERE (repo=? AND meta_type=? AND version=?);",
static_cast<int>(repo), role.ToInt(), -1);
23 int result = statement.step();
25 if (
result == SQLITE_DONE) {
28 }
else if (
result != SQLITE_ROW) {
29 LOG_ERROR <<
"Failed to get " << repo.toString() <<
" " << role.ToString() <<
" metadata: " << db.errmsg();
32 const std::string meta = std::string(
reinterpret_cast<const char*
>(sqlite3_column_blob(statement.get(), 0)));
34 const int version = Uptane::extractVersionUntrusted(meta);
36 LOG_ERROR <<
"Corrupted " << repo.toString() <<
" " << role.ToString() <<
" metadata.";
41 statement = db.prepareStatement<int, int,
int>(
"DELETE FROM meta WHERE (repo=? AND meta_type=? AND version=?);",
42 static_cast<int>(repo), role.ToInt(), version);
44 if (statement.step() != SQLITE_DONE) {
45 LOG_ERROR <<
"Failed to clear " << repo.toString() <<
" " << role.ToString() <<
" metadata: " << db.errmsg();
49 statement = db.prepareStatement<int, int, int,
int>(
50 "UPDATE meta SET version = ? WHERE (repo=? AND meta_type=? AND version=?);", version,
static_cast<int>(repo),
53 if (statement.step() != SQLITE_DONE) {
54 LOG_ERROR <<
"Failed to update " << repo.toString() <<
" " << role.ToString() <<
" metadata: " << db.errmsg();
58 db.commitTransaction();
61 SQLStorage::SQLStorage(
const StorageConfig& config,
bool readonly)
62 :
SQLStorageBase(config.sqldb_path.get(config.path), readonly, libaktualizr_schema_migrations,
63 libaktualizr_schema_rollback_migrations, libaktualizr_current_schema,
64 libaktualizr_current_schema_version),
67 cleanMetaVersion(Uptane::RepositoryType::Director(), Uptane::Role::Root());
68 cleanMetaVersion(Uptane::RepositoryType::Image(), Uptane::Role::Root());
70 LOG_ERROR <<
"SQLite database metadata version migration failed";
74 void SQLStorage::storePrimaryKeys(
const std::string& public_key,
const std::string& private_key) {
77 auto statement = db.prepareStatement<std::string>(
78 "INSERT OR REPLACE INTO primary_keys(unique_mark,public,private) VALUES (0,?,?);", public_key, private_key);
79 if (statement.step() != SQLITE_DONE) {
80 LOG_ERROR <<
"Failed to set Primary keys: " << db.errmsg();
85 bool SQLStorage::loadPrimaryKeys(std::string* public_key, std::string* private_key)
const {
86 return loadPrimaryPublic(public_key) && loadPrimaryPrivate(private_key);
89 bool SQLStorage::loadPrimaryPublic(std::string* public_key)
const {
92 auto statement = db.prepareStatement(
"SELECT public FROM primary_keys LIMIT 1;");
94 int result = statement.step();
95 if (
result == SQLITE_DONE) {
96 LOG_TRACE <<
"Uptane public key not found in database";
98 }
else if (
result != SQLITE_ROW) {
99 LOG_ERROR <<
"Failed to get Uptane public key: " << db.errmsg();
103 auto pub = statement.get_result_col_str(0);
104 if (pub == boost::none) {
108 if (public_key !=
nullptr) {
109 *public_key = std::move(pub.value());
115 bool SQLStorage::loadPrimaryPrivate(std::string* private_key)
const {
118 auto statement = db.prepareStatement(
"SELECT private FROM primary_keys LIMIT 1;");
120 int result = statement.step();
121 if (
result == SQLITE_DONE) {
122 LOG_TRACE <<
"Uptane private key not found in database";
124 }
else if (
result != SQLITE_ROW) {
125 LOG_ERROR <<
"Failed to get Uptane private key: " << db.errmsg();
129 auto priv = statement.get_result_col_str(0);
130 if (priv == boost::none) {
134 if (private_key !=
nullptr) {
135 *private_key = std::move(priv.value());
141 void SQLStorage::clearPrimaryKeys() {
144 if (db.exec(
"DELETE FROM primary_keys;",
nullptr,
nullptr) != SQLITE_OK) {
145 LOG_ERROR <<
"Failed to clear Primary keys: " << db.errmsg();
150 void SQLStorage::saveSecondaryInfo(
const Uptane::EcuSerial& ecu_serial,
const std::string& sec_type,
154 std::stringstream key_type_ss;
155 key_type_ss << public_key.Type();
156 std::string key_type_str;
157 key_type_str = key_type_ss.str();
158 key_type_str.erase(std::remove(key_type_str.begin(), key_type_str.end(),
'"'), key_type_str.end());
160 db.beginTransaction();
163 db.prepareStatement<std::string>(
"SELECT count(*) FROM secondary_ecus WHERE serial = ?;", ecu_serial.ToString());
164 if (statement.step() != SQLITE_ROW) {
165 throw SQLException(db.errmsg().insert(0,
"Failed to get count of secondary_ecus table: "));
169 if (statement.get_result_col_int(0) != 0) {
170 req =
"UPDATE secondary_ecus SET sec_type = ?, public_key_type = ?, public_key = ? WHERE serial = ?;";
173 "INSERT INTO secondary_ecus (serial, sec_type, public_key_type, public_key) SELECT "
174 "serial,?,?,? FROM ecus WHERE (serial = ? AND is_primary = 0);";
177 statement = db.prepareStatement<std::string, std::string, std::string, std::string>(
178 req, sec_type, key_type_str, public_key.Value(), ecu_serial.ToString());
179 if (statement.step() != SQLITE_DONE || sqlite3_changes(db.get()) != 1) {
180 throw SQLException(db.errmsg().insert(0,
"Failed to set Secondary key: "));
183 db.commitTransaction();
189 db.beginTransaction();
192 db.prepareStatement<std::string>(
"SELECT count(*) FROM secondary_ecus WHERE serial = ?;", ecu_serial.ToString());
193 if (statement.step() != SQLITE_ROW) {
194 throw SQLException(db.errmsg().insert(0,
"Failed to get count of secondary_ecus table: "));
198 if (statement.get_result_col_int(0) != 0) {
199 req =
"UPDATE secondary_ecus SET extra = ? WHERE serial = ?;";
201 req =
"INSERT INTO secondary_ecus (extra, serial) VALUES (?,?);";
204 statement = db.prepareStatement<std::string, std::string>(req,
data, ecu_serial.ToString());
205 if (statement.step() != SQLITE_DONE || sqlite3_changes(db.get()) != 1) {
206 throw SQLException(db.errmsg().insert(0,
"Failed to set Secondary data: "));
209 db.commitTransaction();
217 auto statement = db.prepareStatement<std::string>(
218 "SELECT serial, hardware_id, sec_type, public_key_type, public_key, extra FROM ecus LEFT JOIN secondary_ecus "
220 "(serial) WHERE (serial = ? AND is_primary = 0);",
221 ecu_serial.ToString());
222 int statement_state = statement.step();
223 if (statement_state == SQLITE_DONE) {
224 LOG_TRACE <<
"Secondary ECU " << ecu_serial <<
" not found in database";
226 }
else if (statement_state != SQLITE_ROW) {
227 LOG_ERROR <<
"Failed to load Secondary info: " << db.errmsg();
234 std::string sec_type = statement.get_result_col_str(2).value_or(
"");
235 std::string kt_str = statement.get_result_col_str(3).value_or(
"");
237 if (!kt_str.empty()) {
239 std::stringstream(kt_str) >> key_type;
240 key =
PublicKey(statement.get_result_col_str(4).value_or(
""), key_type);
242 std::string extra = statement.get_result_col_str(5).value_or(
"");
243 new_sec =
SecondaryInfo{serial, hw_id, sec_type, key, extra};
244 }
catch (
const boost::bad_optional_access&) {
248 if (secondary !=
nullptr) {
249 *secondary = std::move(new_sec);
255 bool SQLStorage::loadSecondariesInfo(std::vector<SecondaryInfo>* secondaries)
const {
258 std::vector<SecondaryInfo> new_secs;
263 auto statement = db.prepareStatement(
264 "SELECT serial, hardware_id, sec_type, public_key_type, public_key, extra FROM ecus LEFT JOIN secondary_ecus "
266 "(serial) WHERE is_primary = 0 ORDER BY ecus.id;");
267 while ((statement_state = statement.step()) == SQLITE_ROW) {
271 std::string sec_type = statement.get_result_col_str(2).value_or(
"");
272 std::string kt_str = statement.get_result_col_str(3).value_or(
"");
274 if (!kt_str.empty()) {
276 std::stringstream(kt_str) >> key_type;
277 key =
PublicKey(statement.get_result_col_str(4).value_or(
""), key_type);
279 std::string extra = statement.get_result_col_str(5).value_or(
"");
280 new_secs.emplace_back(
SecondaryInfo{serial, hw_id, sec_type, key, extra});
282 }
catch (
const boost::bad_optional_access&) {
286 if (statement_state != SQLITE_DONE) {
287 LOG_ERROR <<
"Failed to load Secondary info" << db.errmsg();
290 if (secondaries !=
nullptr) {
291 *secondaries = std::move(new_secs);
297 void SQLStorage::storeTlsCreds(
const std::string& ca,
const std::string& cert,
const std::string& pkey) {
303 void SQLStorage::storeTlsCa(
const std::string& ca) {
306 db.beginTransaction();
308 auto statement = db.prepareStatement(
"SELECT count(*) FROM tls_creds;");
309 if (statement.step() != SQLITE_ROW) {
310 LOG_ERROR <<
"Failed to get count of tls_creds table: " << db.errmsg();
315 if (statement.get_result_col_int(0) != 0) {
316 req =
"UPDATE OR REPLACE tls_creds SET ca_cert = ?;";
318 req =
"INSERT INTO tls_creds(ca_cert) VALUES (?);";
322 if (statement.step() != SQLITE_DONE) {
323 LOG_ERROR <<
"Failed to set CA certificate: " << db.errmsg();
327 db.commitTransaction();
330 void SQLStorage::storeTlsCert(
const std::string& cert) {
333 db.beginTransaction();
335 auto statement = db.prepareStatement(
"SELECT count(*) FROM tls_creds;");
336 if (statement.step() != SQLITE_ROW) {
337 LOG_ERROR <<
"Failed to get count of tls_creds table: " << db.errmsg();
342 if (statement.get_result_col_int(0) != 0) {
343 req =
"UPDATE OR REPLACE tls_creds SET client_cert = ?;";
345 req =
"INSERT INTO tls_creds(client_cert) VALUES (?);";
349 if (statement.step() != SQLITE_DONE) {
350 LOG_ERROR <<
"Failed to set client certificate: " << db.errmsg();
354 db.commitTransaction();
357 void SQLStorage::storeTlsPkey(
const std::string& pkey) {
360 db.beginTransaction();
362 auto statement = db.prepareStatement(
"SELECT count(*) FROM tls_creds;");
363 if (statement.step() != SQLITE_ROW) {
364 LOG_ERROR <<
"Failed to get count of tls_creds table: " << db.errmsg();
369 if (statement.get_result_col_int(0) != 0) {
370 req =
"UPDATE OR REPLACE tls_creds SET client_pkey = ?;";
372 req =
"INSERT INTO tls_creds(client_pkey) VALUES (?);";
376 if (statement.step() != SQLITE_DONE) {
377 LOG_ERROR <<
"Failed to set client private key: " << db.errmsg();
381 db.commitTransaction();
384 bool SQLStorage::loadTlsCreds(std::string* ca, std::string* cert, std::string* pkey)
const {
387 auto statement = db.prepareStatement(
"SELECT ca_cert, client_cert, client_pkey FROM tls_creds LIMIT 1;");
389 int result = statement.step();
390 if (
result == SQLITE_DONE) {
391 LOG_TRACE <<
"TLS credentials not found in database";
393 }
else if (
result != SQLITE_ROW) {
394 LOG_ERROR <<
"Failed to get TLS credentials: " << db.errmsg();
402 ca_v = statement.get_result_col_str(0).value();
403 cert_v = statement.get_result_col_str(1).value();
404 pkey_v = statement.get_result_col_str(2).value();
405 }
catch (
const boost::bad_optional_access&) {
410 *ca = std::move(ca_v);
412 if (cert !=
nullptr) {
413 *cert = std::move(cert_v);
415 if (pkey !=
nullptr) {
416 *pkey = std::move(pkey_v);
422 void SQLStorage::clearTlsCreds() {
425 if (db.exec(
"DELETE FROM tls_creds;",
nullptr,
nullptr) != SQLITE_OK) {
426 LOG_ERROR <<
"Failed to clear TLS credentials: " << db.errmsg();
431 bool SQLStorage::loadTlsCa(std::string* ca)
const {
434 auto statement = db.prepareStatement(
"SELECT ca_cert FROM tls_creds LIMIT 1;");
436 int result = statement.step();
437 if (
result == SQLITE_DONE) {
438 LOG_TRACE <<
"CA certificate not found in database";
440 }
else if (
result != SQLITE_ROW) {
441 LOG_ERROR <<
"Failed to get CA certificate: " << db.errmsg();
445 auto ca_r = statement.get_result_col_str(0);
446 if (ca_r == boost::none) {
451 *ca = std::move(ca_r.value());
457 bool SQLStorage::loadTlsCert(std::string* cert)
const {
460 auto statement = db.prepareStatement(
"SELECT client_cert FROM tls_creds LIMIT 1;");
462 int result = statement.step();
463 if (
result == SQLITE_DONE) {
464 LOG_TRACE <<
"Client certificate not found in database";
466 }
else if (
result != SQLITE_ROW) {
467 LOG_ERROR <<
"Failed to get client certificate: " << db.errmsg();
471 auto cert_r = statement.get_result_col_str(0);
472 if (cert_r == boost::none) {
476 if (cert !=
nullptr) {
477 *cert = std::move(cert_r.value());
483 bool SQLStorage::loadTlsPkey(std::string* pkey)
const {
486 auto statement = db.prepareStatement(
"SELECT client_pkey FROM tls_creds LIMIT 1;");
488 int result = statement.step();
489 if (
result == SQLITE_DONE) {
490 LOG_TRACE <<
"Client private key not found in database";
492 }
else if (
result != SQLITE_ROW) {
493 LOG_ERROR <<
"Failed to get client private key: " << db.errmsg();
497 auto pkey_r = statement.get_result_col_str(0);
498 if (pkey_r == boost::none) {
502 if (pkey !=
nullptr) {
503 *pkey = std::move(pkey_r.value());
512 db.beginTransaction();
515 db.prepareStatement<int, int,
int>(
"DELETE FROM meta WHERE (repo=? AND meta_type=? AND version=?);",
516 static_cast<int>(repo), Uptane::Role::Root().ToInt(), version.version());
518 if (del_statement.step() != SQLITE_DONE) {
519 LOG_ERROR <<
"Failed to clear Root metadata: " << db.errmsg();
523 auto ins_statement = db.prepareStatement<
SQLBlob, int, int,
int>(
"INSERT INTO meta VALUES (?, ?, ?, ?);",
525 Uptane::Role::Root().ToInt(), version.version());
527 if (ins_statement.step() != SQLITE_DONE) {
528 LOG_ERROR <<
"Failed to store Root metadata: " << db.errmsg();
532 db.commitTransaction();
538 db.beginTransaction();
540 auto del_statement = db.prepareStatement<int,
int>(
"DELETE FROM meta WHERE (repo=? AND meta_type=?);",
541 static_cast<int>(repo), role.ToInt());
543 if (del_statement.step() != SQLITE_DONE) {
544 LOG_ERROR <<
"Failed to clear " << role.ToString() <<
" metadata: " << db.errmsg();
549 db.prepareStatement<
SQLBlob, int, int,
int>(
"INSERT INTO meta VALUES (?, ?, ?, ?);",
SQLBlob(
data),
552 if (ins_statement.step() != SQLITE_DONE) {
553 LOG_ERROR <<
"Failed to add " << role.ToString() <<
"metadata: " << db.errmsg();
557 db.commitTransaction();
564 if (version.version() < 0) {
565 auto statement = db.prepareStatement<int,
int>(
566 "SELECT meta FROM meta WHERE (repo=? AND meta_type=?) ORDER BY version DESC LIMIT 1;",
static_cast<int>(repo),
567 Uptane::Role::Root().ToInt());
568 int result = statement.step();
570 if (
result == SQLITE_DONE) {
571 LOG_TRACE <<
"Root metadata not found in database";
573 }
else if (
result != SQLITE_ROW) {
574 LOG_ERROR <<
"Failed to get Root metadata: " << db.errmsg();
577 if (
data !=
nullptr) {
578 *
data = std::string(
reinterpret_cast<const char*
>(sqlite3_column_blob(statement.get(), 0)));
582 db.prepareStatement<int, int,
int>(
"SELECT meta FROM meta WHERE (repo=? AND meta_type=? AND version=?);",
583 static_cast<int>(repo), Uptane::Role::Root().ToInt(), version.version());
585 int result = statement.step();
587 if (
result == SQLITE_DONE) {
588 LOG_TRACE <<
"Root metadata not found in database";
590 }
else if (
result != SQLITE_ROW) {
591 LOG_ERROR <<
"Failed to get Root metadata: " << db.errmsg();
595 const auto*
const blob =
reinterpret_cast<const char*
>(sqlite3_column_blob(statement.get(), 0));
596 if (blob ==
nullptr) {
597 LOG_ERROR <<
"Failed to get Root metadata: " << db.errmsg();
601 if (
data !=
nullptr) {
602 *
data = std::string(blob);
612 auto statement = db.prepareStatement<int,
int>(
613 "SELECT meta FROM meta WHERE (repo=? AND meta_type=?) ORDER BY version DESC LIMIT 1;",
static_cast<int>(repo),
615 int result = statement.step();
617 if (
result == SQLITE_DONE) {
618 LOG_TRACE << role.ToString() <<
" metadata not found in database";
620 }
else if (
result != SQLITE_ROW) {
621 LOG_ERROR <<
"Failed to get " << role.ToString() <<
" metadata: " << db.errmsg();
624 if (
data !=
nullptr) {
625 *
data = std::string(
reinterpret_cast<const char*
>(sqlite3_column_blob(statement.get(), 0)));
635 db.prepareStatement<
int>(
"DELETE FROM meta WHERE (repo=? AND meta_type != 0);",
static_cast<int>(repo));
637 if (del_statement.step() != SQLITE_DONE) {
638 LOG_ERROR <<
"Failed to clear metadata: " << db.errmsg();
642 void SQLStorage::clearMetadata() {
645 if (db.exec(
"DELETE FROM meta;",
nullptr,
nullptr) != SQLITE_OK) {
646 LOG_ERROR <<
"Failed to clear metadata: " << db.errmsg();
651 void SQLStorage::storeDelegation(
const std::string&
data,
const Uptane::Role role) {
654 auto statement = db.prepareStatement<
SQLBlob, std::string>(
"INSERT OR REPLACE INTO delegations VALUES (?, ?);",
656 if (statement.step() != SQLITE_DONE) {
657 LOG_ERROR <<
"Failed to store delegation metadata: " << db.errmsg();
662 bool SQLStorage::loadDelegation(std::string*
data,
const Uptane::Role role)
const {
666 db.prepareStatement<std::string>(
"SELECT meta FROM delegations WHERE role_name=? LIMIT 1;", role.ToString());
667 int result = statement.step();
669 if (
result == SQLITE_DONE) {
670 LOG_TRACE <<
"Delegations metadata not found in database";
672 }
else if (
result != SQLITE_ROW) {
673 LOG_ERROR <<
"Failed to get delegations metadata: " << db.errmsg();
676 if (
data !=
nullptr) {
677 *
data = std::string(
reinterpret_cast<const char*
>(sqlite3_column_blob(statement.get(), 0)));
683 bool SQLStorage::loadAllDelegations(std::vector<std::pair<Uptane::Role, std::string>>&
data)
const {
689 auto statement = db.prepareStatement(
"SELECT meta, role_name FROM delegations;");
690 auto statement_state = statement.step();
692 if (statement_state == SQLITE_DONE) {
693 LOG_TRACE <<
"Delegations metadata not found in database";
695 }
else if (statement_state != SQLITE_ROW) {
696 LOG_ERROR <<
"Failed to get delegations metadata: " << db.errmsg();
701 data.emplace_back(Uptane::Role::Delegation(statement.get_result_col_str(1).value()),
702 statement.get_result_col_blob(0).value());
703 }
while ((statement_state = statement.step()) == SQLITE_ROW);
705 if (statement_state != SQLITE_DONE) {
706 LOG_ERROR <<
"Error reading delegations metadata: " << db.errmsg();
711 }
catch (
const std::exception& exc) {
712 LOG_ERROR <<
"Failed to fetch records from `delegations` table: " << exc.what();
718 void SQLStorage::deleteDelegation(
const Uptane::Role role) {
721 auto statement = db.prepareStatement<std::string>(
"DELETE FROM delegations WHERE role_name=?;", role.ToString());
725 void SQLStorage::clearDelegations() {
728 if (db.exec(
"DELETE FROM delegations;",
nullptr,
nullptr) != SQLITE_OK) {
729 LOG_ERROR <<
"Failed to clear delegations metadata: " << db.errmsg();
733 void SQLStorage::storeDeviceId(
const std::string& device_id) {
736 auto statement = db.prepareStatement<std::string>(
737 "INSERT OR REPLACE INTO device_info(unique_mark,device_id,is_registered) VALUES(0,?,0);", device_id);
738 if (statement.step() != SQLITE_DONE) {
739 LOG_ERROR <<
"Failed to set device ID: " << db.errmsg();
744 bool SQLStorage::loadDeviceId(std::string* device_id)
const {
747 auto statement = db.prepareStatement(
"SELECT device_id FROM device_info LIMIT 1;");
749 int result = statement.step();
750 if (
result == SQLITE_DONE) {
751 LOG_TRACE <<
"Device ID key not found in database";
753 }
else if (
result != SQLITE_ROW) {
754 LOG_ERROR <<
"Failed to get device ID: " << db.errmsg();
758 auto did = statement.get_result_col_str(0);
759 if (did == boost::none) {
760 LOG_ERROR <<
"Empty device ID: " << db.errmsg();
764 if (device_id !=
nullptr) {
765 *device_id = std::move(did.value());
771 void SQLStorage::clearDeviceId() {
774 if (db.exec(
"DELETE FROM device_info;",
nullptr,
nullptr) != SQLITE_OK) {
775 LOG_ERROR <<
"Failed to clear device ID: " << db.errmsg();
780 void SQLStorage::storeEcuRegistered() {
783 db.beginTransaction();
785 auto statement = db.prepareStatement(
"SELECT count(*) FROM device_info;");
786 if (statement.step() != SQLITE_ROW) {
787 throw SQLException(std::string(
"Failed to get device_info count: ") + db.errmsg());
789 if (statement.get_result_col_int(0) != 1) {
790 throw SQLException(
"Failed to set ECU registered because device info is empty.");
793 std::string req =
"UPDATE device_info SET is_registered = 1";
794 if (db.exec(req.c_str(),
nullptr,
nullptr) != SQLITE_OK) {
795 LOG_ERROR <<
"Failed to set registration flag: " << db.errmsg();
799 db.commitTransaction();
802 bool SQLStorage::loadEcuRegistered()
const {
805 auto statement = db.prepareStatement(
"SELECT is_registered FROM device_info LIMIT 1;");
807 int result = statement.step();
808 if (
result == SQLITE_DONE) {
809 LOG_TRACE <<
"Registration flag not found in database";
811 }
else if (
result != SQLITE_ROW) {
812 LOG_ERROR <<
"Failed to get registration flag: " << db.errmsg();
816 return statement.get_result_col_int(0) != 0;
819 void SQLStorage::clearEcuRegistered() {
823 std::string req =
"UPDATE device_info SET is_registered = 0";
824 if (db.exec(req.c_str(),
nullptr,
nullptr) != SQLITE_OK) {
825 LOG_ERROR <<
"Failed to clear registration flag: " << db.errmsg();
830 void SQLStorage::storeNeedReboot() {
833 auto statement = db.prepareStatement<
int>(
"INSERT OR REPLACE INTO need_reboot(unique_mark,flag) VALUES(0,?);", 1);
834 if (statement.step() != SQLITE_DONE) {
835 LOG_ERROR <<
"Failed to set reboot flag: " << db.errmsg();
840 bool SQLStorage::loadNeedReboot(
bool* need_reboot)
const {
843 auto statement = db.prepareStatement(
"SELECT flag FROM need_reboot LIMIT 1;");
845 int result = statement.step();
846 if (
result == SQLITE_DONE) {
847 if (need_reboot !=
nullptr) {
848 *need_reboot =
false;
851 }
else if (
result != SQLITE_ROW) {
852 LOG_ERROR <<
"Failed to get reboot flag: " << db.errmsg();
856 auto flag =
static_cast<bool>(statement.get_result_col_int(0));
857 if (need_reboot !=
nullptr) {
864 void SQLStorage::clearNeedReboot() {
867 if (db.exec(
"DELETE FROM need_reboot;",
nullptr,
nullptr) != SQLITE_OK) {
868 LOG_ERROR <<
"Failed to clear reboot flag: " << db.errmsg();
873 void SQLStorage::storeEcuSerials(
const EcuSerials& serials) {
874 if (!serials.empty()) {
877 db.beginTransaction();
879 if (db.exec(
"DELETE FROM ecus;",
nullptr,
nullptr) != SQLITE_OK) {
880 LOG_ERROR <<
"Failed to clear ECU serials: " << db.errmsg();
885 std::string serial = serials[0].first.ToString();
886 std::string hwid = serials[0].second.ToString();
888 auto statement = db.prepareStatement<std::string, std::string>(
889 "INSERT INTO ecus(id, serial,hardware_id,is_primary) VALUES (0, ?,?,1);", serial, hwid);
890 if (statement.step() != SQLITE_DONE) {
891 LOG_ERROR <<
"Failed to store ECU serials: " << db.errmsg();
896 auto statement_ivupdate = db.prepareStatement<std::string>(
897 "UPDATE installed_versions SET ecu_serial = ? WHERE ecu_serial = '';", serial);
899 if (statement_ivupdate.step() != SQLITE_DONE) {
900 LOG_ERROR <<
"Failed to store ECU serials: " << db.errmsg();
905 for (
auto it = serials.cbegin() + 1; it != serials.cend(); it++) {
906 auto statement = db.prepareStatement<int64_t, std::string, std::string>(
907 "INSERT INTO ecus(id,serial,hardware_id) VALUES (?,?,?);", it - serials.cbegin(), it->first.ToString(),
908 it->second.ToString());
910 if (statement.step() != SQLITE_DONE) {
911 LOG_ERROR <<
"Failed to store ECU serials: " << db.errmsg();
916 db.commitTransaction();
920 bool SQLStorage::loadEcuSerials(EcuSerials* serials)
const {
924 auto statement = db.prepareStatement(
"SELECT serial, hardware_id FROM ecus ORDER BY id;");
927 EcuSerials new_serials;
929 while ((statement_state = statement.step()) == SQLITE_ROW) {
931 new_serials.emplace_back(
Uptane::EcuSerial(statement.get_result_col_str(0).value()),
934 }
catch (
const boost::bad_optional_access&) {
939 if (statement_state != SQLITE_DONE) {
940 LOG_ERROR <<
"Failed to get ECU serials: " << db.errmsg();
944 if (serials !=
nullptr) {
945 *serials = std::move(new_serials);
951 void SQLStorage::clearEcuSerials() {
954 db.beginTransaction();
956 if (db.exec(
"DELETE FROM ecus;",
nullptr,
nullptr) != SQLITE_OK) {
957 LOG_ERROR <<
"Failed to clear ECU serials: " << db.errmsg();
961 if (db.exec(
"DELETE FROM secondary_ecus;",
nullptr,
nullptr) != SQLITE_OK) {
962 LOG_ERROR <<
"Failed to clear Secondary ECUs: " << db.errmsg();
966 db.commitTransaction();
969 void SQLStorage::storeCachedEcuManifest(
const Uptane::EcuSerial& ecu_serial,
const std::string& manifest) {
972 auto statement = db.prepareStatement<std::string, std::string>(
973 "UPDATE secondary_ecus SET manifest = ? WHERE (serial = ?);", manifest, ecu_serial.ToString());
974 if (statement.step() != SQLITE_DONE || sqlite3_changes(db.get()) != 1) {
975 LOG_ERROR <<
"Failed to store Secondary manifest: " << db.errmsg();
980 bool SQLStorage::loadCachedEcuManifest(
const Uptane::EcuSerial& ecu_serial, std::string* manifest)
const {
983 std::string stmanifest;
987 auto statement = db.prepareStatement<std::string>(
"SELECT manifest FROM secondary_ecus WHERE (serial = ?);",
988 ecu_serial.ToString());
990 if (statement.step() != SQLITE_ROW) {
991 LOG_WARNING <<
"Could not find manifest for ECU " << ecu_serial;
994 stmanifest = statement.get_result_col_str(0).value_or(
"");
996 empty = stmanifest.empty();
999 if (manifest !=
nullptr) {
1000 *manifest = std::move(stmanifest);
1009 auto statement = db.prepareStatement<std::string, std::string,
int>(
1010 "INSERT OR REPLACE INTO misconfigured_ecus VALUES (?,?,?);", ecu.serial.ToString(), ecu.hardware_id.ToString(),
1011 static_cast<int>(ecu.state));
1012 if (statement.step() != SQLITE_DONE) {
1013 throw SQLException(db.errmsg().insert(0,
"Failed to set misconfigured ECUs: "));
1017 bool SQLStorage::loadMisconfiguredEcus(std::vector<MisconfiguredEcu>* ecus)
const {
1020 auto statement = db.prepareStatement(
"SELECT serial, hardware_id, state FROM misconfigured_ecus;");
1021 int statement_state;
1023 std::vector<MisconfiguredEcu> new_ecus;
1025 while ((statement_state = statement.step()) == SQLITE_ROW) {
1027 new_ecus.emplace_back(
Uptane::EcuSerial(statement.get_result_col_str(0).value()),
1029 static_cast<EcuState
>(statement.get_result_col_int(2)));
1031 }
catch (
const boost::bad_optional_access&) {
1036 if (statement_state != SQLITE_DONE) {
1037 LOG_ERROR <<
"Failed to get misconfigured ECUs: " << db.errmsg();
1041 if (ecus !=
nullptr) {
1042 *ecus = std::move(new_ecus);
1048 void SQLStorage::clearMisconfiguredEcus() {
1051 if (db.exec(
"DELETE FROM misconfigured_ecus;",
nullptr,
nullptr) != SQLITE_OK) {
1052 LOG_ERROR <<
"Failed to clear misconfigured ECUs: " << db.errmsg();
1057 void SQLStorage::saveInstalledVersion(
const std::string& ecu_serial,
const Uptane::Target& target,
1058 InstalledVersionUpdateMode update_mode) {
1061 db.beginTransaction();
1066 std::string ecu_serial_real = ecu_serial;
1067 if (ecu_serial_real.empty()) {
1068 auto statement = db.prepareStatement(
"SELECT serial FROM ecus WHERE is_primary = 1;");
1069 if (statement.step() == SQLITE_ROW) {
1070 ecu_serial_real = statement.get_result_col_str(0).value();
1072 LOG_WARNING <<
"Could not find Primary ECU serial, set to lazy init mode";
1076 std::string hashes_encoded = Hash::encodeVector(target.hashes());
1079 boost::optional<int64_t> old_id;
1080 bool old_was_installed =
false;
1082 auto statement = db.prepareStatement<std::string>(
1083 "SELECT id, sha256, name, was_installed FROM installed_versions WHERE ecu_serial = ? ORDER BY id DESC "
1087 if (statement.step() == SQLITE_ROW) {
1088 int64_t rid = statement.get_result_col_int(0);
1089 std::string rsha256 = statement.get_result_col_str(1).value_or(
"");
1090 std::string rname = statement.get_result_col_str(2).value_or(
"");
1091 bool rwasi = statement.get_result_col_int(3) == 1;
1093 if (rsha256 == target.sha256Hash() && rname == target.filename()) {
1095 old_was_installed = rwasi;
1100 if (update_mode == InstalledVersionUpdateMode::kCurrent) {
1102 auto statement = db.prepareStatement<std::string>(
1103 "UPDATE installed_versions SET is_current = 0, is_pending = 0 WHERE ecu_serial = ?", ecu_serial_real);
1104 if (statement.step() != SQLITE_DONE) {
1105 LOG_ERROR <<
"Failed to save installed versions: " << db.errmsg();
1108 }
else if (update_mode == InstalledVersionUpdateMode::kPending) {
1110 auto statement = db.prepareStatement<std::string>(
1111 "UPDATE installed_versions SET is_pending = 0 WHERE ecu_serial = ?", ecu_serial_real);
1112 if (statement.step() != SQLITE_DONE) {
1113 LOG_ERROR <<
"Failed to save installed versions: " << db.errmsg();
1119 auto statement = db.prepareStatement<std::string, int, int, int64_t>(
1120 "UPDATE installed_versions SET correlation_id = ?, is_current = ?, is_pending = ?, was_installed = ? WHERE id "
1122 target.correlation_id(),
static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent),
1123 static_cast<int>(update_mode == InstalledVersionUpdateMode::kPending),
1124 static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent || old_was_installed), old_id.value());
1126 if (statement.step() != SQLITE_DONE) {
1127 LOG_ERROR <<
"Failed to save installed versions: " << db.errmsg();
1131 std::string custom = Utils::jsonToCanonicalStr(target.custom_data());
1132 auto statement = db.prepareStatement<std::string, std::string, std::string, std::string, int64_t, std::string,
1133 std::string, int,
int>(
1134 "INSERT INTO installed_versions(ecu_serial, sha256, name, hashes, length, custom_meta, correlation_id, "
1135 "is_current, is_pending, was_installed) VALUES (?,?,?,?,?,?,?,?,?,?);",
1136 ecu_serial_real, target.sha256Hash(), target.filename(), hashes_encoded,
static_cast<int64_t
>(target.length()),
1137 custom, target.correlation_id(),
static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent),
1138 static_cast<int>(update_mode == InstalledVersionUpdateMode::kPending),
1139 static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent));
1141 if (statement.step() != SQLITE_DONE) {
1142 LOG_ERROR <<
"Failed to save installed versions: " << db.errmsg();
1147 db.commitTransaction();
1150 static void loadEcuMap(
SQLite3Guard& db, std::string& ecu_serial, Uptane::EcuMap& ecu_map) {
1153 if (ecu_serial.empty()) {
1154 auto statement = db.prepareStatement(
"SELECT serial FROM ecus WHERE is_primary = 1;");
1155 if (statement.step() == SQLITE_ROW) {
1156 ecu_serial = statement.get_result_col_str(0).value();
1157 }
else if (statement.step() == SQLITE_DONE) {
1158 LOG_DEBUG <<
"No serial found in database for this ECU, defaulting to empty serial";
1160 LOG_ERROR <<
"Error getting serial for this ECU, defaulting to empty serial: " << db.errmsg();
1164 if (!ecu_serial.empty()) {
1165 auto statement = db.prepareStatement<std::string>(
"SELECT hardware_id FROM ecus WHERE serial = ?;", ecu_serial);
1166 if (statement.step() == SQLITE_ROW) {
1169 }
else if (statement.step() == SQLITE_DONE) {
1170 LOG_DEBUG <<
"No hardware ID found in database for ECU serial " << ecu_serial;
1172 LOG_ERROR <<
"Error getting hardware ID for ECU serial " << ecu_serial <<
": " << db.errmsg();
1177 bool SQLStorage::loadInstallationLog(
const std::string& ecu_serial, std::vector<Uptane::Target>* log,
1178 bool only_installed)
const {
1181 std::string ecu_serial_real = ecu_serial;
1182 Uptane::EcuMap ecu_map;
1183 loadEcuMap(db, ecu_serial_real, ecu_map);
1186 "SELECT id, sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1187 "ecu_serial = ? ORDER BY id;";
1188 if (only_installed) {
1190 "SELECT id, sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1191 "ecu_serial = ? AND was_installed = 1 ORDER BY id;";
1194 auto statement = db.prepareStatement<std::string>(query, ecu_serial_real);
1195 int statement_state;
1197 std::vector<Uptane::Target> new_log;
1198 std::map<int64_t, size_t> ids_map;
1200 while ((statement_state = statement.step()) == SQLITE_ROW) {
1202 auto id = statement.get_result_col_int(0);
1203 auto sha256 = statement.get_result_col_str(1).value();
1204 auto filename = statement.get_result_col_str(2).value();
1205 auto hashes_str = statement.get_result_col_str(3).value();
1206 auto length = statement.get_result_col_int(4);
1207 auto correlation_id = statement.get_result_col_str(5).value();
1208 auto custom_str = statement.get_result_col_str(6).value();
1212 std::vector<Hash> hashes = Hash::decodeVector(hashes_str);
1215 std::find_if(hashes.cbegin(), hashes.cend(), [](
const Hash& h) { return h.type() == Hash::Type::kSha256; });
1216 if (find_sha256 == hashes.cend()) {
1217 LOG_WARNING <<
"No sha256 in hashes list";
1218 hashes.emplace_back(Hash::Type::kSha256, sha256);
1221 Uptane::Target t(filename, ecu_map, hashes,
static_cast<uint64_t
>(length), correlation_id);
1222 if (!custom_str.empty()) {
1223 std::istringstream css(custom_str);
1226 if (Json::parseFromStream(Json::CharReaderBuilder(), css, &custom,
nullptr)) {
1227 t.updateCustom(custom);
1229 LOG_ERROR <<
"Unable to parse custom data: " << errs;
1232 new_log.emplace_back(t);
1236 }
catch (
const boost::bad_optional_access&) {
1237 LOG_ERROR <<
"Incomplete installed version list; keeping previous entries.";
1242 if (statement_state != SQLITE_DONE) {
1243 LOG_ERROR <<
"Failed to get installed versions: " << db.errmsg();
1247 if (log ==
nullptr) {
1251 *log = std::move(new_log);
1256 bool SQLStorage::loadInstalledVersions(
const std::string& ecu_serial, boost::optional<Uptane::Target>* current_version,
1257 boost::optional<Uptane::Target>* pending_version)
const {
1260 std::string ecu_serial_real = ecu_serial;
1261 Uptane::EcuMap ecu_map;
1262 loadEcuMap(db, ecu_serial_real, ecu_map);
1265 auto sha256 = statement.get_result_col_str(0).value();
1266 auto filename = statement.get_result_col_str(1).value();
1267 auto hashes_str = statement.get_result_col_str(2).value();
1268 auto length = statement.get_result_col_int(3);
1269 auto correlation_id = statement.get_result_col_str(4).value();
1270 auto custom_str = statement.get_result_col_str(5).value();
1274 std::vector<Hash> hashes = Hash::decodeVector(hashes_str);
1277 std::find_if(hashes.cbegin(), hashes.cend(), [](
const Hash& h) { return h.type() == Hash::Type::kSha256; });
1278 if (find_sha256 == hashes.cend()) {
1279 LOG_WARNING <<
"No sha256 in hashes list";
1280 hashes.emplace_back(Hash::Type::kSha256, sha256);
1282 Uptane::Target t(filename, ecu_map, hashes,
static_cast<uint64_t
>(length), correlation_id);
1283 if (!custom_str.empty()) {
1284 std::istringstream css(custom_str);
1287 if (Json::parseFromStream(Json::CharReaderBuilder(), css, &custom, &errs)) {
1288 t.updateCustom(custom);
1290 LOG_ERROR <<
"Unable to parse custom data: " << errs;
1297 if (current_version !=
nullptr) {
1298 auto statement = db.prepareStatement<std::string>(
1299 "SELECT sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1300 "ecu_serial = ? AND is_current = 1 LIMIT 1;",
1303 if (statement.step() == SQLITE_ROW) {
1305 *current_version = read_target(statement);
1306 }
catch (
const boost::bad_optional_access&) {
1307 LOG_ERROR <<
"Could not read current installed version";
1311 LOG_TRACE <<
"Failed to get current installed version: " << db.errmsg();
1312 *current_version = boost::none;
1316 if (pending_version !=
nullptr) {
1317 auto statement = db.prepareStatement<std::string>(
1318 "SELECT sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1319 "ecu_serial = ? AND is_pending = 1 LIMIT 1;",
1322 if (statement.step() == SQLITE_ROW) {
1324 *pending_version = read_target(statement);
1325 }
catch (
const boost::bad_optional_access&) {
1326 LOG_ERROR <<
"Could not read pending installed version";
1330 LOG_TRACE <<
"Failed to get pending installed version: " << db.errmsg();
1331 *pending_version = boost::none;
1338 bool SQLStorage::hasPendingInstall() {
1341 auto statement = db.prepareStatement(
"SELECT count(*) FROM installed_versions where is_pending = 1");
1342 if (statement.step() != SQLITE_ROW) {
1343 LOG_ERROR <<
"Failed to get pending installation count: " << db.errmsg();
1344 throw SQLException(std::string(
"Failed to get pending installation count: ") + db.errmsg());
1347 return statement.get_result_col_int(0) > 0;
1350 void SQLStorage::getPendingEcus(std::vector<std::pair<Uptane::EcuSerial, Hash>>* pendingEcus) {
1353 auto statement = db.prepareStatement(
"SELECT ecu_serial, sha256 FROM installed_versions where is_pending = 1");
1354 int statement_result = statement.step();
1355 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1356 throw SQLException(
"Failed to get ECUs with a pending target installation: " + db.errmsg());
1359 std::vector<std::pair<Uptane::EcuSerial, Hash>> ecu_res;
1361 if (statement_result == SQLITE_DONE) {
1366 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1367 std::string ecu_serial = statement.get_result_col_str(0).value();
1368 std::string hash = statement.get_result_col_str(1).value();
1369 ecu_res.emplace_back(std::make_pair(
Uptane::EcuSerial(ecu_serial),
Hash(Hash::Type::kSha256, hash)));
1372 if (pendingEcus !=
nullptr) {
1373 *pendingEcus = std::move(ecu_res);
1377 void SQLStorage::clearInstalledVersions() {
1380 if (db.exec(
"DELETE FROM installed_versions;",
nullptr,
nullptr) != SQLITE_OK) {
1381 LOG_ERROR <<
"Failed to clear installed versions: " << db.errmsg();
1390 auto statement = db.prepareStatement<std::string, int, std::string, std::string>(
1391 "INSERT OR REPLACE INTO ecu_installation_results (ecu_serial, success, result_code, description) VALUES "
1393 ecu_serial.ToString(),
static_cast<int>(
result.success),
result.result_code.toRepr(),
result.description);
1394 if (statement.step() != SQLITE_DONE) {
1395 LOG_ERROR <<
"Failed to set ECU installation result: " << db.errmsg();
1400 bool SQLStorage::loadEcuInstallationResults(
1401 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>>* results)
const {
1404 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> ecu_res;
1407 auto statement = db.prepareStatement(
1408 "SELECT ecu_serial, success, result_code, description FROM ecu_installation_results INNER JOIN ecus ON "
1409 "ecus.serial = ecu_serial ORDER BY ecus.id;");
1410 int statement_result = statement.step();
1411 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1412 LOG_ERROR <<
"Failed to get ECU installation results: " << db.errmsg();
1416 if (statement_result == SQLITE_DONE) {
1421 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1423 std::string ecu_serial = statement.get_result_col_str(0).value();
1424 auto success =
static_cast<bool>(statement.get_result_col_int(1));
1425 data::ResultCode result_code = data::ResultCode::fromRepr(statement.get_result_col_str(2).value());
1426 std::string description = statement.get_result_col_str(3).value();
1429 }
catch (
const boost::bad_optional_access&) {
1434 if (results !=
nullptr) {
1435 *results = std::move(ecu_res);
1442 const std::string& correlation_id) {
1445 auto statement = db.prepareStatement<int, std::string, std::string, std::string, std::string>(
1446 "INSERT OR REPLACE INTO device_installation_result (unique_mark, success, result_code, description, raw_report, "
1448 "VALUES (0,?,?,?,?,?);",
1449 static_cast<int>(
result.success),
result.result_code.toRepr(),
result.description, raw_report, correlation_id);
1450 if (statement.step() != SQLITE_DONE) {
1451 LOG_ERROR <<
"Failed to store device installation result: " << db.errmsg();
1456 bool SQLStorage::storeDeviceInstallationRawReport(
const std::string& raw_report) {
1458 auto statement = db.prepareStatement<std::string>(
"UPDATE device_installation_result SET raw_report=?;", raw_report);
1459 if (statement.step() != SQLITE_DONE || sqlite3_changes(db.get()) != 1) {
1460 LOG_ERROR <<
"Failed to store device installation raw report: " << db.errmsg();
1467 std::string* correlation_id)
const {
1471 std::string raw_report_res;
1472 std::string corrid_res;
1474 auto statement = db.prepareStatement(
1475 "SELECT success, result_code, description, raw_report, correlation_id FROM device_installation_result;");
1476 int statement_result = statement.step();
1477 if (statement_result == SQLITE_DONE) {
1478 LOG_TRACE <<
"Device installation result not found in database";
1480 }
else if (statement_result != SQLITE_ROW) {
1481 LOG_ERROR <<
"Failed to get device installation result: " << db.errmsg();
1486 auto success =
static_cast<bool>(statement.get_result_col_int(0));
1487 data::ResultCode result_code = data::ResultCode::fromRepr(statement.get_result_col_str(1).value());
1488 std::string description = statement.get_result_col_str(2).value();
1489 raw_report_res = statement.get_result_col_str(3).value();
1490 corrid_res = statement.get_result_col_str(4).value();
1493 }
catch (
const boost::bad_optional_access&) {
1498 *
result = std::move(dev_res);
1501 if (raw_report !=
nullptr) {
1502 *raw_report = std::move(raw_report_res);
1505 if (correlation_id !=
nullptr) {
1506 *correlation_id = std::move(corrid_res);
1512 void SQLStorage::saveEcuReportCounter(
const Uptane::EcuSerial& ecu_serial,
const int64_t counter) {
1515 auto statement = db.prepareStatement<std::string, int64_t>(
1516 "INSERT OR REPLACE INTO ecu_report_counter (ecu_serial, counter) VALUES "
1518 ecu_serial.ToString(), counter);
1519 if (statement.step() != SQLITE_DONE) {
1520 LOG_ERROR <<
"Failed to set ECU report counter: " << db.errmsg();
1525 bool SQLStorage::loadEcuReportCounter(std::vector<std::pair<Uptane::EcuSerial, int64_t>>* results)
const {
1528 std::vector<std::pair<Uptane::EcuSerial, int64_t>> ecu_cnt;
1531 auto statement = db.prepareStatement(
1532 "SELECT ecu_serial, counter FROM ecu_report_counter INNER JOIN ecus ON "
1533 "ecus.serial = ecu_serial ORDER BY ecus.id;");
1534 int statement_result = statement.step();
1535 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1536 LOG_ERROR <<
"Failed to get ECU report counter: " << db.errmsg();
1540 if (statement_result == SQLITE_DONE) {
1545 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1547 std::string ecu_serial = statement.get_result_col_str(0).value();
1548 int64_t counter = statement.get_result_col_int(1);
1551 }
catch (
const boost::bad_optional_access&) {
1556 if (results !=
nullptr) {
1557 *results = std::move(ecu_cnt);
1563 void SQLStorage::saveReportEvent(
const Json::Value& json_value) {
1564 std::string json_string = Utils::jsonToCanonicalStr(json_value);
1566 auto statement = db.prepareStatement<std::string>(
1567 "INSERT INTO report_events SELECT MAX(id) + 1, ? FROM report_events", json_string);
1568 if (statement.step() != SQLITE_DONE) {
1569 LOG_ERROR <<
"Failed to save report event: " << db.errmsg();
1574 bool SQLStorage::loadReportEvents(Json::Value* report_array, int64_t* id_max)
const {
1576 auto statement = db.prepareStatement(
"SELECT id, json_string FROM report_events;");
1577 int statement_result = statement.step();
1578 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1579 LOG_ERROR <<
"Failed to get report events: " << db.errmsg();
1582 if (statement_result == SQLITE_DONE) {
1587 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1589 int64_t
id = statement.get_result_col_int(0);
1590 std::string json_string = statement.get_result_col_str(1).value();
1591 std::istringstream jss(json_string);
1592 Json::Value event_json;
1594 if (Json::parseFromStream(Json::CharReaderBuilder(), jss, &event_json, &errs)) {
1595 report_array->append(event_json);
1596 *id_max = (*id_max) >
id ? (*id_max) : id;
1598 LOG_ERROR <<
"Unable to parse event data: " << errs;
1600 }
catch (
const boost::bad_optional_access&) {
1608 void SQLStorage::deleteReportEvents(int64_t id_max) {
1611 auto statement = db.prepareStatement<int64_t>(
"DELETE FROM report_events WHERE id <= ?;", id_max);
1612 if (statement.step() != SQLITE_DONE) {
1613 LOG_ERROR <<
"Failed to clear report events: " << db.errmsg();
1617 void SQLStorage::clearInstallationResults() {
1620 db.beginTransaction();
1622 if (db.exec(
"DELETE FROM device_installation_result;",
nullptr,
nullptr) != SQLITE_OK) {
1623 LOG_ERROR <<
"Failed to clear device installation result: " << db.errmsg();
1627 if (db.exec(
"DELETE FROM ecu_installation_results;",
nullptr,
nullptr) != SQLITE_OK) {
1628 LOG_ERROR <<
"Failed to clear ECU installation results: " << db.errmsg();
1632 db.commitTransaction();
1635 void SQLStorage::storeDeviceDataHash(
const std::string& data_type,
const std::string& hash) {
1638 auto statement = db.prepareStatement<std::string, std::string>(
1639 "INSERT OR REPLACE INTO device_data(data_type,hash) VALUES (?,?);", data_type, hash);
1640 if (statement.step() != SQLITE_DONE) {
1641 LOG_ERROR <<
"Failed to store " << data_type <<
" hash: " << db.errmsg();
1642 throw SQLException(
"Failed to store " + data_type +
" hash: " + db.errmsg());
1646 bool SQLStorage::loadDeviceDataHash(
const std::string& data_type, std::string* hash)
const {
1650 db.prepareStatement<std::string>(
"SELECT hash FROM device_data WHERE data_type = ? LIMIT 1;", data_type);
1652 int result = statement.step();
1653 if (
result == SQLITE_DONE) {
1654 LOG_TRACE << data_type <<
" hash not found in database";
1656 }
else if (
result != SQLITE_ROW) {
1657 LOG_ERROR <<
"Failed to get " << data_type <<
" hash: " << db.errmsg();
1661 if (hash !=
nullptr) {
1662 *hash = statement.get_result_col_str(0).value();
1668 void SQLStorage::clearDeviceData() {
1671 if (db.exec(
"DELETE FROM device_data;",
nullptr,
nullptr) != SQLITE_OK) {
1672 LOG_ERROR <<
"Failed to clear device data: " << db.errmsg();
1677 void SQLStorage::storeTargetFilename(
const std::string& targetname,
const std::string& filename)
const {
1679 auto statement = db.prepareStatement<std::string, std::string>(
1680 "INSERT OR REPLACE INTO target_images (targetname, filename) VALUES (?, ?);", targetname, filename);
1682 if (statement.step() != SQLITE_DONE) {
1683 LOG_ERROR <<
"Failed to store Target filename: " << db.errmsg();
1684 throw SQLException(std::string(
"Failed to store Target filename: ") + db.errmsg());
1688 std::string SQLStorage::getTargetFilename(
const std::string& targetname)
const {
1692 db.prepareStatement<std::string>(
"SELECT filename FROM target_images WHERE targetname = ?;", targetname);
1694 switch (statement.step()) {
1696 return statement.get_result_col_str(0).value();
1700 throw SQLException(db.errmsg().insert(0,
"Failed to read Target filename from database: "));
1704 std::vector<std::string> SQLStorage::getAllTargetNames()
const {
1707 auto statement = db.prepareStatement<>(
"SELECT targetname FROM target_images;");
1709 std::vector<std::string> names;
1711 int result = statement.step();
1712 while (
result != SQLITE_DONE) {
1713 if (
result != SQLITE_ROW) {
1714 LOG_ERROR <<
"Failed to get Target filenames: " << db.errmsg();
1715 throw SQLException(std::string(
"Failed to get Target filenames: ") + db.errmsg());
1717 names.push_back(statement.get_result_col_str(0).value());
1718 result = statement.step();
1723 void SQLStorage::deleteTargetInfo(
const std::string& targetname)
const {
1726 auto statement = db.prepareStatement<std::string>(
"DELETE FROM target_images WHERE targetname=?;", targetname);
1728 if (statement.step() != SQLITE_DONE) {
1729 LOG_ERROR <<
"Failed to clear Target filenames: " << db.errmsg();
1730 throw SQLException(std::string(
"Failed to clear Target filenames: ") + db.errmsg());
1734 void SQLStorage::cleanUp() { boost::filesystem::remove_all(dbPath()); }