summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-10-13 15:27:59 -0400
committerJonathan Bradley <jcb@pikum.xyz>2025-10-13 15:44:17 -0400
commit6d53452ebc24287a72eedb9a2cc3f9e21c55362c (patch)
tree04ce0135a9718c41f24f217b587088dd9d59241a
parent62dae6011db94dd52c3ac0fce517c6e9cc0abcf6 (diff)
pke-at: second-pass sql storage
-rw-r--r--Makefile5
-rw-r--r--src/embedded-sql.cpp32
-rw-r--r--src/embedded-sql.hpp10
-rw-r--r--src/pke-at-setlist-types.hpp3
-rw-r--r--src/pke-at-storage-interface.hpp11
-rw-r--r--src/pke-at-storage-sql.cpp474
-rw-r--r--src/pke-at-storage-sql.hpp4
-rw-r--r--src/pke-at.cpp5
-rw-r--r--src/sql/schema-000-000.sql12
-rw-r--r--src/sql/section_get.sql2
-rw-r--r--src/sql/section_upsert.sql9
-rw-r--r--src/sql/song_upsert.sql2
12 files changed, 447 insertions, 122 deletions
diff --git a/Makefile b/Makefile
index ac18f45..edf856e 100644
--- a/Makefile
+++ b/Makefile
@@ -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