1 #include "sqlstorage.h" 9 #include "logging/logging.h" 10 #include "sql_utils.h" 11 #include "utilities/utils.h" 13 boost::filesystem::path SQLStorage::dbPath()
const {
return config_.sqldb_path.get(config_.path); }
19 if (!db.beginTransaction()) {
20 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
24 auto statement = db.prepareStatement<int, int,
int>(
25 "SELECT meta FROM meta WHERE (repo=? AND meta_type=? AND version=?);",
static_cast<int>(repo), role.ToInt(), -1);
27 int result = statement.step();
29 if (result == SQLITE_DONE) {
30 LOG_TRACE <<
"meta with role " << role.ToString() <<
" in repo " << Uptane::RepoString(repo)
31 <<
" not present in db";
33 }
else if (result != SQLITE_ROW) {
34 LOG_ERROR <<
"Can't get meta: " << db.errmsg();
37 std::string meta = std::string(reinterpret_cast<const char*>(sqlite3_column_blob(statement.get(), 0)));
39 int version = Uptane::extractVersionUntrusted(meta);
41 LOG_ERROR <<
"Corrupted metadata";
46 statement = db.prepareStatement<int, int,
int>(
"DELETE FROM meta WHERE (repo=? AND meta_type=? AND version=?);",
47 static_cast<int>(repo), role.ToInt(), version);
49 if (statement.step() != SQLITE_DONE) {
50 LOG_ERROR <<
"Can't clear metadata: " << db.errmsg();
54 statement = db.prepareStatement<int, int, int,
int>(
55 "UPDATE meta SET version = ? WHERE (repo=? AND meta_type=? AND version=?);", version,
static_cast<int>(repo),
58 if (statement.step() != SQLITE_DONE) {
59 LOG_ERROR <<
"Can't update metadata: " << db.errmsg();
63 db.commitTransaction();
67 boost::filesystem::path db_parent_path = dbPath().parent_path();
68 if (!boost::filesystem::is_directory(db_parent_path)) {
69 Utils::createDirectories(db_parent_path, S_IRWXU);
72 stat(db_parent_path.c_str(), &st);
73 if ((st.st_mode & (S_IWGRP | S_IWOTH)) != 0) {
76 if ((st.st_mode & (S_IRGRP | S_IROTH)) != 0) {
78 chmod(db_parent_path.c_str(), S_IRWXU);
83 LOG_ERROR <<
"SQLite database migration failed";
88 cleanMetaVersion(Uptane::RepositoryType::Director, Uptane::Role::Root());
89 cleanMetaVersion(Uptane::RepositoryType::Images, Uptane::Role::Root());
91 LOG_ERROR <<
"SQLite database metadata version migration failed";
97 if (db.get_rc() != SQLITE_OK) {
98 throw SQLException(std::string(
"Can't open database: ") + db.errmsg());
103 void SQLStorage::storePrimaryKeys(
const std::string& public_key,
const std::string& private_key) {
106 auto statement = db.prepareStatement<std::string>(
107 "INSERT OR REPLACE INTO primary_keys(unique_mark,public,private) VALUES (0,?,?);", public_key, private_key);
108 if (statement.step() != SQLITE_DONE) {
109 LOG_ERROR <<
"Can't set primary keys: " << db.errmsg();
114 bool SQLStorage::loadPrimaryKeys(std::string* public_key, std::string* private_key) {
115 return loadPrimaryPublic(public_key) && loadPrimaryPrivate(private_key);
118 bool SQLStorage::loadPrimaryPublic(std::string* public_key) {
121 auto statement = db.prepareStatement(
"SELECT public FROM primary_keys LIMIT 1;");
123 int result = statement.step();
124 if (result == SQLITE_DONE) {
125 LOG_TRACE <<
"No public key in db";
127 }
else if (result != SQLITE_ROW) {
128 LOG_ERROR <<
"Can't get public key: " << db.errmsg();
132 auto pub = statement.get_result_col_str(0);
133 if (pub == boost::none) {
137 if (public_key !=
nullptr) {
138 *public_key = std::move(pub.value());
144 bool SQLStorage::loadPrimaryPrivate(std::string* private_key) {
147 auto statement = db.prepareStatement(
"SELECT private FROM primary_keys LIMIT 1;");
149 int result = statement.step();
150 if (result == SQLITE_DONE) {
151 LOG_TRACE <<
"No private key in db";
153 }
else if (result != SQLITE_ROW) {
154 LOG_ERROR <<
"Can't get private key: " << db.errmsg();
158 auto priv = statement.get_result_col_str(0);
159 if (priv == boost::none) {
163 if (private_key !=
nullptr) {
164 *private_key = std::move(priv.value());
170 void SQLStorage::clearPrimaryKeys() {
173 if (db.exec(
"DELETE FROM primary_keys;",
nullptr,
nullptr) != SQLITE_OK) {
174 LOG_ERROR <<
"Can't clear primary keys: " << db.errmsg();
179 void SQLStorage::storeTlsCreds(
const std::string& ca,
const std::string& cert,
const std::string& pkey) {
185 void SQLStorage::storeTlsCa(
const std::string& ca) {
188 if (!db.beginTransaction()) {
189 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
193 auto statement = db.prepareStatement(
"SELECT count(*) FROM tls_creds;");
194 if (statement.step() != SQLITE_ROW) {
195 LOG_ERROR <<
"Can't get count of tls_creds table: " << db.errmsg();
200 if (statement.get_result_col_int(0) != 0) {
201 req =
"UPDATE OR REPLACE tls_creds SET ca_cert = ?;";
203 req =
"INSERT INTO tls_creds(ca_cert) VALUES (?);";
207 if (statement.step() != SQLITE_DONE) {
208 LOG_ERROR <<
"Can't set ca_cert: " << db.errmsg();
212 db.commitTransaction();
215 void SQLStorage::storeTlsCert(
const std::string& cert) {
218 if (!db.beginTransaction()) {
219 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
223 auto statement = db.prepareStatement(
"SELECT count(*) FROM tls_creds;");
224 if (statement.step() != SQLITE_ROW) {
225 LOG_ERROR <<
"Can't get count of tls_creds table: " << db.errmsg();
230 if (statement.get_result_col_int(0) != 0) {
231 req =
"UPDATE OR REPLACE tls_creds SET client_cert = ?;";
233 req =
"INSERT INTO tls_creds(client_cert) VALUES (?);";
237 if (statement.step() != SQLITE_DONE) {
238 LOG_ERROR <<
"Can't set client_cert: " << db.errmsg();
242 db.commitTransaction();
245 void SQLStorage::storeTlsPkey(
const std::string& pkey) {
248 if (!db.beginTransaction()) {
249 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
252 auto statement = db.prepareStatement(
"SELECT count(*) FROM tls_creds;");
253 if (statement.step() != SQLITE_ROW) {
254 LOG_ERROR <<
"Can't get count of tls_creds table: " << db.errmsg();
259 if (statement.get_result_col_int(0) != 0) {
260 req =
"UPDATE OR REPLACE tls_creds SET client_pkey = ?;";
262 req =
"INSERT INTO tls_creds(client_pkey) VALUES (?);";
266 if (statement.step() != SQLITE_DONE) {
267 LOG_ERROR <<
"Can't set client_pkey: " << db.errmsg();
271 db.commitTransaction();
274 bool SQLStorage::loadTlsCreds(std::string* ca, std::string* cert, std::string* pkey) {
277 if (!db.beginTransaction()) {
278 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
281 auto statement = db.prepareStatement(
"SELECT ca_cert, client_cert, client_pkey FROM tls_creds LIMIT 1;");
283 int result = statement.step();
284 if (result == SQLITE_DONE) {
285 LOG_TRACE <<
"Tls creds not present";
287 }
else if (result != SQLITE_ROW) {
288 LOG_ERROR <<
"Can't get tls_creds: " << db.errmsg();
292 std::string ca_v, cert_v, pkey_v;
294 ca_v = statement.get_result_col_str(0).value();
295 cert_v = statement.get_result_col_str(1).value();
296 pkey_v = statement.get_result_col_str(2).value();
297 }
catch (
const boost::bad_optional_access&) {
302 *ca = std::move(ca_v);
304 if (cert !=
nullptr) {
305 *cert = std::move(cert_v);
307 if (pkey !=
nullptr) {
308 *pkey = std::move(pkey_v);
311 db.commitTransaction();
316 void SQLStorage::clearTlsCreds() {
319 if (db.exec(
"DELETE FROM tls_creds;",
nullptr,
nullptr) != SQLITE_OK) {
320 LOG_ERROR <<
"Can't clear tls_creds: " << db.errmsg();
325 bool SQLStorage::loadTlsCa(std::string* ca) {
328 auto statement = db.prepareStatement(
"SELECT ca_cert FROM tls_creds LIMIT 1;");
330 int result = statement.step();
331 if (result == SQLITE_DONE) {
332 LOG_TRACE <<
"ca_cert not present";
334 }
else if (result != SQLITE_ROW) {
335 LOG_ERROR <<
"Can't get ca_cert: " << db.errmsg();
339 auto ca_r = statement.get_result_col_str(0);
340 if (ca_r == boost::none) {
345 *ca = std::move(ca_r.value());
351 bool SQLStorage::loadTlsCert(std::string* cert) {
354 auto statement = db.prepareStatement(
"SELECT client_cert FROM tls_creds LIMIT 1;");
356 int result = statement.step();
357 if (result == SQLITE_DONE) {
358 LOG_TRACE <<
"client_cert not present in db";
360 }
else if (result != SQLITE_ROW) {
361 LOG_ERROR <<
"Can't get client_cert: " << db.errmsg();
365 auto cert_r = statement.get_result_col_str(0);
366 if (cert_r == boost::none) {
370 if (cert !=
nullptr) {
371 *cert = std::move(cert_r.value());
377 bool SQLStorage::loadTlsPkey(std::string* pkey) {
380 auto statement = db.prepareStatement(
"SELECT client_pkey FROM tls_creds LIMIT 1;");
382 int result = statement.step();
383 if (result == SQLITE_DONE) {
384 LOG_TRACE <<
"client_pkey not present in db";
386 }
else if (result != SQLITE_ROW) {
387 LOG_ERROR <<
"Can't get client_pkey: " << db.errmsg();
391 auto pkey_r = statement.get_result_col_str(0);
392 if (pkey_r == boost::none) {
396 if (pkey !=
nullptr) {
397 *pkey = std::move(pkey_r.value());
406 if (!db.beginTransaction()) {
407 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
412 db.prepareStatement<int, int,
int>(
"DELETE FROM meta WHERE (repo=? AND meta_type=? AND version=?);",
413 static_cast<int>(repo), Uptane::Role::Root().ToInt(), version.version());
415 if (del_statement.step() != SQLITE_DONE) {
416 LOG_ERROR <<
"Can't clear root metadata: " << db.errmsg();
420 auto ins_statement = db.prepareStatement<
SQLBlob, int, int,
int>(
"INSERT INTO meta VALUES (?, ?, ?, ?);",
422 Uptane::Role::Root().ToInt(), version.version());
424 if (ins_statement.step() != SQLITE_DONE) {
425 LOG_ERROR <<
"Can't add metadata: " << db.errmsg();
429 db.commitTransaction();
435 if (!db.beginTransaction()) {
436 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
440 auto del_statement = db.prepareStatement<int,
int>(
"DELETE FROM meta WHERE (repo=? AND meta_type=?);",
441 static_cast<int>(repo), role.ToInt());
443 if (del_statement.step() != SQLITE_DONE) {
444 LOG_ERROR <<
"Can't clear metadata: " << db.errmsg();
449 db.prepareStatement<
SQLBlob, int, int,
int>(
"INSERT INTO meta VALUES (?, ?, ?, ?);",
SQLBlob(
data),
452 if (ins_statement.step() != SQLITE_DONE) {
453 LOG_ERROR <<
"Can't add metadata: " << db.errmsg();
457 db.commitTransaction();
464 if (version.version() < 0) {
465 auto statement = db.prepareStatement<int,
int>(
466 "SELECT meta FROM meta WHERE (repo=? AND meta_type=?) ORDER BY version DESC LIMIT 1;",
static_cast<int>(repo),
467 Uptane::Role::Root().ToInt());
468 int result = statement.step();
470 if (result == SQLITE_DONE) {
471 LOG_TRACE <<
"Meta not present";
473 }
else if (result != SQLITE_ROW) {
474 LOG_ERROR <<
"Can't get meta: " << db.errmsg();
477 if (
data !=
nullptr) {
478 *
data = std::string(reinterpret_cast<const char*>(sqlite3_column_blob(statement.get(), 0)));
482 db.prepareStatement<int, int,
int>(
"SELECT meta FROM meta WHERE (repo=? AND meta_type=? AND version=?);",
483 static_cast<int>(repo), Uptane::Role::Root().ToInt(), version.version());
485 int result = statement.step();
487 if (result == SQLITE_DONE) {
488 LOG_TRACE <<
"Meta not present";
490 }
else if (result != SQLITE_ROW) {
491 LOG_ERROR <<
"Can't get meta: " << db.errmsg();
494 if (
data !=
nullptr) {
495 *
data = std::string(reinterpret_cast<const char*>(sqlite3_column_blob(statement.get(), 0)));
505 auto statement = db.prepareStatement<int,
int>(
506 "SELECT meta FROM meta WHERE (repo=? AND meta_type=?) ORDER BY version DESC LIMIT 1;",
static_cast<int>(repo),
508 int result = statement.step();
510 if (result == SQLITE_DONE) {
511 LOG_TRACE <<
"Meta not present";
513 }
else if (result != SQLITE_ROW) {
514 LOG_ERROR <<
"Can't get meta: " << db.errmsg();
517 if (
data !=
nullptr) {
518 *
data = std::string(reinterpret_cast<const char*>(sqlite3_column_blob(statement.get(), 0)));
528 db.prepareStatement<
int>(
"DELETE FROM meta WHERE (repo=? AND meta_type != 0);",
static_cast<int>(repo));
530 if (del_statement.step() != SQLITE_DONE) {
531 LOG_ERROR <<
"Can't clear metadata: " << db.errmsg();
535 void SQLStorage::clearMetadata() {
538 if (db.exec(
"DELETE FROM meta;",
nullptr,
nullptr) != SQLITE_OK) {
539 LOG_ERROR <<
"Can't clear metadata: " << db.errmsg();
544 void SQLStorage::storeDeviceId(
const std::string& device_id) {
547 auto statement = db.prepareStatement<std::string>(
548 "INSERT OR REPLACE INTO device_info(unique_mark,device_id,is_registered) VALUES(0,?,0);", device_id);
549 if (statement.step() != SQLITE_DONE) {
550 LOG_ERROR <<
"Can't set device ID: " << db.errmsg();
555 bool SQLStorage::loadDeviceId(std::string* device_id) {
558 auto statement = db.prepareStatement(
"SELECT device_id FROM device_info LIMIT 1;");
560 int result = statement.step();
561 if (result == SQLITE_DONE) {
562 LOG_TRACE <<
"device_id not present in db";
564 }
else if (result != SQLITE_ROW) {
565 LOG_ERROR <<
"Can't get device ID: " << db.errmsg();
569 auto did = statement.get_result_col_str(0);
570 if (did == boost::none) {
571 LOG_ERROR <<
"Empty device ID" << db.errmsg();
575 if (device_id !=
nullptr) {
576 *device_id = std::move(did.value());
582 void SQLStorage::clearDeviceId() {
585 if (db.exec(
"DELETE FROM device_info;",
nullptr,
nullptr) != SQLITE_OK) {
586 LOG_ERROR <<
"Can't clear device ID: " << db.errmsg();
591 void SQLStorage::storeEcuRegistered() {
594 if (!db.beginTransaction()) {
595 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
599 auto statement = db.prepareStatement(
"SELECT count(*) FROM device_info;");
600 if (statement.step() != SQLITE_ROW) {
601 throw std::runtime_error(
"Could not get device_info count");
603 if (statement.get_result_col_int(0) != 1) {
604 throw std::runtime_error(
"Cannot set ecu registered if no device_info set");
607 std::string req =
"UPDATE device_info SET is_registered = 1";
608 if (db.exec(req.c_str(),
nullptr,
nullptr) != SQLITE_OK) {
609 LOG_ERROR <<
"Can't set is_registered: " << db.errmsg();
613 db.commitTransaction();
616 bool SQLStorage::loadEcuRegistered() {
619 auto statement = db.prepareStatement(
"SELECT is_registered FROM device_info LIMIT 1;");
621 int result = statement.step();
622 if (result == SQLITE_DONE) {
624 }
else if (result != SQLITE_ROW) {
625 LOG_ERROR <<
"Can't get is_registered in device_info " << db.errmsg();
629 return statement.get_result_col_int(0) != 0;
632 void SQLStorage::clearEcuRegistered() {
636 std::string req =
"UPDATE device_info SET is_registered = 0";
637 if (db.exec(req.c_str(),
nullptr,
nullptr) != SQLITE_OK) {
638 LOG_ERROR <<
"Can't set is_registered: " << db.errmsg();
643 void SQLStorage::storeEcuSerials(
const EcuSerials& serials) {
644 if (serials.size() >= 1) {
647 if (!db.beginTransaction()) {
648 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
652 if (db.exec(
"DELETE FROM ecu_serials;",
nullptr,
nullptr) != SQLITE_OK) {
653 LOG_ERROR <<
"Can't clear ecu_serials: " << db.errmsg();
657 std::string serial = serials[0].first.ToString();
658 std::string hwid = serials[0].second.ToString();
661 db.prepareStatement<std::string, std::string>(
"INSERT INTO ecu_serials VALUES (?,?,1);", serial, hwid);
662 if (statement.step() != SQLITE_DONE) {
663 LOG_ERROR <<
"Can't set ecu_serial: " << db.errmsg();
668 EcuSerials::const_iterator it;
669 for (it = serials.begin() + 1; it != serials.end(); it++) {
670 auto statement = db.prepareStatement<std::string, std::string>(
"INSERT INTO ecu_serials VALUES (?,?,0);",
671 it->first.ToString(), it->second.ToString());
673 if (statement.step() != SQLITE_DONE) {
674 LOG_ERROR <<
"Can't set ecu_serial: " << db.errmsg();
679 db.commitTransaction();
683 bool SQLStorage::loadEcuSerials(EcuSerials* serials) {
686 auto statement = db.prepareStatement(
"SELECT serial, hardware_id FROM ecu_serials ORDER BY is_primary DESC;");
689 EcuSerials new_serials;
691 while ((statement_state = statement.step()) == SQLITE_ROW) {
693 new_serials.emplace_back(
Uptane::EcuSerial(statement.get_result_col_str(0).value()),
696 }
catch (
const boost::bad_optional_access&) {
701 if (statement_state != SQLITE_DONE) {
702 LOG_ERROR <<
"Can't get ecu_serials: " << db.errmsg();
706 if (serials !=
nullptr) {
707 *serials = std::move(new_serials);
713 void SQLStorage::clearEcuSerials() {
716 if (db.exec(
"DELETE FROM ecu_serials;",
nullptr,
nullptr) != SQLITE_OK) {
717 LOG_ERROR <<
"Can't clear ecu_serials: " << db.errmsg();
722 void SQLStorage::storeMisconfiguredEcus(
const std::vector<MisconfiguredEcu>& ecus) {
723 if (ecus.size() >= 1) {
726 if (!db.beginTransaction()) {
727 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
731 if (db.exec(
"DELETE FROM misconfigured_ecus;",
nullptr,
nullptr) != SQLITE_OK) {
732 LOG_ERROR <<
"Can't clear misconfigured_ecus: " << db.errmsg();
736 std::vector<MisconfiguredEcu>::const_iterator it;
737 for (it = ecus.begin(); it != ecus.end(); it++) {
738 auto statement = db.prepareStatement<std::string, std::string,
int>(
739 "INSERT INTO misconfigured_ecus VALUES (?,?,?);", it->serial.ToString(), it->hardware_id.ToString(),
740 static_cast<int>(it->state));
742 if (statement.step() != SQLITE_DONE) {
743 LOG_ERROR <<
"Can't set misconfigured_ecus: " << db.errmsg();
748 db.commitTransaction();
752 bool SQLStorage::loadMisconfiguredEcus(std::vector<MisconfiguredEcu>* ecus) {
755 auto statement = db.prepareStatement(
"SELECT serial, hardware_id, state FROM misconfigured_ecus;");
758 std::vector<MisconfiguredEcu> new_ecus;
760 while ((statement_state = statement.step()) == SQLITE_ROW) {
762 new_ecus.emplace_back(
Uptane::EcuSerial(statement.get_result_col_str(0).value()),
764 static_cast<EcuState>(statement.get_result_col_int(2)));
766 }
catch (
const boost::bad_optional_access&) {
771 if (statement_state != SQLITE_DONE) {
772 LOG_ERROR <<
"Can't get misconfigured_ecus: " << db.errmsg();
776 if (ecus !=
nullptr) {
777 *ecus = std::move(new_ecus);
783 void SQLStorage::clearMisconfiguredEcus() {
786 if (db.exec(
"DELETE FROM misconfigured_ecus;",
nullptr,
nullptr) != SQLITE_OK) {
787 LOG_ERROR <<
"Can't clear misconfigured_ecus: " << db.errmsg();
792 void SQLStorage::storeInstalledVersions(
const std::vector<Uptane::Target>& installed_versions,
793 const std::string& current_hash) {
794 if (installed_versions.size() >= 1) {
797 if (!db.beginTransaction()) {
798 LOG_ERROR <<
"Can't start transaction: " << db.errmsg();
802 if (db.exec(
"DELETE FROM installed_versions;",
nullptr,
nullptr) != SQLITE_OK) {
803 LOG_ERROR <<
"Can't clear installed_versions: " << db.errmsg();
807 std::vector<Uptane::Target>::const_iterator it;
808 for (it = installed_versions.cbegin(); it != installed_versions.cend(); it++) {
809 std::string sql =
"INSERT INTO installed_versions VALUES (?,?,?,?);";
810 std::string hash = it->sha256Hash();
811 std::string filename = it->filename();
812 bool is_current = current_hash == it->sha256Hash();
813 int64_t size = it->length();
814 auto statement = db.prepareStatement<std::string, std::string, int,
int>(
815 sql, hash, filename,
static_cast<int>(is_current), static_cast<int>(size));
817 if (statement.step() != SQLITE_DONE) {
818 LOG_ERROR <<
"Can't set installed_versions: " << db.errmsg();
823 db.commitTransaction();
827 std::string SQLStorage::loadInstalledVersions(std::vector<Uptane::Target>* installed_versions) {
830 std::string current_hash;
831 auto statement = db.prepareStatement(
"SELECT name, hash, length, is_current FROM installed_versions;");
834 std::vector<Uptane::Target> new_installed_versions;
835 std::string new_hash;
836 while ((statement_state = statement.step()) == SQLITE_ROW) {
838 Json::Value installed_version;
839 auto name = statement.get_result_col_str(0).value();
840 auto hash = statement.get_result_col_str(1).value();
841 auto length = statement.get_result_col_int(2);
842 auto is_current = statement.get_result_col_int(3) != 0;
844 installed_version[
"hashes"][
"sha256"] = hash;
845 installed_version[
"length"] = Json::UInt64(length);
849 std::string filename = name;
850 new_installed_versions.emplace_back(filename, installed_version);
851 }
catch (
const boost::bad_optional_access&) {
852 LOG_ERROR <<
"Incompleted installed version, keeping old one";
857 if (new_hash !=
"") {
858 current_hash = new_hash;
861 if (statement_state != SQLITE_DONE) {
862 LOG_ERROR <<
"Can't get installed_versions: " << db.errmsg();
866 if (installed_versions !=
nullptr) {
867 *installed_versions = std::move(new_installed_versions);
873 void SQLStorage::clearInstalledVersions() {
876 if (db.exec(
"DELETE FROM installed_versions;",
nullptr,
nullptr) != SQLITE_OK) {
877 LOG_ERROR <<
"Can't clear installed_versions: " << db.errmsg();
885 auto statement = db.prepareStatement<std::string, int, std::string>(
886 "INSERT OR REPLACE INTO installation_result (unique_mark, id, result_code, result_text) VALUES (0,?,?,?);",
887 result.id,
static_cast<int>(result.result_code), result.result_text);
888 if (statement.step() != SQLITE_DONE) {
889 LOG_ERROR <<
"Can't set installation_result: " << db.errmsg();
897 auto statement = db.prepareStatement(
"SELECT id, result_code, result_text FROM installation_result LIMIT 1;");
898 int statement_result = statement.step();
899 if (statement_result == SQLITE_DONE) {
900 LOG_TRACE <<
"installation_result not present in db";
902 }
else if (statement_result != SQLITE_ROW) {
903 LOG_ERROR <<
"Can't get installation_result: " << db.errmsg();
909 std::string result_text;
911 id = statement.get_result_col_str(0).value();
912 result_code = statement.get_result_col_int(1);
913 result_text = statement.get_result_col_str(2).value();
914 }
catch (
const boost::bad_optional_access&) {
918 if (result !=
nullptr) {
919 result->id = std::move(
id);
921 result->result_text = std::move(result_text);
927 void SQLStorage::clearInstallationResult() {
930 if (db.exec(
"DELETE FROM installation_result;",
nullptr,
nullptr) != SQLITE_OK) {
931 LOG_ERROR <<
"Can't clear installation_result: " << db.errmsg();
939 : db_(storage.dbPath()),
940 filename_(std::move(filename)),
941 expected_size_(size),
947 if (db_.get_rc() != SQLITE_OK) {
948 LOG_ERROR <<
"Can't open database: " << db_.errmsg();
953 if (!db_.beginTransaction()) {
957 auto statement = db_.prepareStatement<std::string,
SQLZeroBlob>(
958 "INSERT OR REPLACE INTO target_images (filename, image_data) VALUES (?, ?);", filename_,
961 if (statement.step() != SQLITE_DONE) {
962 LOG_ERROR <<
"Statement step failure: " << db_.errmsg();
967 sqlite3_int64 row_id = sqlite3_last_insert_rowid(db_.get());
969 if (sqlite3_blob_open(db_.get(),
"main",
"target_images",
"image_data", row_id, 1, &blob_) != SQLITE_OK) {
970 LOG_ERROR <<
"Could not open blob " << db_.errmsg();
977 LOG_WARNING <<
"Handle for file " << filename_ <<
" has not been committed or aborted, forcing abort";
978 SQLTargetWHandle::wabort();
982 size_t wfeed(
const uint8_t* buf,
size_t size)
override {
983 if (sqlite3_blob_write(blob_, buf, static_cast<int>(size), static_cast<int>(written_size_)) != SQLITE_OK) {
984 LOG_ERROR <<
"Could not write in blob: " << db_.errmsg();
987 written_size_ += size;
991 void wcommit()
override {
993 sqlite3_blob_close(blob_);
995 if (!db_.commitTransaction()) {
1000 void wabort() noexcept
override {
1002 if (blob_ !=
nullptr) {
1003 sqlite3_blob_close(blob_);
1007 db_.rollbackTransaction();
1012 const std::string filename_;
1013 size_t expected_size_;
1014 size_t written_size_;
1016 sqlite3_blob* blob_;
1019 std::unique_ptr<StorageTargetWHandle> SQLStorage::allocateTargetFile(
bool from_director,
const std::string& filename,
1021 (void)from_director;
1023 return std::unique_ptr<StorageTargetWHandle>(
new SQLTargetWHandle(*
this, filename, size));
1029 : db_(storage.dbPath()), filename_(filename), size_(0), read_size_(0), closed_(
false), blob_(
nullptr) {
1032 if (db_.get_rc() != SQLITE_OK) {
1033 LOG_ERROR <<
"Can't open database: " << db_.errmsg();
1037 if (!db_.beginTransaction()) {
1041 auto statement = db_.prepareStatement<std::string>(
"SELECT rowid FROM target_images WHERE filename = ?;", filename);
1043 int err = statement.step();
1044 if (err == SQLITE_DONE) {
1045 LOG_ERROR <<
"No such file in db: " + filename_;
1048 if (err != SQLITE_ROW) {
1049 LOG_ERROR <<
"Statement step failure: " << db_.errmsg();
1053 auto row_id = statement.get_result_col_int(0);
1055 if (sqlite3_blob_open(db_.get(),
"main",
"target_images",
"image_data", row_id, 0, &blob_) != SQLITE_OK) {
1056 LOG_ERROR <<
"Could not open blob: " << db_.errmsg();
1059 size_ =
static_cast<size_t>(sqlite3_blob_bytes(blob_));
1061 if (!db_.commitTransaction()) {
1068 SQLTargetRHandle::rclose();
1072 size_t rsize()
const override {
return size_; }
1074 size_t rread(uint8_t* buf,
size_t size)
override {
1075 if (read_size_ + size > size_) {
1076 size = size_ - read_size_;
1082 if (sqlite3_blob_read(blob_, buf, static_cast<int>(size), static_cast<int>(read_size_)) != SQLITE_OK) {
1083 LOG_ERROR <<
"Could not read from blob: " << db_.errmsg();
1091 void rclose() noexcept
override {
1092 sqlite3_blob_close(blob_);
1098 const std::string filename_;
1102 sqlite3_blob* blob_;
1105 std::unique_ptr<StorageTargetRHandle> SQLStorage::openTargetFile(
const std::string& filename) {
1106 return std::unique_ptr<StorageTargetRHandle>(
new SQLTargetRHandle(*
this, filename));
1109 void SQLStorage::removeTargetFile(
const std::string& filename) {
1112 auto statement = db.prepareStatement<std::string>(
"DELETE FROM target_images WHERE filename=?;", filename);
1114 if (statement.step() != SQLITE_DONE) {
1115 LOG_ERROR <<
"Statement step failure: " << db.errmsg();
1116 throw std::runtime_error(
"Could not remove target file");
1119 if (sqlite3_changes(db.get()) != 1) {
1120 throw std::runtime_error(
"Target file " + filename +
" not found");
1124 void SQLStorage::cleanUp() { boost::filesystem::remove_all(dbPath()); }
1126 std::string SQLStorage::getTableSchemaFromDb(
const std::string& tablename) {
1129 auto statement = db.prepareStatement<std::string>(
1130 "SELECT sql FROM sqlite_master WHERE type='table' AND tbl_name=? LIMIT 1;", tablename);
1132 if (statement.step() != SQLITE_ROW) {
1133 LOG_ERROR <<
"Can't get schema of " << tablename <<
": " << db.errmsg();
1137 auto schema = statement.get_result_col_str(0);
1138 if (schema == boost::none) {
1142 return schema.value() +
";";
1145 bool SQLStorage::dbMigrate() {
1148 DbVersion schema_version = getVersion();
1150 if (schema_version == DbVersion::kInvalid) {
1151 LOG_ERROR <<
"Sqlite database file is invalid.";
1155 auto schema_num_version =
static_cast<int32_t
>(schema_version);
1156 if (schema_num_version == current_schema_version) {
1161 LOG_ERROR <<
"Database is opened in readonly mode and cannot be migrated to latest version";
1165 if (schema_num_version > current_schema_version) {
1166 LOG_ERROR <<
"Only forward migrations are supported. You cannot migrate to an older schema.";
1170 for (int32_t k = schema_num_version + 1; k <= current_schema_version; k++) {
1171 if (db.exec(schema_migrations.at(static_cast<size_t>(k)),
nullptr,
nullptr) != SQLITE_OK) {
1172 LOG_ERROR <<
"Can't migrate db from version " << (k - 1) <<
" to version " << k <<
": " << db.errmsg();
1180 DbVersion SQLStorage::getVersion() {
1184 auto statement = db.prepareStatement(
"SELECT count(*) FROM sqlite_master WHERE type='table';");
1185 if (statement.step() != SQLITE_ROW) {
1186 LOG_ERROR <<
"Can't get tables count: " << db.errmsg();
1187 return DbVersion::kInvalid;
1190 if (statement.get_result_col_int(0) == 0) {
1191 return DbVersion::kEmpty;
1194 statement = db.prepareStatement(
"SELECT version FROM version LIMIT 1;");
1196 if (statement.step() != SQLITE_ROW) {
1197 LOG_ERROR <<
"Can't get database version: " << db.errmsg();
1198 return DbVersion::kInvalid;
1202 return DbVersion(statement.get_result_col_int(0));
1203 }
catch (
const std::exception&) {
1204 return DbVersion::kInvalid;
1207 return DbVersion::kInvalid;
Metadata version numbers.
RepositoryType
This must match the repo_type table in sqlstorage.
UpdateResultCode
Result of an update.