From 3ed7916856f03eafbe0891f2ab39c34d20d2bd24 Mon Sep 17 00:00:00 2001 From: KernelDeimos Date: Mon, 8 Jul 2024 15:24:26 -0400 Subject: [PATCH] feat: JSON support for kv driver --- src/backend/src/drivers/DBKVStore.js | 18 ++++++++--- .../database/SqliteDatabaseAccessService.js | 7 ++++- .../database/sqlite_setup/0023_fix-kv.sql | 31 +++++++++++++++++++ 3 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 src/backend/src/services/database/sqlite_setup/0023_fix-kv.sql diff --git a/src/backend/src/drivers/DBKVStore.js b/src/backend/src/drivers/DBKVStore.js index 2131e46a85..a4e2f05cca 100644 --- a/src/backend/src/drivers/DBKVStore.js +++ b/src/backend/src/drivers/DBKVStore.js @@ -58,6 +58,11 @@ class DBKVStore extends Driver { `SELECT * FROM kv WHERE user_id=? AND (app IS NULL OR app = 'global') AND kkey_hash=? LIMIT 1`, [ user.id, key_hash ] ); + + if ( kv[0] ) kv[0].value = db.case({ + mysql: () => kv[0].value, + otherwise: () => JSON.parse(kv[0].value ?? 'null'), + })(); return kv[0]?.value ?? null; }, @@ -74,10 +79,11 @@ class DBKVStore extends Driver { } // Validate the value - value = value === undefined ? null : String(value); + value = value === undefined ? null : value; if ( value !== null && - Buffer.byteLength(value, 'utf8') > config.kv_max_value_size + Buffer.byteLength(JSON.stringify(value), 'utf8') > + config.kv_max_value_size ) { throw new Error(`value is too large. Max size is ${config.kv_max_value_size}.`); } @@ -102,7 +108,8 @@ class DBKVStore extends Driver { sqlite: 'ON CONFLICT(user_id, app, kkey_hash) DO UPDATE SET value = excluded.value', }), [ - user.id, app?.uid ?? 'global', key_hash, key, value, + user.id, app?.uid ?? 'global', key_hash, key, + JSON.stringify(value), ...db.case({ mysql: [value], otherwise: [] }), ] ); @@ -164,7 +171,10 @@ class DBKVStore extends Driver { rows = rows.map(row => ({ key: row.kkey, - value: row.value, + value: db.case({ + mysql: () => row.value, + otherwise: () => JSON.parse(row.value ?? 'null') + })(), })); as = as || 'entries'; diff --git a/src/backend/src/services/database/SqliteDatabaseAccessService.js b/src/backend/src/services/database/SqliteDatabaseAccessService.js index 7472d15700..4d987c4067 100644 --- a/src/backend/src/services/database/SqliteDatabaseAccessService.js +++ b/src/backend/src/services/database/SqliteDatabaseAccessService.js @@ -42,7 +42,7 @@ class SqliteDatabaseAccessService extends BaseDatabaseAccessService { this.db = new Database(this.config.path); // Database upgrade logic - const TARGET_VERSION = 20; + const TARGET_VERSION = 21; if ( do_setup ) { this.log.noticeme(`SETUP: creating database at ${this.config.path}`); @@ -69,6 +69,7 @@ class SqliteDatabaseAccessService extends BaseDatabaseAccessService { '0020_dev-center.sql', '0021_app-owner-id.sql', '0022_dev-center-max.sql', + '0023_fix-kv.sql', ].map(p => path_.join(__dirname, 'sqlite_setup', p)); const fs = require('fs'); for ( const filename of sql_files ) { @@ -165,6 +166,10 @@ class SqliteDatabaseAccessService extends BaseDatabaseAccessService { upgrade_files.push('0022_dev-center-max.sql'); } + if ( user_version <= 20 ) { + upgrade_files.push('0023_fix-kv.sql'); + } + if ( upgrade_files.length > 0 ) { this.log.noticeme(`Database out of date: ${this.config.path}`); this.log.noticeme(`UPGRADING DATABASE: ${user_version} -> ${TARGET_VERSION}`); diff --git a/src/backend/src/services/database/sqlite_setup/0023_fix-kv.sql b/src/backend/src/services/database/sqlite_setup/0023_fix-kv.sql new file mode 100644 index 0000000000..9d76e6d0d8 --- /dev/null +++ b/src/backend/src/services/database/sqlite_setup/0023_fix-kv.sql @@ -0,0 +1,31 @@ +CREATE TABLE `new_kv` ( + `id` INTEGER PRIMARY KEY, + `app` char(40) DEFAULT NULL, + `user_id` int(10) NOT NULL, + `kkey_hash` bigint(20) NOT NULL, + `kkey` text NOT NULL, + `value` JSON, + `migrated` tinyint(1) DEFAULT '0', + UNIQUE (user_id, app, kkey_hash) +); + +INSERT INTO `new_kv` +( + `app`, + `user_id`, + `kkey_hash`, + `kkey`, + `value` +) +SELECT + `app`, + `user_id`, + `kkey_hash`, + `kkey`, + json_quote(value) +FROM `kv`; + +DROP TABLE `kv`; + +ALTER TABLE `new_kv` +RENAME TO `kv`;