Formatting
ci / checks (push) Successful in 42m54s

This commit is contained in:
khodowany
2026-09-15 00:06:02 -05:00
parent 44e100985a
commit fe42d811fa
81 changed files with 4349 additions and 3340 deletions
+48 -42
View File
@@ -1,6 +1,3 @@
#include <vamp_zero/database.hpp>
#include <algorithm>
#include <chrono>
#include <cstdint>
#include <expected>
@@ -16,16 +13,19 @@
#include <noto.hpp>
#include <vamp_zero/database.hpp>
#include <vamp_zero/errors.hpp>
#include <vamp_zero/library.hpp>
#include <vamp_zero/score.hpp>
namespace {
constexpr auto application_id = std::int64_t{0x56414D50};
auto connection_config(vamp_zero::database_config const& config) -> noto::connection_config {
auto result = config.path == ":memory:" ? noto::memory_connection_config("product-vamp") : noto::file_connection_config(config.path, "product-vamp");
auto connection_config(vamp_zero::database_config const &config) -> noto::connection_config {
auto result = config.path == ":memory:" ? noto::memory_connection_config("product-vamp")
: noto::file_connection_config(config.path, "product-vamp");
result.busy_timeout = std::chrono::seconds{5};
result.foreign_keys = true;
result.pragmas = {
@@ -35,12 +35,12 @@ auto connection_config(vamp_zero::database_config const& config) -> noto::connec
return result;
}
auto text_value(noto::sqlite_value const& value) -> std::string {
auto text_value(noto::sqlite_value const &value) -> std::string {
auto text = std::get_if<std::string>(&value.value);
return text == nullptr ? std::string{} : *text;
}
auto execute_schema_statement(noto::connection& connection, std::string statement) -> boost::asio::awaitable<std::expected<void, modulus::error>> {
auto execute_schema_statement(noto::connection &connection, std::string statement) -> boost::asio::awaitable<std::expected<void, modulus::error>> {
auto result = co_await connection.async_execute(std::move(statement));
if (!result) {
co_return std::unexpected(result.error());
@@ -48,12 +48,12 @@ auto execute_schema_statement(noto::connection& connection, std::string statemen
co_return std::expected<void, modulus::error>{};
}
auto column_exists(noto::connection& connection, std::string table, std::string column) -> boost::asio::awaitable<std::expected<std::bool_t, modulus::error>> {
auto column_exists(noto::connection &connection, std::string table, std::string column) -> boost::asio::awaitable<std::expected<std::bool_t, modulus::error>> {
auto selected = co_await connection.async_execute("PRAGMA table_info(" + table + ")");
if (!selected) {
co_return std::unexpected(selected.error());
}
for (auto const& row : selected->rows) {
for (auto const &row : selected->rows) {
if (row.size() >= 2U && text_value(row[1]) == column) {
co_return true;
}
@@ -61,7 +61,7 @@ auto column_exists(noto::connection& connection, std::string table, std::string
co_return false;
}
auto ensure_column(noto::connection& connection, std::string table, std::string column, std::string alter_statement) -> boost::asio::awaitable<std::expected<void, modulus::error>> {
auto ensure_column(noto::connection &connection, std::string table, std::string column, std::string alter_statement) -> boost::asio::awaitable<std::expected<void, modulus::error>> {
auto exists = co_await column_exists(connection, std::move(table), std::move(column));
if (!exists) {
co_return std::unexpected(exists.error());
@@ -72,12 +72,11 @@ auto ensure_column(noto::connection& connection, std::string table, std::string
co_return co_await execute_schema_statement(connection, std::move(alter_statement));
}
auto ensure_current_schema(noto::connection& connection) -> boost::asio::awaitable<std::expected<void, modulus::error>> {
auto ensure_current_schema(noto::connection &connection) -> boost::asio::awaitable<std::expected<void, modulus::error>> {
auto begin = co_await connection.async_execute("BEGIN IMMEDIATE");
if (!begin) {
co_return std::unexpected(begin.error());
}
auto ensured = std::expected<void, modulus::error>{};
auto schema_statements = std::vector<std::string>{
R"sql(
@@ -121,16 +120,15 @@ CREATE TABLE IF NOT EXISTS practice_exercises (
)sql",
"DROP TABLE IF EXISTS _noto_schema_migrations",
};
for (auto& statement : schema_statements) {
for (auto &statement : schema_statements) {
if (!ensured) {
break;
}
ensured = co_await execute_schema_statement(connection, std::move(statement));
}
if (ensured) {
ensured = co_await ensure_column(connection, "songs", "part", "ALTER TABLE songs ADD COLUMN part TEXT NOT NULL DEFAULT ''");
ensured =
co_await ensure_column(connection, "songs", "part", "ALTER TABLE songs ADD COLUMN part TEXT NOT NULL DEFAULT ''");
}
if (ensured) {
ensured = co_await ensure_column(connection, "songs", "source_path", "ALTER TABLE songs ADD COLUMN source_path TEXT NOT NULL DEFAULT ''");
@@ -142,39 +140,43 @@ CREATE TABLE IF NOT EXISTS practice_exercises (
ensured = co_await ensure_column(connection, "songs", "catalog_managed", "ALTER TABLE songs ADD COLUMN catalog_managed INTEGER NOT NULL DEFAULT 1 CHECK(catalog_managed IN (0, 1))");
}
if (ensured) {
ensured = co_await ensure_column(connection, "practice_exercises", "practice_type_id", "ALTER TABLE practice_exercises ADD COLUMN practice_type_id TEXT NOT NULL DEFAULT 'general' CHECK(length(trim(practice_type_id)) BETWEEN 1 AND 120)");
ensured = co_await ensure_column(connection, "practice_exercises", "practice_type_id", "ALTER TABLE practice_exercises ADD COLUMN practice_type_id TEXT NOT NULL DEFAULT 'general' "
"CHECK(length(trim(practice_type_id)) BETWEEN 1 AND 120)");
}
if (ensured) {
ensured = co_await ensure_column(connection, "practice_exercises", "practice_type_title", "ALTER TABLE practice_exercises ADD COLUMN practice_type_title TEXT NOT NULL DEFAULT 'General Practice' CHECK(length(trim(practice_type_title)) BETWEEN 1 AND 200)");
ensured = co_await ensure_column(connection, "practice_exercises", "practice_type_title", "ALTER TABLE practice_exercises ADD COLUMN practice_type_title TEXT NOT NULL DEFAULT 'General Practice' "
"CHECK(length(trim(practice_type_title)) BETWEEN 1 AND 200)");
}
if (ensured) {
ensured = co_await ensure_column(connection, "practice_exercises", "lesson_group_id", "ALTER TABLE practice_exercises ADD COLUMN lesson_group_id TEXT NOT NULL DEFAULT 'general' CHECK(length(trim(lesson_group_id)) BETWEEN 1 AND 120)");
ensured = co_await ensure_column(connection, "practice_exercises", "lesson_group_id", "ALTER TABLE practice_exercises ADD COLUMN lesson_group_id TEXT NOT NULL DEFAULT 'general' "
"CHECK(length(trim(lesson_group_id)) BETWEEN 1 AND 120)");
}
if (ensured) {
ensured = co_await ensure_column(connection, "practice_exercises", "lesson_group_title", "ALTER TABLE practice_exercises ADD COLUMN lesson_group_title TEXT NOT NULL DEFAULT 'General' CHECK(length(trim(lesson_group_title)) BETWEEN 1 AND 200)");
ensured = co_await ensure_column(connection, "practice_exercises", "lesson_group_title", "ALTER TABLE practice_exercises ADD COLUMN lesson_group_title TEXT NOT NULL DEFAULT 'General' "
"CHECK(length(trim(lesson_group_title)) BETWEEN 1 AND 200)");
}
if (ensured) {
ensured = co_await ensure_column(connection, "practice_exercises", "source_path", "ALTER TABLE practice_exercises ADD COLUMN source_path TEXT NOT NULL DEFAULT ''");
}
if (ensured) {
ensured = co_await ensure_column(connection, "practice_exercises", "catalog_managed", "ALTER TABLE practice_exercises ADD COLUMN catalog_managed INTEGER NOT NULL DEFAULT 1 CHECK(catalog_managed IN (0, 1))");
ensured = co_await ensure_column(connection, "practice_exercises", "catalog_managed", "ALTER TABLE practice_exercises ADD COLUMN catalog_managed INTEGER NOT NULL DEFAULT 1 CHECK(catalog_managed IN "
"(0, 1))");
}
auto index_statements = std::vector<std::string>{
"CREATE INDEX IF NOT EXISTS idx_songs_title ON songs(title COLLATE NOCASE)",
"CREATE INDEX IF NOT EXISTS idx_songs_title_part ON songs(title COLLATE NOCASE, part COLLATE NOCASE)",
"CREATE INDEX IF NOT EXISTS idx_songs_catalog_managed ON songs(catalog_managed)",
"CREATE INDEX IF NOT EXISTS idx_practice_exercises_title ON practice_exercises(title COLLATE NOCASE)",
"CREATE INDEX IF NOT EXISTS idx_practice_exercises_hierarchy ON practice_exercises(practice_type_id COLLATE NOCASE, lesson_group_id COLLATE NOCASE, title COLLATE NOCASE)",
"CREATE INDEX IF NOT EXISTS idx_practice_exercises_hierarchy ON practice_exercises(practice_type_id COLLATE "
"NOCASE, lesson_group_id COLLATE NOCASE, title COLLATE NOCASE)",
"CREATE INDEX IF NOT EXISTS idx_practice_exercises_catalog_managed ON practice_exercises(catalog_managed)",
};
for (auto& statement : index_statements) {
for (auto &statement : index_statements) {
if (!ensured) {
break;
}
ensured = co_await execute_schema_statement(connection, std::move(statement));
}
if (ensured) {
auto committed = co_await connection.async_execute("COMMIT");
if (!committed) {
@@ -183,7 +185,6 @@ CREATE TABLE IF NOT EXISTS practice_exercises (
} else {
static_cast<void>(co_await connection.async_execute("ROLLBACK"));
}
if (!ensured) {
co_return std::unexpected(ensured.error());
}
@@ -194,15 +195,15 @@ CREATE TABLE IF NOT EXISTS practice_exercises (
co_return std::expected<void, modulus::error>{};
}
auto path_parts(std::filesystem::path const& path) -> std::vector<std::string> {
auto path_parts(std::filesystem::path const &path) -> std::vector<std::string> {
auto parts = std::vector<std::string>{};
for (auto const& part : path) {
for (auto const &part : path) {
parts.push_back(part.string());
}
return parts;
}
auto logical_practice_exercise_id(std::string const& type_id, std::string const& lesson_id, std::string const& source_path, std::string const& fallback) -> std::string {
auto logical_practice_exercise_id(std::string const &type_id, std::string const &lesson_id, std::string const &source_path, std::string const &fallback) -> std::string {
auto parts = path_parts(std::filesystem::path{source_path});
for (auto index = std::size_t{}; index + 3U < parts.size(); ++index) {
if (parts[index] == "practice" && parts[index + 1U] == type_id && parts[index + 2U] == lesson_id) {
@@ -217,10 +218,11 @@ auto logical_practice_exercise_id(std::string const& type_id, std::string const&
}
auto now_ms() -> std::int64_t {
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch())
.count();
}
auto execute_delete_stale_catalog_rows(noto::connection& connection, std::string_view table, std::vector<std::string> const& ids) -> boost::asio::awaitable<std::expected<void, modulus::error>> {
auto execute_delete_stale_catalog_rows(noto::connection &connection, std::string_view table, std::vector<std::string> const &ids) -> boost::asio::awaitable<std::expected<void, modulus::error>> {
auto sql = std::string{"DELETE FROM "};
sql += table;
sql += " WHERE catalog_managed = 1";
@@ -261,7 +263,6 @@ auto vamp_zero::async_ensure_database(boost::asio::any_io_executor executor, vam
}
}
}
auto connection = noto::connection{executor, connection_config(config)};
auto connected = co_await connection.async_connect();
if (!connected) {
@@ -290,7 +291,6 @@ auto vamp_zero::async_ensure_database(boost::asio::any_io_executor executor, vam
co_return std::unexpected(set.error());
}
}
auto ensured = co_await ensure_current_schema(connection);
if (!ensured) {
auto close = co_await connection.async_close();
@@ -324,7 +324,7 @@ auto vamp_zero::async_import_catalogs(boost::asio::any_io_executor executor, vam
auto timestamp = now_ms();
auto song_ids = std::vector<std::string>{};
song_ids.reserve(performance->parts.size());
for (auto const& part : performance->parts) {
for (auto const &part : performance->parts) {
if (!imported) {
break;
}
@@ -370,11 +370,11 @@ WHERE songs.catalog_managed = 1
}
}
auto practice_ids = std::vector<std::string>{};
for (auto const& exercise : practice->exercises) {
for (auto const &exercise : practice->exercises) {
if (!imported) {
break;
}
for (auto const& variant : exercise.variants) {
for (auto const &variant : exercise.variants) {
practice_ids.push_back(variant.id);
auto params = std::vector<noto::sqlite_value>{
noto::sqlite_value{variant.id},
@@ -457,13 +457,16 @@ WHERE practice_exercises.catalog_managed = 1
co_return co_await connection.async_close();
}
auto vamp_zero::async_load_performance_library(boost::asio::any_io_executor executor, vamp_zero::database_config config) -> boost::asio::awaitable<std::expected<vamp_zero::library_state, modulus::error>> {
auto vamp_zero::async_load_performance_library(boost::asio::any_io_executor executor, vamp_zero::database_config config)
-> boost::asio::awaitable<std::expected<vamp_zero::library_state, modulus::error>> {
auto connection = noto::connection{executor, connection_config(config)};
auto connected = co_await connection.async_connect();
if (!connected) {
co_return std::unexpected(connected.error());
}
auto selected = co_await connection.async_execute("SELECT id, title, composer, part, source_path, source_json, key_signature FROM songs ORDER BY title COLLATE NOCASE, part COLLATE NOCASE");
auto selected =
co_await connection.async_execute("SELECT id, title, composer, part, source_path, source_json, key_signature FROM "
"songs ORDER BY title COLLATE NOCASE, part COLLATE NOCASE");
if (!selected) {
auto close = co_await connection.async_close();
if (!close) {
@@ -472,7 +475,7 @@ auto vamp_zero::async_load_performance_library(boost::asio::any_io_executor exec
co_return std::unexpected(selected.error());
}
auto parts = std::vector<vamp_zero::library_part>{};
for (auto const& row : selected->rows) {
for (auto const &row : selected->rows) {
if (row.size() < 7U) {
continue;
}
@@ -504,13 +507,16 @@ auto vamp_zero::async_load_performance_library(boost::asio::any_io_executor exec
co_return vamp_zero::group_library_parts(std::move(parts));
}
auto vamp_zero::async_load_practice_library(boost::asio::any_io_executor executor, vamp_zero::database_config config) -> boost::asio::awaitable<std::expected<vamp_zero::practice_library, modulus::error>> {
auto vamp_zero::async_load_practice_library(boost::asio::any_io_executor executor, vamp_zero::database_config config)
-> boost::asio::awaitable<std::expected<vamp_zero::practice_library, modulus::error>> {
auto connection = noto::connection{executor, connection_config(config)};
auto connected = co_await connection.async_connect();
if (!connected) {
co_return std::unexpected(connected.error());
}
auto selected = co_await connection.async_execute("SELECT id, practice_type_id, practice_type_title, lesson_group_id, lesson_group_title, title, composer, key_signature, source_path, source_json FROM practice_exercises ORDER BY practice_type_id COLLATE NOCASE, lesson_group_id COLLATE NOCASE, source_path COLLATE NOCASE, title COLLATE NOCASE, id COLLATE NOCASE");
auto selected = co_await connection.async_execute("SELECT id, practice_type_id, practice_type_title, lesson_group_id, lesson_group_title, title, composer, "
"key_signature, source_path, source_json FROM practice_exercises ORDER BY practice_type_id COLLATE NOCASE, "
"lesson_group_id COLLATE NOCASE, source_path COLLATE NOCASE, title COLLATE NOCASE, id COLLATE NOCASE");
if (!selected) {
auto close = co_await connection.async_close();
if (!close) {
@@ -519,7 +525,7 @@ auto vamp_zero::async_load_practice_library(boost::asio::any_io_executor executo
co_return std::unexpected(selected.error());
}
auto exercises = std::vector<vamp_zero::practice_exercise>{};
for (auto const& row : selected->rows) {
for (auto const &row : selected->rows) {
if (row.size() < 10U) {
continue;
}