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 <<
"Can't 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 <<
"Can't 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 <<
"Can't 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 <<
"Can't 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 <<
"No public key in db";
98 }
else if (
result != SQLITE_ROW) {
99 LOG_ERROR <<
"Can't get 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 <<
"No private key in db";
124 }
else if (
result != SQLITE_ROW) {
125 LOG_ERROR <<
"Can't get 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 <<
"Can't 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 std::runtime_error(db.errmsg().insert(0,
"Can't 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 std::runtime_error(db.errmsg().insert(0,
"Can't save 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 std::runtime_error(db.errmsg().insert(0,
"Can't 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 std::runtime_error(db.errmsg().insert(0,
"Can't save 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";
226 }
else if (statement_state != SQLITE_ROW) {
227 LOG_ERROR <<
"Cannot 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 <<
"Can't 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 <<
"Can't 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 <<
"Can't set ca_cert: " << 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 <<
"Can't 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 <<
"Can't set client_cert: " << 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 <<
"Can't 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 <<
"Can't set client_pkey: " << 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 creds not present";
393 }
else if (
result != SQLITE_ROW) {
394 LOG_ERROR <<
"Can't get tls_creds: " << 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 <<
"Can't clear tls_creds: " << 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_cert not present";
440 }
else if (
result != SQLITE_ROW) {
441 LOG_ERROR <<
"Can't get ca_cert: " << 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_cert not present in db";
466 }
else if (
result != SQLITE_ROW) {
467 LOG_ERROR <<
"Can't get client_cert: " << 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_pkey not present in db";
492 }
else if (
result != SQLITE_ROW) {
493 LOG_ERROR <<
"Can't get client_pkey: " << 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 <<
"Can't 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 <<
"Can't add 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 <<
"Can't 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 <<
"Can't 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 present";
573 }
else if (
result != SQLITE_ROW) {
574 LOG_ERROR <<
"Can't 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 present";
590 }
else if (
result != SQLITE_ROW) {
591 LOG_ERROR <<
"Can't 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 <<
"Can't 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 present";
620 }
else if (
result != SQLITE_ROW) {
621 LOG_ERROR <<
"Can't 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 <<
"Can't clear metadata: " << db.errmsg();
642 void SQLStorage::clearMetadata() {
645 if (db.exec(
"DELETE FROM meta;",
nullptr,
nullptr) != SQLITE_OK) {
646 LOG_ERROR <<
"Can't 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 <<
"Can't add 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 present";
672 }
else if (
result != SQLITE_ROW) {
673 LOG_ERROR <<
"Can't 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 are not present";
695 }
else if (statement_state != SQLITE_ROW) {
696 LOG_ERROR <<
"Can't 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 <<
"Can't 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 <<
"Can't 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 not present in db";
753 }
else if (
result != SQLITE_ROW) {
754 LOG_ERROR <<
"Can't 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 <<
"Can't 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 std::runtime_error(
"Could not get device_info count");
789 if (statement.get_result_col_int(0) != 1) {
790 throw std::runtime_error(
"Cannot set ECU registered if no device_info set");
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 <<
"Can't set is_registered: " << 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) {
810 }
else if (
result != SQLITE_ROW) {
811 LOG_ERROR <<
"Can't get is_registered in device_info " << db.errmsg();
815 return statement.get_result_col_int(0) != 0;
818 void SQLStorage::clearEcuRegistered() {
822 std::string req =
"UPDATE device_info SET is_registered = 0";
823 if (db.exec(req.c_str(),
nullptr,
nullptr) != SQLITE_OK) {
824 LOG_ERROR <<
"Can't set is_registered: " << db.errmsg();
829 void SQLStorage::storeNeedReboot() {
832 auto statement = db.prepareStatement<
int>(
"INSERT OR REPLACE INTO need_reboot(unique_mark,flag) VALUES(0,?);", 1);
833 if (statement.step() != SQLITE_DONE) {
834 LOG_ERROR <<
"Can't set need_reboot: " << db.errmsg();
839 bool SQLStorage::loadNeedReboot(
bool* need_reboot)
const {
842 auto statement = db.prepareStatement(
"SELECT flag FROM need_reboot LIMIT 1;");
844 int result = statement.step();
845 if (
result == SQLITE_DONE) {
846 if (need_reboot !=
nullptr) {
847 *need_reboot =
false;
850 }
else if (
result != SQLITE_ROW) {
851 LOG_ERROR <<
"Can't get need_reboot: " << db.errmsg();
855 auto flag =
static_cast<bool>(statement.get_result_col_int(0));
856 if (need_reboot !=
nullptr) {
863 void SQLStorage::clearNeedReboot() {
866 if (db.exec(
"DELETE FROM need_reboot;",
nullptr,
nullptr) != SQLITE_OK) {
867 LOG_ERROR <<
"Can't clear need_reboot: " << db.errmsg();
872 void SQLStorage::storeEcuSerials(
const EcuSerials& serials) {
873 if (!serials.empty()) {
876 db.beginTransaction();
878 if (db.exec(
"DELETE FROM ecus;",
nullptr,
nullptr) != SQLITE_OK) {
879 LOG_ERROR <<
"Can't clear ecus: " << db.errmsg();
884 std::string serial = serials[0].first.ToString();
885 std::string hwid = serials[0].second.ToString();
887 auto statement = db.prepareStatement<std::string, std::string>(
888 "INSERT INTO ecus(id, serial,hardware_id,is_primary) VALUES (0, ?,?,1);", serial, hwid);
889 if (statement.step() != SQLITE_DONE) {
890 LOG_ERROR <<
"Can't set ecu_serial: " << db.errmsg();
895 auto statement_ivupdate = db.prepareStatement<std::string>(
896 "UPDATE installed_versions SET ecu_serial = ? WHERE ecu_serial = '';", serial);
898 if (statement_ivupdate.step() != SQLITE_DONE) {
899 LOG_ERROR <<
"Can't set ecu_serial: " << db.errmsg();
904 for (
auto it = serials.cbegin() + 1; it != serials.cend(); it++) {
905 auto statement = db.prepareStatement<int64_t, std::string, std::string>(
906 "INSERT INTO ecus(id,serial,hardware_id) VALUES (?,?,?);", it - serials.cbegin(), it->first.ToString(),
907 it->second.ToString());
909 if (statement.step() != SQLITE_DONE) {
910 LOG_ERROR <<
"Can't set ecu_serial: " << db.errmsg();
915 db.commitTransaction();
919 bool SQLStorage::loadEcuSerials(EcuSerials* serials)
const {
923 auto statement = db.prepareStatement(
"SELECT serial, hardware_id FROM ecus ORDER BY id;");
926 EcuSerials new_serials;
928 while ((statement_state = statement.step()) == SQLITE_ROW) {
930 new_serials.emplace_back(
Uptane::EcuSerial(statement.get_result_col_str(0).value()),
933 }
catch (
const boost::bad_optional_access&) {
938 if (statement_state != SQLITE_DONE) {
939 LOG_ERROR <<
"Can't get ECU serials: " << db.errmsg();
943 if (serials !=
nullptr) {
944 *serials = std::move(new_serials);
950 void SQLStorage::clearEcuSerials() {
953 db.beginTransaction();
955 if (db.exec(
"DELETE FROM ecus;",
nullptr,
nullptr) != SQLITE_OK) {
956 LOG_ERROR <<
"Can't clear ECUs: " << db.errmsg();
960 if (db.exec(
"DELETE FROM secondary_ecus;",
nullptr,
nullptr) != SQLITE_OK) {
961 LOG_ERROR <<
"Can't clear Secondary ECUs: " << db.errmsg();
965 db.commitTransaction();
968 void SQLStorage::storeCachedEcuManifest(
const Uptane::EcuSerial& ecu_serial,
const std::string& manifest) {
971 auto statement = db.prepareStatement<std::string, std::string>(
972 "UPDATE secondary_ecus SET manifest = ? WHERE (serial = ?);", manifest, ecu_serial.ToString());
973 if (statement.step() != SQLITE_DONE || sqlite3_changes(db.get()) != 1) {
974 LOG_ERROR <<
"Can't save Secondary manifest: " << db.errmsg();
979 bool SQLStorage::loadCachedEcuManifest(
const Uptane::EcuSerial& ecu_serial, std::string* manifest)
const {
982 std::string stmanifest;
986 auto statement = db.prepareStatement<std::string>(
"SELECT manifest FROM secondary_ecus WHERE (serial = ?);",
987 ecu_serial.ToString());
989 if (statement.step() != SQLITE_ROW) {
990 LOG_WARNING <<
"Could not find manifest for ECU " << ecu_serial;
993 stmanifest = statement.get_result_col_str(0).value_or(
"");
995 empty = stmanifest.empty();
998 if (manifest !=
nullptr) {
999 *manifest = std::move(stmanifest);
1008 auto statement = db.prepareStatement<std::string, std::string,
int>(
1009 "INSERT OR REPLACE INTO misconfigured_ecus VALUES (?,?,?);", ecu.serial.ToString(), ecu.hardware_id.ToString(),
1010 static_cast<int>(ecu.state));
1011 if (statement.step() != SQLITE_DONE) {
1012 throw std::runtime_error(db.errmsg().insert(0,
"Can't save misconfigured_ecus: "));
1016 bool SQLStorage::loadMisconfiguredEcus(std::vector<MisconfiguredEcu>* ecus)
const {
1019 auto statement = db.prepareStatement(
"SELECT serial, hardware_id, state FROM misconfigured_ecus;");
1020 int statement_state;
1022 std::vector<MisconfiguredEcu> new_ecus;
1024 while ((statement_state = statement.step()) == SQLITE_ROW) {
1026 new_ecus.emplace_back(
Uptane::EcuSerial(statement.get_result_col_str(0).value()),
1028 static_cast<EcuState
>(statement.get_result_col_int(2)));
1030 }
catch (
const boost::bad_optional_access&) {
1035 if (statement_state != SQLITE_DONE) {
1036 LOG_ERROR <<
"Can't get misconfigured_ecus: " << db.errmsg();
1040 if (ecus !=
nullptr) {
1041 *ecus = std::move(new_ecus);
1047 void SQLStorage::clearMisconfiguredEcus() {
1050 if (db.exec(
"DELETE FROM misconfigured_ecus;",
nullptr,
nullptr) != SQLITE_OK) {
1051 LOG_ERROR <<
"Can't clear misconfigured_ecus: " << db.errmsg();
1056 void SQLStorage::saveInstalledVersion(
const std::string& ecu_serial,
const Uptane::Target& target,
1057 InstalledVersionUpdateMode update_mode) {
1060 db.beginTransaction();
1065 std::string ecu_serial_real = ecu_serial;
1066 if (ecu_serial_real.empty()) {
1067 auto statement = db.prepareStatement(
"SELECT serial FROM ecus WHERE is_primary = 1;");
1068 if (statement.step() == SQLITE_ROW) {
1069 ecu_serial_real = statement.get_result_col_str(0).value();
1071 LOG_WARNING <<
"Could not find Primary ECU serial, set to lazy init mode";
1075 std::string hashes_encoded = Hash::encodeVector(target.hashes());
1078 boost::optional<int64_t> old_id;
1079 bool old_was_installed =
false;
1081 auto statement = db.prepareStatement<std::string>(
1082 "SELECT id, sha256, name, was_installed FROM installed_versions WHERE ecu_serial = ? ORDER BY id DESC "
1086 if (statement.step() == SQLITE_ROW) {
1087 int64_t rid = statement.get_result_col_int(0);
1088 std::string rsha256 = statement.get_result_col_str(1).value_or(
"");
1089 std::string rname = statement.get_result_col_str(2).value_or(
"");
1090 bool rwasi = statement.get_result_col_int(3) == 1;
1092 if (rsha256 == target.sha256Hash() && rname == target.filename()) {
1094 old_was_installed = rwasi;
1099 if (update_mode == InstalledVersionUpdateMode::kCurrent) {
1101 auto statement = db.prepareStatement<std::string>(
1102 "UPDATE installed_versions SET is_current = 0, is_pending = 0 WHERE ecu_serial = ?", ecu_serial_real);
1103 if (statement.step() != SQLITE_DONE) {
1104 LOG_ERROR <<
"Can't set installed_versions: " << db.errmsg();
1107 }
else if (update_mode == InstalledVersionUpdateMode::kPending) {
1109 auto statement = db.prepareStatement<std::string>(
1110 "UPDATE installed_versions SET is_pending = 0 WHERE ecu_serial = ?", ecu_serial_real);
1111 if (statement.step() != SQLITE_DONE) {
1112 LOG_ERROR <<
"Can't set installed_versions: " << db.errmsg();
1118 auto statement = db.prepareStatement<std::string, int, int, int64_t>(
1119 "UPDATE installed_versions SET correlation_id = ?, is_current = ?, is_pending = ?, was_installed = ? WHERE id "
1121 target.correlation_id(),
static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent),
1122 static_cast<int>(update_mode == InstalledVersionUpdateMode::kPending),
1123 static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent || old_was_installed), old_id.value());
1125 if (statement.step() != SQLITE_DONE) {
1126 LOG_ERROR <<
"Can't set installed_versions: " << db.errmsg();
1130 std::string custom = Utils::jsonToCanonicalStr(target.custom_data());
1131 auto statement = db.prepareStatement<std::string, std::string, std::string, std::string, int64_t, std::string,
1132 std::string, int,
int>(
1133 "INSERT INTO installed_versions(ecu_serial, sha256, name, hashes, length, custom_meta, correlation_id, "
1134 "is_current, is_pending, was_installed) VALUES (?,?,?,?,?,?,?,?,?,?);",
1135 ecu_serial_real, target.sha256Hash(), target.filename(), hashes_encoded,
static_cast<int64_t
>(target.length()),
1136 custom, target.correlation_id(),
static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent),
1137 static_cast<int>(update_mode == InstalledVersionUpdateMode::kPending),
1138 static_cast<int>(update_mode == InstalledVersionUpdateMode::kCurrent));
1140 if (statement.step() != SQLITE_DONE) {
1141 LOG_ERROR <<
"Can't set installed_versions: " << db.errmsg();
1146 db.commitTransaction();
1149 static void loadEcuMap(
SQLite3Guard& db, std::string& ecu_serial, Uptane::EcuMap& ecu_map) {
1152 if (ecu_serial.empty()) {
1153 auto statement = db.prepareStatement(
"SELECT serial FROM ecus WHERE is_primary = 1;");
1154 if (statement.step() == SQLITE_ROW) {
1155 ecu_serial = statement.get_result_col_str(0).value();
1156 }
else if (statement.step() == SQLITE_DONE) {
1157 LOG_DEBUG <<
"No serial found in database for this ECU, defaulting to empty serial";
1159 LOG_ERROR <<
"Error getting serial for this ECU, defaulting to empty serial: " << db.errmsg();
1163 if (!ecu_serial.empty()) {
1164 auto statement = db.prepareStatement<std::string>(
"SELECT hardware_id FROM ecus WHERE serial = ?;", ecu_serial);
1165 if (statement.step() == SQLITE_ROW) {
1168 }
else if (statement.step() == SQLITE_DONE) {
1169 LOG_DEBUG <<
"No hardware ID found in database for ECU serial " << ecu_serial;
1171 LOG_ERROR <<
"Error getting hardware ID for ECU serial " << ecu_serial <<
": " << db.errmsg();
1176 bool SQLStorage::loadInstallationLog(
const std::string& ecu_serial, std::vector<Uptane::Target>* log,
1177 bool only_installed)
const {
1180 std::string ecu_serial_real = ecu_serial;
1181 Uptane::EcuMap ecu_map;
1182 loadEcuMap(db, ecu_serial_real, ecu_map);
1185 "SELECT id, sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1186 "ecu_serial = ? ORDER BY id;";
1187 if (only_installed) {
1189 "SELECT id, sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1190 "ecu_serial = ? AND was_installed = 1 ORDER BY id;";
1193 auto statement = db.prepareStatement<std::string>(query, ecu_serial_real);
1194 int statement_state;
1196 std::vector<Uptane::Target> new_log;
1197 std::map<int64_t, size_t> ids_map;
1199 while ((statement_state = statement.step()) == SQLITE_ROW) {
1201 auto id = statement.get_result_col_int(0);
1202 auto sha256 = statement.get_result_col_str(1).value();
1203 auto filename = statement.get_result_col_str(2).value();
1204 auto hashes_str = statement.get_result_col_str(3).value();
1205 auto length = statement.get_result_col_int(4);
1206 auto correlation_id = statement.get_result_col_str(5).value();
1207 auto custom_str = statement.get_result_col_str(6).value();
1211 std::vector<Hash> hashes = Hash::decodeVector(hashes_str);
1214 std::find_if(hashes.cbegin(), hashes.cend(), [](
const Hash& h) { return h.type() == Hash::Type::kSha256; });
1215 if (find_sha256 == hashes.cend()) {
1216 LOG_WARNING <<
"No sha256 in hashes list";
1217 hashes.emplace_back(Hash::Type::kSha256, sha256);
1220 Uptane::Target t(filename, ecu_map, hashes,
static_cast<uint64_t
>(length), correlation_id);
1221 if (!custom_str.empty()) {
1222 std::istringstream css(custom_str);
1225 if (Json::parseFromStream(Json::CharReaderBuilder(), css, &custom,
nullptr)) {
1226 t.updateCustom(custom);
1228 LOG_ERROR <<
"Unable to parse custom data: " << errs;
1231 new_log.emplace_back(t);
1235 }
catch (
const boost::bad_optional_access&) {
1236 LOG_ERROR <<
"Incompleted installed version, keeping old one";
1241 if (statement_state != SQLITE_DONE) {
1242 LOG_ERROR <<
"Can't get installed_versions: " << db.errmsg();
1246 if (log ==
nullptr) {
1250 *log = std::move(new_log);
1255 bool SQLStorage::loadInstalledVersions(
const std::string& ecu_serial, boost::optional<Uptane::Target>* current_version,
1256 boost::optional<Uptane::Target>* pending_version)
const {
1259 std::string ecu_serial_real = ecu_serial;
1260 Uptane::EcuMap ecu_map;
1261 loadEcuMap(db, ecu_serial_real, ecu_map);
1264 auto sha256 = statement.get_result_col_str(0).value();
1265 auto filename = statement.get_result_col_str(1).value();
1266 auto hashes_str = statement.get_result_col_str(2).value();
1267 auto length = statement.get_result_col_int(3);
1268 auto correlation_id = statement.get_result_col_str(4).value();
1269 auto custom_str = statement.get_result_col_str(5).value();
1273 std::vector<Hash> hashes = Hash::decodeVector(hashes_str);
1276 std::find_if(hashes.cbegin(), hashes.cend(), [](
const Hash& h) { return h.type() == Hash::Type::kSha256; });
1277 if (find_sha256 == hashes.cend()) {
1278 LOG_WARNING <<
"No sha256 in hashes list";
1279 hashes.emplace_back(Hash::Type::kSha256, sha256);
1281 Uptane::Target t(filename, ecu_map, hashes,
static_cast<uint64_t
>(length), correlation_id);
1282 if (!custom_str.empty()) {
1283 std::istringstream css(custom_str);
1286 if (Json::parseFromStream(Json::CharReaderBuilder(), css, &custom, &errs)) {
1287 t.updateCustom(custom);
1289 LOG_ERROR <<
"Unable to parse custom data: " << errs;
1296 if (current_version !=
nullptr) {
1297 auto statement = db.prepareStatement<std::string>(
1298 "SELECT sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1299 "ecu_serial = ? AND is_current = 1 LIMIT 1;",
1302 if (statement.step() == SQLITE_ROW) {
1304 *current_version = read_target(statement);
1305 }
catch (
const boost::bad_optional_access&) {
1306 LOG_ERROR <<
"Could not read current installed version";
1310 LOG_TRACE <<
"Cannot get current installed version: " << db.errmsg();
1311 *current_version = boost::none;
1315 if (pending_version !=
nullptr) {
1316 auto statement = db.prepareStatement<std::string>(
1317 "SELECT sha256, name, hashes, length, correlation_id, custom_meta FROM installed_versions WHERE "
1318 "ecu_serial = ? AND is_pending = 1 LIMIT 1;",
1321 if (statement.step() == SQLITE_ROW) {
1323 *pending_version = read_target(statement);
1324 }
catch (
const boost::bad_optional_access&) {
1325 LOG_ERROR <<
"Could not read pending installed version";
1329 LOG_TRACE <<
"Cannot get pending installed version: " << db.errmsg();
1330 *pending_version = boost::none;
1337 bool SQLStorage::hasPendingInstall() {
1340 auto statement = db.prepareStatement(
"SELECT count(*) FROM installed_versions where is_pending = 1");
1341 if (statement.step() != SQLITE_ROW) {
1342 LOG_ERROR <<
"Can't get tables count: " << db.errmsg();
1343 throw std::runtime_error(
"Could not count pending installations");
1346 return statement.get_result_col_int(0) > 0;
1349 void SQLStorage::getPendingEcus(std::vector<std::pair<Uptane::EcuSerial, Hash>>* pendingEcus) {
1352 auto statement = db.prepareStatement(
"SELECT ecu_serial, sha256 FROM installed_versions where is_pending = 1");
1353 int statement_result = statement.step();
1354 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1355 throw std::runtime_error(
"Failed to get ECUs with a pending target installation: " + db.errmsg());
1358 std::vector<std::pair<Uptane::EcuSerial, Hash>> ecu_res;
1360 if (statement_result == SQLITE_DONE) {
1365 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1366 std::string ecu_serial = statement.get_result_col_str(0).value();
1367 std::string hash = statement.get_result_col_str(1).value();
1368 ecu_res.emplace_back(std::make_pair(
Uptane::EcuSerial(ecu_serial),
Hash(Hash::Type::kSha256, hash)));
1371 if (pendingEcus !=
nullptr) {
1372 *pendingEcus = std::move(ecu_res);
1376 void SQLStorage::clearInstalledVersions() {
1379 if (db.exec(
"DELETE FROM installed_versions;",
nullptr,
nullptr) != SQLITE_OK) {
1380 LOG_ERROR <<
"Can't clear installed_versions: " << db.errmsg();
1389 auto statement = db.prepareStatement<std::string, int, std::string, std::string>(
1390 "INSERT OR REPLACE INTO ecu_installation_results (ecu_serial, success, result_code, description) VALUES "
1392 ecu_serial.ToString(),
static_cast<int>(
result.success),
result.result_code.toRepr(),
result.description);
1393 if (statement.step() != SQLITE_DONE) {
1394 LOG_ERROR <<
"Can't set ECU installation result: " << db.errmsg();
1399 bool SQLStorage::loadEcuInstallationResults(
1400 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>>* results)
const {
1403 std::vector<std::pair<Uptane::EcuSerial, data::InstallationResult>> ecu_res;
1406 auto statement = db.prepareStatement(
1407 "SELECT ecu_serial, success, result_code, description FROM ecu_installation_results INNER JOIN ecus ON "
1408 "ecus.serial = ecu_serial ORDER BY ecus.id;");
1409 int statement_result = statement.step();
1410 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1411 LOG_ERROR <<
"Can't get ecu_installation_results: " << db.errmsg();
1415 if (statement_result == SQLITE_DONE) {
1420 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1422 std::string ecu_serial = statement.get_result_col_str(0).value();
1423 auto success =
static_cast<bool>(statement.get_result_col_int(1));
1424 data::ResultCode result_code = data::ResultCode::fromRepr(statement.get_result_col_str(2).value());
1425 std::string description = statement.get_result_col_str(3).value();
1428 }
catch (
const boost::bad_optional_access&) {
1433 if (results !=
nullptr) {
1434 *results = std::move(ecu_res);
1441 const std::string& correlation_id) {
1444 auto statement = db.prepareStatement<int, std::string, std::string, std::string, std::string>(
1445 "INSERT OR REPLACE INTO device_installation_result (unique_mark, success, result_code, description, raw_report, "
1447 "VALUES (0,?,?,?,?,?);",
1448 static_cast<int>(
result.success),
result.result_code.toRepr(),
result.description, raw_report, correlation_id);
1449 if (statement.step() != SQLITE_DONE) {
1450 LOG_ERROR <<
"Can't set device installation result: " << db.errmsg();
1455 bool SQLStorage::storeDeviceInstallationRawReport(
const std::string& raw_report) {
1457 auto statement = db.prepareStatement<std::string>(
"UPDATE device_installation_result SET raw_report=?;", raw_report);
1458 if (statement.step() != SQLITE_DONE || sqlite3_changes(db.get()) != 1) {
1459 LOG_ERROR <<
"Can't set device raw report result: " << db.errmsg();
1466 std::string* correlation_id)
const {
1470 std::string raw_report_res;
1471 std::string corrid_res;
1473 auto statement = db.prepareStatement(
1474 "SELECT success, result_code, description, raw_report, correlation_id FROM device_installation_result;");
1475 int statement_result = statement.step();
1476 if (statement_result == SQLITE_DONE) {
1477 LOG_TRACE <<
"No device installation result in db";
1479 }
else if (statement_result != SQLITE_ROW) {
1480 LOG_ERROR <<
"Can't get device_installation_result: " << db.errmsg();
1485 auto success =
static_cast<bool>(statement.get_result_col_int(0));
1486 data::ResultCode result_code = data::ResultCode::fromRepr(statement.get_result_col_str(1).value());
1487 std::string description = statement.get_result_col_str(2).value();
1488 raw_report_res = statement.get_result_col_str(3).value();
1489 corrid_res = statement.get_result_col_str(4).value();
1492 }
catch (
const boost::bad_optional_access&) {
1497 *
result = std::move(dev_res);
1500 if (raw_report !=
nullptr) {
1501 *raw_report = std::move(raw_report_res);
1504 if (correlation_id !=
nullptr) {
1505 *correlation_id = std::move(corrid_res);
1511 void SQLStorage::saveEcuReportCounter(
const Uptane::EcuSerial& ecu_serial,
const int64_t counter) {
1514 auto statement = db.prepareStatement<std::string, int64_t>(
1515 "INSERT OR REPLACE INTO ecu_report_counter (ecu_serial, counter) VALUES "
1517 ecu_serial.ToString(), counter);
1518 if (statement.step() != SQLITE_DONE) {
1519 LOG_ERROR <<
"Can't set ECU counter: " << db.errmsg();
1524 bool SQLStorage::loadEcuReportCounter(std::vector<std::pair<Uptane::EcuSerial, int64_t>>* results)
const {
1527 std::vector<std::pair<Uptane::EcuSerial, int64_t>> ecu_cnt;
1530 auto statement = db.prepareStatement(
1531 "SELECT ecu_serial, counter FROM ecu_report_counter INNER JOIN ecus ON "
1532 "ecus.serial = ecu_serial ORDER BY ecus.id;");
1533 int statement_result = statement.step();
1534 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1535 LOG_ERROR <<
"Can't get ecu_report_counter: " << db.errmsg();
1539 if (statement_result == SQLITE_DONE) {
1544 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1546 std::string ecu_serial = statement.get_result_col_str(0).value();
1547 int64_t counter = statement.get_result_col_int(1);
1550 }
catch (
const boost::bad_optional_access&) {
1555 if (results !=
nullptr) {
1556 *results = std::move(ecu_cnt);
1562 void SQLStorage::saveReportEvent(
const Json::Value& json_value) {
1563 std::string json_string = Utils::jsonToCanonicalStr(json_value);
1565 auto statement = db.prepareStatement<std::string>(
1566 "INSERT INTO report_events SELECT MAX(id) + 1, ? FROM report_events", json_string);
1567 if (statement.step() != SQLITE_DONE) {
1568 LOG_ERROR <<
"Can't save report event: " << db.errmsg();
1573 bool SQLStorage::loadReportEvents(Json::Value* report_array, int64_t* id_max)
const {
1575 auto statement = db.prepareStatement(
"SELECT id, json_string FROM report_events;");
1576 int statement_result = statement.step();
1577 if (statement_result != SQLITE_DONE && statement_result != SQLITE_ROW) {
1578 LOG_ERROR <<
"Can't get report_events: " << db.errmsg();
1581 if (statement_result == SQLITE_DONE) {
1586 for (; statement_result != SQLITE_DONE; statement_result = statement.step()) {
1588 int64_t
id = statement.get_result_col_int(0);
1589 std::string json_string = statement.get_result_col_str(1).value();
1590 std::istringstream jss(json_string);
1591 Json::Value event_json;
1593 if (Json::parseFromStream(Json::CharReaderBuilder(), jss, &event_json, &errs)) {
1594 report_array->append(event_json);
1595 *id_max = (*id_max) >
id ? (*id_max) : id;
1597 LOG_ERROR <<
"Unable to parse event data: " << errs;
1599 }
catch (
const boost::bad_optional_access&) {
1607 void SQLStorage::deleteReportEvents(int64_t id_max) {
1610 auto statement = db.prepareStatement<int64_t>(
"DELETE FROM report_events WHERE id <= ?;", id_max);
1611 if (statement.step() != SQLITE_DONE) {
1612 LOG_ERROR <<
"Can't delete report_events";
1616 void SQLStorage::clearInstallationResults() {
1619 db.beginTransaction();
1621 if (db.exec(
"DELETE FROM device_installation_result;",
nullptr,
nullptr) != SQLITE_OK) {
1622 LOG_ERROR <<
"Can't clear device_installation_result: " << db.errmsg();
1626 if (db.exec(
"DELETE FROM ecu_installation_results;",
nullptr,
nullptr) != SQLITE_OK) {
1627 LOG_ERROR <<
"Can't clear ecu_installation_results: " << db.errmsg();
1631 db.commitTransaction();
1634 void SQLStorage::storeDeviceDataHash(
const std::string& data_type,
const std::string& hash) {
1637 auto statement = db.prepareStatement<std::string, std::string>(
1638 "INSERT OR REPLACE INTO device_data(data_type,hash) VALUES (?,?);", data_type, hash);
1639 if (statement.step() != SQLITE_DONE) {
1640 LOG_ERROR <<
"Can't set " << data_type <<
" hash: " << db.errmsg();
1641 throw std::runtime_error(
"Can't set " + data_type +
" hash: " + db.errmsg());
1645 bool SQLStorage::loadDeviceDataHash(
const std::string& data_type, std::string* hash)
const {
1649 db.prepareStatement<std::string>(
"SELECT hash FROM device_data WHERE data_type = ? LIMIT 1;", data_type);
1651 int result = statement.step();
1652 if (
result == SQLITE_DONE) {
1653 LOG_TRACE << data_type <<
" hash not present in db";
1655 }
else if (
result != SQLITE_ROW) {
1656 LOG_ERROR <<
"Can't get " << data_type <<
" hash: " << db.errmsg();
1660 if (hash !=
nullptr) {
1661 *hash = statement.get_result_col_str(0).value();
1667 void SQLStorage::clearDeviceData() {
1670 if (db.exec(
"DELETE FROM device_data;",
nullptr,
nullptr) != SQLITE_OK) {
1671 LOG_ERROR <<
"Can't clear device_data: " << db.errmsg();
1676 void SQLStorage::storeTargetFilename(
const std::string& targetname,
const std::string& filename)
const {
1678 auto statement = db.prepareStatement<std::string, std::string>(
1679 "INSERT OR REPLACE INTO target_images (targetname, filename) VALUES (?, ?);", targetname, filename);
1681 if (statement.step() != SQLITE_DONE) {
1682 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1683 throw std::runtime_error(
"Could not write to db");
1687 std::string SQLStorage::getTargetFilename(
const std::string& targetname)
const {
1691 db.prepareStatement<std::string>(
"SELECT filename FROM target_images WHERE targetname = ?;", targetname);
1693 switch (statement.step()) {
1695 return statement.get_result_col_str(0).value();
1699 throw std::runtime_error(db.errmsg().insert(0,
"Error reading target filename from db: "));
1703 std::vector<std::string> SQLStorage::getAllTargetNames()
const {
1706 auto statement = db.prepareStatement<>(
"SELECT targetname FROM target_images;");
1708 std::vector<std::string> names;
1710 int result = statement.step();
1711 while (
result != SQLITE_DONE) {
1712 if (
result != SQLITE_ROW) {
1713 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1714 throw std::runtime_error(
"Error getting target files");
1716 names.push_back(statement.get_result_col_str(0).value());
1717 result = statement.step();
1722 void SQLStorage::deleteTargetInfo(
const std::string& targetname)
const {
1725 auto statement = db.prepareStatement<std::string>(
"DELETE FROM target_images WHERE targetname=?;", targetname);
1727 if (statement.step() != SQLITE_DONE) {
1728 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1729 throw std::runtime_error(
"Could not remove target file");
1733 void SQLStorage::cleanUp() { boost::filesystem::remove_all(dbPath()); }