std::string_view 的使用

This commit is contained in:
2026-06-29 09:40:55 +08:00
parent cd446b7ca8
commit 8daf67aa5d
52 changed files with 1420 additions and 1367 deletions
@@ -17,6 +17,7 @@
#include <stdexcept>
#include <utility>
#include <variant>
#include <string_view>
namespace {
Psc::JSON
@@ -77,8 +78,8 @@ asio::awaitable<T> await_external_database_callback(Starter starter) {
} // namespace
std::optional<std::string>
External_Database_Row::get(const std::string &column) const {
const auto iter = columns.find(column);
External_Database_Row::get(std::string_view column) const {
const auto iter = columns.find(std::string(column));
return iter == columns.end() ? std::nullopt : iter->second;
}
@@ -91,12 +92,12 @@ Psc::JSON External_Database_Row::to_json() const {
}
External_Resources::External_Resources(
std::string name, std::string cache_file_name, std::string download_url,
std::string description, const std::uint64_t update_interval_seconds) {
this->name = std::move(name);
this->cache_file_name = std::move(cache_file_name);
this->download_url = std::move(download_url);
this->description = std::move(description);
std::string_view name, std::string_view cache_file_name, std::string_view download_url,
std::string_view description, const std::uint64_t update_interval_seconds) {
this->name = std::string(name);
this->cache_file_name = std::string(cache_file_name);
this->download_url = std::string(download_url);
this->description = std::string(description);
this->update_interval_seconds = update_interval_seconds;
}
@@ -280,7 +281,7 @@ Psc::JSON External_Resources_Manager::to_base_json() const {
return ret;
}
void External_Resources_Manager::load_sqlite_db(std::string path) {
void External_Resources_Manager::load_sqlite_db(std::string_view path) {
try {
db_ = std::make_unique<SQLite::Database>(path, SQLite::OPEN_READWRITE |
SQLite::OPEN_CREATE);
@@ -301,32 +302,32 @@ External_Resources_Manager::refresh_external_databases(
}
External_Resource_Status External_Resources_Manager::refresh_external_database(
const std::string &resource_name, const bool force_download) {
std::string_view resource_name, const bool force_download) {
return refresh_one(require_db(), resource_name, force_download);
}
External_Resource_Status External_Resources_Manager::import_external_database(
const std::string &resource_name,
std::string_view resource_name,
const std::filesystem::path &source_file) {
return import_offline(require_db(), resource_name, source_file);
}
External_Resource_Status
External_Resources_Manager::clear_external_database_table(
const std::string &resource_name) {
std::string_view resource_name) {
return clear_table(require_db(), resource_name);
}
std::optional<External_Database_Row>
External_Resources_Manager::query_external_database(
const std::string &resource_name,
std::string_view resource_name,
const std::vector<std::string> &primary_key_values) const {
return query_one(require_db(), resource_name, primary_key_values);
}
std::map<std::string, std::shared_ptr<External_Database_Row>>
External_Resources_Manager::query_aircraft_external_databases(
const std::string &icao24) const {
std::string_view icao24) const {
return query_aircraft(require_db(), icao24);
}
@@ -351,7 +352,7 @@ void External_Resources_Manager::async_refresh_external_databases(
}
void External_Resources_Manager::async_refresh_external_database(
std::string resource_name, const bool force_download,
std::string_view resource_name, const bool force_download,
Status_Callback callback) {
run_external_database_async<External_Resource_Status>(
[this, resource_name = std::move(resource_name), force_download]() {
@@ -361,7 +362,7 @@ void External_Resources_Manager::async_refresh_external_database(
}
void External_Resources_Manager::async_import_external_database(
std::string resource_name, std::filesystem::path source_file,
std::string_view resource_name, std::filesystem::path source_file,
Status_Callback callback) {
run_external_database_async<External_Resource_Status>(
[this, resource_name = std::move(resource_name),
@@ -372,7 +373,7 @@ void External_Resources_Manager::async_import_external_database(
}
void External_Resources_Manager::async_clear_external_database_table(
std::string resource_name, Status_Callback callback) {
std::string_view resource_name, Status_Callback callback) {
run_external_database_async<External_Resource_Status>(
[this, resource_name = std::move(resource_name)]() {
return clear_external_database_table(resource_name);
@@ -381,7 +382,7 @@ void External_Resources_Manager::async_clear_external_database_table(
}
void External_Resources_Manager::async_query_external_database(
std::string resource_name, std::vector<std::string> primary_key_values,
std::string_view resource_name, std::vector<std::string> primary_key_values,
Row_Callback callback) const {
run_external_database_async<std::optional<External_Database_Row>>(
[this, resource_name = std::move(resource_name),
@@ -392,7 +393,7 @@ void External_Resources_Manager::async_query_external_database(
}
void External_Resources_Manager::async_query_aircraft_external_databases(
std::string icao24, Row_Map_Callback callback) const {
std::string_view icao24, Row_Map_Callback callback) const {
run_external_database_async<
std::map<std::string, std::shared_ptr<External_Database_Row>>>(
[this, icao24 = std::move(icao24)]() {
@@ -429,7 +430,7 @@ External_Resources_Manager::refresh_external_databases_coro(
asio::awaitable<External_Resource_Status>
External_Resources_Manager::refresh_external_database_coro(
std::string resource_name, const bool force_download) {
std::string_view resource_name, const bool force_download) {
co_return co_await await_external_database_callback<External_Resource_Status>(
[this, resource_name = std::move(resource_name),
force_download](Status_Callback callback) mutable {
@@ -440,7 +441,7 @@ External_Resources_Manager::refresh_external_database_coro(
asio::awaitable<External_Resource_Status>
External_Resources_Manager::import_external_database_coro(
std::string resource_name, std::filesystem::path source_file) {
std::string_view resource_name, std::filesystem::path source_file) {
co_return co_await await_external_database_callback<External_Resource_Status>(
[this, resource_name = std::move(resource_name),
source_file = std::move(source_file)](Status_Callback callback) mutable {
@@ -452,7 +453,7 @@ External_Resources_Manager::import_external_database_coro(
asio::awaitable<External_Resource_Status>
External_Resources_Manager::clear_external_database_table_coro(
std::string resource_name) {
std::string_view resource_name) {
co_return co_await await_external_database_callback<External_Resource_Status>(
[this, resource_name =
std::move(resource_name)](Status_Callback callback) mutable {
@@ -463,7 +464,7 @@ External_Resources_Manager::clear_external_database_table_coro(
asio::awaitable<std::optional<External_Database_Row>>
External_Resources_Manager::query_external_database_coro(
std::string resource_name,
std::string_view resource_name,
std::vector<std::string> primary_key_values) const {
co_return co_await await_external_database_callback<
std::optional<External_Database_Row>>(
@@ -478,7 +479,7 @@ External_Resources_Manager::query_external_database_coro(
asio::awaitable<std::shared_ptr<External_Database_Row_Map>>
External_Resources_Manager::query_aircraft_external_databases_coro(
std::string icao24) const {
std::string_view icao24) const {
auto result = co_await Psc::coro::callback_result<
std::shared_ptr<External_Database_Row_Map>>(
[this, icao24 = std::move(icao24)](auto done) mutable {
@@ -677,7 +678,7 @@ External_Resources_Manager::refresh_all(SQLite::Database &db,
External_Resource_Status
External_Resources_Manager::refresh_one(SQLite::Database &db,
const std::string &resource_name,
std::string_view resource_name,
const bool force_download) {
std::lock_guard lock(mtx_);
return get_resource(resource_name)
@@ -685,7 +686,7 @@ External_Resources_Manager::refresh_one(SQLite::Database &db,
}
External_Resource_Status External_Resources_Manager::import_offline(
SQLite::Database &db, const std::string &resource_name,
SQLite::Database &db, std::string_view resource_name,
const std::filesystem::path &source_file) {
std::lock_guard lock(mtx_);
return get_resource(resource_name).import_offline(db, source_file);
@@ -693,13 +694,13 @@ External_Resource_Status External_Resources_Manager::import_offline(
External_Resource_Status
External_Resources_Manager::clear_table(SQLite::Database &db,
const std::string &resource_name) {
std::string_view resource_name) {
std::lock_guard lock(mtx_);
return get_resource(resource_name).clear_table(db, cache_pos_);
}
std::optional<External_Database_Row> External_Resources_Manager::query_one(
SQLite::Database &db, const std::string &resource_name,
SQLite::Database &db, std::string_view resource_name,
const std::vector<std::string> &primary_key_values) const {
std::lock_guard lock(mtx_);
return get_resource(resource_name).query_one(db, primary_key_values);
@@ -707,7 +708,7 @@ std::optional<External_Database_Row> External_Resources_Manager::query_one(
std::map<std::string, std::shared_ptr<External_Database_Row>>
External_Resources_Manager::query_aircraft(SQLite::Database &db,
const std::string &icao24) const {
std::string_view icao24) const {
Scope_Timer timer(
"external_database.query_aircraft",
Global::instance()->http_monitor_config.slow_scope_threshold_ms);
@@ -718,22 +719,22 @@ External_Resources_Manager::query_aircraft(SQLite::Database &db,
};
std::lock_guard lock(mtx_);
std::map<std::string, std::shared_ptr<External_Database_Row>> result;
const auto add_row = [&](const std::string &resource_name,
const auto add_row = [&](std::string_view resource_name,
const std::vector<std::string> &primary_key_values,
const std::string &result_name = std::string{}) {
std::string_view result_name = std::string{}) {
auto &resource = get_resource(resource_name);
auto row = resource.query_one(db, primary_key_values);
if (!row)
return std::shared_ptr<External_Database_Row>{};
auto shared_row = std::make_shared<External_Database_Row>(std::move(*row));
result.emplace(result_name.empty() ? resource_name : result_name,
result.emplace(std::string(result_name.empty() ? resource_name : result_name),
shared_row);
return shared_row;
};
std::optional<std::string> type_code;
for (const auto &resource_name : kAircraftResourceKeys) {
const auto row = add_row(resource_name, {icao24});
const auto row = add_row(resource_name, std::vector<std::string>{std::string(icao24)});
if (row && !type_code) {
type_code = row->get("type_code");
if (!type_code)
@@ -760,9 +761,9 @@ External_Resources_Manager::query_callsign(
std::lock_guard lock(mtx_);
std::map<std::string, std::shared_ptr<External_Database_Row>> result;
const auto add_row = [&](const std::string &resource_name,
const auto add_row = [&](std::string_view resource_name,
const std::vector<std::string> &primary_key_values,
const std::string &result_name = std::string{}) {
std::string_view result_name = std::string{}) {
auto &resource = get_resource(resource_name);
auto row = resource.query_one(db, primary_key_values);
if (!row)
@@ -821,12 +822,12 @@ SQLite::Database &External_Resources_Manager::require_db() const {
}
External_Resources &External_Resources_Manager::get_resource(
const std::string &resource_name) const {
std::string_view resource_name) const {
for (const auto &resource : resources_) {
if (resource->name == resource_name)
return *resource;
}
throw std::invalid_argument("unknown external resource: " + resource_name);
throw std::invalid_argument("unknown external resource: " + std::string(resource_name));
}
std::vector<External_Resource_Status>
@@ -14,6 +14,7 @@
#include <stdexcept>
#include <system_error>
#include <utility>
#include <string_view>
namespace External_Database_Utils {
namespace {
@@ -27,15 +28,15 @@ const std::vector<std::string> kTar1090Columns = {
"type_name", "year", "operator_info"};
const std::vector<std::string> kTar1090PrimaryKey = {"icao24"};
std::pair<std::string, std::string> split_url(const std::string &url) {
std::pair<std::string, std::string> split_url(std::string_view url) {
const auto scheme_end = url.find("://");
if (scheme_end == std::string::npos) {
throw std::runtime_error("Invalid download URL: " + url);
throw std::runtime_error("Invalid download URL: " + std::string(url));
}
const auto path_begin = url.find('/', scheme_end + 3);
if (path_begin == std::string::npos)
return {url, "/"};
return {url.substr(0, path_begin), url.substr(path_begin)};
return {std::string(url), "/"};
return {std::string(url.substr(0, path_begin)), std::string(url.substr(path_begin))};
}
void replace_file(const std::filesystem::path &temp_file,
@@ -51,7 +52,7 @@ void replace_file(const std::filesystem::path &temp_file,
}
std::string
create_csv_table_sql(const std::string &table_name,
create_csv_table_sql(std::string_view table_name,
const std::vector<std::string> &columns,
const std::vector<std::string> &primary_key_columns) {
std::ostringstream sql;
@@ -133,7 +134,7 @@ private:
class Tar1090_Aircraft_Resource final : public External_Resources {
public:
Tar1090_Aircraft_Resource(std::string name, std::string description,
Tar1090_Aircraft_Resource(std::string_view name, std::string_view description,
const std::uint64_t update_interval_seconds)
: External_Resources(std::move(name), "aircraft.csv", kTar1090Url,
std::move(description), update_interval_seconds) {}
@@ -205,7 +206,7 @@ protected:
} // namespace
std::string quote_identifier(const std::string &value) {
std::string quote_identifier(std::string_view value) {
std::string result = "\"";
for (const char ch : value) {
result += ch;
@@ -216,33 +217,35 @@ std::string quote_identifier(const std::string &value) {
return result;
}
std::string normalize_key(std::string value) {
std::string normalize_key(std::string_view value) {
std::string result(value);
const auto is_space = [](unsigned char ch) { return std::isspace(ch) != 0; };
value.erase(value.begin(),
std::find_if(value.begin(), value.end(),
result.erase(result.begin(),
std::find_if(result.begin(), result.end(),
[&](char ch) { return !is_space(ch); }));
value.erase(std::find_if(value.rbegin(), value.rend(),
result.erase(std::find_if(result.rbegin(), result.rend(),
[&](char ch) { return !is_space(ch); })
.base(),
value.end());
.base(),
result.end());
std::transform(
value.begin(), value.end(), value.begin(),
result.begin(), result.end(), result.begin(),
[](unsigned char ch) { return static_cast<char>(std::toupper(ch)); });
return value;
return result;
}
std::optional<std::string> normalize_field(std::string value) {
std::optional<std::string> normalize_field(std::string_view value) {
std::string result(value);
const auto is_space = [](unsigned char ch) { return std::isspace(ch) != 0; };
value.erase(value.begin(),
std::find_if(value.begin(), value.end(),
result.erase(result.begin(),
std::find_if(result.begin(), result.end(),
[&](char ch) { return !is_space(ch); }));
value.erase(std::find_if(value.rbegin(), value.rend(),
result.erase(std::find_if(result.rbegin(), result.rend(),
[&](char ch) { return !is_space(ch); })
.base(),
value.end());
if (value.empty())
.base(),
result.end());
if (result.empty())
return std::nullopt;
return value;
return result;
}
void bind_optional(SQLite::Statement &statement, const int index,
@@ -295,7 +298,7 @@ bool read_csv_row(std::istream &input, std::vector<std::string> &fields,
}
std::string
make_upsert_sql(const std::string &table_name,
make_upsert_sql(std::string_view table_name,
const std::vector<std::string> &columns,
const std::vector<std::string> &primary_key_columns) {
std::ostringstream sql;
@@ -335,12 +338,13 @@ make_upsert_sql(const std::string &table_name,
return sql.str();
}
void download_to_file(std::string url,
void download_to_file(std::string_view url,
const std::filesystem::path &target_file) {
std::filesystem::create_directories(target_file.parent_path());
constexpr int kMaxRedirects = 5;
auto current_url = std::string(url);
for (int redirect = 0; redirect <= kMaxRedirects; ++redirect) {
const auto [origin, path] = split_url(url);
const auto [origin, path] = split_url(current_url);
auto client = drogon::HttpClient::newHttpClient(origin);
auto request = drogon::HttpRequest::newHttpRequest();
request->setMethod(drogon::Get);
@@ -348,19 +352,19 @@ void download_to_file(std::string url,
request->addHeader("User-Agent", "ECAP_Server external database updater");
const auto [result, response] = client->sendRequest(request, 600.0);
if (result != drogon::ReqResult::Ok || !response) {
throw std::runtime_error("Download failed: " + url);
throw std::runtime_error("Download failed: " + current_url);
}
const int status = static_cast<int>(response->getStatusCode());
if (status >= 300 && status < 400) {
const auto location = response->getHeader("location");
if (location.empty())
throw std::runtime_error("Redirect has no location: " + url);
url = location.front() == '/' ? origin + location : location;
throw std::runtime_error("Redirect has no location: " + current_url);
current_url = location.front() == '/' ? origin + location : location;
continue;
}
if (status != 200) {
throw std::runtime_error("Download returned HTTP " +
std::to_string(status) + ": " + url);
std::to_string(status) + ": " + current_url);
}
const auto temp_file = target_file.string() + ".tmp";
std::ofstream output(temp_file, std::ios::binary | std::ios::trunc);
@@ -374,7 +378,7 @@ void download_to_file(std::string url,
replace_file(temp_file, target_file);
return;
}
throw std::runtime_error("Too many redirects while downloading: " + url);
throw std::runtime_error("Too many redirects while downloading: " + current_url);
}
void decompress_gzip(const std::filesystem::path &gzip_file,
@@ -404,7 +408,7 @@ void decompress_gzip(const std::filesystem::path &gzip_file,
std::size_t import_header_csv(
SQLite::Database &db, const std::filesystem::path &source_file,
const std::string &table_name, const std::vector<std::string> &columns,
std::string_view table_name, const std::vector<std::string> &columns,
const std::vector<std::string> &primary_key_columns, const char delimiter) {
std::ifstream input(source_file, std::ios::binary);
if (!input)
@@ -478,7 +482,7 @@ make_schema_only_resource(Schema_Only_Resource_Config config) {
}
std::unique_ptr<External_Resources>
make_tar1090_aircraft_resource(std::string name, std::string description,
make_tar1090_aircraft_resource(std::string_view name, std::string_view description,
const std::uint64_t update_interval_seconds) {
return std::make_unique<Tar1090_Aircraft_Resource>(
std::move(name), std::move(description), update_interval_seconds);
@@ -1,4 +1,5 @@
#pragma once
#include <string_view>
#include "global.h"
@@ -33,24 +34,24 @@ struct Schema_Only_Resource_Config {
std::vector<std::string> primary_key_columns;
};
std::string quote_identifier(const std::string &value);
std::string normalize_key(std::string value);
std::optional<std::string> normalize_field(std::string value);
std::string quote_identifier(std::string_view value);
std::string normalize_key(std::string_view value);
std::optional<std::string> normalize_field(std::string_view value);
void bind_optional(SQLite::Statement &statement, int index,
const std::optional<std::string> &value);
bool read_csv_row(std::istream &input, std::vector<std::string> &fields,
char delimiter);
std::string
make_upsert_sql(const std::string &table_name,
make_upsert_sql(std::string_view table_name,
const std::vector<std::string> &columns,
const std::vector<std::string> &primary_key_columns);
void download_to_file(std::string url,
void download_to_file(std::string_view url,
const std::filesystem::path &target_file);
void decompress_gzip(const std::filesystem::path &gzip_file,
const std::filesystem::path &target_file);
std::size_t import_header_csv(
SQLite::Database &db, const std::filesystem::path &source_file,
const std::string &table_name, const std::vector<std::string> &columns,
std::string_view table_name, const std::vector<std::string> &columns,
const std::vector<std::string> &primary_key_columns, char delimiter = ',');
std::unique_ptr<External_Resources>
@@ -58,7 +59,7 @@ make_header_csv_resource(Header_Csv_Resource_Config config);
std::unique_ptr<External_Resources>
make_schema_only_resource(Schema_Only_Resource_Config config);
std::unique_ptr<External_Resources>
make_tar1090_aircraft_resource(std::string name, std::string description,
make_tar1090_aircraft_resource(std::string_view name, std::string_view description,
std::uint64_t update_interval_seconds);
} // namespace External_Database_Utils
+26 -25
View File
@@ -1,4 +1,5 @@
#pragma once
#include <string_view>
#include "Core/Base/JSON.h"
#include <SQLiteCpp/Database.h>
#include <asio/awaitable.hpp>
@@ -22,7 +23,7 @@ struct External_Database_Row {
External_Database_Row& operator=(const External_Database_Row&) = default;
External_Database_Row(External_Database_Row&&) noexcept = default;
External_Database_Row& operator=(External_Database_Row&&) noexcept = default;
[[nodiscard]] std::optional<std::string> get(const std::string& column) const;
[[nodiscard]] std::optional<std::string> get(std::string_view column) const;
[[nodiscard]] Psc::JSON to_json() const;
};
using External_Database_Row_Map =
@@ -45,8 +46,8 @@ public:
};
class External_Resources : public External_Resources_Data {
public:
External_Resources(std::string name, std::string cache_file_name,
std::string download_url, std::string description,
External_Resources(std::string_view name, std::string_view cache_file_name,
std::string_view download_url, std::string_view description,
std::uint64_t update_interval_seconds);
virtual ~External_Resources() = default;
[[nodiscard]] std::size_t row_count(SQLite::Database& db) const;
@@ -86,47 +87,47 @@ public:
void init(const Psc::JSON* that_json);
[[nodiscard]] Psc::JSON to_base_json() const;
void server(Global* g);
void load_sqlite_db(std::string path);
void load_sqlite_db(std::string_view path);
std::vector<External_Resource_Status> refresh_external_databases(bool force_download = true);
External_Resource_Status refresh_external_database(const std::string& resource_name, bool force_download = true);
External_Resource_Status import_external_database(const std::string& resource_name, const std::filesystem::path& source_file);
External_Resource_Status clear_external_database_table(const std::string& resource_name);
[[nodiscard]] std::optional<External_Database_Row> query_external_database(const std::string& resource_name, const std::vector<std::string>& primary_key_values) const;
[[nodiscard]] std::map<std::string, std::shared_ptr<External_Database_Row>> query_aircraft_external_databases(const std::string& icao24) const;
External_Resource_Status refresh_external_database(std::string_view resource_name, bool force_download = true);
External_Resource_Status import_external_database(std::string_view resource_name, const std::filesystem::path& source_file);
External_Resource_Status clear_external_database_table(std::string_view resource_name);
[[nodiscard]] std::optional<External_Database_Row> query_external_database(std::string_view resource_name, const std::vector<std::string>& primary_key_values) const;
[[nodiscard]] std::map<std::string, std::shared_ptr<External_Database_Row>> query_aircraft_external_databases(std::string_view icao24) const;
[[nodiscard]] std::map<std::string, std::shared_ptr<External_Database_Row>> query_callsign_external_databases(const std::optional<std::string>& callsign) const;
[[nodiscard]] std::vector<External_Resource_Status> external_database_status() const;
void async_refresh_external_databases(bool force_download, Status_List_Callback callback);
void async_refresh_external_database(std::string resource_name, bool force_download, Status_Callback callback);
void async_import_external_database(std::string resource_name, std::filesystem::path source_file, Status_Callback callback);
void async_clear_external_database_table(std::string resource_name, Status_Callback callback);
void async_query_external_database(std::string resource_name, std::vector<std::string> primary_key_values, Row_Callback callback) const;
void async_query_aircraft_external_databases(std::string icao24, Row_Map_Callback callback) const;
void async_refresh_external_database(std::string_view resource_name, bool force_download, Status_Callback callback);
void async_import_external_database(std::string_view resource_name, std::filesystem::path source_file, Status_Callback callback);
void async_clear_external_database_table(std::string_view resource_name, Status_Callback callback);
void async_query_external_database(std::string_view resource_name, std::vector<std::string> primary_key_values, Row_Callback callback) const;
void async_query_aircraft_external_databases(std::string_view icao24, Row_Map_Callback callback) const;
void async_query_callsign_external_databases(std::optional<std::string> callsign, Row_Map_Callback callback) const;
void async_external_database_status(Status_List_Callback callback) const;
[[nodiscard]] asio::awaitable<std::vector<External_Resource_Status>> refresh_external_databases_coro(bool force_download = true);
[[nodiscard]] asio::awaitable<External_Resource_Status> refresh_external_database_coro(std::string resource_name, bool force_download = true);
[[nodiscard]] asio::awaitable<External_Resource_Status> import_external_database_coro(std::string resource_name, std::filesystem::path source_file);
[[nodiscard]] asio::awaitable<External_Resource_Status> clear_external_database_table_coro(std::string resource_name);
[[nodiscard]] asio::awaitable<std::optional<External_Database_Row>> query_external_database_coro(std::string resource_name, std::vector<std::string> primary_key_values) const;
[[nodiscard]] asio::awaitable<std::shared_ptr<External_Database_Row_Map>> query_aircraft_external_databases_coro(std::string icao24) const;
[[nodiscard]] asio::awaitable<External_Resource_Status> refresh_external_database_coro(std::string_view resource_name, bool force_download = true);
[[nodiscard]] asio::awaitable<External_Resource_Status> import_external_database_coro(std::string_view resource_name, std::filesystem::path source_file);
[[nodiscard]] asio::awaitable<External_Resource_Status> clear_external_database_table_coro(std::string_view resource_name);
[[nodiscard]] asio::awaitable<std::optional<External_Database_Row>> query_external_database_coro(std::string_view resource_name, std::vector<std::string> primary_key_values) const;
[[nodiscard]] asio::awaitable<std::shared_ptr<External_Database_Row_Map>> query_aircraft_external_databases_coro(std::string_view icao24) const;
[[nodiscard]] asio::awaitable<std::shared_ptr<External_Database_Row_Map>> query_callsign_external_databases_coro(std::optional<std::string> callsign) const;
[[nodiscard]] asio::awaitable<std::vector<External_Resource_Status>> external_database_status_coro() const;
void register_external_resource(std::unique_ptr<External_Resources> external_res);
void initialize(SQLite::Database& db, std::filesystem::path cache_pos);
std::vector<External_Resource_Status> sync_missing(SQLite::Database& db);
std::vector<External_Resource_Status> refresh_all(SQLite::Database& db, bool force_download = true);
External_Resource_Status refresh_one(SQLite::Database& db, const std::string& resource_name, bool force_download = true);
External_Resource_Status import_offline(SQLite::Database& db, const std::string& resource_name, const std::filesystem::path& source_file);
External_Resource_Status clear_table(SQLite::Database& db, const std::string& resource_name);
[[nodiscard]] std::optional<External_Database_Row> query_one(SQLite::Database& db, const std::string& resource_name, const std::vector<std::string>& primary_key_values) const;
[[nodiscard]] std::map<std::string, std::shared_ptr<External_Database_Row>> query_aircraft(SQLite::Database& db, const std::string& icao24) const;
External_Resource_Status refresh_one(SQLite::Database& db, std::string_view resource_name, bool force_download = true);
External_Resource_Status import_offline(SQLite::Database& db, std::string_view resource_name, const std::filesystem::path& source_file);
External_Resource_Status clear_table(SQLite::Database& db, std::string_view resource_name);
[[nodiscard]] std::optional<External_Database_Row> query_one(SQLite::Database& db, std::string_view resource_name, const std::vector<std::string>& primary_key_values) const;
[[nodiscard]] std::map<std::string, std::shared_ptr<External_Database_Row>> query_aircraft(SQLite::Database& db, std::string_view icao24) const;
[[nodiscard]] std::map<std::string, std::shared_ptr<External_Database_Row>> query_callsign(SQLite::Database& db, const std::optional<std::string>& callsign) const;
[[nodiscard]] std::vector<External_Resource_Status> status(SQLite::Database& db) const;
std::string ecap_sqlite_path;
std::filesystem::path cache_pos_;
private:
[[nodiscard]] SQLite::Database& require_db() const;
External_Resources& get_resource(const std::string& resource_name) const;
External_Resources& get_resource(std::string_view resource_name) const;
std::vector<External_Resource_Status> update_all(SQLite::Database& db, bool force_download, bool only_when_empty);
std::unique_ptr<SQLite::Database> db_;
std::vector<std::unique_ptr<External_Resources>> resources_;