diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-10-13 15:27:59 -0400 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-10-13 15:44:17 -0400 |
| commit | 6d53452ebc24287a72eedb9a2cc3f9e21c55362c (patch) | |
| tree | 04ce0135a9718c41f24f217b587088dd9d59241a | |
| parent | 62dae6011db94dd52c3ac0fce517c6e9cc0abcf6 (diff) | |
pke-at: second-pass sql storage
| -rw-r--r-- | Makefile | 5 | ||||
| -rw-r--r-- | src/embedded-sql.cpp | 32 | ||||
| -rw-r--r-- | src/embedded-sql.hpp | 10 | ||||
| -rw-r--r-- | src/pke-at-setlist-types.hpp | 3 | ||||
| -rw-r--r-- | src/pke-at-storage-interface.hpp | 11 | ||||
| -rw-r--r-- | src/pke-at-storage-sql.cpp | 474 | ||||
| -rw-r--r-- | src/pke-at-storage-sql.hpp | 4 | ||||
| -rw-r--r-- | src/pke-at.cpp | 5 | ||||
| -rw-r--r-- | src/sql/schema-000-000.sql | 12 | ||||
| -rw-r--r-- | src/sql/section_get.sql | 2 | ||||
| -rw-r--r-- | src/sql/section_upsert.sql | 9 | ||||
| -rw-r--r-- | src/sql/song_upsert.sql | 2 |
12 files changed, 447 insertions, 122 deletions
@@ -19,7 +19,7 @@ endef define cc-encode-binary-command $(1): $(2) - xxd -i $$< | sed -e 's/^unsigned /const unsigned /' > $$@ + xxd -i $$< | sed 's/};/ ,0x00\n};/' | sed -e 's/^unsigned /const unsigned /' > $$@ endef define cc-pre-compile-header-command @@ -76,14 +76,13 @@ options: prepare .WAIT @echo "CC = $(CC)" @echo "CXX = $(CXX)" -obj/embedded-sql.o : $(FILES_BIN_GCH) +obj/pke-at-storage-sql.o : $(FILES_BIN_GCH) obj/%.o : src/%.c | prepare $(cc-command) obj/%.o : src/%.cpp | prepare $(cxx-command) bin/pke-at: ## Builds the pke-at executable -bin/pke-at: obj/embedded-sql.o bin/pke-at: obj/level-main.o bin/pke-at: obj/level-init.o bin/pke-at: obj/main.o diff --git a/src/embedded-sql.cpp b/src/embedded-sql.cpp deleted file mode 100644 index 16593c4..0000000 --- a/src/embedded-sql.cpp +++ /dev/null @@ -1,32 +0,0 @@ - -#include "embedded-sql.hpp" - -#include "sql/schema_000_000_sql.h" -#include "sql/section_delete_sql.h" -#include "sql/section_get_sql.h" -#include "sql/section_upsert_sql.h" -#include "sql/setlist_delete_sql.h" -#include "sql/setlist_get_sql.h" -#include "sql/setlist_upsert_sql.h" -#include "sql/setlist_song_delete_sql.h" -#include "sql/setlist_song_get_sql.h" -#include "sql/setlist_song_upsert_sql.h" -#include "sql/song_delete_sql.h" -#include "sql/song_get_sql.h" -#include "sql/song_upsert_sql.h" - -struct embedded_file embedded_sql[] = { - { "sql_scm_000_000", src_sql_schema_000_000_sql, src_sql_schema_000_000_sql_len }, - { "sql_sect_del\0\0\0", src_sql_section_delete_sql, src_sql_section_delete_sql_len }, - { "sql_sect_get\0\0\0", src_sql_section_get_sql, src_sql_section_get_sql_len }, - { "sql_sect_upsrt\0", src_sql_section_upsert_sql, src_sql_section_upsert_sql_len }, - { "sql_setl_del\0\0\0", src_sql_setlist_delete_sql, src_sql_setlist_delete_sql_len }, - { "sql_setl_get\0\0\0", src_sql_setlist_get_sql, src_sql_setlist_get_sql_len }, - { "sql_setl_upsrt\0", src_sql_setlist_upsert_sql, src_sql_setlist_upsert_sql_len }, - { "sql_ssng_del\0\0\0", src_sql_setlist_song_delete_sql, src_sql_setlist_song_delete_sql_len }, - { "sql_ssng_get\0\0\0", src_sql_setlist_song_get_sql, src_sql_setlist_song_get_sql_len }, - { "sql_ssng_upsrt\0", src_sql_setlist_song_upsert_sql, src_sql_setlist_song_upsert_sql_len }, - { "sql_song_del\0\0\0", src_sql_song_delete_sql, src_sql_song_delete_sql_len }, - { "sql_song_get\0\0\0", src_sql_song_get_sql, src_sql_song_get_sql_len }, - { "sql_song_upsrt\0", src_sql_song_upsert_sql, src_sql_song_upsert_sql_len }, -}; diff --git a/src/embedded-sql.hpp b/src/embedded-sql.hpp deleted file mode 100644 index af08435..0000000 --- a/src/embedded-sql.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef PKE_AT_EMBEDDED_SQL_HPP -#define PKE_AT_EMBEDDED_SQL_HPP - -#include "embedded-file.hpp" - -const unsigned long embedded_sql_count = 13; - -extern struct embedded_file embedded_sql[]; - -#endif /* PKE_AT_EMBEDDED_SQL_HPP */ diff --git a/src/pke-at-setlist-types.hpp b/src/pke-at-setlist-types.hpp index bea7b18..0ab6815 100644 --- a/src/pke-at-setlist-types.hpp +++ b/src/pke-at-setlist-types.hpp @@ -23,10 +23,10 @@ struct pke_at_section_type { struct pke_at_section_details { pk_uuid song_uuid; - enum PKE_AT_SECTION_TYPE_INDEX section_type_index = PKE_AT_SECTION_TYPE_INDEX_NONE; uint8_t sequence; uint8_t beats_per_bar = 0; uint8_t bar_count = 0; + enum PKE_AT_SECTION_TYPE_INDEX section_type_index = PKE_AT_SECTION_TYPE_INDEX_NONE; }; struct pke_at_section { pke_at_section_details details{}; @@ -46,6 +46,7 @@ struct pke_at_song { }; struct pke_at_setlist_details { + pk_uuid uuid; pk_cstr title; }; struct pke_at_setlist { diff --git a/src/pke-at-storage-interface.hpp b/src/pke-at-storage-interface.hpp index f240974..5cbe5a7 100644 --- a/src/pke-at-storage-interface.hpp +++ b/src/pke-at-storage-interface.hpp @@ -6,8 +6,9 @@ #include <pke/pke.hpp> enum pke_at_storage_interface_result_code { - pke_at_storage_interface_result_code_success = 0, - pke_at_storage_interface_result_code_err = 1, + pke_at_storage_interface_result_code_none = 0, + pke_at_storage_interface_result_code_success = 1, + pke_at_storage_interface_result_code_err = 2, }; struct pke_at_storage_interface_response { @@ -27,6 +28,8 @@ struct pke_at_storage_interface_response_t { #define PASIR_DEL(type) pke_at_storage_interface_response PASI(type,delete)(pk_uuid uuid) #define PASIR_GET(type,T) pke_at_storage_interface_response_t<T> PASI(type,get)(pk_uuid uuid) #define PASIR_UPS(type,T) pke_at_storage_interface_response PASI(type,upsert)(const T &val) +#define PASIRA_DEL(type,...) pke_at_storage_interface_response PASI(type,delete)(__VA_ARGS__) +#define PASIRA_GET(type,T,...) pke_at_storage_interface_response_t<T> PASI(type,get)(__VA_ARGS__) struct pke_at_storage_interface { pke_at_storage_interface() = default; @@ -39,8 +42,8 @@ struct pke_at_storage_interface { virtual PASIR_DEL(setlist) const = 0; virtual PASIR_GET(setlist, pke_at_setlist_details) const = 0; virtual PASIR_UPS(setlist, pke_at_setlist_details) const = 0; - virtual PASIR_DEL(setlist_song) const = 0; - virtual PASIR_GET(setlist_song, pke_at_setlist_song_details) const = 0; + virtual PASIRA_DEL(setlist_song, pk_uuid setlist_uuid, pk_uuid song_uuid) const = 0; + virtual PASIRA_GET(setlist_song, pke_at_setlist_song_details, pk_uuid setlist_uuid, pk_uuid song_uuid) const = 0; virtual PASIR_UPS(setlist_song, pke_at_setlist_song_details) const = 0; virtual PASIR_DEL(song) const = 0; virtual PASIR_GET(song, pke_at_song_details) const = 0; diff --git a/src/pke-at-storage-sql.cpp b/src/pke-at-storage-sql.cpp index e028ff5..ca71174 100644 --- a/src/pke-at-storage-sql.cpp +++ b/src/pke-at-storage-sql.cpp @@ -1,6 +1,24 @@ #include "pke-at-storage-sql.hpp" +#include "pke-at-settings.hpp" + +#include "sql/schema_000_000_sql.h" +#include "sql/section_delete_sql.h" +#include "sql/section_get_sql.h" +#include "sql/section_upsert_sql.h" +#include "sql/setlist_delete_sql.h" +#include "sql/setlist_get_sql.h" +#include "sql/setlist_upsert_sql.h" +#include "sql/setlist_song_delete_sql.h" +#include "sql/setlist_song_get_sql.h" +#include "sql/setlist_song_upsert_sql.h" +#include "sql/song_delete_sql.h" +#include "sql/song_get_sql.h" +#include "sql/song_upsert_sql.h" + +#include "pke/asset-manager.hpp" #include "pke/asset-types.h" +#include "pke/pk.h" #include <sqlite3.h> @@ -9,12 +27,14 @@ constexpr unsigned long query_text_length = 1024; +static const char *SQLITE_DB_PATH = "pke-at.sqlite3"; + static struct pke_at_storage_sql_master { - sqlite3 *db = nullptr; char query_text[query_text_length]; } sql_mstr; void pke_at_storage_sql::init() const { + sqlite3 *db = nullptr; char *sql_err_string = nullptr; int res, null_count; AssetKey asset_key; @@ -25,10 +45,9 @@ void pke_at_storage_sql::init() const { } version; const Asset *asset = nullptr; db_version check_version; - assert(sql_mstr.db == nullptr); - res = sqlite3_open("pke-at.sqlite3", &sql_mstr.db); + res = sqlite3_open(SQLITE_DB_PATH, &db); if (res != SQLITE_OK) { - fprintf(stderr, "[pke_at_storage_sql::init] Failed to open database, sqlite err: %i, %s\n", res, sqlite3_errmsg(sql_mstr.db)); + fprintf(stderr, "[pke_at_storage_sql::init] Failed to open database, sqlite err: %i, %s\n", res, sqlite3_errmsg(db)); goto cleanup; } @@ -44,7 +63,7 @@ void pke_at_storage_sql::init() const { } return SQLITE_OK; }; - res = sqlite3_exec(sql_mstr.db, query, fn, &version, &sql_err_string); + res = sqlite3_exec(db, query, fn, &version, &sql_err_string); if (res != SQLITE_OK) { fprintf(stderr, "[pke_at_storage_sql::init] Failed to query db schema, sqlite err: %i, %s\n", res, sql_err_string); goto cleanup; @@ -76,7 +95,7 @@ void pke_at_storage_sql::init() const { } return SQLITE_OK; }; - res = sqlite3_exec(sql_mstr.db, query, fn, &version, &sql_err_string); + res = sqlite3_exec(db, query, fn, &version, &sql_err_string); if (res != SQLITE_OK) { fprintf(stderr, "[pke_at_storage_sql::init] Failed to query [db_version], sqlite err: %i, %s\n", res, sql_err_string); goto cleanup; @@ -103,7 +122,7 @@ void pke_at_storage_sql::init() const { (void)user_data; (void)column_count; (void)argv; (void)colname; return SQLITE_OK; }; - res = sqlite3_exec(sql_mstr.db, (char*)asset->ptr, fn, nullptr, &sql_err_string); + res = sqlite3_exec(db, (char*)asset->ptr, fn, nullptr, &sql_err_string); if (res != SQLITE_OK) { fprintf(stderr, "[pke_at_storage_sql::init] failed updating database at step %03i_%03i: %i, %s\n", check_version.maj, check_version.min, res, sql_err_string); goto cleanup; @@ -112,7 +131,7 @@ void pke_at_storage_sql::init() const { } cleanup: - if (sql_mstr.db != nullptr) sqlite3_close(sql_mstr.db); + if (db != nullptr) sqlite3_close(db); fflush(stderr); if (res != SQLITE_OK) exit(1); } @@ -126,95 +145,446 @@ const { pke_at_storage_interface_response pke_at_storage_sql::pke_at_storage_interface_section_delete(pk_uuid uuid) const { - (void)uuid; - /* TODO */ - return PASIS_RES(0); + int res, ret = 1; + sqlite3 *db = nullptr; + char *sql_err_string = nullptr; + res = sqlite3_open(SQLITE_DB_PATH, &db); + assert(res == SQLITE_OK); + { + snprintf(sql_mstr.query_text, query_text_length, + "%.*s WHERE uuid='" pk_uuid_printf_format "'", + src_sql_section_delete_sql_len, src_sql_section_delete_sql, + pk_uuid_printf_var(uuid)); + res = sqlite3_exec(db, sql_mstr.query_text, nullptr, nullptr, &sql_err_string); + if (res != SQLITE_OK) { + fprintf(stderr, "[pke_at_storage_sql::pke_at_storage_interface_section_delete] Failed, sqlite err: %i, %s\n", res, sql_err_string); + ret = 2; + goto cleanup; + } + } +cleanup: + if (db != nullptr) sqlite3_close(db); + return PASIS_RES(ret); } pke_at_storage_interface_response_t<pke_at_section_details> pke_at_storage_sql::pke_at_storage_interface_section_get(pk_uuid uuid) const { - (void)uuid; - /* TODO */ - return PASIS_REST(0, nullptr); + int res, ret = 1; + sqlite3 *db = nullptr; + char *sql_err_string = nullptr; + pke_at_section_details *details = nullptr; + res = sqlite3_open(SQLITE_DB_PATH, &db); + assert(res == SQLITE_OK); + { + snprintf(sql_mstr.query_text, query_text_length, + "%.*s WHERE uuid='" pk_uuid_printf_format "'", + src_sql_section_get_sql_len, src_sql_section_get_sql, + pk_uuid_printf_var(uuid)); + auto fn = [](void *user_data, int column_count, char **argv, char **colname) -> int { + int i; + (void)colname; + PK_STN_RES stn_res; + auto **deets = reinterpret_cast<pke_at_section_details**>(user_data); + if (*deets != nullptr) { + fprintf(stderr, "[pke_at_storage_sql::pke_at_storage_interface_section_get::fn] More than one result returned.\n"); + return SQLITE_ERROR; + } + *deets = pk_new<pke_at_section_details>(g_at.mem.bkt_transient); + auto *d = *deets; + new (d) pke_at_section_details(); + for (i = 0; i < column_count; ++i) { + if (i == 0) { + d->song_uuid << argv[i]; + } + if (i == 1) { + stn_res = pk_stn(&d->sequence, argv[i], nullptr); + if (stn_res != PK_STN_RES_SUCCESS) { + fprintf(stderr, "[pke_at_storage_sql::pke_at_storage_interface_section_get::fn] sequence STN err: %i.\n", stn_res); + return SQLITE_ERROR; + } + } + if (i == 2) { + stn_res = pk_stn(&d->section_type_index, argv[i], nullptr); + if (stn_res != PK_STN_RES_SUCCESS) { + fprintf(stderr, "[pke_at_storage_sql::pke_at_storage_interface_section_get::fn] section_type_index STN err: %i.\n", stn_res); + return SQLITE_ERROR; + } + } + if (i == 3) { + stn_res = pk_stn(&d->beats_per_bar, argv[i], nullptr); + if (stn_res != PK_STN_RES_SUCCESS) { + fprintf(stderr, "[pke_at_storage_sql::pke_at_storage_interface_section_get::fn] beats_per_bar STN err: %i.\n", stn_res); + return SQLITE_ERROR; + } + } + if (i == 4) { + stn_res = pk_stn(&d->bar_count, argv[i], nullptr); + if (stn_res != PK_STN_RES_SUCCESS) { + fprintf(stderr, "[pke_at_storage_sql::pke_at_storage_interface_section_get::fn] bar_count STN err: %i.\n", stn_res); + return SQLITE_ERROR; + } + } + } + return SQLITE_OK; + }; + res = sqlite3_exec(db, sql_mstr.query_text, fn, &details, &sql_err_string); + if (res != SQLITE_OK) { + fprintf(stderr, "[pke_at_storage_sql::pke_at_storage_interface_section_get] Failed, sqlite err: %i, %s\n", res, sql_err_string); + ret = 2; + goto cleanup; + } + } +cleanup: + if (db != nullptr) sqlite3_close(db); + return PASIS_REST(ret, details); } pke_at_storage_interface_response pke_at_storage_sql::pke_at_storage_interface_section_upsert(const pke_at_section_details &val) const { - (void)val; - /* TODO */ - return PASIS_RES(0); + int res, ret = 1; + sqlite3 *db = nullptr; + char *sql_err_string = nullptr; + res = sqlite3_open(SQLITE_DB_PATH, &db); + assert(res == SQLITE_OK); + { + char uuid[59]; + snprintf(uuid, 59, pk_uuid_printf_format, pk_uuid_printf_var(val.song_uuid)); + snprintf(sql_mstr.query_text, query_text_length, + (char*)src_sql_section_upsert_sql, uuid, val.sequence, + val.section_type_index, val.beats_per_bar, val.bar_count); + res = sqlite3_exec(db, sql_mstr.query_text, nullptr, nullptr, &sql_err_string); + if (res != SQLITE_OK) { + fprintf(stderr, "[pke_at_storage_sql::pke_at_storage_interface_section_upsert] Failed, sqlite err: %i, %s\n", res, sql_err_string); + ret = 2; + goto cleanup; + } + } +cleanup: + if (db != nullptr) sqlite3_close(db); + return PASIS_RES(ret); } pke_at_storage_interface_response pke_at_storage_sql::pke_at_storage_interface_setlist_delete(pk_uuid uuid) const { - (void)uuid; - /* TODO */ - return PASIS_RES(0); + int res, ret = 1; + sqlite3 *db = nullptr; + char *sql_err_string = nullptr; + res = sqlite3_open(SQLITE_DB_PATH, &db); + assert(res == SQLITE_OK); + { + snprintf(sql_mstr.query_text, query_text_length, + "%.*s WHERE uuid='" pk_uuid_printf_format "'", + src_sql_setlist_delete_sql_len, src_sql_setlist_delete_sql, + pk_uuid_printf_var(uuid)); + res = sqlite3_exec(db, sql_mstr.query_text, nullptr, nullptr, &sql_err_string); + if (res != SQLITE_OK) { + fprintf(stderr, "[pke_at_storage_sql::pke_at_storage_interface_setlist_delete] Failed, sqlite err: %i, %s\n", res, sql_err_string); + ret = 2; + goto cleanup; + } + } +cleanup: + if (db != nullptr) sqlite3_close(db); + return PASIS_RES(ret); } pke_at_storage_interface_response_t<pke_at_setlist_details> pke_at_storage_sql::pke_at_storage_interface_setlist_get(pk_uuid uuid) const { - (void)uuid; - /* TODO */ - return PASIS_REST(0, nullptr); + int res, ret = 1; + sqlite3 *db = nullptr; + char *sql_err_string = nullptr; + pke_at_setlist_details *details = nullptr; + res = sqlite3_open(SQLITE_DB_PATH, &db); + assert(res == SQLITE_OK); + { + snprintf(sql_mstr.query_text, query_text_length, + "%.*s WHERE uuid='" pk_uuid_printf_format "'", + src_sql_setlist_get_sql_len, src_sql_setlist_get_sql, + pk_uuid_printf_var(uuid)); + auto fn = [](void *user_data, int column_count, char **argv, char **colname) -> int { + int i; + (void)colname; + auto **deets = reinterpret_cast<pke_at_setlist_details**>(user_data); + if (*deets != nullptr) { + fprintf(stderr, "[pke_at_storage_sql::pke_at_storage_interface_setlist_get::fn] More than one result returned.\n"); + return SQLITE_ERROR; + } + *deets = pk_new<pke_at_setlist_details>(g_at.mem.bkt_transient); + auto *d = *deets; + new (d) pke_at_setlist_details(); + for (i = 0; i < column_count; ++i) { + if (i == 0) { + d->uuid << argv[i]; + } + if (i == 1) { + d->title.length = strlen(argv[i]); + d->title.reserved = d->title.length + 1; + char *str = pk_new_arr<char>(d->title.reserved, g_at.mem.bkt); + strncpy(str, argv[i], d->title.length); + d->title.val = str; + } + } + return SQLITE_OK; + }; + res = sqlite3_exec(db, sql_mstr.query_text, fn, &details, &sql_err_string); + if (res != SQLITE_OK) { + fprintf(stderr, "[pke_at_storage_sql::pke_at_storage_interface_setlist_get] Failed, sqlite err: %i, %s\n", res, sql_err_string); + ret = 2; + goto cleanup; + } + } +cleanup: + if (db != nullptr) sqlite3_close(db); + return PASIS_REST(ret, details); } pke_at_storage_interface_response pke_at_storage_sql::pke_at_storage_interface_setlist_upsert(const pke_at_setlist_details &val) const { - (void)val; - /* TODO */ - return PASIS_RES(0); + int res, ret = 1; + sqlite3 *db = nullptr; + char *sql_err_string = nullptr; + res = sqlite3_open(SQLITE_DB_PATH, &db); + assert(res == SQLITE_OK); + { + char uuid[59]; + snprintf(uuid, 59, pk_uuid_printf_format, pk_uuid_printf_var(val.uuid)); + snprintf(sql_mstr.query_text, query_text_length, + (char*)src_sql_setlist_upsert_sql, uuid, val.title); + res = sqlite3_exec(db, sql_mstr.query_text, nullptr, nullptr, &sql_err_string); + if (res != SQLITE_OK) { + fprintf(stderr, "[pke_at_storage_sql::pke_at_storage_interface_setlist_upsert] Failed, sqlite err: %i, %s\n", res, sql_err_string); + ret = 2; + goto cleanup; + } + } +cleanup: + if (db != nullptr) sqlite3_close(db); + return PASIS_RES(ret); } pke_at_storage_interface_response -pke_at_storage_sql::pke_at_storage_interface_song_delete(pk_uuid uuid) +pke_at_storage_sql::pke_at_storage_interface_setlist_song_delete(pk_uuid setlist_uuid, pk_uuid song_uuid) const { - (void)uuid; - /* TODO */ - return PASIS_RES(0); + int res, ret = 1; + sqlite3 *db = nullptr; + char *sql_err_string = nullptr; + res = sqlite3_open(SQLITE_DB_PATH, &db); + assert(res == SQLITE_OK); + { + snprintf(sql_mstr.query_text, query_text_length, + "%.*s WHERE setlist_uuid='" pk_uuid_printf_format "' AND song_uuid='" pk_uuid_printf_format "'", + src_sql_setlist_song_delete_sql_len, src_sql_setlist_song_delete_sql, + pk_uuid_printf_var(setlist_uuid), pk_uuid_printf_var(song_uuid)); + res = sqlite3_exec(db, sql_mstr.query_text, nullptr, nullptr, &sql_err_string); + if (res != SQLITE_OK) { + fprintf(stderr, "[pke_at_storage_sql::pke_at_storage_interface_setlist_song_delete] Failed, sqlite err: %i, %s\n", res, sql_err_string); + ret = 2; + goto cleanup; + } + } +cleanup: + if (db != nullptr) sqlite3_close(db); + return PASIS_RES(ret); } -pke_at_storage_interface_response_t<pke_at_song_details> -pke_at_storage_sql::pke_at_storage_interface_song_get(pk_uuid uuid) +pke_at_storage_interface_response_t<pke_at_setlist_song_details> +pke_at_storage_sql::pke_at_storage_interface_setlist_song_get(pk_uuid setlist_uuid, pk_uuid song_uuid) const { - (void)uuid; - /* TODO */ - return PASIS_REST(0, nullptr); + int res, ret = 1; + sqlite3 *db = nullptr; + char *sql_err_string = nullptr; + pke_at_setlist_song_details *details = nullptr; + res = sqlite3_open(SQLITE_DB_PATH, &db); + assert(res == SQLITE_OK); + { + snprintf(sql_mstr.query_text, query_text_length, + "%.*s WHERE setlist_uuid='" pk_uuid_printf_format "' AND song_uuid='" pk_uuid_printf_format "'", + src_sql_setlist_song_get_sql_len, src_sql_setlist_song_get_sql, + pk_uuid_printf_var(setlist_uuid), pk_uuid_printf_var(song_uuid)); + auto fn = [](void *user_data, int column_count, char **argv, char **colname) -> int { + int i; + (void)colname; + auto **deets = reinterpret_cast<pke_at_setlist_song_details**>(user_data); + if (*deets != nullptr) { + fprintf(stderr, "[pke_at_storage_sql::pke_at_storage_interface_setlist_song_get::fn] More than one result returned.\n"); + return SQLITE_ERROR; + } + *deets = pk_new<pke_at_setlist_song_details>(g_at.mem.bkt_transient); + auto *d = *deets; + new (d) pke_at_setlist_song_details(); + for (i = 0; i < column_count; ++i) { + if (i == 0) { + d->setlist_uuid << argv[i]; + } + if (i == 1) { + d->song_uuid << argv[i]; + } + } + return SQLITE_OK; + }; + res = sqlite3_exec(db, sql_mstr.query_text, fn, &details, &sql_err_string); + if (res != SQLITE_OK) { + fprintf(stderr, "[pke_at_storage_sql::pke_at_storage_interface_setlist_song_get] Failed, sqlite err: %i, %s\n", res, sql_err_string); + ret = 2; + goto cleanup; + } + } +cleanup: + if (db != nullptr) sqlite3_close(db); + return PASIS_REST(ret, details); } pke_at_storage_interface_response -pke_at_storage_sql::pke_at_storage_interface_song_upsert(const pke_at_song_details &val) +pke_at_storage_sql::pke_at_storage_interface_setlist_song_upsert(const pke_at_setlist_song_details &val) const { - (void)val; - /* TODO */ - return PASIS_RES(0); + int res, ret = 1; + sqlite3 *db = nullptr; + char *sql_err_string = nullptr; + res = sqlite3_open(SQLITE_DB_PATH, &db); + assert(res == SQLITE_OK); + { + char uuid[59], uuid2[59]; + snprintf(uuid, 59, pk_uuid_printf_format, pk_uuid_printf_var(val.setlist_uuid)); + snprintf(uuid2, 59, pk_uuid_printf_format, pk_uuid_printf_var(val.song_uuid)); + snprintf(sql_mstr.query_text, query_text_length, + (char*)src_sql_setlist_song_upsert_sql, uuid, uuid2); + res = sqlite3_exec(db, sql_mstr.query_text, nullptr, nullptr, &sql_err_string); + if (res != SQLITE_OK) { + fprintf(stderr, "[pke_at_storage_sql::pke_at_storage_interface_setlist_song_upsert] Failed, sqlite err: %i, %s\n", res, sql_err_string); + ret = 2; + goto cleanup; + } + } +cleanup: + if (db != nullptr) sqlite3_close(db); + return PASIS_RES(ret); } pke_at_storage_interface_response -pke_at_storage_sql::pke_at_storage_interface_setlist_song_delete(pk_uuid uuid) +pke_at_storage_sql::pke_at_storage_interface_song_delete(pk_uuid uuid) const { - (void)uuid; - /* TODO */ - return PASIS_RES(0); + int res, ret = 1; + sqlite3 *db = nullptr; + char *sql_err_string = nullptr; + res = sqlite3_open(SQLITE_DB_PATH, &db); + assert(res == SQLITE_OK); + { + snprintf(sql_mstr.query_text, query_text_length, + "%.*s WHERE uuid='" pk_uuid_printf_format "'", + src_sql_song_delete_sql_len, src_sql_song_delete_sql, + pk_uuid_printf_var(uuid)); + res = sqlite3_exec(db, sql_mstr.query_text, nullptr, nullptr, &sql_err_string); + if (res != SQLITE_OK) { + fprintf(stderr, "[pke_at_storage_sql::pke_at_storage_interface_song_delete] Failed, sqlite err: %i, %s\n", res, sql_err_string); + ret = 2; + goto cleanup; + } + } +cleanup: + if (db != nullptr) sqlite3_close(db); + return PASIS_RES(ret); } -pke_at_storage_interface_response_t<pke_at_setlist_song_details> -pke_at_storage_sql::pke_at_storage_interface_setlist_song_get(pk_uuid uuid) +pke_at_storage_interface_response_t<pke_at_song_details> +pke_at_storage_sql::pke_at_storage_interface_song_get(pk_uuid uuid) const { - (void)uuid; - /* TODO */ - return PASIS_REST(0, nullptr); + int res, ret = 1; + sqlite3 *db = nullptr; + char *sql_err_string = nullptr; + pke_at_song_details *details = nullptr; + res = sqlite3_open(SQLITE_DB_PATH, &db); + assert(res == SQLITE_OK); + { + snprintf(sql_mstr.query_text, query_text_length, + "%.*s WHERE uuid='" pk_uuid_printf_format "'", + src_sql_song_get_sql_len, src_sql_song_get_sql, + pk_uuid_printf_var(uuid)); + auto fn = [](void *user_data, int column_count, char **argv, char **colname) -> int { + int i; + (void)colname; + PK_STN_RES stn_res; + auto **deets = reinterpret_cast<pke_at_song_details**>(user_data); + if (*deets != nullptr) { + fprintf(stderr, "[pke_at_storage_sql::pke_at_storage_interface_song_get::fn] More than one result returned.\n"); + return SQLITE_ERROR; + } + *deets = pk_new<pke_at_song_details>(g_at.mem.bkt_transient); + auto *d = *deets; + new (d) pke_at_song_details(); + for (i = 0; i < column_count; ++i) { + if (i == 0) { + d->uuid << argv[i]; + } + if (i == 1) { + stn_res = pk_stn(&d->ccli, argv[i], nullptr); + if (stn_res != PK_STN_RES_SUCCESS) { + fprintf(stderr, "[pke_at_storage_sql::pke_at_storage_interface_song_get::fn] ccli STN err: %i.\n", stn_res); + return SQLITE_ERROR; + } + } + if (i == 2) { + d->title.length = strlen(argv[i]); + d->title.reserved = d->title.length + 1; + char *str = pk_new_arr<char>(d->title.reserved, g_at.mem.bkt); + strncpy(str, argv[i], d->title.length); + d->title.val = str; + } + if (i == 3) { + d->arrangement.length = strlen(argv[i]); + d->arrangement.reserved = d->title.length + 1; + char *str = pk_new_arr<char>(d->title.reserved, g_at.mem.bkt); + strncpy(str, argv[i], d->title.length); + d->arrangement.val = str; + } + if (i == 4) { + stn_res = pk_stn(&d->bpm, argv[i], nullptr); + if (stn_res != PK_STN_RES_SUCCESS) { + fprintf(stderr, "[pke_at_storage_sql::pke_at_storage_interface_song_get::fn] bpm STN err: %i.\n", stn_res); + return SQLITE_ERROR; + } + } + } + return SQLITE_OK; + }; + res = sqlite3_exec(db, sql_mstr.query_text, fn, &details, &sql_err_string); + if (res != SQLITE_OK) { + fprintf(stderr, "[pke_at_storage_sql::pke_at_storage_interface_song_get] Failed, sqlite err: %i, %s\n", res, sql_err_string); + ret = 2; + goto cleanup; + } + } +cleanup: + if (db != nullptr) sqlite3_close(db); + return PASIS_REST(ret, details); } pke_at_storage_interface_response -pke_at_storage_sql::pke_at_storage_interface_setlist_song_upsert(const pke_at_setlist_song_details &val) +pke_at_storage_sql::pke_at_storage_interface_song_upsert(const pke_at_song_details &val) const { - (void)val; - /* TODO */ - return PASIS_RES(0); + int res, ret = 1; + sqlite3 *db = nullptr; + char *sql_err_string = nullptr; + res = sqlite3_open(SQLITE_DB_PATH, &db); + assert(res == SQLITE_OK); + { + char uuid[59]; + snprintf(uuid, 59, pk_uuid_printf_format, pk_uuid_printf_var(val.uuid)); + snprintf(sql_mstr.query_text, query_text_length, + (char*)src_sql_song_upsert_sql, uuid, val.ccli, val.title.val, + val.arrangement.val, val.bpm); + res = sqlite3_exec(db, sql_mstr.query_text, nullptr, nullptr, &sql_err_string); + if (res != SQLITE_OK) { + fprintf(stderr, "[pke_at_storage_sql::pke_at_storage_interface_song_upsert] Failed, sqlite err: %i, %s\n", res, sql_err_string); + ret = 2; + goto cleanup; + } + } +cleanup: + if (db != nullptr) sqlite3_close(db); + return PASIS_RES(ret); } diff --git a/src/pke-at-storage-sql.hpp b/src/pke-at-storage-sql.hpp index 39c8ed8..e050929 100644 --- a/src/pke-at-storage-sql.hpp +++ b/src/pke-at-storage-sql.hpp @@ -12,8 +12,8 @@ struct pke_at_storage_sql : public pke_at_storage_interface { PASIR_DEL(setlist) const override; PASIR_GET(setlist, pke_at_setlist_details) const override; PASIR_UPS(setlist, pke_at_setlist_details) const override; - PASIR_DEL(setlist_song) const override; - PASIR_GET(setlist_song, pke_at_setlist_song_details) const override; + PASIRA_DEL(setlist_song, pk_uuid setlist_uuid, pk_uuid song_uuid) const override; + PASIRA_GET(setlist_song, pke_at_setlist_song_details, pk_uuid setlist_uuid, pk_uuid song_uuid) const override; PASIR_UPS(setlist_song, pke_at_setlist_song_details) const override; PASIR_DEL(song) const override; PASIR_GET(song, pke_at_song_details) const override; diff --git a/src/pke-at.cpp b/src/pke-at.cpp index 65acedf..0831c08 100644 --- a/src/pke-at.cpp +++ b/src/pke-at.cpp @@ -1,5 +1,4 @@ -#include "embedded-sql.hpp" #include "level-init.hpp" #include "pke-at-setlist-types.hpp" #include "pke-at-settings.hpp" @@ -21,10 +20,6 @@ void pke_at_init() { uint64_t i; pkeSettings.rt.nextLevel = pke_at_level_init_create(); - for (i = 0; i < embedded_sql_count; ++i) { - embedded_sql[i].handle = AM_Register_Static(embedded_sql[i].key, PKE_ASSET_TYPE_UNSET, embedded_sql[i].data, embedded_sql[i].size); - } - for (i = 0; i < PKE_AT_SECTION_TYPE_INDEX_COUNT; ++i) { if (g_section_types[i].title_key[0] == '\0') continue; g_section_types[i].title_handle = AM_GetHandle(g_section_types[i].title_key); diff --git a/src/sql/schema-000-000.sql b/src/sql/schema-000-000.sql index f80977f..f1881cc 100644 --- a/src/sql/schema-000-000.sql +++ b/src/sql/schema-000-000.sql @@ -8,7 +8,7 @@ CREATE TABLE [db_version] ( ); CREATE TABLE [at_setlist] ( - uuid BLOB PRIMARY KEY + uuid NCHAR(56) PRIMARY KEY ,title nvarchar(128) DEFAULT '' ,is_deleted INTEGER NOT NULL DEFAULT 0 ,creation_dt INTEGER DEFAULT (unixepoch('now')) @@ -16,7 +16,7 @@ CREATE TABLE [at_setlist] ( ); CREATE TABLE [at_song] ( - uuid BLOB PRIMARY KEY + uuid NCHAR(56) PRIMARY KEY ,ccli INTEGER ,title nvarchar(128) DEFAULT '' ,arrangement nvarchar(128) DEFAULT '' @@ -27,17 +27,17 @@ CREATE TABLE [at_song] ( ); CREATE TABLE [at_setlist_song] ( - setlist_uuid BLOB - ,song_uuid BLOB + setlist_uuid NCHAR(56) + ,song_uuid NCHAR(56) ,is_deleted INTEGER NOT NULL DEFAULT 0 ,creation_dt INTEGER DEFAULT (unixepoch('now')) ,modification_dt INTEGER DEFAULT (unixepoch('now')) ); CREATE TABLE [at_section] ( - song_uuid BLOB - ,section_type INTEGER + song_uuid NCHAR(56) ,sequence INTEGER + ,section_type INTEGER ,beats_per_bar INTEGER ,bar_count INTEGER ,is_deleted INTEGER NOT NULL DEFAULT 0 diff --git a/src/sql/section_get.sql b/src/sql/section_get.sql index bbd0a73..81c5ca8 100644 --- a/src/sql/section_get.sql +++ b/src/sql/section_get.sql @@ -1 +1 @@ -SELECT uuid,section_type,sequence,beats_per_bar,bar_count FROM [at_setlist] +SELECT uuid,sequence,section_type,beats_per_bar,bar_count FROM [at_setlist] diff --git a/src/sql/section_upsert.sql b/src/sql/section_upsert.sql index 4ca1025..659d66a 100644 --- a/src/sql/section_upsert.sql +++ b/src/sql/section_upsert.sql @@ -1,10 +1,9 @@ -INSERT INTO [at_section] (uuid,section_type,sequence,beats_per_bar,bar_count) - VALUES('%s','%s','%s','%s','%s') - ON CONFLICT(uuid) DO UPDATE SET +INSERT INTO [at_section] (uuid,sequence,section_type,beats_per_bar,bar_count) + VALUES('%s','%i','%u','%u','%u') + ON CONFLICT(song_uuid,sequence) DO UPDATE SET section_type=excluded.section_type - ,sequence=excluded.sequence ,beats_per_bar=excluded.beats_per_bar ,bar_count=excluded.bar_count ,is_deleted=0 ,modification_dt=unixepoch('now') - WHERE uuid=excluded.uuid; + WHERE song_uuid=excluded.uuid AND sequence=excluded.sequence; diff --git a/src/sql/song_upsert.sql b/src/sql/song_upsert.sql index d0e4fcc..4f2a165 100644 --- a/src/sql/song_upsert.sql +++ b/src/sql/song_upsert.sql @@ -1,5 +1,5 @@ INSERT INTO [at_song] (uuid,ccli,title,arrangement,beats_per_minute) - VALUES('%s','%s','%s','%s','%s') + VALUES('%s','%lu','%s','%s','%u') ON CONFLICT(uuid) DO UPDATE SET ccli=excluded.ccli ,title=excluded.title |
