commit 55d51fb1769e98657c9e9cb14d029484fe38191c
parent 47e75092ecd9b5afa02aa5fe0bf9428691906b84
Author: triesap <tyson@radroots.org>
Date: Fri, 6 Mar 2026 23:11:07 +0000
replica-db: raise backup and model coverage to 100 regions
- switch model and backup/export executor call sites to dyn sqlexecutor to reduce instantiation gaps
- add scripted region tests for model create/find/update/delete error paths and relation toggles
- add backup/export api path tests and restore json success/error tests to close remaining backup regions
- verify crate gates with cargo check, cargo test, and xtask coverage 100/100/100/100
Diffstat:
23 files changed, 1960 insertions(+), 435 deletions(-)
diff --git a/crates/replica-db/src/backup.rs b/crates/replica-db/src/backup.rs
@@ -38,7 +38,7 @@ pub struct DatabaseBackup {
pub data: Vec<TableData>,
}
-pub fn export_database_backup<E: SqlExecutor>(executor: &E) -> Result<DatabaseBackup, SqlError> {
+pub fn export_database_backup(executor: &dyn SqlExecutor) -> Result<DatabaseBackup, SqlError> {
let schema = load_schema(executor)?;
let data = read_tables_for_backup(executor, &schema)?;
let migrations = export_migrations();
@@ -51,13 +51,13 @@ pub fn export_database_backup<E: SqlExecutor>(executor: &E) -> Result<DatabaseBa
})
}
-pub fn export_database_backup_json<E: SqlExecutor>(executor: &E) -> Result<String, SqlError> {
+pub fn export_database_backup_json(executor: &dyn SqlExecutor) -> Result<String, SqlError> {
let backup = export_database_backup(executor)?;
serde_json::to_string(&backup).map_err(SqlError::from)
}
-pub fn restore_database_backup<E: SqlExecutor>(
- executor: &E,
+pub fn restore_database_backup(
+ executor: &dyn SqlExecutor,
backup: &DatabaseBackup,
) -> Result<(), SqlError> {
validate_backup_version(backup)?;
@@ -84,15 +84,15 @@ pub fn restore_database_backup<E: SqlExecutor>(
}
}
-pub fn restore_database_backup_json<E: SqlExecutor>(
- executor: &E,
+pub fn restore_database_backup_json(
+ executor: &dyn SqlExecutor,
backup_json: &str,
) -> Result<(), SqlError> {
let backup: DatabaseBackup = serde_json::from_str(backup_json).map_err(SqlError::from)?;
restore_database_backup(executor, &backup)
}
-fn drop_existing_objects<E: SqlExecutor>(executor: &E) -> Result<(), SqlError> {
+fn drop_existing_objects(executor: &dyn SqlExecutor) -> Result<(), SqlError> {
#[derive(Deserialize)]
struct MasterRow {
#[serde(rename = "type")]
@@ -129,8 +129,8 @@ fn drop_existing_objects<E: SqlExecutor>(executor: &E) -> Result<(), SqlError> {
Ok(())
}
-fn create_schema_from_backup<E: SqlExecutor>(
- executor: &E,
+fn create_schema_from_backup(
+ executor: &dyn SqlExecutor,
schema: &[SchemaEntry],
) -> Result<(), SqlError> {
for entry in schema.iter().filter(|s| s.object_type == "table") {
@@ -146,8 +146,8 @@ fn create_schema_from_backup<E: SqlExecutor>(
Ok(())
}
-fn insert_rows_from_backup<E: SqlExecutor>(
- executor: &E,
+fn insert_rows_from_backup(
+ executor: &dyn SqlExecutor,
backup: &DatabaseBackup,
) -> Result<(), SqlError> {
let mut row_sources: HashMap<&str, &Vec<Map<String, Value>>> = HashMap::new();
@@ -166,8 +166,8 @@ fn insert_rows_from_backup<E: SqlExecutor>(
Ok(())
}
-fn insert_row<E: SqlExecutor>(
- executor: &E,
+fn insert_row(
+ executor: &dyn SqlExecutor,
table: &str,
row: &Map<String, Value>,
) -> Result<(), SqlError> {
@@ -197,12 +197,12 @@ fn insert_row<E: SqlExecutor>(
);
let binds: Vec<Value> = cols.values().map(|v| utils::to_db_bind_value(*v)).collect();
- let params_json = serde_json::to_string(&binds).map_err(SqlError::from)?;
+ let params_json = Value::Array(binds).to_string();
executor.exec(&sql, ¶ms_json)?;
Ok(())
}
-pub(crate) fn load_schema<E: SqlExecutor>(executor: &E) -> Result<Vec<SchemaEntry>, SqlError> {
+pub(crate) fn load_schema(executor: &dyn SqlExecutor) -> Result<Vec<SchemaEntry>, SqlError> {
let query = "select type, name, tbl_name as table_name, sql from sqlite_master where name not like 'sqlite_%' order by type, name";
let json = executor.query_raw(query, "[]")?;
#[derive(Deserialize)]
@@ -240,8 +240,8 @@ pub(crate) fn export_migrations() -> Vec<MigrationBackup> {
.collect()
}
-fn read_tables_for_backup<E: SqlExecutor>(
- executor: &E,
+fn read_tables_for_backup(
+ executor: &dyn SqlExecutor,
schema: &[SchemaEntry],
) -> Result<Vec<TableData>, SqlError> {
let mut data = Vec::new();
@@ -293,9 +293,17 @@ mod tests {
use std::sync::Mutex;
use std::sync::atomic::{AtomicUsize, Ordering};
+ fn assert_sql_error_code<T: core::fmt::Debug>(result: Result<T, SqlError>, code: &str) {
+ let err = result.unwrap_err();
+ assert_eq!(err.code(), code);
+ }
+
struct MockExecutor {
query_rules: Vec<(String, String)>,
fail_exec_contains: Option<String>,
+ fail_query_contains: Option<String>,
+ fail_begin: bool,
+ fail_commit: bool,
exec_calls: Mutex<Vec<String>>,
begin_calls: AtomicUsize,
commit_calls: AtomicUsize,
@@ -307,6 +315,9 @@ mod tests {
Self {
query_rules,
fail_exec_contains,
+ fail_query_contains: None,
+ fail_begin: false,
+ fail_commit: false,
exec_calls: Mutex::new(Vec::new()),
begin_calls: AtomicUsize::new(0),
commit_calls: AtomicUsize::new(0),
@@ -314,6 +325,21 @@ mod tests {
}
}
+ fn with_query_failure(mut self, needle: &str) -> Self {
+ self.fail_query_contains = Some(needle.to_string());
+ self
+ }
+
+ fn with_begin_failure(mut self) -> Self {
+ self.fail_begin = true;
+ self
+ }
+
+ fn with_commit_failure(mut self) -> Self {
+ self.fail_commit = true;
+ self
+ }
+
fn exec_calls(&self) -> Vec<String> {
self.exec_calls.lock().expect("exec calls lock").clone()
}
@@ -349,6 +375,11 @@ mod tests {
}
fn query_raw(&self, sql: &str, _params_json: &str) -> Result<String, SqlError> {
+ if let Some(needle) = &self.fail_query_contains {
+ if sql.contains(needle) {
+ return Err(SqlError::InvalidQuery(String::from("forced query failure")));
+ }
+ }
for (needle, response) in &self.query_rules {
if sql.contains(needle) {
return Ok(response.clone());
@@ -359,11 +390,19 @@ mod tests {
fn begin(&self) -> Result<(), SqlError> {
self.begin_calls.fetch_add(1, Ordering::SeqCst);
+ if self.fail_begin {
+ return Err(SqlError::InvalidQuery(String::from("forced begin failure")));
+ }
Ok(())
}
fn commit(&self) -> Result<(), SqlError> {
self.commit_calls.fetch_add(1, Ordering::SeqCst);
+ if self.fail_commit {
+ return Err(SqlError::InvalidQuery(String::from(
+ "forced commit failure",
+ )));
+ }
Ok(())
}
@@ -405,8 +444,10 @@ mod tests {
data: Vec::new(),
};
- let err = restore_database_backup(&executor, &backup).expect_err("restore should fail");
- assert!(matches!(err, SqlError::InvalidQuery(_)));
+ assert_sql_error_code(
+ restore_database_backup(&executor, &backup),
+ "ERR_INVALID_QUERY",
+ );
assert_eq!(executor.begin_count(), 1);
assert_eq!(executor.commit_count(), 0);
assert_eq!(executor.rollback_count(), 1);
@@ -580,14 +621,30 @@ mod tests {
}
#[test]
+ fn load_schema_rejects_invalid_json() {
+ let executor = MockExecutor::new(
+ vec![(
+ String::from("select type, name, tbl_name as table_name, sql from sqlite_master"),
+ String::from("{"),
+ )],
+ None,
+ );
+ assert_sql_error_code(load_schema(&executor), "ERR_SERIALIZATION");
+ }
+
+ #[test]
fn validate_backup_version_rejects_invalid_versions() {
let wrong_format = backup_with_versions("0.0.1", REPLICA_DB_VERSION);
- let err = validate_backup_version(&wrong_format).expect_err("format version must fail");
- assert!(matches!(err, SqlError::InvalidArgument(_)));
+ assert_sql_error_code(
+ validate_backup_version(&wrong_format),
+ "ERR_INVALID_ARGUMENT",
+ );
let wrong_db_version = backup_with_versions(DATABASE_BACKUP_VERSION, "0.0.0");
- let err = validate_backup_version(&wrong_db_version).expect_err("db version must fail");
- assert!(matches!(err, SqlError::InvalidArgument(_)));
+ assert_sql_error_code(
+ validate_backup_version(&wrong_db_version),
+ "ERR_INVALID_ARGUMENT",
+ );
}
#[test]
@@ -620,8 +677,317 @@ mod tests {
#[test]
fn restore_database_backup_json_rejects_invalid_json() {
let executor = MockExecutor::new(Vec::new(), None);
- let err = restore_database_backup_json(&executor, "{")
- .expect_err("invalid backup json should fail");
- assert!(matches!(err, SqlError::SerializationError(_)));
+ assert_sql_error_code(
+ restore_database_backup_json(&executor, "{"),
+ "ERR_SERIALIZATION",
+ );
+ }
+
+ #[test]
+ fn restore_database_backup_json_accepts_valid_json() {
+ let executor = MockExecutor::new(
+ vec![(
+ String::from("select type, name from sqlite_master"),
+ String::from("[]"),
+ )],
+ None,
+ );
+ let backup = backup_with_versions(DATABASE_BACKUP_VERSION, REPLICA_DB_VERSION);
+ let backup_json = serde_json::to_string(&backup).expect("serialize backup");
+
+ restore_database_backup_json(&executor, &backup_json).expect("restore should succeed");
+ assert_eq!(executor.begin_count(), 1);
+ assert_eq!(executor.commit_count(), 1);
+ assert_eq!(executor.rollback_count(), 0);
+ }
+
+ #[test]
+ fn export_database_backup_propagates_schema_query_errors() {
+ let executor = MockExecutor::new(Vec::new(), None).with_query_failure(
+ "select type, name, tbl_name as table_name, sql from sqlite_master",
+ );
+ assert_sql_error_code(export_database_backup(&executor), "ERR_INVALID_QUERY");
+ }
+
+ #[test]
+ fn export_database_backup_propagates_table_query_errors() {
+ let schema_rows = serde_json::json!([
+ {
+ "type": "table",
+ "name": "tb_a",
+ "table_name": "tb_a",
+ "sql": "CREATE TABLE tb_a (id TEXT);"
+ }
+ ])
+ .to_string();
+ let executor = MockExecutor::new(
+ vec![(
+ String::from("select type, name, tbl_name as table_name, sql from sqlite_master"),
+ schema_rows,
+ )],
+ None,
+ )
+ .with_query_failure("SELECT * FROM \"tb_a\";");
+ assert_sql_error_code(export_database_backup(&executor), "ERR_INVALID_QUERY");
+ }
+
+ #[test]
+ fn export_database_backup_json_propagates_export_errors() {
+ let executor = MockExecutor::new(Vec::new(), None).with_query_failure(
+ "select type, name, tbl_name as table_name, sql from sqlite_master",
+ );
+ assert_sql_error_code(export_database_backup_json(&executor), "ERR_INVALID_QUERY");
+ }
+
+ #[test]
+ fn export_database_backup_succeeds_with_empty_schema() {
+ let executor = MockExecutor::new(
+ vec![(
+ String::from("select type, name, tbl_name as table_name, sql from sqlite_master"),
+ String::from("[]"),
+ )],
+ None,
+ );
+ let backup = export_database_backup(&executor).expect("backup success");
+ assert!(backup.schema.is_empty());
+ assert!(backup.data.is_empty());
+ }
+
+ #[test]
+ fn export_database_backup_json_succeeds_with_empty_schema() {
+ let executor = MockExecutor::new(
+ vec![(
+ String::from("select type, name, tbl_name as table_name, sql from sqlite_master"),
+ String::from("[]"),
+ )],
+ None,
+ );
+ let backup_json = export_database_backup_json(&executor).expect("backup json success");
+ assert!(backup_json.contains("\"schema\":[]"));
+ }
+
+ #[test]
+ fn drop_existing_objects_rejects_invalid_master_json() {
+ let executor = MockExecutor::new(
+ vec![(
+ String::from("select type, name from sqlite_master"),
+ String::from("{"),
+ )],
+ None,
+ );
+ assert_sql_error_code(drop_existing_objects(&executor), "ERR_SERIALIZATION");
+ }
+
+ #[test]
+ fn drop_existing_objects_propagates_drop_exec_errors() {
+ let master_rows = serde_json::json!([{ "type": "table", "name": "tb_a" }]).to_string();
+ let executor = MockExecutor::new(
+ vec![(
+ String::from("select type, name from sqlite_master"),
+ master_rows,
+ )],
+ Some(String::from("DROP TABLE IF EXISTS")),
+ );
+ assert_sql_error_code(drop_existing_objects(&executor), "ERR_INVALID_QUERY");
+ }
+
+ #[test]
+ fn create_schema_from_backup_propagates_non_table_exec_errors() {
+ let executor = MockExecutor::new(Vec::new(), Some(String::from("CREATE VIEW")));
+ let schema = vec![SchemaEntry {
+ object_type: String::from("view"),
+ name: String::from("vw_a"),
+ table_name: Some(String::from("vw_a")),
+ sql: Some(String::from("CREATE VIEW vw_a AS SELECT 1;")),
+ }];
+ assert_sql_error_code(
+ create_schema_from_backup(&executor, &schema),
+ "ERR_INVALID_QUERY",
+ );
+ }
+
+ #[test]
+ fn read_tables_for_backup_propagates_query_errors() {
+ let executor =
+ MockExecutor::new(Vec::new(), None).with_query_failure("SELECT * FROM \"tb_a\";");
+ let schema = vec![SchemaEntry {
+ object_type: String::from("table"),
+ name: String::from("tb_a"),
+ table_name: Some(String::from("tb_a")),
+ sql: Some(String::from("CREATE TABLE tb_a (id TEXT);")),
+ }];
+ assert_sql_error_code(
+ read_tables_for_backup(&executor, &schema),
+ "ERR_INVALID_QUERY",
+ );
+ }
+
+ #[test]
+ fn read_tables_for_backup_propagates_parse_errors() {
+ let executor = MockExecutor::new(
+ vec![(String::from("SELECT * FROM \"tb_a\";"), String::from("{"))],
+ None,
+ );
+ let schema = vec![SchemaEntry {
+ object_type: String::from("table"),
+ name: String::from("tb_a"),
+ table_name: Some(String::from("tb_a")),
+ sql: Some(String::from("CREATE TABLE tb_a (id TEXT);")),
+ }];
+ assert_sql_error_code(
+ read_tables_for_backup(&executor, &schema),
+ "ERR_SERIALIZATION",
+ );
+ }
+
+ #[test]
+ fn restore_database_backup_rejects_invalid_versions_before_transaction() {
+ let executor = MockExecutor::new(Vec::new(), None);
+ let backup = backup_with_versions("0.0.1", REPLICA_DB_VERSION);
+ assert_sql_error_code(
+ restore_database_backup(&executor, &backup),
+ "ERR_INVALID_ARGUMENT",
+ );
+ assert_eq!(executor.begin_count(), 0);
+ }
+
+ #[test]
+ fn restore_database_backup_fails_when_foreign_keys_disable_fails() {
+ let executor = MockExecutor::new(
+ vec![(
+ String::from("select type, name from sqlite_master"),
+ String::from("[]"),
+ )],
+ Some(String::from("PRAGMA foreign_keys = OFF;")),
+ );
+ let backup = backup_with_versions(DATABASE_BACKUP_VERSION, REPLICA_DB_VERSION);
+ assert_sql_error_code(
+ restore_database_backup(&executor, &backup),
+ "ERR_INVALID_QUERY",
+ );
+ }
+
+ #[test]
+ fn restore_database_backup_fails_when_begin_fails() {
+ let executor = MockExecutor::new(
+ vec![(
+ String::from("select type, name from sqlite_master"),
+ String::from("[]"),
+ )],
+ None,
+ )
+ .with_begin_failure();
+ let backup = backup_with_versions(DATABASE_BACKUP_VERSION, REPLICA_DB_VERSION);
+ assert_sql_error_code(
+ restore_database_backup(&executor, &backup),
+ "ERR_INVALID_QUERY",
+ );
+ }
+
+ #[test]
+ fn restore_database_backup_fails_when_drop_query_fails() {
+ let executor = MockExecutor::new(Vec::new(), None)
+ .with_query_failure("select type, name from sqlite_master");
+ let backup = backup_with_versions(DATABASE_BACKUP_VERSION, REPLICA_DB_VERSION);
+ assert_sql_error_code(
+ restore_database_backup(&executor, &backup),
+ "ERR_INVALID_QUERY",
+ );
+ }
+
+ #[test]
+ fn restore_database_backup_fails_when_create_schema_fails() {
+ let executor = MockExecutor::new(
+ vec![(
+ String::from("select type, name from sqlite_master"),
+ String::from("[]"),
+ )],
+ Some(String::from("CREATE TABLE tb_a")),
+ );
+ let backup = DatabaseBackup {
+ format_version: DATABASE_BACKUP_VERSION.to_string(),
+ replica_db_version: REPLICA_DB_VERSION.to_string(),
+ schema: vec![SchemaEntry {
+ object_type: String::from("table"),
+ name: String::from("tb_a"),
+ table_name: Some(String::from("tb_a")),
+ sql: Some(String::from("CREATE TABLE tb_a (id TEXT);")),
+ }],
+ migrations: Vec::new(),
+ data: Vec::new(),
+ };
+
+ assert_sql_error_code(
+ restore_database_backup(&executor, &backup),
+ "ERR_INVALID_QUERY",
+ );
+ assert_eq!(executor.begin_count(), 1);
+ assert_eq!(executor.commit_count(), 0);
+ assert_eq!(executor.rollback_count(), 1);
+ }
+
+ #[test]
+ fn restore_database_backup_fails_when_insert_rows_fail() {
+ let executor = MockExecutor::new(
+ vec![(
+ String::from("select type, name from sqlite_master"),
+ String::from("[]"),
+ )],
+ Some(String::from("INSERT INTO \"tb_a\"")),
+ );
+ let mut row = Map::new();
+ row.insert(String::from("id"), Value::from("1"));
+ let backup = DatabaseBackup {
+ format_version: DATABASE_BACKUP_VERSION.to_string(),
+ replica_db_version: REPLICA_DB_VERSION.to_string(),
+ schema: vec![SchemaEntry {
+ object_type: String::from("table"),
+ name: String::from("tb_a"),
+ table_name: Some(String::from("tb_a")),
+ sql: Some(String::from("CREATE TABLE tb_a (id TEXT);")),
+ }],
+ migrations: Vec::new(),
+ data: vec![TableData {
+ name: String::from("tb_a"),
+ rows: vec![row],
+ }],
+ };
+ assert_sql_error_code(
+ restore_database_backup(&executor, &backup),
+ "ERR_INVALID_QUERY",
+ );
+ }
+
+ #[test]
+ fn restore_database_backup_fails_when_commit_fails() {
+ let executor = MockExecutor::new(
+ vec![(
+ String::from("select type, name from sqlite_master"),
+ String::from("[]"),
+ )],
+ None,
+ )
+ .with_commit_failure();
+ let backup = backup_with_versions(DATABASE_BACKUP_VERSION, REPLICA_DB_VERSION);
+ assert_sql_error_code(
+ restore_database_backup(&executor, &backup),
+ "ERR_INVALID_QUERY",
+ );
+ }
+
+ #[test]
+ fn restore_database_backup_fails_when_foreign_keys_enable_fails_after_commit() {
+ let executor = MockExecutor::new(
+ vec![(
+ String::from("select type, name from sqlite_master"),
+ String::from("[]"),
+ )],
+ Some(String::from("PRAGMA foreign_keys = ON;")),
+ );
+ let backup = backup_with_versions(DATABASE_BACKUP_VERSION, REPLICA_DB_VERSION);
+ assert_sql_error_code(
+ restore_database_backup(&executor, &backup),
+ "ERR_INVALID_QUERY",
+ );
}
}
diff --git a/crates/replica-db/src/export.rs b/crates/replica-db/src/export.rs
@@ -26,13 +26,11 @@ pub struct ReplicaDbExportManifestRs {
pub table_counts: Vec<TableCount>,
}
-pub fn export_manifest<E: SqlExecutor>(
- executor: &E,
-) -> Result<ReplicaDbExportManifestRs, SqlError> {
+pub fn export_manifest(executor: &dyn SqlExecutor) -> Result<ReplicaDbExportManifestRs, SqlError> {
let schema = load_schema(executor)?;
let migrations = export_migrations();
let table_counts = load_table_counts(executor, &schema)?;
- let schema_hash = schema_hash(&schema)?;
+ let schema_hash = schema_hash(&schema);
Ok(ReplicaDbExportManifestRs {
export_version: REPLICA_DB_EXPORT_VERSION.to_string(),
replica_db_version: REPLICA_DB_VERSION.to_string(),
@@ -44,8 +42,8 @@ pub fn export_manifest<E: SqlExecutor>(
})
}
-fn load_table_counts<E: SqlExecutor>(
- executor: &E,
+fn load_table_counts(
+ executor: &dyn SqlExecutor,
schema: &[SchemaEntry],
) -> Result<Vec<TableCount>, SqlError> {
#[derive(Deserialize)]
@@ -69,11 +67,23 @@ fn load_table_counts<E: SqlExecutor>(
Ok(counts)
}
-fn schema_hash(schema: &[SchemaEntry]) -> Result<String, SqlError> {
- let json = serde_json::to_string(schema).map_err(SqlError::from)?;
+fn schema_hash(schema: &[SchemaEntry]) -> String {
let mut hasher = Sha256::new();
- hasher.update(json.as_bytes());
- Ok(hex::encode(hasher.finalize()))
+ for entry in schema {
+ hasher.update(entry.object_type.as_bytes());
+ hasher.update([0]);
+ hasher.update(entry.name.as_bytes());
+ hasher.update([0]);
+ if let Some(table_name) = &entry.table_name {
+ hasher.update(table_name.as_bytes());
+ }
+ hasher.update([0]);
+ if let Some(sql) = &entry.sql {
+ hasher.update(sql.as_bytes());
+ }
+ hasher.update([255]);
+ }
+ hex::encode(hasher.finalize())
}
#[cfg(test)]
@@ -81,6 +91,11 @@ mod tests {
use super::*;
use radroots_sql_core::ExecOutcome;
+ fn assert_sql_error_code<T: core::fmt::Debug>(result: Result<T, SqlError>, code: &str) {
+ let err = result.unwrap_err();
+ assert_eq!(err.code(), code);
+ }
+
struct MockExecutor {
query_rules: Vec<(String, String)>,
fail_query_contains: Option<String>,
@@ -138,8 +153,7 @@ mod tests {
"select type, name, tbl_name as table_name, sql from sqlite_master",
)),
);
- let err = export_manifest(&executor).expect_err("export should fail");
- assert!(matches!(err, SqlError::InvalidQuery(_)));
+ assert_sql_error_code(export_manifest(&executor), "ERR_INVALID_QUERY");
}
#[test]
@@ -160,8 +174,36 @@ mod tests {
)],
Some(String::from("select count(1) as count from \"tb_a\"")),
);
- let err = export_manifest(&executor).expect_err("export should fail");
- assert!(matches!(err, SqlError::InvalidQuery(_)));
+ assert_sql_error_code(export_manifest(&executor), "ERR_INVALID_QUERY");
+ }
+
+ #[test]
+ fn export_manifest_propagates_table_count_parse_errors() {
+ let schema_rows = serde_json::json!([
+ {
+ "type": "table",
+ "name": "tb_a",
+ "table_name": "tb_a",
+ "sql": "CREATE TABLE tb_a (id TEXT);"
+ }
+ ])
+ .to_string();
+ let executor = MockExecutor::new(
+ vec![
+ (
+ String::from(
+ "select type, name, tbl_name as table_name, sql from sqlite_master",
+ ),
+ schema_rows,
+ ),
+ (
+ String::from("select count(1) as count from \"tb_a\""),
+ String::from("{"),
+ ),
+ ],
+ None,
+ );
+ assert_sql_error_code(export_manifest(&executor), "ERR_SERIALIZATION");
}
#[test]
@@ -178,10 +220,15 @@ mod tests {
let executor = MockExecutor::new(
vec![
(
- String::from("select type, name, tbl_name as table_name, sql from sqlite_master"),
+ String::from(
+ "select type, name, tbl_name as table_name, sql from sqlite_master",
+ ),
schema_rows,
),
- (String::from("select count(1) as count from \"tb_a\""), String::from("[]")),
+ (
+ String::from("select count(1) as count from \"tb_a\""),
+ String::from("[]"),
+ ),
],
None,
);
@@ -192,6 +239,24 @@ mod tests {
}
#[test]
+ fn schema_hash_handles_optional_fields() {
+ let with_all = SchemaEntry {
+ object_type: String::from("table"),
+ name: String::from("tb_a"),
+ table_name: Some(String::from("tb_a")),
+ sql: Some(String::from("CREATE TABLE tb_a (id TEXT);")),
+ };
+ let without_optional = SchemaEntry {
+ object_type: String::from("index"),
+ name: String::from("ix_a"),
+ table_name: None,
+ sql: None,
+ };
+ let hash = schema_hash(&[with_all, without_optional]);
+ assert_eq!(hash.len(), 64);
+ }
+
+ #[test]
fn mock_executor_trait_and_query_paths_are_covered() {
let executor = MockExecutor::new(
vec![(String::from("select 1"), String::from("[{\"count\":1}]"))],
@@ -207,13 +272,12 @@ mod tests {
let matched = executor.query_raw("select 1", "[]").expect("matched query");
assert_eq!(matched, "[{\"count\":1}]");
- let fallback = executor.query_raw("select 2", "[]").expect("fallback query");
+ let fallback = executor
+ .query_raw("select 2", "[]")
+ .expect("fallback query");
assert_eq!(fallback, "[]");
let failing = MockExecutor::new(Vec::new(), Some(String::from("select fail")));
- let err = failing
- .query_raw("select fail", "[]")
- .expect_err("query should fail");
- assert!(matches!(err, SqlError::InvalidQuery(_)));
+ assert_sql_error_code(failing.query_raw("select fail", "[]"), "ERR_INVALID_QUERY");
}
}
diff --git a/crates/replica-db/src/models/farm.rs b/crates/replica-db/src/models/farm.rs
@@ -10,11 +10,11 @@ use serde_json::Value;
const TABLE_NAME: &str = "farm";
-pub fn create<E: SqlExecutor>(
- exec: &E,
+pub fn create(
+ exec: &dyn SqlExecutor,
opts: &IFarmCreate,
) -> Result<IFarmCreateResolve, IError<SqlError>> {
- let field_map = utils::to_object_map(opts)?;
+ let field_map = utils::to_object_map(opts).expect("farm create fields serialize");
let id = utils::uuidv4();
let now = utils::time_created_on();
let meta: [(&str, Value); 3] = [
@@ -23,15 +23,16 @@ pub fn create<E: SqlExecutor>(
("updated_at", Value::from(now.clone())),
];
let (sql, bind_values) = utils::build_insert_query_with_meta(TABLE_NAME, &meta, &field_map);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json =
+ utils::to_params_json(bind_values).expect("farm create bind params serialize");
let _ = exec.exec(&sql, ¶ms_json)?;
let on = FarmQueryBindValues::Id { id: id.clone() };
let result = find_one_by_on(exec, &on)?.ok_or(IError::from(SqlError::NotFound(id.clone())))?;
Ok(IResult { result })
}
-pub fn find_one<E: SqlExecutor>(
- exec: &E,
+pub fn find_one(
+ exec: &dyn SqlExecutor,
opts: &IFarmFindOne,
) -> Result<IFarmFindOneResolve, IError<SqlError>> {
let result = match opts {
@@ -40,39 +41,42 @@ pub fn find_one<E: SqlExecutor>(
Ok(IResult { result })
}
-pub fn find_many<E: SqlExecutor>(
- exec: &E,
+pub fn find_many(
+ exec: &dyn SqlExecutor,
opts: &IFarmFindMany,
) -> Result<IFarmFindManyResolve, IError<SqlError>> {
let results = find_many_filter(exec, &opts.filter)?;
Ok(IResultList { results })
}
-fn find_many_filter<E: SqlExecutor>(
- exec: &E,
+fn find_many_filter(
+ exec: &dyn SqlExecutor,
filter: &Option<IFarmFieldsFilter>,
) -> Result<Vec<Farm>, IError<SqlError>> {
let (sql, bind_values) = utils::build_select_query_with_meta(TABLE_NAME, filter.as_ref());
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json =
+ utils::to_params_json(bind_values).expect("farm find_many bind params serialize");
let json = exec.query_raw(&sql, ¶ms_json)?;
let rows: Vec<Farm> = utils::parse_json(&json)?;
Ok(rows)
}
-fn find_one_by_on<E: SqlExecutor>(
- exec: &E,
+fn find_one_by_on(
+ exec: &dyn SqlExecutor,
on: &FarmQueryBindValues,
) -> Result<Option<Farm>, IError<SqlError>> {
let (column, value) = on.to_filter_param();
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE {column} = ? LIMIT 1;");
- let params_json = utils::to_params_json(vec![value])?;
+ let params_json =
+ utils::to_params_json(vec![value]).expect("farm find_one bind params serialize");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<Farm> = utils::parse_json(&json)?;
Ok(rows.pop())
}
-fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<Farm, IError<SqlError>> {
- let params_json = utils::to_params_json(vec![Value::from(id.to_owned())])?;
+fn select_by_id(exec: &dyn SqlExecutor, id: &str) -> Result<Farm, IError<SqlError>> {
+ let params_json = utils::to_params_json(vec![Value::from(id.to_owned())])
+ .expect("farm select_by_id bind params serialize");
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE id = ?;");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<Farm> = utils::parse_json(&json)?;
@@ -80,11 +84,12 @@ fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<Farm, IError<SqlEr
.ok_or(IError::from(SqlError::NotFound(id.to_owned())))
}
-pub fn update<E: SqlExecutor>(
- exec: &E,
+pub fn update(
+ exec: &dyn SqlExecutor,
opts: &IFarmUpdate,
) -> Result<IFarmUpdateResolve, IError<SqlError>> {
- let mut updates = utils::to_partial_object_map(&opts.fields)?;
+ let mut updates =
+ utils::to_partial_object_map(&opts.fields).expect("farm update fields serialize");
if updates.is_empty() {
return Err(IError::from(SqlError::InvalidArgument(String::from(
"no fields to update",
@@ -113,14 +118,15 @@ pub fn update<E: SqlExecutor>(
"UPDATE {TABLE_NAME} SET {} WHERE id = ?;",
set_parts.join(", ")
);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json =
+ utils::to_params_json(bind_values).expect("farm update bind params serialize");
let _ = exec.exec(&sql, ¶ms_json)?;
let updated = select_by_id(exec, &id_for_lookup)?;
Ok(IResult { result: updated })
}
-pub fn delete<E: SqlExecutor>(
- exec: &E,
+pub fn delete(
+ exec: &dyn SqlExecutor,
opts: &IFarmDelete,
) -> Result<IFarmDeleteResolve, IError<SqlError>> {
let id_for_lookup = match opts {
@@ -133,7 +139,8 @@ pub fn delete<E: SqlExecutor>(
}
},
};
- let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])?;
+ let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])
+ .expect("farm delete bind params serialize");
let sql = format!("DELETE FROM {TABLE_NAME} WHERE id = ?;");
let outcome = exec.exec(&sql, ¶ms_json)?;
if outcome.changes == 0 {
diff --git a/crates/replica-db/src/models/farm_gcs_location.rs b/crates/replica-db/src/models/farm_gcs_location.rs
@@ -12,11 +12,11 @@ use serde_json::Value;
const TABLE_NAME: &str = "farm_gcs_location";
-pub fn create<E: SqlExecutor>(
- exec: &E,
+pub fn create(
+ exec: &dyn SqlExecutor,
opts: &IFarmGcsLocationCreate,
) -> Result<IFarmGcsLocationCreateResolve, IError<SqlError>> {
- let field_map = utils::to_object_map(opts)?;
+ let field_map = utils::to_object_map(opts).expect("serialize object map");
let id = utils::uuidv4();
let now = utils::time_created_on();
let meta: [(&str, Value); 3] = [
@@ -25,15 +25,15 @@ pub fn create<E: SqlExecutor>(
("updated_at", Value::from(now.clone())),
];
let (sql, bind_values) = utils::build_insert_query_with_meta(TABLE_NAME, &meta, &field_map);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let on = FarmGcsLocationQueryBindValues::Id { id: id.clone() };
let result = find_one_by_on(exec, &on)?.ok_or(IError::from(SqlError::NotFound(id.clone())))?;
Ok(IResult { result })
}
-pub fn find_one<E: SqlExecutor>(
- exec: &E,
+pub fn find_one(
+ exec: &dyn SqlExecutor,
opts: &IFarmGcsLocationFindOne,
) -> Result<IFarmGcsLocationFindOneResolve, IError<SqlError>> {
let result = match opts {
@@ -42,39 +42,40 @@ pub fn find_one<E: SqlExecutor>(
Ok(IResult { result })
}
-pub fn find_many<E: SqlExecutor>(
- exec: &E,
+pub fn find_many(
+ exec: &dyn SqlExecutor,
opts: &IFarmGcsLocationFindMany,
) -> Result<IFarmGcsLocationFindManyResolve, IError<SqlError>> {
let results = find_many_filter(exec, &opts.filter)?;
Ok(IResultList { results })
}
-fn find_many_filter<E: SqlExecutor>(
- exec: &E,
+fn find_many_filter(
+ exec: &dyn SqlExecutor,
filter: &Option<IFarmGcsLocationFieldsFilter>,
) -> Result<Vec<FarmGcsLocation>, IError<SqlError>> {
let (sql, bind_values) = utils::build_select_query_with_meta(TABLE_NAME, filter.as_ref());
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let rows: Vec<FarmGcsLocation> = utils::parse_json(&json)?;
Ok(rows)
}
-fn find_one_by_on<E: SqlExecutor>(
- exec: &E,
+fn find_one_by_on(
+ exec: &dyn SqlExecutor,
on: &FarmGcsLocationQueryBindValues,
) -> Result<Option<FarmGcsLocation>, IError<SqlError>> {
let (column, value) = on.to_filter_param();
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE {column} = ? LIMIT 1;");
- let params_json = utils::to_params_json(vec![value])?;
+ let params_json = utils::to_params_json(vec![value]).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<FarmGcsLocation> = utils::parse_json(&json)?;
Ok(rows.pop())
}
-fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<FarmGcsLocation, IError<SqlError>> {
- let params_json = utils::to_params_json(vec![Value::from(id.to_owned())])?;
+fn select_by_id(exec: &dyn SqlExecutor, id: &str) -> Result<FarmGcsLocation, IError<SqlError>> {
+ let params_json =
+ utils::to_params_json(vec![Value::from(id.to_owned())]).expect("serialize bind params");
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE id = ?;");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<FarmGcsLocation> = utils::parse_json(&json)?;
@@ -82,11 +83,12 @@ fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<FarmGcsLocation, I
.ok_or(IError::from(SqlError::NotFound(id.to_owned())))
}
-pub fn update<E: SqlExecutor>(
- exec: &E,
+pub fn update(
+ exec: &dyn SqlExecutor,
opts: &IFarmGcsLocationUpdate,
) -> Result<IFarmGcsLocationUpdateResolve, IError<SqlError>> {
- let mut updates = utils::to_partial_object_map(&opts.fields)?;
+ let mut updates =
+ utils::to_partial_object_map(&opts.fields).expect("serialize partial object map");
if updates.is_empty() {
return Err(IError::from(SqlError::InvalidArgument(String::from(
"no fields to update",
@@ -115,14 +117,14 @@ pub fn update<E: SqlExecutor>(
"UPDATE {TABLE_NAME} SET {} WHERE id = ?;",
set_parts.join(", ")
);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let updated = select_by_id(exec, &id_for_lookup)?;
Ok(IResult { result: updated })
}
-pub fn delete<E: SqlExecutor>(
- exec: &E,
+pub fn delete(
+ exec: &dyn SqlExecutor,
opts: &IFarmGcsLocationDelete,
) -> Result<IFarmGcsLocationDeleteResolve, IError<SqlError>> {
let id_for_lookup = match opts {
@@ -135,7 +137,8 @@ pub fn delete<E: SqlExecutor>(
}
},
};
- let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])?;
+ let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])
+ .expect("serialize bind params");
let sql = format!("DELETE FROM {TABLE_NAME} WHERE id = ?;");
let outcome = exec.exec(&sql, ¶ms_json)?;
if outcome.changes == 0 {
diff --git a/crates/replica-db/src/models/farm_member.rs b/crates/replica-db/src/models/farm_member.rs
@@ -11,11 +11,11 @@ use serde_json::Value;
const TABLE_NAME: &str = "farm_member";
-pub fn create<E: SqlExecutor>(
- exec: &E,
+pub fn create(
+ exec: &dyn SqlExecutor,
opts: &IFarmMemberCreate,
) -> Result<IFarmMemberCreateResolve, IError<SqlError>> {
- let field_map = utils::to_object_map(opts)?;
+ let field_map = utils::to_object_map(opts).expect("serialize object map");
let id = utils::uuidv4();
let now = utils::time_created_on();
let meta: [(&str, Value); 3] = [
@@ -24,15 +24,15 @@ pub fn create<E: SqlExecutor>(
("updated_at", Value::from(now.clone())),
];
let (sql, bind_values) = utils::build_insert_query_with_meta(TABLE_NAME, &meta, &field_map);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let on = FarmMemberQueryBindValues::Id { id: id.clone() };
let result = find_one_by_on(exec, &on)?.ok_or(IError::from(SqlError::NotFound(id.clone())))?;
Ok(IResult { result })
}
-pub fn find_one<E: SqlExecutor>(
- exec: &E,
+pub fn find_one(
+ exec: &dyn SqlExecutor,
opts: &IFarmMemberFindOne,
) -> Result<IFarmMemberFindOneResolve, IError<SqlError>> {
let result = match opts {
@@ -41,39 +41,40 @@ pub fn find_one<E: SqlExecutor>(
Ok(IResult { result })
}
-pub fn find_many<E: SqlExecutor>(
- exec: &E,
+pub fn find_many(
+ exec: &dyn SqlExecutor,
opts: &IFarmMemberFindMany,
) -> Result<IFarmMemberFindManyResolve, IError<SqlError>> {
let results = find_many_filter(exec, &opts.filter)?;
Ok(IResultList { results })
}
-fn find_many_filter<E: SqlExecutor>(
- exec: &E,
+fn find_many_filter(
+ exec: &dyn SqlExecutor,
filter: &Option<IFarmMemberFieldsFilter>,
) -> Result<Vec<FarmMember>, IError<SqlError>> {
let (sql, bind_values) = utils::build_select_query_with_meta(TABLE_NAME, filter.as_ref());
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let rows: Vec<FarmMember> = utils::parse_json(&json)?;
Ok(rows)
}
-fn find_one_by_on<E: SqlExecutor>(
- exec: &E,
+fn find_one_by_on(
+ exec: &dyn SqlExecutor,
on: &FarmMemberQueryBindValues,
) -> Result<Option<FarmMember>, IError<SqlError>> {
let (column, value) = on.to_filter_param();
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE {column} = ? LIMIT 1;");
- let params_json = utils::to_params_json(vec![value])?;
+ let params_json = utils::to_params_json(vec![value]).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<FarmMember> = utils::parse_json(&json)?;
Ok(rows.pop())
}
-fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<FarmMember, IError<SqlError>> {
- let params_json = utils::to_params_json(vec![Value::from(id.to_owned())])?;
+fn select_by_id(exec: &dyn SqlExecutor, id: &str) -> Result<FarmMember, IError<SqlError>> {
+ let params_json =
+ utils::to_params_json(vec![Value::from(id.to_owned())]).expect("serialize bind params");
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE id = ?;");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<FarmMember> = utils::parse_json(&json)?;
@@ -81,11 +82,12 @@ fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<FarmMember, IError
.ok_or(IError::from(SqlError::NotFound(id.to_owned())))
}
-pub fn update<E: SqlExecutor>(
- exec: &E,
+pub fn update(
+ exec: &dyn SqlExecutor,
opts: &IFarmMemberUpdate,
) -> Result<IFarmMemberUpdateResolve, IError<SqlError>> {
- let mut updates = utils::to_partial_object_map(&opts.fields)?;
+ let mut updates =
+ utils::to_partial_object_map(&opts.fields).expect("serialize partial object map");
if updates.is_empty() {
return Err(IError::from(SqlError::InvalidArgument(String::from(
"no fields to update",
@@ -114,14 +116,14 @@ pub fn update<E: SqlExecutor>(
"UPDATE {TABLE_NAME} SET {} WHERE id = ?;",
set_parts.join(", ")
);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let updated = select_by_id(exec, &id_for_lookup)?;
Ok(IResult { result: updated })
}
-pub fn delete<E: SqlExecutor>(
- exec: &E,
+pub fn delete(
+ exec: &dyn SqlExecutor,
opts: &IFarmMemberDelete,
) -> Result<IFarmMemberDeleteResolve, IError<SqlError>> {
let id_for_lookup = match opts {
@@ -134,7 +136,8 @@ pub fn delete<E: SqlExecutor>(
}
},
};
- let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])?;
+ let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])
+ .expect("serialize bind params");
let sql = format!("DELETE FROM {TABLE_NAME} WHERE id = ?;");
let outcome = exec.exec(&sql, ¶ms_json)?;
if outcome.changes == 0 {
diff --git a/crates/replica-db/src/models/farm_member_claim.rs b/crates/replica-db/src/models/farm_member_claim.rs
@@ -12,11 +12,11 @@ use serde_json::Value;
const TABLE_NAME: &str = "farm_member_claim";
-pub fn create<E: SqlExecutor>(
- exec: &E,
+pub fn create(
+ exec: &dyn SqlExecutor,
opts: &IFarmMemberClaimCreate,
) -> Result<IFarmMemberClaimCreateResolve, IError<SqlError>> {
- let field_map = utils::to_object_map(opts)?;
+ let field_map = utils::to_object_map(opts).expect("serialize object map");
let id = utils::uuidv4();
let now = utils::time_created_on();
let meta: [(&str, Value); 3] = [
@@ -25,15 +25,15 @@ pub fn create<E: SqlExecutor>(
("updated_at", Value::from(now.clone())),
];
let (sql, bind_values) = utils::build_insert_query_with_meta(TABLE_NAME, &meta, &field_map);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let on = FarmMemberClaimQueryBindValues::Id { id: id.clone() };
let result = find_one_by_on(exec, &on)?.ok_or(IError::from(SqlError::NotFound(id.clone())))?;
Ok(IResult { result })
}
-pub fn find_one<E: SqlExecutor>(
- exec: &E,
+pub fn find_one(
+ exec: &dyn SqlExecutor,
opts: &IFarmMemberClaimFindOne,
) -> Result<IFarmMemberClaimFindOneResolve, IError<SqlError>> {
let result = match opts {
@@ -42,39 +42,40 @@ pub fn find_one<E: SqlExecutor>(
Ok(IResult { result })
}
-pub fn find_many<E: SqlExecutor>(
- exec: &E,
+pub fn find_many(
+ exec: &dyn SqlExecutor,
opts: &IFarmMemberClaimFindMany,
) -> Result<IFarmMemberClaimFindManyResolve, IError<SqlError>> {
let results = find_many_filter(exec, &opts.filter)?;
Ok(IResultList { results })
}
-fn find_many_filter<E: SqlExecutor>(
- exec: &E,
+fn find_many_filter(
+ exec: &dyn SqlExecutor,
filter: &Option<IFarmMemberClaimFieldsFilter>,
) -> Result<Vec<FarmMemberClaim>, IError<SqlError>> {
let (sql, bind_values) = utils::build_select_query_with_meta(TABLE_NAME, filter.as_ref());
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let rows: Vec<FarmMemberClaim> = utils::parse_json(&json)?;
Ok(rows)
}
-fn find_one_by_on<E: SqlExecutor>(
- exec: &E,
+fn find_one_by_on(
+ exec: &dyn SqlExecutor,
on: &FarmMemberClaimQueryBindValues,
) -> Result<Option<FarmMemberClaim>, IError<SqlError>> {
let (column, value) = on.to_filter_param();
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE {column} = ? LIMIT 1;");
- let params_json = utils::to_params_json(vec![value])?;
+ let params_json = utils::to_params_json(vec![value]).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<FarmMemberClaim> = utils::parse_json(&json)?;
Ok(rows.pop())
}
-fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<FarmMemberClaim, IError<SqlError>> {
- let params_json = utils::to_params_json(vec![Value::from(id.to_owned())])?;
+fn select_by_id(exec: &dyn SqlExecutor, id: &str) -> Result<FarmMemberClaim, IError<SqlError>> {
+ let params_json =
+ utils::to_params_json(vec![Value::from(id.to_owned())]).expect("serialize bind params");
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE id = ?;");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<FarmMemberClaim> = utils::parse_json(&json)?;
@@ -82,11 +83,12 @@ fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<FarmMemberClaim, I
.ok_or(IError::from(SqlError::NotFound(id.to_owned())))
}
-pub fn update<E: SqlExecutor>(
- exec: &E,
+pub fn update(
+ exec: &dyn SqlExecutor,
opts: &IFarmMemberClaimUpdate,
) -> Result<IFarmMemberClaimUpdateResolve, IError<SqlError>> {
- let mut updates = utils::to_partial_object_map(&opts.fields)?;
+ let mut updates =
+ utils::to_partial_object_map(&opts.fields).expect("serialize partial object map");
if updates.is_empty() {
return Err(IError::from(SqlError::InvalidArgument(String::from(
"no fields to update",
@@ -115,14 +117,14 @@ pub fn update<E: SqlExecutor>(
"UPDATE {TABLE_NAME} SET {} WHERE id = ?;",
set_parts.join(", ")
);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let updated = select_by_id(exec, &id_for_lookup)?;
Ok(IResult { result: updated })
}
-pub fn delete<E: SqlExecutor>(
- exec: &E,
+pub fn delete(
+ exec: &dyn SqlExecutor,
opts: &IFarmMemberClaimDelete,
) -> Result<IFarmMemberClaimDeleteResolve, IError<SqlError>> {
let id_for_lookup = match opts {
@@ -135,7 +137,8 @@ pub fn delete<E: SqlExecutor>(
}
},
};
- let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])?;
+ let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])
+ .expect("serialize bind params");
let sql = format!("DELETE FROM {TABLE_NAME} WHERE id = ?;");
let outcome = exec.exec(&sql, ¶ms_json)?;
if outcome.changes == 0 {
diff --git a/crates/replica-db/src/models/farm_tag.rs b/crates/replica-db/src/models/farm_tag.rs
@@ -10,11 +10,11 @@ use serde_json::Value;
const TABLE_NAME: &str = "farm_tag";
-pub fn create<E: SqlExecutor>(
- exec: &E,
+pub fn create(
+ exec: &dyn SqlExecutor,
opts: &IFarmTagCreate,
) -> Result<IFarmTagCreateResolve, IError<SqlError>> {
- let field_map = utils::to_object_map(opts)?;
+ let field_map = utils::to_object_map(opts).expect("serialize object map");
let id = utils::uuidv4();
let now = utils::time_created_on();
let meta: [(&str, Value); 3] = [
@@ -23,15 +23,15 @@ pub fn create<E: SqlExecutor>(
("updated_at", Value::from(now.clone())),
];
let (sql, bind_values) = utils::build_insert_query_with_meta(TABLE_NAME, &meta, &field_map);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let on = FarmTagQueryBindValues::Id { id: id.clone() };
let result = find_one_by_on(exec, &on)?.ok_or(IError::from(SqlError::NotFound(id.clone())))?;
Ok(IResult { result })
}
-pub fn find_one<E: SqlExecutor>(
- exec: &E,
+pub fn find_one(
+ exec: &dyn SqlExecutor,
opts: &IFarmTagFindOne,
) -> Result<IFarmTagFindOneResolve, IError<SqlError>> {
let result = match opts {
@@ -40,39 +40,40 @@ pub fn find_one<E: SqlExecutor>(
Ok(IResult { result })
}
-pub fn find_many<E: SqlExecutor>(
- exec: &E,
+pub fn find_many(
+ exec: &dyn SqlExecutor,
opts: &IFarmTagFindMany,
) -> Result<IFarmTagFindManyResolve, IError<SqlError>> {
let results = find_many_filter(exec, &opts.filter)?;
Ok(IResultList { results })
}
-fn find_many_filter<E: SqlExecutor>(
- exec: &E,
+fn find_many_filter(
+ exec: &dyn SqlExecutor,
filter: &Option<IFarmTagFieldsFilter>,
) -> Result<Vec<FarmTag>, IError<SqlError>> {
let (sql, bind_values) = utils::build_select_query_with_meta(TABLE_NAME, filter.as_ref());
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let rows: Vec<FarmTag> = utils::parse_json(&json)?;
Ok(rows)
}
-fn find_one_by_on<E: SqlExecutor>(
- exec: &E,
+fn find_one_by_on(
+ exec: &dyn SqlExecutor,
on: &FarmTagQueryBindValues,
) -> Result<Option<FarmTag>, IError<SqlError>> {
let (column, value) = on.to_filter_param();
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE {column} = ? LIMIT 1;");
- let params_json = utils::to_params_json(vec![value])?;
+ let params_json = utils::to_params_json(vec![value]).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<FarmTag> = utils::parse_json(&json)?;
Ok(rows.pop())
}
-fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<FarmTag, IError<SqlError>> {
- let params_json = utils::to_params_json(vec![Value::from(id.to_owned())])?;
+fn select_by_id(exec: &dyn SqlExecutor, id: &str) -> Result<FarmTag, IError<SqlError>> {
+ let params_json =
+ utils::to_params_json(vec![Value::from(id.to_owned())]).expect("serialize bind params");
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE id = ?;");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<FarmTag> = utils::parse_json(&json)?;
@@ -80,11 +81,12 @@ fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<FarmTag, IError<Sq
.ok_or(IError::from(SqlError::NotFound(id.to_owned())))
}
-pub fn update<E: SqlExecutor>(
- exec: &E,
+pub fn update(
+ exec: &dyn SqlExecutor,
opts: &IFarmTagUpdate,
) -> Result<IFarmTagUpdateResolve, IError<SqlError>> {
- let mut updates = utils::to_partial_object_map(&opts.fields)?;
+ let mut updates =
+ utils::to_partial_object_map(&opts.fields).expect("serialize partial object map");
if updates.is_empty() {
return Err(IError::from(SqlError::InvalidArgument(String::from(
"no fields to update",
@@ -113,14 +115,14 @@ pub fn update<E: SqlExecutor>(
"UPDATE {TABLE_NAME} SET {} WHERE id = ?;",
set_parts.join(", ")
);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let updated = select_by_id(exec, &id_for_lookup)?;
Ok(IResult { result: updated })
}
-pub fn delete<E: SqlExecutor>(
- exec: &E,
+pub fn delete(
+ exec: &dyn SqlExecutor,
opts: &IFarmTagDelete,
) -> Result<IFarmTagDeleteResolve, IError<SqlError>> {
let id_for_lookup = match opts {
@@ -133,7 +135,8 @@ pub fn delete<E: SqlExecutor>(
}
},
};
- let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])?;
+ let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])
+ .expect("serialize bind params");
let sql = format!("DELETE FROM {TABLE_NAME} WHERE id = ?;");
let outcome = exec.exec(&sql, ¶ms_json)?;
if outcome.changes == 0 {
diff --git a/crates/replica-db/src/models/gcs_location.rs b/crates/replica-db/src/models/gcs_location.rs
@@ -11,11 +11,11 @@ use serde_json::Value;
const TABLE_NAME: &str = "gcs_location";
-pub fn create<E: SqlExecutor>(
- exec: &E,
+pub fn create(
+ exec: &dyn SqlExecutor,
opts: &IGcsLocationCreate,
) -> Result<IGcsLocationCreateResolve, IError<SqlError>> {
- let field_map = utils::to_object_map(opts)?;
+ let field_map = utils::to_object_map(opts).expect("serialize object map");
let id = utils::uuidv4();
let now = utils::time_created_on();
let meta: [(&str, Value); 3] = [
@@ -24,15 +24,15 @@ pub fn create<E: SqlExecutor>(
("updated_at", Value::from(now.clone())),
];
let (sql, bind_values) = utils::build_insert_query_with_meta(TABLE_NAME, &meta, &field_map);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let on = GcsLocationQueryBindValues::Id { id: id.clone() };
let result = find_one_by_on(exec, &on)?.ok_or(IError::from(SqlError::NotFound(id.clone())))?;
Ok(IResult { result })
}
-pub fn find_one<E: SqlExecutor>(
- exec: &E,
+pub fn find_one(
+ exec: &dyn SqlExecutor,
opts: &IGcsLocationFindOne,
) -> Result<IGcsLocationFindOneResolve, IError<SqlError>> {
let result = match opts {
@@ -42,8 +42,8 @@ pub fn find_one<E: SqlExecutor>(
Ok(IResult { result })
}
-pub fn find_many<E: SqlExecutor>(
- exec: &E,
+pub fn find_many(
+ exec: &dyn SqlExecutor,
opts: &IGcsLocationFindMany,
) -> Result<IGcsLocationFindManyResolve, IError<SqlError>> {
let results = match opts {
@@ -53,24 +53,24 @@ pub fn find_many<E: SqlExecutor>(
Ok(IResultList { results })
}
-fn find_many_filter<E: SqlExecutor>(
- exec: &E,
+fn find_many_filter(
+ exec: &dyn SqlExecutor,
filter: &Option<IGcsLocationFieldsFilter>,
) -> Result<Vec<GcsLocation>, IError<SqlError>> {
let (sql, bind_values) = utils::build_select_query_with_meta(TABLE_NAME, filter.as_ref());
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let rows: Vec<GcsLocation> = utils::parse_json(&json)?;
Ok(rows)
}
-fn find_one_by_on<E: SqlExecutor>(
- exec: &E,
+fn find_one_by_on(
+ exec: &dyn SqlExecutor,
on: &GcsLocationQueryBindValues,
) -> Result<Option<GcsLocation>, IError<SqlError>> {
let (column, value) = on.to_filter_param();
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE {column} = ? LIMIT 1;");
- let params_json = utils::to_params_json(vec![value])?;
+ let params_json = utils::to_params_json(vec![value]).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<GcsLocation> = utils::parse_json(&json)?;
Ok(rows.pop())
@@ -105,32 +105,33 @@ fn rel_query(rel: &GcsLocationFindManyRel) -> (&'static str, Vec<Value>) {
}
}
-fn find_one_by_rel<E: SqlExecutor>(
- exec: &E,
+fn find_one_by_rel(
+ exec: &dyn SqlExecutor,
rel: &GcsLocationFindManyRel,
) -> Result<Option<GcsLocation>, IError<SqlError>> {
let (sql, bind_values) = rel_query(rel);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let sql = format!("{sql} LIMIT 1;");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<GcsLocation> = utils::parse_json(&json)?;
Ok(rows.pop())
}
-fn find_many_by_rel<E: SqlExecutor>(
- exec: &E,
+fn find_many_by_rel(
+ exec: &dyn SqlExecutor,
rel: &GcsLocationFindManyRel,
) -> Result<Vec<GcsLocation>, IError<SqlError>> {
let (sql, bind_values) = rel_query(rel);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let sql = format!("{sql};");
let json = exec.query_raw(&sql, ¶ms_json)?;
let rows: Vec<GcsLocation> = utils::parse_json(&json)?;
Ok(rows)
}
-fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<GcsLocation, IError<SqlError>> {
- let params_json = utils::to_params_json(vec![Value::from(id.to_owned())])?;
+fn select_by_id(exec: &dyn SqlExecutor, id: &str) -> Result<GcsLocation, IError<SqlError>> {
+ let params_json =
+ utils::to_params_json(vec![Value::from(id.to_owned())]).expect("serialize bind params");
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE id = ?;");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<GcsLocation> = utils::parse_json(&json)?;
@@ -138,11 +139,12 @@ fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<GcsLocation, IErro
.ok_or(IError::from(SqlError::NotFound(id.to_owned())))
}
-pub fn update<E: SqlExecutor>(
- exec: &E,
+pub fn update(
+ exec: &dyn SqlExecutor,
opts: &IGcsLocationUpdate,
) -> Result<IGcsLocationUpdateResolve, IError<SqlError>> {
- let mut updates = utils::to_partial_object_map(&opts.fields)?;
+ let mut updates =
+ utils::to_partial_object_map(&opts.fields).expect("serialize partial object map");
if updates.is_empty() {
return Err(IError::from(SqlError::InvalidArgument(String::from(
"no fields to update",
@@ -171,14 +173,14 @@ pub fn update<E: SqlExecutor>(
"UPDATE {TABLE_NAME} SET {} WHERE id = ?;",
set_parts.join(", ")
);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let updated = select_by_id(exec, &id_for_lookup)?;
Ok(IResult { result: updated })
}
-pub fn delete<E: SqlExecutor>(
- exec: &E,
+pub fn delete(
+ exec: &dyn SqlExecutor,
opts: &IGcsLocationDelete,
) -> Result<IGcsLocationDeleteResolve, IError<SqlError>> {
let id_for_lookup = match opts {
@@ -196,7 +198,8 @@ pub fn delete<E: SqlExecutor>(
model.id
}
};
- let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])?;
+ let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])
+ .expect("serialize bind params");
let sql = format!("DELETE FROM {TABLE_NAME} WHERE id = ?;");
let outcome = exec.exec(&sql, ¶ms_json)?;
if outcome.changes == 0 {
diff --git a/crates/replica-db/src/models/log_error.rs b/crates/replica-db/src/models/log_error.rs
@@ -11,11 +11,11 @@ use serde_json::Value;
const TABLE_NAME: &str = "log_error";
-pub fn create<E: SqlExecutor>(
- exec: &E,
+pub fn create(
+ exec: &dyn SqlExecutor,
opts: &ILogErrorCreate,
) -> Result<ILogErrorCreateResolve, IError<SqlError>> {
- let field_map = utils::to_object_map(opts)?;
+ let field_map = utils::to_object_map(opts).expect("serialize object map");
let id = utils::uuidv4();
let now = utils::time_created_on();
let meta: [(&str, Value); 3] = [
@@ -24,15 +24,15 @@ pub fn create<E: SqlExecutor>(
("updated_at", Value::from(now.clone())),
];
let (sql, bind_values) = utils::build_insert_query_with_meta(TABLE_NAME, &meta, &field_map);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let on = LogErrorQueryBindValues::Id { id: id.clone() };
let result = find_one_by_on(exec, &on)?.ok_or(IError::from(SqlError::NotFound(id.clone())))?;
Ok(IResult { result })
}
-pub fn find_one<E: SqlExecutor>(
- exec: &E,
+pub fn find_one(
+ exec: &dyn SqlExecutor,
opts: &ILogErrorFindOne,
) -> Result<ILogErrorFindOneResolve, IError<SqlError>> {
let result = match opts {
@@ -41,39 +41,40 @@ pub fn find_one<E: SqlExecutor>(
Ok(IResult { result })
}
-pub fn find_many<E: SqlExecutor>(
- exec: &E,
+pub fn find_many(
+ exec: &dyn SqlExecutor,
opts: &ILogErrorFindMany,
) -> Result<ILogErrorFindManyResolve, IError<SqlError>> {
let results = find_many_filter(exec, &opts.filter)?;
Ok(IResultList { results })
}
-fn find_many_filter<E: SqlExecutor>(
- exec: &E,
+fn find_many_filter(
+ exec: &dyn SqlExecutor,
filter: &Option<ILogErrorFieldsFilter>,
) -> Result<Vec<LogError>, IError<SqlError>> {
let (sql, bind_values) = utils::build_select_query_with_meta(TABLE_NAME, filter.as_ref());
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let rows: Vec<LogError> = utils::parse_json(&json)?;
Ok(rows)
}
-fn find_one_by_on<E: SqlExecutor>(
- exec: &E,
+fn find_one_by_on(
+ exec: &dyn SqlExecutor,
on: &LogErrorQueryBindValues,
) -> Result<Option<LogError>, IError<SqlError>> {
let (column, value) = on.to_filter_param();
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE {column} = ? LIMIT 1;");
- let params_json = utils::to_params_json(vec![value])?;
+ let params_json = utils::to_params_json(vec![value]).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<LogError> = utils::parse_json(&json)?;
Ok(rows.pop())
}
-fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<LogError, IError<SqlError>> {
- let params_json = utils::to_params_json(vec![Value::from(id.to_owned())])?;
+fn select_by_id(exec: &dyn SqlExecutor, id: &str) -> Result<LogError, IError<SqlError>> {
+ let params_json =
+ utils::to_params_json(vec![Value::from(id.to_owned())]).expect("serialize bind params");
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE id = ?;");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<LogError> = utils::parse_json(&json)?;
@@ -81,11 +82,12 @@ fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<LogError, IError<S
.ok_or(IError::from(SqlError::NotFound(id.to_owned())))
}
-pub fn update<E: SqlExecutor>(
- exec: &E,
+pub fn update(
+ exec: &dyn SqlExecutor,
opts: &ILogErrorUpdate,
) -> Result<ILogErrorUpdateResolve, IError<SqlError>> {
- let mut updates = utils::to_partial_object_map(&opts.fields)?;
+ let mut updates =
+ utils::to_partial_object_map(&opts.fields).expect("serialize partial object map");
if updates.is_empty() {
return Err(IError::from(SqlError::InvalidArgument(String::from(
"no fields to update",
@@ -114,14 +116,14 @@ pub fn update<E: SqlExecutor>(
"UPDATE {TABLE_NAME} SET {} WHERE id = ?;",
set_parts.join(", ")
);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let updated = select_by_id(exec, &id_for_lookup)?;
Ok(IResult { result: updated })
}
-pub fn delete<E: SqlExecutor>(
- exec: &E,
+pub fn delete(
+ exec: &dyn SqlExecutor,
opts: &ILogErrorDelete,
) -> Result<ILogErrorDeleteResolve, IError<SqlError>> {
let id_for_lookup = match opts {
@@ -134,7 +136,8 @@ pub fn delete<E: SqlExecutor>(
}
},
};
- let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])?;
+ let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])
+ .expect("serialize bind params");
let sql = format!("DELETE FROM {TABLE_NAME} WHERE id = ?;");
let outcome = exec.exec(&sql, ¶ms_json)?;
if outcome.changes == 0 {
diff --git a/crates/replica-db/src/models/media_image.rs b/crates/replica-db/src/models/media_image.rs
@@ -11,11 +11,11 @@ use serde_json::Value;
const TABLE_NAME: &str = "media_image";
-pub fn create<E: SqlExecutor>(
- exec: &E,
+pub fn create(
+ exec: &dyn SqlExecutor,
opts: &IMediaImageCreate,
) -> Result<IMediaImageCreateResolve, IError<SqlError>> {
- let field_map = utils::to_object_map(opts)?;
+ let field_map = utils::to_object_map(opts).expect("serialize object map");
let id = utils::uuidv4();
let now = utils::time_created_on();
let meta: [(&str, Value); 3] = [
@@ -24,15 +24,15 @@ pub fn create<E: SqlExecutor>(
("updated_at", Value::from(now.clone())),
];
let (sql, bind_values) = utils::build_insert_query_with_meta(TABLE_NAME, &meta, &field_map);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let on = MediaImageQueryBindValues::Id { id: id.clone() };
let result = find_one_by_on(exec, &on)?.ok_or(IError::from(SqlError::NotFound(id.clone())))?;
Ok(IResult { result })
}
-pub fn find_one<E: SqlExecutor>(
- exec: &E,
+pub fn find_one(
+ exec: &dyn SqlExecutor,
opts: &IMediaImageFindOne,
) -> Result<IMediaImageFindOneResolve, IError<SqlError>> {
let result = match opts {
@@ -42,8 +42,8 @@ pub fn find_one<E: SqlExecutor>(
Ok(IResult { result })
}
-pub fn find_many<E: SqlExecutor>(
- exec: &E,
+pub fn find_many(
+ exec: &dyn SqlExecutor,
opts: &IMediaImageFindMany,
) -> Result<IMediaImageFindManyResolve, IError<SqlError>> {
let results = match opts {
@@ -53,24 +53,24 @@ pub fn find_many<E: SqlExecutor>(
Ok(IResultList { results })
}
-fn find_many_filter<E: SqlExecutor>(
- exec: &E,
+fn find_many_filter(
+ exec: &dyn SqlExecutor,
filter: &Option<IMediaImageFieldsFilter>,
) -> Result<Vec<MediaImage>, IError<SqlError>> {
let (sql, bind_values) = utils::build_select_query_with_meta(TABLE_NAME, filter.as_ref());
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let rows: Vec<MediaImage> = utils::parse_json(&json)?;
Ok(rows)
}
-fn find_one_by_on<E: SqlExecutor>(
- exec: &E,
+fn find_one_by_on(
+ exec: &dyn SqlExecutor,
on: &MediaImageQueryBindValues,
) -> Result<Option<MediaImage>, IError<SqlError>> {
let (column, value) = on.to_filter_param();
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE {column} = ? LIMIT 1;");
- let params_json = utils::to_params_json(vec![value])?;
+ let params_json = utils::to_params_json(vec![value]).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<MediaImage> = utils::parse_json(&json)?;
Ok(rows.pop())
@@ -89,32 +89,33 @@ fn rel_query(rel: &MediaImageFindManyRel) -> (&'static str, Vec<Value>) {
}
}
-fn find_one_by_rel<E: SqlExecutor>(
- exec: &E,
+fn find_one_by_rel(
+ exec: &dyn SqlExecutor,
rel: &MediaImageFindManyRel,
) -> Result<Option<MediaImage>, IError<SqlError>> {
let (sql, bind_values) = rel_query(rel);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let sql = format!("{sql} LIMIT 1;");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<MediaImage> = utils::parse_json(&json)?;
Ok(rows.pop())
}
-fn find_many_by_rel<E: SqlExecutor>(
- exec: &E,
+fn find_many_by_rel(
+ exec: &dyn SqlExecutor,
rel: &MediaImageFindManyRel,
) -> Result<Vec<MediaImage>, IError<SqlError>> {
let (sql, bind_values) = rel_query(rel);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let sql = format!("{sql};");
let json = exec.query_raw(&sql, ¶ms_json)?;
let rows: Vec<MediaImage> = utils::parse_json(&json)?;
Ok(rows)
}
-fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<MediaImage, IError<SqlError>> {
- let params_json = utils::to_params_json(vec![Value::from(id.to_owned())])?;
+fn select_by_id(exec: &dyn SqlExecutor, id: &str) -> Result<MediaImage, IError<SqlError>> {
+ let params_json =
+ utils::to_params_json(vec![Value::from(id.to_owned())]).expect("serialize bind params");
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE id = ?;");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<MediaImage> = utils::parse_json(&json)?;
@@ -122,11 +123,12 @@ fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<MediaImage, IError
.ok_or(IError::from(SqlError::NotFound(id.to_owned())))
}
-pub fn update<E: SqlExecutor>(
- exec: &E,
+pub fn update(
+ exec: &dyn SqlExecutor,
opts: &IMediaImageUpdate,
) -> Result<IMediaImageUpdateResolve, IError<SqlError>> {
- let mut updates = utils::to_partial_object_map(&opts.fields)?;
+ let mut updates =
+ utils::to_partial_object_map(&opts.fields).expect("serialize partial object map");
if updates.is_empty() {
return Err(IError::from(SqlError::InvalidArgument(String::from(
"no fields to update",
@@ -155,14 +157,14 @@ pub fn update<E: SqlExecutor>(
"UPDATE {TABLE_NAME} SET {} WHERE id = ?;",
set_parts.join(", ")
);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let updated = select_by_id(exec, &id_for_lookup)?;
Ok(IResult { result: updated })
}
-pub fn delete<E: SqlExecutor>(
- exec: &E,
+pub fn delete(
+ exec: &dyn SqlExecutor,
opts: &IMediaImageDelete,
) -> Result<IMediaImageDeleteResolve, IError<SqlError>> {
let id_for_lookup = match opts {
@@ -180,7 +182,8 @@ pub fn delete<E: SqlExecutor>(
model.id
}
};
- let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])?;
+ let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])
+ .expect("serialize bind params");
let sql = format!("DELETE FROM {TABLE_NAME} WHERE id = ?;");
let outcome = exec.exec(&sql, ¶ms_json)?;
if outcome.changes == 0 {
diff --git a/crates/replica-db/src/models/nostr_event_state.rs b/crates/replica-db/src/models/nostr_event_state.rs
@@ -12,11 +12,11 @@ use serde_json::Value;
const TABLE_NAME: &str = "nostr_event_state";
-pub fn create<E: SqlExecutor>(
- exec: &E,
+pub fn create(
+ exec: &dyn SqlExecutor,
opts: &INostrEventStateCreate,
) -> Result<INostrEventStateCreateResolve, IError<SqlError>> {
- let field_map = utils::to_object_map(opts)?;
+ let field_map = utils::to_object_map(opts).expect("serialize object map");
let id = utils::uuidv4();
let now = utils::time_created_on();
let meta: [(&str, Value); 3] = [
@@ -25,15 +25,15 @@ pub fn create<E: SqlExecutor>(
("updated_at", Value::from(now.clone())),
];
let (sql, bind_values) = utils::build_insert_query_with_meta(TABLE_NAME, &meta, &field_map);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let on = NostrEventStateQueryBindValues::Id { id: id.clone() };
let result = find_one_by_on(exec, &on)?.ok_or(IError::from(SqlError::NotFound(id.clone())))?;
Ok(IResult { result })
}
-pub fn find_one<E: SqlExecutor>(
- exec: &E,
+pub fn find_one(
+ exec: &dyn SqlExecutor,
opts: &INostrEventStateFindOne,
) -> Result<INostrEventStateFindOneResolve, IError<SqlError>> {
let result = match opts {
@@ -42,39 +42,40 @@ pub fn find_one<E: SqlExecutor>(
Ok(IResult { result })
}
-pub fn find_many<E: SqlExecutor>(
- exec: &E,
+pub fn find_many(
+ exec: &dyn SqlExecutor,
opts: &INostrEventStateFindMany,
) -> Result<INostrEventStateFindManyResolve, IError<SqlError>> {
let results = find_many_filter(exec, &opts.filter)?;
Ok(IResultList { results })
}
-fn find_many_filter<E: SqlExecutor>(
- exec: &E,
+fn find_many_filter(
+ exec: &dyn SqlExecutor,
filter: &Option<INostrEventStateFieldsFilter>,
) -> Result<Vec<NostrEventState>, IError<SqlError>> {
let (sql, bind_values) = utils::build_select_query_with_meta(TABLE_NAME, filter.as_ref());
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let rows: Vec<NostrEventState> = utils::parse_json(&json)?;
Ok(rows)
}
-fn find_one_by_on<E: SqlExecutor>(
- exec: &E,
+fn find_one_by_on(
+ exec: &dyn SqlExecutor,
on: &NostrEventStateQueryBindValues,
) -> Result<Option<NostrEventState>, IError<SqlError>> {
let (column, value) = on.to_filter_param();
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE {column} = ? LIMIT 1;");
- let params_json = utils::to_params_json(vec![value])?;
+ let params_json = utils::to_params_json(vec![value]).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<NostrEventState> = utils::parse_json(&json)?;
Ok(rows.pop())
}
-fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<NostrEventState, IError<SqlError>> {
- let params_json = utils::to_params_json(vec![Value::from(id.to_owned())])?;
+fn select_by_id(exec: &dyn SqlExecutor, id: &str) -> Result<NostrEventState, IError<SqlError>> {
+ let params_json =
+ utils::to_params_json(vec![Value::from(id.to_owned())]).expect("serialize bind params");
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE id = ?;");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<NostrEventState> = utils::parse_json(&json)?;
@@ -82,11 +83,12 @@ fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<NostrEventState, I
.ok_or(IError::from(SqlError::NotFound(id.to_owned())))
}
-pub fn update<E: SqlExecutor>(
- exec: &E,
+pub fn update(
+ exec: &dyn SqlExecutor,
opts: &INostrEventStateUpdate,
) -> Result<INostrEventStateUpdateResolve, IError<SqlError>> {
- let mut updates = utils::to_partial_object_map(&opts.fields)?;
+ let mut updates =
+ utils::to_partial_object_map(&opts.fields).expect("serialize partial object map");
if updates.is_empty() {
return Err(IError::from(SqlError::InvalidArgument(String::from(
"no fields to update",
@@ -115,14 +117,14 @@ pub fn update<E: SqlExecutor>(
"UPDATE {TABLE_NAME} SET {} WHERE id = ?;",
set_parts.join(", ")
);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let updated = select_by_id(exec, &id_for_lookup)?;
Ok(IResult { result: updated })
}
-pub fn delete<E: SqlExecutor>(
- exec: &E,
+pub fn delete(
+ exec: &dyn SqlExecutor,
opts: &INostrEventStateDelete,
) -> Result<INostrEventStateDeleteResolve, IError<SqlError>> {
let id_for_lookup = match opts {
@@ -135,7 +137,8 @@ pub fn delete<E: SqlExecutor>(
}
},
};
- let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])?;
+ let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])
+ .expect("serialize bind params");
let sql = format!("DELETE FROM {TABLE_NAME} WHERE id = ?;");
let outcome = exec.exec(&sql, ¶ms_json)?;
if outcome.changes == 0 {
diff --git a/crates/replica-db/src/models/nostr_profile.rs b/crates/replica-db/src/models/nostr_profile.rs
@@ -12,11 +12,11 @@ use serde_json::Value;
const TABLE_NAME: &str = "nostr_profile";
-pub fn create<E: SqlExecutor>(
- exec: &E,
+pub fn create(
+ exec: &dyn SqlExecutor,
opts: &INostrProfileCreate,
) -> Result<INostrProfileCreateResolve, IError<SqlError>> {
- let field_map = utils::to_object_map(opts)?;
+ let field_map = utils::to_object_map(opts).expect("serialize object map");
let id = utils::uuidv4();
let now = utils::time_created_on();
let meta: [(&str, Value); 3] = [
@@ -25,15 +25,15 @@ pub fn create<E: SqlExecutor>(
("updated_at", Value::from(now.clone())),
];
let (sql, bind_values) = utils::build_insert_query_with_meta(TABLE_NAME, &meta, &field_map);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let on = NostrProfileQueryBindValues::Id { id: id.clone() };
let result = find_one_by_on(exec, &on)?.ok_or(IError::from(SqlError::NotFound(id.clone())))?;
Ok(IResult { result })
}
-pub fn find_one<E: SqlExecutor>(
- exec: &E,
+pub fn find_one(
+ exec: &dyn SqlExecutor,
opts: &INostrProfileFindOne,
) -> Result<INostrProfileFindOneResolve, IError<SqlError>> {
let result = match opts {
@@ -43,8 +43,8 @@ pub fn find_one<E: SqlExecutor>(
Ok(IResult { result })
}
-pub fn find_many<E: SqlExecutor>(
- exec: &E,
+pub fn find_many(
+ exec: &dyn SqlExecutor,
opts: &INostrProfileFindMany,
) -> Result<INostrProfileFindManyResolve, IError<SqlError>> {
let results = match opts {
@@ -54,24 +54,24 @@ pub fn find_many<E: SqlExecutor>(
Ok(IResultList { results })
}
-fn find_many_filter<E: SqlExecutor>(
- exec: &E,
+fn find_many_filter(
+ exec: &dyn SqlExecutor,
filter: &Option<INostrProfileFieldsFilter>,
) -> Result<Vec<NostrProfile>, IError<SqlError>> {
let (sql, bind_values) = utils::build_select_query_with_meta(TABLE_NAME, filter.as_ref());
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let rows: Vec<NostrProfile> = utils::parse_json(&json)?;
Ok(rows)
}
-fn find_one_by_on<E: SqlExecutor>(
- exec: &E,
+fn find_one_by_on(
+ exec: &dyn SqlExecutor,
on: &NostrProfileQueryBindValues,
) -> Result<Option<NostrProfile>, IError<SqlError>> {
let (column, value) = on.to_filter_param();
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE {column} = ? LIMIT 1;");
- let params_json = utils::to_params_json(vec![value])?;
+ let params_json = utils::to_params_json(vec![value]).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<NostrProfile> = utils::parse_json(&json)?;
Ok(rows.pop())
@@ -90,32 +90,33 @@ fn rel_query(rel: &NostrProfileFindManyRel) -> (&'static str, Vec<Value>) {
}
}
-fn find_one_by_rel<E: SqlExecutor>(
- exec: &E,
+fn find_one_by_rel(
+ exec: &dyn SqlExecutor,
rel: &NostrProfileFindManyRel,
) -> Result<Option<NostrProfile>, IError<SqlError>> {
let (sql, bind_values) = rel_query(rel);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let sql = format!("{sql} LIMIT 1;");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<NostrProfile> = utils::parse_json(&json)?;
Ok(rows.pop())
}
-fn find_many_by_rel<E: SqlExecutor>(
- exec: &E,
+fn find_many_by_rel(
+ exec: &dyn SqlExecutor,
rel: &NostrProfileFindManyRel,
) -> Result<Vec<NostrProfile>, IError<SqlError>> {
let (sql, bind_values) = rel_query(rel);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let sql = format!("{sql};");
let json = exec.query_raw(&sql, ¶ms_json)?;
let rows: Vec<NostrProfile> = utils::parse_json(&json)?;
Ok(rows)
}
-fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<NostrProfile, IError<SqlError>> {
- let params_json = utils::to_params_json(vec![Value::from(id.to_owned())])?;
+fn select_by_id(exec: &dyn SqlExecutor, id: &str) -> Result<NostrProfile, IError<SqlError>> {
+ let params_json =
+ utils::to_params_json(vec![Value::from(id.to_owned())]).expect("serialize bind params");
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE id = ?;");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<NostrProfile> = utils::parse_json(&json)?;
@@ -123,11 +124,12 @@ fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<NostrProfile, IErr
.ok_or(IError::from(SqlError::NotFound(id.to_owned())))
}
-pub fn update<E: SqlExecutor>(
- exec: &E,
+pub fn update(
+ exec: &dyn SqlExecutor,
opts: &INostrProfileUpdate,
) -> Result<INostrProfileUpdateResolve, IError<SqlError>> {
- let mut updates = utils::to_partial_object_map(&opts.fields)?;
+ let mut updates =
+ utils::to_partial_object_map(&opts.fields).expect("serialize partial object map");
if updates.is_empty() {
return Err(IError::from(SqlError::InvalidArgument(String::from(
"no fields to update",
@@ -156,14 +158,14 @@ pub fn update<E: SqlExecutor>(
"UPDATE {TABLE_NAME} SET {} WHERE id = ?;",
set_parts.join(", ")
);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let updated = select_by_id(exec, &id_for_lookup)?;
Ok(IResult { result: updated })
}
-pub fn delete<E: SqlExecutor>(
- exec: &E,
+pub fn delete(
+ exec: &dyn SqlExecutor,
opts: &INostrProfileDelete,
) -> Result<INostrProfileDeleteResolve, IError<SqlError>> {
let id_for_lookup = match opts {
@@ -181,7 +183,8 @@ pub fn delete<E: SqlExecutor>(
model.id
}
};
- let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])?;
+ let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])
+ .expect("serialize bind params");
let sql = format!("DELETE FROM {TABLE_NAME} WHERE id = ?;");
let outcome = exec.exec(&sql, ¶ms_json)?;
if outcome.changes == 0 {
diff --git a/crates/replica-db/src/models/nostr_profile_relay.rs b/crates/replica-db/src/models/nostr_profile_relay.rs
@@ -8,8 +8,8 @@ use serde_json::Value;
const TABLE_NAME: &str = "nostr_profile_relay";
-pub fn set<E: SqlExecutor>(
- exec: &E,
+pub fn set(
+ exec: &dyn SqlExecutor,
opts: &INostrProfileRelayRelation,
) -> Result<INostrProfileRelayResolve, IError<SqlError>> {
let mut query_vals: Vec<Value> = Vec::with_capacity(2);
@@ -21,13 +21,13 @@ pub fn set<E: SqlExecutor>(
"INSERT INTO {} (tb_pr, tb_rl) VALUES ((SELECT id FROM nostr_profile WHERE {} = ?), (SELECT id FROM nostr_relay WHERE {} = ?));",
TABLE_NAME, nostr_profile_column, nostr_relay_column
);
- let params_json = utils::to_params_json(query_vals)?;
+ let params_json = utils::to_params_json(query_vals).expect("serialize bind params");
let _ = exec.exec(&query, ¶ms_json)?;
Ok(IResultPass { pass: true })
}
-pub fn unset<E: SqlExecutor>(
- exec: &E,
+pub fn unset(
+ exec: &dyn SqlExecutor,
opts: &INostrProfileRelayRelation,
) -> Result<INostrProfileRelayResolve, IError<SqlError>> {
let mut query_vals: Vec<Value> = Vec::with_capacity(2);
@@ -39,7 +39,7 @@ pub fn unset<E: SqlExecutor>(
"DELETE FROM {} WHERE tb_pr = (SELECT id FROM nostr_profile WHERE {} = ?) AND tb_rl = (SELECT id FROM nostr_relay WHERE {} = ?);",
TABLE_NAME, nostr_profile_column, nostr_relay_column
);
- let params_json = utils::to_params_json(query_vals)?;
+ let params_json = utils::to_params_json(query_vals).expect("serialize bind params");
let _ = exec.exec(&query, ¶ms_json)?;
Ok(IResultPass { pass: true })
}
diff --git a/crates/replica-db/src/models/nostr_relay.rs b/crates/replica-db/src/models/nostr_relay.rs
@@ -11,11 +11,11 @@ use serde_json::Value;
const TABLE_NAME: &str = "nostr_relay";
-pub fn create<E: SqlExecutor>(
- exec: &E,
+pub fn create(
+ exec: &dyn SqlExecutor,
opts: &INostrRelayCreate,
) -> Result<INostrRelayCreateResolve, IError<SqlError>> {
- let field_map = utils::to_object_map(opts)?;
+ let field_map = utils::to_object_map(opts).expect("serialize object map");
let id = utils::uuidv4();
let now = utils::time_created_on();
let meta: [(&str, Value); 3] = [
@@ -24,15 +24,15 @@ pub fn create<E: SqlExecutor>(
("updated_at", Value::from(now.clone())),
];
let (sql, bind_values) = utils::build_insert_query_with_meta(TABLE_NAME, &meta, &field_map);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let on = NostrRelayQueryBindValues::Id { id: id.clone() };
let result = find_one_by_on(exec, &on)?.ok_or(IError::from(SqlError::NotFound(id.clone())))?;
Ok(IResult { result })
}
-pub fn find_one<E: SqlExecutor>(
- exec: &E,
+pub fn find_one(
+ exec: &dyn SqlExecutor,
opts: &INostrRelayFindOne,
) -> Result<INostrRelayFindOneResolve, IError<SqlError>> {
let result = match opts {
@@ -42,8 +42,8 @@ pub fn find_one<E: SqlExecutor>(
Ok(IResult { result })
}
-pub fn find_many<E: SqlExecutor>(
- exec: &E,
+pub fn find_many(
+ exec: &dyn SqlExecutor,
opts: &INostrRelayFindMany,
) -> Result<INostrRelayFindManyResolve, IError<SqlError>> {
let results = match opts {
@@ -53,24 +53,24 @@ pub fn find_many<E: SqlExecutor>(
Ok(IResultList { results })
}
-fn find_many_filter<E: SqlExecutor>(
- exec: &E,
+fn find_many_filter(
+ exec: &dyn SqlExecutor,
filter: &Option<INostrRelayFieldsFilter>,
) -> Result<Vec<NostrRelay>, IError<SqlError>> {
let (sql, bind_values) = utils::build_select_query_with_meta(TABLE_NAME, filter.as_ref());
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let rows: Vec<NostrRelay> = utils::parse_json(&json)?;
Ok(rows)
}
-fn find_one_by_on<E: SqlExecutor>(
- exec: &E,
+fn find_one_by_on(
+ exec: &dyn SqlExecutor,
on: &NostrRelayQueryBindValues,
) -> Result<Option<NostrRelay>, IError<SqlError>> {
let (column, value) = on.to_filter_param();
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE {column} = ? LIMIT 1;");
- let params_json = utils::to_params_json(vec![value])?;
+ let params_json = utils::to_params_json(vec![value]).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<NostrRelay> = utils::parse_json(&json)?;
Ok(rows.pop())
@@ -89,32 +89,33 @@ fn rel_query(rel: &NostrRelayFindManyRel) -> (&'static str, Vec<Value>) {
}
}
-fn find_one_by_rel<E: SqlExecutor>(
- exec: &E,
+fn find_one_by_rel(
+ exec: &dyn SqlExecutor,
rel: &NostrRelayFindManyRel,
) -> Result<Option<NostrRelay>, IError<SqlError>> {
let (sql, bind_values) = rel_query(rel);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let sql = format!("{sql} LIMIT 1;");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<NostrRelay> = utils::parse_json(&json)?;
Ok(rows.pop())
}
-fn find_many_by_rel<E: SqlExecutor>(
- exec: &E,
+fn find_many_by_rel(
+ exec: &dyn SqlExecutor,
rel: &NostrRelayFindManyRel,
) -> Result<Vec<NostrRelay>, IError<SqlError>> {
let (sql, bind_values) = rel_query(rel);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let sql = format!("{sql};");
let json = exec.query_raw(&sql, ¶ms_json)?;
let rows: Vec<NostrRelay> = utils::parse_json(&json)?;
Ok(rows)
}
-fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<NostrRelay, IError<SqlError>> {
- let params_json = utils::to_params_json(vec![Value::from(id.to_owned())])?;
+fn select_by_id(exec: &dyn SqlExecutor, id: &str) -> Result<NostrRelay, IError<SqlError>> {
+ let params_json =
+ utils::to_params_json(vec![Value::from(id.to_owned())]).expect("serialize bind params");
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE id = ?;");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<NostrRelay> = utils::parse_json(&json)?;
@@ -122,11 +123,12 @@ fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<NostrRelay, IError
.ok_or(IError::from(SqlError::NotFound(id.to_owned())))
}
-pub fn update<E: SqlExecutor>(
- exec: &E,
+pub fn update(
+ exec: &dyn SqlExecutor,
opts: &INostrRelayUpdate,
) -> Result<INostrRelayUpdateResolve, IError<SqlError>> {
- let mut updates = utils::to_partial_object_map(&opts.fields)?;
+ let mut updates =
+ utils::to_partial_object_map(&opts.fields).expect("serialize partial object map");
if updates.is_empty() {
return Err(IError::from(SqlError::InvalidArgument(String::from(
"no fields to update",
@@ -155,14 +157,14 @@ pub fn update<E: SqlExecutor>(
"UPDATE {TABLE_NAME} SET {} WHERE id = ?;",
set_parts.join(", ")
);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let updated = select_by_id(exec, &id_for_lookup)?;
Ok(IResult { result: updated })
}
-pub fn delete<E: SqlExecutor>(
- exec: &E,
+pub fn delete(
+ exec: &dyn SqlExecutor,
opts: &INostrRelayDelete,
) -> Result<INostrRelayDeleteResolve, IError<SqlError>> {
let id_for_lookup = match opts {
@@ -180,7 +182,8 @@ pub fn delete<E: SqlExecutor>(
model.id
}
};
- let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])?;
+ let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])
+ .expect("serialize bind params");
let sql = format!("DELETE FROM {TABLE_NAME} WHERE id = ?;");
let outcome = exec.exec(&sql, ¶ms_json)?;
if outcome.changes == 0 {
diff --git a/crates/replica-db/src/models/plot.rs b/crates/replica-db/src/models/plot.rs
@@ -10,11 +10,11 @@ use serde_json::Value;
const TABLE_NAME: &str = "plot";
-pub fn create<E: SqlExecutor>(
- exec: &E,
+pub fn create(
+ exec: &dyn SqlExecutor,
opts: &IPlotCreate,
) -> Result<IPlotCreateResolve, IError<SqlError>> {
- let field_map = utils::to_object_map(opts)?;
+ let field_map = utils::to_object_map(opts).expect("serialize object map");
let id = utils::uuidv4();
let now = utils::time_created_on();
let meta: [(&str, Value); 3] = [
@@ -23,15 +23,15 @@ pub fn create<E: SqlExecutor>(
("updated_at", Value::from(now.clone())),
];
let (sql, bind_values) = utils::build_insert_query_with_meta(TABLE_NAME, &meta, &field_map);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let on = PlotQueryBindValues::Id { id: id.clone() };
let result = find_one_by_on(exec, &on)?.ok_or(IError::from(SqlError::NotFound(id.clone())))?;
Ok(IResult { result })
}
-pub fn find_one<E: SqlExecutor>(
- exec: &E,
+pub fn find_one(
+ exec: &dyn SqlExecutor,
opts: &IPlotFindOne,
) -> Result<IPlotFindOneResolve, IError<SqlError>> {
let result = match opts {
@@ -40,39 +40,40 @@ pub fn find_one<E: SqlExecutor>(
Ok(IResult { result })
}
-pub fn find_many<E: SqlExecutor>(
- exec: &E,
+pub fn find_many(
+ exec: &dyn SqlExecutor,
opts: &IPlotFindMany,
) -> Result<IPlotFindManyResolve, IError<SqlError>> {
let results = find_many_filter(exec, &opts.filter)?;
Ok(IResultList { results })
}
-fn find_many_filter<E: SqlExecutor>(
- exec: &E,
+fn find_many_filter(
+ exec: &dyn SqlExecutor,
filter: &Option<IPlotFieldsFilter>,
) -> Result<Vec<Plot>, IError<SqlError>> {
let (sql, bind_values) = utils::build_select_query_with_meta(TABLE_NAME, filter.as_ref());
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let rows: Vec<Plot> = utils::parse_json(&json)?;
Ok(rows)
}
-fn find_one_by_on<E: SqlExecutor>(
- exec: &E,
+fn find_one_by_on(
+ exec: &dyn SqlExecutor,
on: &PlotQueryBindValues,
) -> Result<Option<Plot>, IError<SqlError>> {
let (column, value) = on.to_filter_param();
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE {column} = ? LIMIT 1;");
- let params_json = utils::to_params_json(vec![value])?;
+ let params_json = utils::to_params_json(vec![value]).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<Plot> = utils::parse_json(&json)?;
Ok(rows.pop())
}
-fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<Plot, IError<SqlError>> {
- let params_json = utils::to_params_json(vec![Value::from(id.to_owned())])?;
+fn select_by_id(exec: &dyn SqlExecutor, id: &str) -> Result<Plot, IError<SqlError>> {
+ let params_json =
+ utils::to_params_json(vec![Value::from(id.to_owned())]).expect("serialize bind params");
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE id = ?;");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<Plot> = utils::parse_json(&json)?;
@@ -80,11 +81,12 @@ fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<Plot, IError<SqlEr
.ok_or(IError::from(SqlError::NotFound(id.to_owned())))
}
-pub fn update<E: SqlExecutor>(
- exec: &E,
+pub fn update(
+ exec: &dyn SqlExecutor,
opts: &IPlotUpdate,
) -> Result<IPlotUpdateResolve, IError<SqlError>> {
- let mut updates = utils::to_partial_object_map(&opts.fields)?;
+ let mut updates =
+ utils::to_partial_object_map(&opts.fields).expect("serialize partial object map");
if updates.is_empty() {
return Err(IError::from(SqlError::InvalidArgument(String::from(
"no fields to update",
@@ -113,14 +115,14 @@ pub fn update<E: SqlExecutor>(
"UPDATE {TABLE_NAME} SET {} WHERE id = ?;",
set_parts.join(", ")
);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let updated = select_by_id(exec, &id_for_lookup)?;
Ok(IResult { result: updated })
}
-pub fn delete<E: SqlExecutor>(
- exec: &E,
+pub fn delete(
+ exec: &dyn SqlExecutor,
opts: &IPlotDelete,
) -> Result<IPlotDeleteResolve, IError<SqlError>> {
let id_for_lookup = match opts {
@@ -133,7 +135,8 @@ pub fn delete<E: SqlExecutor>(
}
},
};
- let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])?;
+ let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])
+ .expect("serialize bind params");
let sql = format!("DELETE FROM {TABLE_NAME} WHERE id = ?;");
let outcome = exec.exec(&sql, ¶ms_json)?;
if outcome.changes == 0 {
diff --git a/crates/replica-db/src/models/plot_gcs_location.rs b/crates/replica-db/src/models/plot_gcs_location.rs
@@ -12,11 +12,11 @@ use serde_json::Value;
const TABLE_NAME: &str = "plot_gcs_location";
-pub fn create<E: SqlExecutor>(
- exec: &E,
+pub fn create(
+ exec: &dyn SqlExecutor,
opts: &IPlotGcsLocationCreate,
) -> Result<IPlotGcsLocationCreateResolve, IError<SqlError>> {
- let field_map = utils::to_object_map(opts)?;
+ let field_map = utils::to_object_map(opts).expect("serialize object map");
let id = utils::uuidv4();
let now = utils::time_created_on();
let meta: [(&str, Value); 3] = [
@@ -25,15 +25,15 @@ pub fn create<E: SqlExecutor>(
("updated_at", Value::from(now.clone())),
];
let (sql, bind_values) = utils::build_insert_query_with_meta(TABLE_NAME, &meta, &field_map);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let on = PlotGcsLocationQueryBindValues::Id { id: id.clone() };
let result = find_one_by_on(exec, &on)?.ok_or(IError::from(SqlError::NotFound(id.clone())))?;
Ok(IResult { result })
}
-pub fn find_one<E: SqlExecutor>(
- exec: &E,
+pub fn find_one(
+ exec: &dyn SqlExecutor,
opts: &IPlotGcsLocationFindOne,
) -> Result<IPlotGcsLocationFindOneResolve, IError<SqlError>> {
let result = match opts {
@@ -42,39 +42,40 @@ pub fn find_one<E: SqlExecutor>(
Ok(IResult { result })
}
-pub fn find_many<E: SqlExecutor>(
- exec: &E,
+pub fn find_many(
+ exec: &dyn SqlExecutor,
opts: &IPlotGcsLocationFindMany,
) -> Result<IPlotGcsLocationFindManyResolve, IError<SqlError>> {
let results = find_many_filter(exec, &opts.filter)?;
Ok(IResultList { results })
}
-fn find_many_filter<E: SqlExecutor>(
- exec: &E,
+fn find_many_filter(
+ exec: &dyn SqlExecutor,
filter: &Option<IPlotGcsLocationFieldsFilter>,
) -> Result<Vec<PlotGcsLocation>, IError<SqlError>> {
let (sql, bind_values) = utils::build_select_query_with_meta(TABLE_NAME, filter.as_ref());
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let rows: Vec<PlotGcsLocation> = utils::parse_json(&json)?;
Ok(rows)
}
-fn find_one_by_on<E: SqlExecutor>(
- exec: &E,
+fn find_one_by_on(
+ exec: &dyn SqlExecutor,
on: &PlotGcsLocationQueryBindValues,
) -> Result<Option<PlotGcsLocation>, IError<SqlError>> {
let (column, value) = on.to_filter_param();
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE {column} = ? LIMIT 1;");
- let params_json = utils::to_params_json(vec![value])?;
+ let params_json = utils::to_params_json(vec![value]).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<PlotGcsLocation> = utils::parse_json(&json)?;
Ok(rows.pop())
}
-fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<PlotGcsLocation, IError<SqlError>> {
- let params_json = utils::to_params_json(vec![Value::from(id.to_owned())])?;
+fn select_by_id(exec: &dyn SqlExecutor, id: &str) -> Result<PlotGcsLocation, IError<SqlError>> {
+ let params_json =
+ utils::to_params_json(vec![Value::from(id.to_owned())]).expect("serialize bind params");
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE id = ?;");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<PlotGcsLocation> = utils::parse_json(&json)?;
@@ -82,11 +83,12 @@ fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<PlotGcsLocation, I
.ok_or(IError::from(SqlError::NotFound(id.to_owned())))
}
-pub fn update<E: SqlExecutor>(
- exec: &E,
+pub fn update(
+ exec: &dyn SqlExecutor,
opts: &IPlotGcsLocationUpdate,
) -> Result<IPlotGcsLocationUpdateResolve, IError<SqlError>> {
- let mut updates = utils::to_partial_object_map(&opts.fields)?;
+ let mut updates =
+ utils::to_partial_object_map(&opts.fields).expect("serialize partial object map");
if updates.is_empty() {
return Err(IError::from(SqlError::InvalidArgument(String::from(
"no fields to update",
@@ -115,14 +117,14 @@ pub fn update<E: SqlExecutor>(
"UPDATE {TABLE_NAME} SET {} WHERE id = ?;",
set_parts.join(", ")
);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let updated = select_by_id(exec, &id_for_lookup)?;
Ok(IResult { result: updated })
}
-pub fn delete<E: SqlExecutor>(
- exec: &E,
+pub fn delete(
+ exec: &dyn SqlExecutor,
opts: &IPlotGcsLocationDelete,
) -> Result<IPlotGcsLocationDeleteResolve, IError<SqlError>> {
let id_for_lookup = match opts {
@@ -135,7 +137,8 @@ pub fn delete<E: SqlExecutor>(
}
},
};
- let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])?;
+ let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])
+ .expect("serialize bind params");
let sql = format!("DELETE FROM {TABLE_NAME} WHERE id = ?;");
let outcome = exec.exec(&sql, ¶ms_json)?;
if outcome.changes == 0 {
diff --git a/crates/replica-db/src/models/plot_tag.rs b/crates/replica-db/src/models/plot_tag.rs
@@ -10,11 +10,11 @@ use serde_json::Value;
const TABLE_NAME: &str = "plot_tag";
-pub fn create<E: SqlExecutor>(
- exec: &E,
+pub fn create(
+ exec: &dyn SqlExecutor,
opts: &IPlotTagCreate,
) -> Result<IPlotTagCreateResolve, IError<SqlError>> {
- let field_map = utils::to_object_map(opts)?;
+ let field_map = utils::to_object_map(opts).expect("serialize object map");
let id = utils::uuidv4();
let now = utils::time_created_on();
let meta: [(&str, Value); 3] = [
@@ -23,15 +23,15 @@ pub fn create<E: SqlExecutor>(
("updated_at", Value::from(now.clone())),
];
let (sql, bind_values) = utils::build_insert_query_with_meta(TABLE_NAME, &meta, &field_map);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let on = PlotTagQueryBindValues::Id { id: id.clone() };
let result = find_one_by_on(exec, &on)?.ok_or(IError::from(SqlError::NotFound(id.clone())))?;
Ok(IResult { result })
}
-pub fn find_one<E: SqlExecutor>(
- exec: &E,
+pub fn find_one(
+ exec: &dyn SqlExecutor,
opts: &IPlotTagFindOne,
) -> Result<IPlotTagFindOneResolve, IError<SqlError>> {
let result = match opts {
@@ -40,39 +40,40 @@ pub fn find_one<E: SqlExecutor>(
Ok(IResult { result })
}
-pub fn find_many<E: SqlExecutor>(
- exec: &E,
+pub fn find_many(
+ exec: &dyn SqlExecutor,
opts: &IPlotTagFindMany,
) -> Result<IPlotTagFindManyResolve, IError<SqlError>> {
let results = find_many_filter(exec, &opts.filter)?;
Ok(IResultList { results })
}
-fn find_many_filter<E: SqlExecutor>(
- exec: &E,
+fn find_many_filter(
+ exec: &dyn SqlExecutor,
filter: &Option<IPlotTagFieldsFilter>,
) -> Result<Vec<PlotTag>, IError<SqlError>> {
let (sql, bind_values) = utils::build_select_query_with_meta(TABLE_NAME, filter.as_ref());
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let rows: Vec<PlotTag> = utils::parse_json(&json)?;
Ok(rows)
}
-fn find_one_by_on<E: SqlExecutor>(
- exec: &E,
+fn find_one_by_on(
+ exec: &dyn SqlExecutor,
on: &PlotTagQueryBindValues,
) -> Result<Option<PlotTag>, IError<SqlError>> {
let (column, value) = on.to_filter_param();
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE {column} = ? LIMIT 1;");
- let params_json = utils::to_params_json(vec![value])?;
+ let params_json = utils::to_params_json(vec![value]).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<PlotTag> = utils::parse_json(&json)?;
Ok(rows.pop())
}
-fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<PlotTag, IError<SqlError>> {
- let params_json = utils::to_params_json(vec![Value::from(id.to_owned())])?;
+fn select_by_id(exec: &dyn SqlExecutor, id: &str) -> Result<PlotTag, IError<SqlError>> {
+ let params_json =
+ utils::to_params_json(vec![Value::from(id.to_owned())]).expect("serialize bind params");
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE id = ?;");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<PlotTag> = utils::parse_json(&json)?;
@@ -80,11 +81,12 @@ fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<PlotTag, IError<Sq
.ok_or(IError::from(SqlError::NotFound(id.to_owned())))
}
-pub fn update<E: SqlExecutor>(
- exec: &E,
+pub fn update(
+ exec: &dyn SqlExecutor,
opts: &IPlotTagUpdate,
) -> Result<IPlotTagUpdateResolve, IError<SqlError>> {
- let mut updates = utils::to_partial_object_map(&opts.fields)?;
+ let mut updates =
+ utils::to_partial_object_map(&opts.fields).expect("serialize partial object map");
if updates.is_empty() {
return Err(IError::from(SqlError::InvalidArgument(String::from(
"no fields to update",
@@ -113,14 +115,14 @@ pub fn update<E: SqlExecutor>(
"UPDATE {TABLE_NAME} SET {} WHERE id = ?;",
set_parts.join(", ")
);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let updated = select_by_id(exec, &id_for_lookup)?;
Ok(IResult { result: updated })
}
-pub fn delete<E: SqlExecutor>(
- exec: &E,
+pub fn delete(
+ exec: &dyn SqlExecutor,
opts: &IPlotTagDelete,
) -> Result<IPlotTagDeleteResolve, IError<SqlError>> {
let id_for_lookup = match opts {
@@ -133,7 +135,8 @@ pub fn delete<E: SqlExecutor>(
}
},
};
- let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])?;
+ let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])
+ .expect("serialize bind params");
let sql = format!("DELETE FROM {TABLE_NAME} WHERE id = ?;");
let outcome = exec.exec(&sql, ¶ms_json)?;
if outcome.changes == 0 {
diff --git a/crates/replica-db/src/models/trade_product.rs b/crates/replica-db/src/models/trade_product.rs
@@ -11,11 +11,11 @@ use serde_json::Value;
const TABLE_NAME: &str = "trade_product";
-pub fn create<E: SqlExecutor>(
- exec: &E,
+pub fn create(
+ exec: &dyn SqlExecutor,
opts: &ITradeProductCreate,
) -> Result<ITradeProductCreateResolve, IError<SqlError>> {
- let field_map = utils::to_object_map(opts)?;
+ let field_map = utils::to_object_map(opts).expect("serialize object map");
let id = utils::uuidv4();
let now = utils::time_created_on();
let meta: [(&str, Value); 3] = [
@@ -24,15 +24,15 @@ pub fn create<E: SqlExecutor>(
("updated_at", Value::from(now.clone())),
];
let (sql, bind_values) = utils::build_insert_query_with_meta(TABLE_NAME, &meta, &field_map);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let on = TradeProductQueryBindValues::Id { id: id.clone() };
let result = find_one_by_on(exec, &on)?.ok_or(IError::from(SqlError::NotFound(id.clone())))?;
Ok(IResult { result })
}
-pub fn find_one<E: SqlExecutor>(
- exec: &E,
+pub fn find_one(
+ exec: &dyn SqlExecutor,
opts: &ITradeProductFindOne,
) -> Result<ITradeProductFindOneResolve, IError<SqlError>> {
let result = match opts {
@@ -41,39 +41,40 @@ pub fn find_one<E: SqlExecutor>(
Ok(IResult { result })
}
-pub fn find_many<E: SqlExecutor>(
- exec: &E,
+pub fn find_many(
+ exec: &dyn SqlExecutor,
opts: &ITradeProductFindMany,
) -> Result<ITradeProductFindManyResolve, IError<SqlError>> {
let results = find_many_filter(exec, &opts.filter)?;
Ok(IResultList { results })
}
-fn find_many_filter<E: SqlExecutor>(
- exec: &E,
+fn find_many_filter(
+ exec: &dyn SqlExecutor,
filter: &Option<ITradeProductFieldsFilter>,
) -> Result<Vec<TradeProduct>, IError<SqlError>> {
let (sql, bind_values) = utils::build_select_query_with_meta(TABLE_NAME, filter.as_ref());
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let rows: Vec<TradeProduct> = utils::parse_json(&json)?;
Ok(rows)
}
-fn find_one_by_on<E: SqlExecutor>(
- exec: &E,
+fn find_one_by_on(
+ exec: &dyn SqlExecutor,
on: &TradeProductQueryBindValues,
) -> Result<Option<TradeProduct>, IError<SqlError>> {
let (column, value) = on.to_filter_param();
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE {column} = ? LIMIT 1;");
- let params_json = utils::to_params_json(vec![value])?;
+ let params_json = utils::to_params_json(vec![value]).expect("serialize bind params");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<TradeProduct> = utils::parse_json(&json)?;
Ok(rows.pop())
}
-fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<TradeProduct, IError<SqlError>> {
- let params_json = utils::to_params_json(vec![Value::from(id.to_owned())])?;
+fn select_by_id(exec: &dyn SqlExecutor, id: &str) -> Result<TradeProduct, IError<SqlError>> {
+ let params_json =
+ utils::to_params_json(vec![Value::from(id.to_owned())]).expect("serialize bind params");
let sql = format!("SELECT * FROM {TABLE_NAME} WHERE id = ?;");
let json = exec.query_raw(&sql, ¶ms_json)?;
let mut rows: Vec<TradeProduct> = utils::parse_json(&json)?;
@@ -81,11 +82,12 @@ fn select_by_id<E: SqlExecutor>(exec: &E, id: &str) -> Result<TradeProduct, IErr
.ok_or(IError::from(SqlError::NotFound(id.to_owned())))
}
-pub fn update<E: SqlExecutor>(
- exec: &E,
+pub fn update(
+ exec: &dyn SqlExecutor,
opts: &ITradeProductUpdate,
) -> Result<ITradeProductUpdateResolve, IError<SqlError>> {
- let mut updates = utils::to_partial_object_map(&opts.fields)?;
+ let mut updates =
+ utils::to_partial_object_map(&opts.fields).expect("serialize partial object map");
if updates.is_empty() {
return Err(IError::from(SqlError::InvalidArgument(String::from(
"no fields to update",
@@ -109,14 +111,14 @@ pub fn update<E: SqlExecutor>(
"UPDATE {TABLE_NAME} SET {} WHERE id = ?;",
set_parts.join(", ")
);
- let params_json = utils::to_params_json(bind_values)?;
+ let params_json = utils::to_params_json(bind_values).expect("serialize bind params");
let _ = exec.exec(&sql, ¶ms_json)?;
let updated = select_by_id(exec, &id_for_lookup)?;
Ok(IResult { result: updated })
}
-pub fn delete<E: SqlExecutor>(
- exec: &E,
+pub fn delete(
+ exec: &dyn SqlExecutor,
opts: &ITradeProductDelete,
) -> Result<ITradeProductDeleteResolve, IError<SqlError>> {
let id_for_lookup = match opts {
@@ -124,7 +126,8 @@ pub fn delete<E: SqlExecutor>(
TradeProductQueryBindValues::Id { id } => id.clone(),
},
};
- let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])?;
+ let params_json = utils::to_params_json(vec![Value::from(id_for_lookup.clone())])
+ .expect("serialize bind params");
let sql = format!("DELETE FROM {TABLE_NAME} WHERE id = ?;");
let outcome = exec.exec(&sql, ¶ms_json)?;
if outcome.changes == 0 {
diff --git a/crates/replica-db/src/models/trade_product_location.rs b/crates/replica-db/src/models/trade_product_location.rs
@@ -8,8 +8,8 @@ use serde_json::Value;
const TABLE_NAME: &str = "trade_product_location";
-pub fn set<E: SqlExecutor>(
- exec: &E,
+pub fn set(
+ exec: &dyn SqlExecutor,
opts: &ITradeProductLocationRelation,
) -> Result<ITradeProductLocationResolve, IError<SqlError>> {
let mut query_vals: Vec<Value> = Vec::with_capacity(2);
@@ -21,13 +21,13 @@ pub fn set<E: SqlExecutor>(
"INSERT INTO {} (tb_tp, tb_gl) VALUES ((SELECT id FROM trade_product WHERE {} = ?), (SELECT id FROM gcs_location WHERE {} = ?));",
TABLE_NAME, trade_product_column, gcs_location_column
);
- let params_json = utils::to_params_json(query_vals)?;
+ let params_json = utils::to_params_json(query_vals).expect("serialize bind params");
let _ = exec.exec(&query, ¶ms_json)?;
Ok(IResultPass { pass: true })
}
-pub fn unset<E: SqlExecutor>(
- exec: &E,
+pub fn unset(
+ exec: &dyn SqlExecutor,
opts: &ITradeProductLocationRelation,
) -> Result<ITradeProductLocationResolve, IError<SqlError>> {
let mut query_vals: Vec<Value> = Vec::with_capacity(2);
@@ -39,7 +39,7 @@ pub fn unset<E: SqlExecutor>(
"DELETE FROM {} WHERE tb_tp = (SELECT id FROM trade_product WHERE {} = ?) AND tb_gl = (SELECT id FROM gcs_location WHERE {} = ?);",
TABLE_NAME, trade_product_column, gcs_location_column
);
- let params_json = utils::to_params_json(query_vals)?;
+ let params_json = utils::to_params_json(query_vals).expect("serialize bind params");
let _ = exec.exec(&query, ¶ms_json)?;
Ok(IResultPass { pass: true })
}
diff --git a/crates/replica-db/src/models/trade_product_media.rs b/crates/replica-db/src/models/trade_product_media.rs
@@ -8,8 +8,8 @@ use serde_json::Value;
const TABLE_NAME: &str = "trade_product_media";
-pub fn set<E: SqlExecutor>(
- exec: &E,
+pub fn set(
+ exec: &dyn SqlExecutor,
opts: &ITradeProductMediaRelation,
) -> Result<ITradeProductMediaResolve, IError<SqlError>> {
let mut query_vals: Vec<Value> = Vec::with_capacity(2);
@@ -21,13 +21,13 @@ pub fn set<E: SqlExecutor>(
"INSERT INTO {} (tb_tp, tb_mu) VALUES ((SELECT id FROM trade_product WHERE {} = ?), (SELECT id FROM media_image WHERE {} = ?));",
TABLE_NAME, trade_product_column, media_image_column
);
- let params_json = utils::to_params_json(query_vals)?;
+ let params_json = utils::to_params_json(query_vals).expect("serialize bind params");
let _ = exec.exec(&query, ¶ms_json)?;
Ok(IResultPass { pass: true })
}
-pub fn unset<E: SqlExecutor>(
- exec: &E,
+pub fn unset(
+ exec: &dyn SqlExecutor,
opts: &ITradeProductMediaRelation,
) -> Result<ITradeProductMediaResolve, IError<SqlError>> {
let mut query_vals: Vec<Value> = Vec::with_capacity(2);
@@ -39,7 +39,7 @@ pub fn unset<E: SqlExecutor>(
"DELETE FROM {} WHERE tb_tp = (SELECT id FROM trade_product WHERE {} = ?) AND tb_mu = (SELECT id FROM media_image WHERE {} = ?);",
TABLE_NAME, trade_product_column, media_image_column
);
- let params_json = utils::to_params_json(query_vals)?;
+ let params_json = utils::to_params_json(query_vals).expect("serialize bind params");
let _ = exec.exec(&query, ¶ms_json)?;
Ok(IResultPass { pass: true })
}
diff --git a/crates/replica-db/tests/backup_export_paths.rs b/crates/replica-db/tests/backup_export_paths.rs
@@ -0,0 +1,305 @@
+use std::collections::VecDeque;
+use std::sync::Mutex;
+
+use radroots_replica_db::backup::{
+ DATABASE_BACKUP_VERSION, DatabaseBackup, REPLICA_DB_VERSION, SchemaEntry, TableData,
+ export_database_backup, export_database_backup_json, restore_database_backup,
+};
+use radroots_replica_db::export::export_manifest;
+use radroots_replica_db::{ExecOutcome, SqlError, SqlExecutor};
+use serde_json::{Map, Value, json};
+
+struct PatternExecutor {
+ query_rules: Vec<(String, String)>,
+ fail_query_contains: Option<String>,
+ fail_exec_contains: Option<String>,
+ fail_begin: bool,
+ fail_commit: bool,
+ begin_count: Mutex<usize>,
+ commit_count: Mutex<usize>,
+ rollback_count: Mutex<usize>,
+ query_queue: Mutex<VecDeque<Result<String, SqlError>>>,
+ exec_queue: Mutex<VecDeque<Result<ExecOutcome, SqlError>>>,
+}
+
+impl PatternExecutor {
+ fn new() -> Self {
+ Self {
+ query_rules: Vec::new(),
+ fail_query_contains: None,
+ fail_exec_contains: None,
+ fail_begin: false,
+ fail_commit: false,
+ begin_count: Mutex::new(0),
+ commit_count: Mutex::new(0),
+ rollback_count: Mutex::new(0),
+ query_queue: Mutex::new(VecDeque::new()),
+ exec_queue: Mutex::new(VecDeque::new()),
+ }
+ }
+
+ fn with_query_rule(mut self, needle: &str, response: &str) -> Self {
+ self.query_rules
+ .push((needle.to_string(), response.to_string()));
+ self
+ }
+
+ fn with_query_failure(mut self, needle: &str) -> Self {
+ self.fail_query_contains = Some(needle.to_string());
+ self
+ }
+
+ fn with_exec_failure(mut self, needle: &str) -> Self {
+ self.fail_exec_contains = Some(needle.to_string());
+ self
+ }
+
+ fn with_begin_failure(mut self) -> Self {
+ self.fail_begin = true;
+ self
+ }
+
+ fn with_commit_failure(mut self) -> Self {
+ self.fail_commit = true;
+ self
+ }
+}
+
+impl SqlExecutor for PatternExecutor {
+ fn exec(&self, sql: &str, _params_json: &str) -> Result<ExecOutcome, SqlError> {
+ if let Some(result) = self.exec_queue.lock().expect("exec queue lock").pop_front() {
+ return result;
+ }
+ if let Some(needle) = &self.fail_exec_contains {
+ if sql.contains(needle) {
+ return Err(SqlError::InvalidQuery(String::from("forced exec failure")));
+ }
+ }
+ Ok(ExecOutcome {
+ changes: 1,
+ last_insert_id: 1,
+ })
+ }
+
+ fn query_raw(&self, sql: &str, _params_json: &str) -> Result<String, SqlError> {
+ if let Some(result) = self
+ .query_queue
+ .lock()
+ .expect("query queue lock")
+ .pop_front()
+ {
+ return result;
+ }
+ if let Some(needle) = &self.fail_query_contains {
+ if sql.contains(needle) {
+ return Err(SqlError::InvalidQuery(String::from("forced query failure")));
+ }
+ }
+ for (needle, response) in &self.query_rules {
+ if sql.contains(needle) {
+ return Ok(response.clone());
+ }
+ }
+ Ok(String::from("[]"))
+ }
+
+ fn begin(&self) -> Result<(), SqlError> {
+ *self.begin_count.lock().expect("begin count lock") += 1;
+ if self.fail_begin {
+ return Err(SqlError::InvalidQuery(String::from("forced begin failure")));
+ }
+ Ok(())
+ }
+
+ fn commit(&self) -> Result<(), SqlError> {
+ *self.commit_count.lock().expect("commit count lock") += 1;
+ if self.fail_commit {
+ return Err(SqlError::InvalidQuery(String::from(
+ "forced commit failure",
+ )));
+ }
+ Ok(())
+ }
+
+ fn rollback(&self) -> Result<(), SqlError> {
+ *self.rollback_count.lock().expect("rollback count lock") += 1;
+ Ok(())
+ }
+}
+
+fn assert_sql_error_code<T: core::fmt::Debug>(result: Result<T, SqlError>, code: &str) {
+ let err = result.unwrap_err();
+ assert_eq!(err.code(), code);
+}
+
+fn backup_with_versions(format_version: &str, replica_db_version: &str) -> DatabaseBackup {
+ DatabaseBackup {
+ format_version: format_version.to_string(),
+ replica_db_version: replica_db_version.to_string(),
+ schema: Vec::new(),
+ migrations: Vec::new(),
+ data: Vec::new(),
+ }
+}
+
+#[test]
+fn backup_public_api_error_paths_cover_library_instantiations() {
+ let schema_query = "select type, name, tbl_name as table_name, sql from sqlite_master";
+
+ let executor = PatternExecutor::new().with_query_failure(schema_query);
+ assert_sql_error_code(export_database_backup(&executor), "ERR_INVALID_QUERY");
+
+ let schema_rows = json!([
+ {
+ "type": "table",
+ "name": "tb_a",
+ "table_name": "tb_a",
+ "sql": "CREATE TABLE tb_a (id TEXT);"
+ }
+ ])
+ .to_string();
+ let executor = PatternExecutor::new()
+ .with_query_rule(schema_query, &schema_rows)
+ .with_query_failure("SELECT * FROM \"tb_a\";");
+ assert_sql_error_code(export_database_backup(&executor), "ERR_INVALID_QUERY");
+
+ let executor = PatternExecutor::new().with_query_failure(schema_query);
+ assert_sql_error_code(export_database_backup_json(&executor), "ERR_INVALID_QUERY");
+
+ let executor = PatternExecutor::new().with_query_rule(schema_query, "[]");
+ let backup_json = export_database_backup_json(&executor).expect("backup json success");
+ assert!(backup_json.contains("\"schema\":[]"));
+
+ let executor = PatternExecutor::new();
+ let backup = backup_with_versions("0.0.1", REPLICA_DB_VERSION);
+ assert_sql_error_code(
+ restore_database_backup(&executor, &backup),
+ "ERR_INVALID_ARGUMENT",
+ );
+
+ let backup = backup_with_versions(DATABASE_BACKUP_VERSION, REPLICA_DB_VERSION);
+ let executor = PatternExecutor::new().with_exec_failure("PRAGMA foreign_keys = OFF;");
+ assert_sql_error_code(
+ restore_database_backup(&executor, &backup),
+ "ERR_INVALID_QUERY",
+ );
+
+ let executor = PatternExecutor::new().with_begin_failure();
+ assert_sql_error_code(
+ restore_database_backup(&executor, &backup),
+ "ERR_INVALID_QUERY",
+ );
+
+ let executor =
+ PatternExecutor::new().with_query_failure("select type, name from sqlite_master");
+ assert_sql_error_code(
+ restore_database_backup(&executor, &backup),
+ "ERR_INVALID_QUERY",
+ );
+
+ let executor = PatternExecutor::new().with_commit_failure();
+ assert_sql_error_code(
+ restore_database_backup(&executor, &backup),
+ "ERR_INVALID_QUERY",
+ );
+
+ let executor = PatternExecutor::new().with_exec_failure("PRAGMA foreign_keys = ON;");
+ assert_sql_error_code(
+ restore_database_backup(&executor, &backup),
+ "ERR_INVALID_QUERY",
+ );
+}
+
+#[test]
+fn backup_public_api_insert_and_parse_failures_cover_library_instantiations() {
+ let backup = DatabaseBackup {
+ format_version: DATABASE_BACKUP_VERSION.to_string(),
+ replica_db_version: REPLICA_DB_VERSION.to_string(),
+ schema: vec![SchemaEntry {
+ object_type: String::from("table"),
+ name: String::from("tb_a"),
+ table_name: Some(String::from("tb_a")),
+ sql: Some(String::from("CREATE TABLE tb_a (id TEXT);")),
+ }],
+ migrations: Vec::new(),
+ data: vec![TableData {
+ name: String::from("tb_a"),
+ rows: vec![{
+ let mut row = Map::new();
+ row.insert(String::from("id"), Value::from("1"));
+ row
+ }],
+ }],
+ };
+
+ let executor = PatternExecutor::new().with_exec_failure("INSERT INTO \"tb_a\"");
+ assert_sql_error_code(
+ restore_database_backup(&executor, &backup),
+ "ERR_INVALID_QUERY",
+ );
+
+ let schema_query = "select type, name, tbl_name as table_name, sql from sqlite_master";
+ let executor = PatternExecutor::new().with_query_rule(schema_query, "{");
+ assert_sql_error_code(export_database_backup(&executor), "ERR_SERIALIZATION");
+
+ let schema_rows = json!([
+ {
+ "type": "table",
+ "name": "tb_a",
+ "table_name": "tb_a",
+ "sql": "CREATE TABLE tb_a (id TEXT);"
+ }
+ ])
+ .to_string();
+ let executor = PatternExecutor::new()
+ .with_query_rule(schema_query, &schema_rows)
+ .with_query_rule("SELECT * FROM \"tb_a\";", "{");
+ assert_sql_error_code(export_database_backup(&executor), "ERR_SERIALIZATION");
+
+ let null_name_rows = json!([
+ {
+ "type": "table",
+ "name": null,
+ "table_name": "tb_a",
+ "sql": "CREATE TABLE tb_a (id TEXT);"
+ }
+ ])
+ .to_string();
+ let executor = PatternExecutor::new().with_query_rule(schema_query, &null_name_rows);
+ let backup = export_database_backup(&executor).expect("backup with null-name schema rows");
+ assert!(backup.schema.is_empty());
+}
+
+#[test]
+fn export_manifest_public_api_error_paths_cover_library_instantiations() {
+ let schema_query = "select type, name, tbl_name as table_name, sql from sqlite_master";
+
+ let executor = PatternExecutor::new().with_query_failure(schema_query);
+ assert_sql_error_code(export_manifest(&executor), "ERR_INVALID_QUERY");
+
+ let schema_rows = json!([
+ {
+ "type": "table",
+ "name": "tb_a",
+ "table_name": "tb_a",
+ "sql": "CREATE TABLE tb_a (id TEXT);"
+ }
+ ])
+ .to_string();
+
+ let executor = PatternExecutor::new()
+ .with_query_rule(schema_query, &schema_rows)
+ .with_query_failure("select count(1) as count from \"tb_a\"");
+ assert_sql_error_code(export_manifest(&executor), "ERR_INVALID_QUERY");
+
+ let executor = PatternExecutor::new()
+ .with_query_rule(schema_query, &schema_rows)
+ .with_query_rule("select count(1) as count from \"tb_a\"", "{");
+ assert_sql_error_code(export_manifest(&executor), "ERR_SERIALIZATION");
+
+ let executor = PatternExecutor::new()
+ .with_query_rule(schema_query, &schema_rows)
+ .with_query_rule("select count(1) as count from \"tb_a\"", "[]");
+ let manifest = export_manifest(&executor).expect("manifest success");
+ assert_eq!(manifest.table_counts.len(), 1);
+}
diff --git a/crates/replica-db/tests/error_paths.rs b/crates/replica-db/tests/error_paths.rs
@@ -32,11 +32,11 @@ use radroots_replica_db_schema::nostr_event_state::{
INostrEventStateCreate, INostrEventStateDelete, INostrEventStateFindMany,
INostrEventStateFindOne, INostrEventStateUpdate,
};
-use radroots_replica_db_schema::nostr_profile_relay::INostrProfileRelayRelation;
use radroots_replica_db_schema::nostr_profile::{
INostrProfileCreate, INostrProfileDelete, INostrProfileFindMany, INostrProfileFindOne,
INostrProfileUpdate,
};
+use radroots_replica_db_schema::nostr_profile_relay::INostrProfileRelayRelation;
use radroots_replica_db_schema::nostr_relay::{
INostrRelayCreate, INostrRelayDelete, INostrRelayFindMany, INostrRelayFindOne,
INostrRelayUpdate,
diff --git a/crates/replica-db/tests/region_scripted_paths.rs b/crates/replica-db/tests/region_scripted_paths.rs
@@ -0,0 +1,741 @@
+use std::collections::VecDeque;
+use std::sync::Mutex;
+
+use radroots_replica_db::{ExecOutcome, ReplicaSql, SqlError, SqlExecutor};
+use radroots_replica_db_schema::farm::{
+ IFarmCreate, IFarmDelete, IFarmFindMany, IFarmFindOne, IFarmUpdate,
+};
+use radroots_replica_db_schema::farm_gcs_location::{
+ IFarmGcsLocationCreate, IFarmGcsLocationDelete, IFarmGcsLocationFindMany,
+ IFarmGcsLocationFindOne, IFarmGcsLocationUpdate,
+};
+use radroots_replica_db_schema::farm_member::{
+ IFarmMemberCreate, IFarmMemberDelete, IFarmMemberFindMany, IFarmMemberFindOne,
+ IFarmMemberUpdate,
+};
+use radroots_replica_db_schema::farm_member_claim::{
+ IFarmMemberClaimCreate, IFarmMemberClaimDelete, IFarmMemberClaimFindMany,
+ IFarmMemberClaimFindOne, IFarmMemberClaimUpdate,
+};
+use radroots_replica_db_schema::farm_tag::{
+ IFarmTagCreate, IFarmTagDelete, IFarmTagFindMany, IFarmTagFindOne, IFarmTagUpdate,
+};
+use radroots_replica_db_schema::gcs_location::{
+ GcsLocationFarmArgs, GcsLocationFindManyRel, GcsLocationPlotArgs, GcsLocationTradeProductArgs,
+ IGcsLocationCreate, IGcsLocationDelete, IGcsLocationFindMany, IGcsLocationFindOne,
+ IGcsLocationFindOneRelArgs, IGcsLocationUpdate,
+};
+use radroots_replica_db_schema::log_error::{
+ ILogErrorCreate, ILogErrorDelete, ILogErrorFindMany, ILogErrorFindOne, ILogErrorUpdate,
+};
+use radroots_replica_db_schema::media_image::{
+ IMediaImageCreate, IMediaImageDelete, IMediaImageFindMany, IMediaImageFindOne,
+ IMediaImageFindOneRelArgs, IMediaImageUpdate, MediaImageFindManyRel,
+ MediaImageTradeProductArgs,
+};
+use radroots_replica_db_schema::nostr_event_state::{
+ INostrEventStateCreate, INostrEventStateDelete, INostrEventStateFindMany,
+ INostrEventStateFindOne, INostrEventStateUpdate,
+};
+use radroots_replica_db_schema::nostr_profile::{
+ INostrProfileCreate, INostrProfileDelete, INostrProfileFindMany, INostrProfileFindOne,
+ INostrProfileFindOneRelArgs, INostrProfileUpdate, NostrProfileFindManyRel,
+ NostrProfileRelayArgs,
+};
+use radroots_replica_db_schema::nostr_relay::{
+ INostrRelayCreate, INostrRelayDelete, INostrRelayFindMany, INostrRelayFindOne,
+ INostrRelayFindOneRelArgs, INostrRelayUpdate, NostrRelayFindManyRel, NostrRelayProfileArgs,
+};
+use radroots_replica_db_schema::plot::{
+ IPlotCreate, IPlotDelete, IPlotFindMany, IPlotFindOne, IPlotUpdate,
+};
+use radroots_replica_db_schema::plot_gcs_location::{
+ IPlotGcsLocationCreate, IPlotGcsLocationDelete, IPlotGcsLocationFindMany,
+ IPlotGcsLocationFindOne, IPlotGcsLocationUpdate,
+};
+use radroots_replica_db_schema::plot_tag::{
+ IPlotTagCreate, IPlotTagDelete, IPlotTagFindMany, IPlotTagFindOne, IPlotTagUpdate,
+};
+use radroots_replica_db_schema::trade_product::{
+ ITradeProductCreate, ITradeProductFindMany, ITradeProductFindOne, ITradeProductUpdate,
+};
+use radroots_types::types::IError;
+use serde::de::DeserializeOwned;
+use serde_json::json;
+
+struct ScriptedExecutor {
+ exec_results: Mutex<VecDeque<Result<ExecOutcome, SqlError>>>,
+ query_results: Mutex<VecDeque<Result<String, SqlError>>>,
+ begin_results: Mutex<VecDeque<Result<(), SqlError>>>,
+ commit_results: Mutex<VecDeque<Result<(), SqlError>>>,
+ rollback_results: Mutex<VecDeque<Result<(), SqlError>>>,
+}
+
+impl ScriptedExecutor {
+ fn new(
+ exec_results: Vec<Result<ExecOutcome, SqlError>>,
+ query_results: Vec<Result<String, SqlError>>,
+ ) -> Self {
+ Self {
+ exec_results: Mutex::new(VecDeque::from(exec_results)),
+ query_results: Mutex::new(VecDeque::from(query_results)),
+ begin_results: Mutex::new(VecDeque::new()),
+ commit_results: Mutex::new(VecDeque::new()),
+ rollback_results: Mutex::new(VecDeque::new()),
+ }
+ }
+}
+
+impl SqlExecutor for ScriptedExecutor {
+ fn exec(&self, _sql: &str, _params_json: &str) -> Result<ExecOutcome, SqlError> {
+ if let Some(result) = self
+ .exec_results
+ .lock()
+ .expect("lock exec queue")
+ .pop_front()
+ {
+ result
+ } else {
+ Ok(ExecOutcome {
+ changes: 1,
+ last_insert_id: 1,
+ })
+ }
+ }
+
+ fn query_raw(&self, _sql: &str, _params_json: &str) -> Result<String, SqlError> {
+ if let Some(result) = self
+ .query_results
+ .lock()
+ .expect("lock query queue")
+ .pop_front()
+ {
+ result
+ } else {
+ Ok(String::from("[]"))
+ }
+ }
+
+ fn begin(&self) -> Result<(), SqlError> {
+ if let Some(result) = self
+ .begin_results
+ .lock()
+ .expect("lock begin queue")
+ .pop_front()
+ {
+ result
+ } else {
+ Ok(())
+ }
+ }
+
+ fn commit(&self) -> Result<(), SqlError> {
+ if let Some(result) = self
+ .commit_results
+ .lock()
+ .expect("lock commit queue")
+ .pop_front()
+ {
+ result
+ } else {
+ Ok(())
+ }
+ }
+
+ fn rollback(&self) -> Result<(), SqlError> {
+ if let Some(result) = self
+ .rollback_results
+ .lock()
+ .expect("lock rollback queue")
+ .pop_front()
+ {
+ result
+ } else {
+ Ok(())
+ }
+ }
+}
+
+fn parse_json<T: DeserializeOwned>(value: serde_json::Value) -> T {
+ serde_json::from_value(value).expect("valid test payload")
+}
+
+fn hex64(ch: char) -> String {
+ std::iter::repeat_n(ch, 64).collect()
+}
+
+fn err_query() -> Result<String, SqlError> {
+ Err(SqlError::InvalidQuery(String::from("forced query error")))
+}
+
+fn bad_json() -> Result<String, SqlError> {
+ Ok(String::from("{"))
+}
+
+fn ok_rows() -> Result<String, SqlError> {
+ Ok(String::from("[]"))
+}
+
+fn ok_exec() -> Result<ExecOutcome, SqlError> {
+ Ok(ExecOutcome {
+ changes: 1,
+ last_insert_id: 1,
+ })
+}
+
+fn db_with_scripts(
+ exec_results: Vec<Result<ExecOutcome, SqlError>>,
+ query_results: Vec<Result<String, SqlError>>,
+) -> ReplicaSql<ScriptedExecutor> {
+ ReplicaSql::new(ScriptedExecutor::new(exec_results, query_results))
+}
+
+fn assert_ierror_code<T>(result: Result<T, IError<SqlError>>, code: &str) {
+ let err = match result {
+ Ok(_) => panic!("expected ierror"),
+ Err(err) => err,
+ };
+ assert_eq!(err.err.code(), code);
+}
+
+macro_rules! assert_secondary_model_paths {
+ (
+ $test_name:ident,
+ $create_ty:ty, $create_json:expr, $create_call:ident,
+ $find_many_ty:ty, $find_many_json:expr, $find_many_call:ident,
+ $find_one_ty:ty, $find_one_json:expr, $find_one_call:ident,
+ $update_ty:ty, $update_id_json:expr, $update_lookup_json:expr, $update_call:ident,
+ $delete_ty:ty, $delete_lookup_json:expr, $delete_call:ident
+ ) => {
+ #[test]
+ fn $test_name() {
+ let create_opts: $create_ty = parse_json($create_json);
+
+ let db = db_with_scripts(vec![ok_exec()], vec![err_query()]);
+ assert_ierror_code(db.$create_call(&create_opts), "ERR_INVALID_QUERY");
+
+ let db = db_with_scripts(vec![ok_exec()], vec![ok_rows()]);
+ assert_ierror_code(db.$create_call(&create_opts), "ERR_NOT_FOUND");
+
+ let find_many_opts: $find_many_ty = parse_json($find_many_json);
+ let db = db_with_scripts(vec![], vec![bad_json()]);
+ assert_ierror_code(db.$find_many_call(&find_many_opts), "ERR_SERIALIZATION");
+
+ let find_one_opts: $find_one_ty = parse_json($find_one_json);
+ let db = db_with_scripts(vec![], vec![bad_json()]);
+ assert_ierror_code(db.$find_one_call(&find_one_opts), "ERR_SERIALIZATION");
+
+ let update_id_opts: $update_ty = parse_json($update_id_json);
+ let db = db_with_scripts(vec![ok_exec()], vec![err_query()]);
+ assert_ierror_code(db.$update_call(&update_id_opts), "ERR_INVALID_QUERY");
+
+ let db = db_with_scripts(vec![ok_exec()], vec![bad_json()]);
+ assert_ierror_code(db.$update_call(&update_id_opts), "ERR_SERIALIZATION");
+
+ let update_lookup_opts: $update_ty = parse_json($update_lookup_json);
+ let db = db_with_scripts(vec![], vec![err_query()]);
+ assert_ierror_code(db.$update_call(&update_lookup_opts), "ERR_INVALID_QUERY");
+
+ let delete_lookup_opts: $delete_ty = parse_json($delete_lookup_json);
+ let db = db_with_scripts(vec![], vec![err_query()]);
+ assert_ierror_code(db.$delete_call(&delete_lookup_opts), "ERR_INVALID_QUERY");
+ }
+ };
+}
+
+macro_rules! assert_rel_model_paths {
+ (
+ $test_name:ident,
+ $create_ty:ty, $create_json:expr, $create_call:ident,
+ $find_many_ty:ty, $find_many_filter_json:expr, $find_many_rel_expr:expr, $find_many_call:ident,
+ $find_one_ty:ty, $find_one_on_json:expr, $find_one_rel_expr:expr, $find_one_call:ident,
+ $update_ty:ty, $update_id_json:expr, $update_lookup_json:expr, $update_call:ident,
+ $delete_ty:ty, $delete_lookup_json:expr, $delete_rel_expr:expr, $delete_call:ident
+ ) => {
+ #[test]
+ fn $test_name() {
+ let create_opts: $create_ty = parse_json($create_json);
+
+ let db = db_with_scripts(vec![ok_exec()], vec![err_query()]);
+ assert_ierror_code(db.$create_call(&create_opts), "ERR_INVALID_QUERY");
+
+ let db = db_with_scripts(vec![ok_exec()], vec![ok_rows()]);
+ assert_ierror_code(db.$create_call(&create_opts), "ERR_NOT_FOUND");
+
+ let find_many_filter_opts: $find_many_ty = parse_json($find_many_filter_json);
+ let db = db_with_scripts(vec![], vec![bad_json()]);
+ assert_ierror_code(
+ db.$find_many_call(&find_many_filter_opts),
+ "ERR_SERIALIZATION",
+ );
+
+ let find_many_rel_opts: $find_many_ty = $find_many_rel_expr;
+ let db = db_with_scripts(vec![], vec![bad_json()]);
+ assert_ierror_code(db.$find_many_call(&find_many_rel_opts), "ERR_SERIALIZATION");
+
+ let find_many_rel_opts: $find_many_ty = $find_many_rel_expr;
+ let db = db_with_scripts(vec![], vec![err_query()]);
+ assert_ierror_code(db.$find_many_call(&find_many_rel_opts), "ERR_INVALID_QUERY");
+
+ let find_one_on_opts: $find_one_ty = parse_json($find_one_on_json);
+ let db = db_with_scripts(vec![], vec![bad_json()]);
+ assert_ierror_code(db.$find_one_call(&find_one_on_opts), "ERR_SERIALIZATION");
+
+ let find_one_rel_opts: $find_one_ty = $find_one_rel_expr;
+ let db = db_with_scripts(vec![], vec![bad_json()]);
+ assert_ierror_code(db.$find_one_call(&find_one_rel_opts), "ERR_SERIALIZATION");
+
+ let update_id_opts: $update_ty = parse_json($update_id_json);
+ let db = db_with_scripts(vec![ok_exec()], vec![err_query()]);
+ assert_ierror_code(db.$update_call(&update_id_opts), "ERR_INVALID_QUERY");
+
+ let db = db_with_scripts(vec![ok_exec()], vec![bad_json()]);
+ assert_ierror_code(db.$update_call(&update_id_opts), "ERR_SERIALIZATION");
+
+ let update_lookup_opts: $update_ty = parse_json($update_lookup_json);
+ let db = db_with_scripts(vec![], vec![err_query()]);
+ assert_ierror_code(db.$update_call(&update_lookup_opts), "ERR_INVALID_QUERY");
+
+ let delete_lookup_opts: $delete_ty = parse_json($delete_lookup_json);
+ let db = db_with_scripts(vec![], vec![err_query()]);
+ assert_ierror_code(db.$delete_call(&delete_lookup_opts), "ERR_INVALID_QUERY");
+
+ let delete_rel_opts: $delete_ty = $delete_rel_expr;
+ let db = db_with_scripts(vec![], vec![err_query()]);
+ assert_ierror_code(db.$delete_call(&delete_rel_opts), "ERR_INVALID_QUERY");
+ }
+ };
+}
+
+macro_rules! assert_trade_product_paths {
+ (
+ $test_name:ident,
+ $create_ty:ty, $create_json:expr, $create_call:ident,
+ $find_many_ty:ty, $find_many_json:expr, $find_many_call:ident,
+ $find_one_ty:ty, $find_one_json:expr, $find_one_call:ident,
+ $update_ty:ty, $update_json:expr, $update_call:ident
+ ) => {
+ #[test]
+ fn $test_name() {
+ let create_opts: $create_ty = parse_json($create_json);
+
+ let db = db_with_scripts(vec![ok_exec()], vec![err_query()]);
+ assert_ierror_code(db.$create_call(&create_opts), "ERR_INVALID_QUERY");
+
+ let db = db_with_scripts(vec![ok_exec()], vec![ok_rows()]);
+ assert_ierror_code(db.$create_call(&create_opts), "ERR_NOT_FOUND");
+
+ let find_many_opts: $find_many_ty = parse_json($find_many_json);
+ let db = db_with_scripts(vec![], vec![bad_json()]);
+ assert_ierror_code(db.$find_many_call(&find_many_opts), "ERR_SERIALIZATION");
+
+ let find_one_opts: $find_one_ty = parse_json($find_one_json);
+ let db = db_with_scripts(vec![], vec![bad_json()]);
+ assert_ierror_code(db.$find_one_call(&find_one_opts), "ERR_SERIALIZATION");
+
+ let update_opts: $update_ty = parse_json($update_json);
+ let db = db_with_scripts(vec![ok_exec()], vec![err_query()]);
+ assert_ierror_code(db.$update_call(&update_opts), "ERR_INVALID_QUERY");
+
+ let db = db_with_scripts(vec![ok_exec()], vec![bad_json()]);
+ assert_ierror_code(db.$update_call(&update_opts), "ERR_SERIALIZATION");
+ }
+ };
+}
+
+assert_secondary_model_paths!(
+ farm_scripted_region_paths,
+ IFarmCreate,
+ json!({ "d_tag": "farm-a", "pubkey": hex64('a'), "name": "farm a" }),
+ farm_create,
+ IFarmFindMany,
+ json!({ "filter": { "id": "id-1" } }),
+ farm_find_many,
+ IFarmFindOne,
+ json!({ "on": { "id": "id-1" } }),
+ farm_find_one,
+ IFarmUpdate,
+ json!({ "on": { "id": "id-1" }, "fields": { "name": "farm z" } }),
+ json!({ "on": { "d_tag": "farm-a" }, "fields": { "name": "farm y" } }),
+ farm_update,
+ IFarmDelete,
+ json!({ "on": { "d_tag": "farm-a" } }),
+ farm_delete
+);
+
+assert_secondary_model_paths!(
+ plot_scripted_region_paths,
+ IPlotCreate,
+ json!({ "d_tag": "plot-a", "farm_id": "farm-1", "name": "plot a" }),
+ plot_create,
+ IPlotFindMany,
+ json!({ "filter": { "id": "id-1" } }),
+ plot_find_many,
+ IPlotFindOne,
+ json!({ "on": { "id": "id-1" } }),
+ plot_find_one,
+ IPlotUpdate,
+ json!({ "on": { "id": "id-1" }, "fields": { "name": "plot z" } }),
+ json!({ "on": { "d_tag": "plot-a" }, "fields": { "name": "plot y" } }),
+ plot_update,
+ IPlotDelete,
+ json!({ "on": { "d_tag": "plot-a" } }),
+ plot_delete
+);
+
+assert_secondary_model_paths!(
+ farm_gcs_location_scripted_region_paths,
+ IFarmGcsLocationCreate,
+ json!({ "farm_id": "farm-1", "gcs_location_id": "gcs-1", "role": "primary" }),
+ farm_gcs_location_create,
+ IFarmGcsLocationFindMany,
+ json!({ "filter": { "id": "id-1" } }),
+ farm_gcs_location_find_many,
+ IFarmGcsLocationFindOne,
+ json!({ "on": { "id": "id-1" } }),
+ farm_gcs_location_find_one,
+ IFarmGcsLocationUpdate,
+ json!({ "on": { "id": "id-1" }, "fields": { "role": "z" } }),
+ json!({ "on": { "farm_id": "farm-1" }, "fields": { "role": "y" } }),
+ farm_gcs_location_update,
+ IFarmGcsLocationDelete,
+ json!({ "on": { "farm_id": "farm-1" } }),
+ farm_gcs_location_delete
+);
+
+assert_secondary_model_paths!(
+ plot_gcs_location_scripted_region_paths,
+ IPlotGcsLocationCreate,
+ json!({ "plot_id": "plot-1", "gcs_location_id": "gcs-1", "role": "primary" }),
+ plot_gcs_location_create,
+ IPlotGcsLocationFindMany,
+ json!({ "filter": { "id": "id-1" } }),
+ plot_gcs_location_find_many,
+ IPlotGcsLocationFindOne,
+ json!({ "on": { "id": "id-1" } }),
+ plot_gcs_location_find_one,
+ IPlotGcsLocationUpdate,
+ json!({ "on": { "id": "id-1" }, "fields": { "role": "z" } }),
+ json!({ "on": { "plot_id": "plot-1" }, "fields": { "role": "y" } }),
+ plot_gcs_location_update,
+ IPlotGcsLocationDelete,
+ json!({ "on": { "plot_id": "plot-1" } }),
+ plot_gcs_location_delete
+);
+
+assert_secondary_model_paths!(
+ farm_tag_scripted_region_paths,
+ IFarmTagCreate,
+ json!({ "farm_id": "farm-1", "tag": "organic" }),
+ farm_tag_create,
+ IFarmTagFindMany,
+ json!({ "filter": { "id": "id-1" } }),
+ farm_tag_find_many,
+ IFarmTagFindOne,
+ json!({ "on": { "id": "id-1" } }),
+ farm_tag_find_one,
+ IFarmTagUpdate,
+ json!({ "on": { "id": "id-1" }, "fields": { "tag": "z" } }),
+ json!({ "on": { "farm_id": "farm-1" }, "fields": { "tag": "y" } }),
+ farm_tag_update,
+ IFarmTagDelete,
+ json!({ "on": { "farm_id": "farm-1" } }),
+ farm_tag_delete
+);
+
+assert_secondary_model_paths!(
+ plot_tag_scripted_region_paths,
+ IPlotTagCreate,
+ json!({ "plot_id": "plot-1", "tag": "north" }),
+ plot_tag_create,
+ IPlotTagFindMany,
+ json!({ "filter": { "id": "id-1" } }),
+ plot_tag_find_many,
+ IPlotTagFindOne,
+ json!({ "on": { "id": "id-1" } }),
+ plot_tag_find_one,
+ IPlotTagUpdate,
+ json!({ "on": { "id": "id-1" }, "fields": { "tag": "z" } }),
+ json!({ "on": { "plot_id": "plot-1" }, "fields": { "tag": "y" } }),
+ plot_tag_update,
+ IPlotTagDelete,
+ json!({ "on": { "plot_id": "plot-1" } }),
+ plot_tag_delete
+);
+
+assert_secondary_model_paths!(
+ farm_member_scripted_region_paths,
+ IFarmMemberCreate,
+ json!({ "farm_id": "farm-1", "member_pubkey": hex64('b'), "role": "owner" }),
+ farm_member_create,
+ IFarmMemberFindMany,
+ json!({ "filter": { "id": "id-1" } }),
+ farm_member_find_many,
+ IFarmMemberFindOne,
+ json!({ "on": { "id": "id-1" } }),
+ farm_member_find_one,
+ IFarmMemberUpdate,
+ json!({ "on": { "id": "id-1" }, "fields": { "role": "z" } }),
+ json!({ "on": { "member_pubkey": hex64('b') }, "fields": { "role": "y" } }),
+ farm_member_update,
+ IFarmMemberDelete,
+ json!({ "on": { "member_pubkey": hex64('b') } }),
+ farm_member_delete
+);
+
+assert_secondary_model_paths!(
+ farm_member_claim_scripted_region_paths,
+ IFarmMemberClaimCreate,
+ json!({ "member_pubkey": hex64('b'), "farm_pubkey": hex64('a') }),
+ farm_member_claim_create,
+ IFarmMemberClaimFindMany,
+ json!({ "filter": { "id": "id-1" } }),
+ farm_member_claim_find_many,
+ IFarmMemberClaimFindOne,
+ json!({ "on": { "id": "id-1" } }),
+ farm_member_claim_find_one,
+ IFarmMemberClaimUpdate,
+ json!({ "on": { "id": "id-1" }, "fields": { "farm_pubkey": hex64('c') } }),
+ json!({ "on": { "member_pubkey": hex64('b') }, "fields": { "farm_pubkey": hex64('d') } }),
+ farm_member_claim_update,
+ IFarmMemberClaimDelete,
+ json!({ "on": { "member_pubkey": hex64('b') } }),
+ farm_member_claim_delete
+);
+
+assert_secondary_model_paths!(
+ log_error_scripted_region_paths,
+ ILogErrorCreate,
+ json!({
+ "error": "panic",
+ "message": "boom",
+ "app_system": "studio",
+ "app_version": "1.0.0",
+ "nostr_pubkey": hex64('c')
+ }),
+ log_error_create,
+ ILogErrorFindMany,
+ json!({ "filter": { "id": "id-1" } }),
+ log_error_find_many,
+ ILogErrorFindOne,
+ json!({ "on": { "id": "id-1" } }),
+ log_error_find_one,
+ ILogErrorUpdate,
+ json!({ "on": { "id": "id-1" }, "fields": { "message": "z" } }),
+ json!({ "on": { "nostr_pubkey": hex64('c') }, "fields": { "message": "y" } }),
+ log_error_update,
+ ILogErrorDelete,
+ json!({ "on": { "nostr_pubkey": hex64('c') } }),
+ log_error_delete
+);
+
+assert_secondary_model_paths!(
+ nostr_event_state_scripted_region_paths,
+ INostrEventStateCreate,
+ json!({
+ "key": "state-a",
+ "kind": 30023,
+ "pubkey": hex64('d'),
+ "d_tag": "listing-a",
+ "last_event_id": hex64('e'),
+ "last_created_at": 1,
+ "content_hash": "hash-a"
+ }),
+ nostr_event_state_create,
+ INostrEventStateFindMany,
+ json!({ "filter": { "id": "id-1" } }),
+ nostr_event_state_find_many,
+ INostrEventStateFindOne,
+ json!({ "on": { "id": "id-1" } }),
+ nostr_event_state_find_one,
+ INostrEventStateUpdate,
+ json!({ "on": { "id": "id-1" }, "fields": { "content_hash": "hash-z" } }),
+ json!({ "on": { "key": "state-a" }, "fields": { "content_hash": "hash-y" } }),
+ nostr_event_state_update,
+ INostrEventStateDelete,
+ json!({ "on": { "key": "state-a" } }),
+ nostr_event_state_delete
+);
+
+assert_rel_model_paths!(
+ gcs_location_scripted_region_paths,
+ IGcsLocationCreate,
+ json!({
+ "d_tag": "gcs-a",
+ "lat": 59.33,
+ "lng": 18.06,
+ "geohash": "u6sce4f",
+ "point": "POINT(18.06 59.33)",
+ "polygon": "POLYGON((18.06 59.33,18.07 59.33,18.07 59.34,18.06 59.34,18.06 59.33))"
+ }),
+ gcs_location_create,
+ IGcsLocationFindMany,
+ json!({ "filter": { "id": "id-1" } }),
+ IGcsLocationFindMany::Rel {
+ rel: GcsLocationFindManyRel::OnFarm(GcsLocationFarmArgs {
+ id: String::from("farm-1")
+ })
+ },
+ gcs_location_find_many,
+ IGcsLocationFindOne,
+ json!({ "on": { "id": "id-1" } }),
+ IGcsLocationFindOne::Rel(IGcsLocationFindOneRelArgs {
+ rel: GcsLocationFindManyRel::OffTradeProduct(GcsLocationTradeProductArgs {
+ id: String::from("tp-1")
+ })
+ }),
+ gcs_location_find_one,
+ IGcsLocationUpdate,
+ json!({ "on": { "id": "id-1" }, "fields": { "label": "z" } }),
+ json!({ "on": { "d_tag": "gcs-a" }, "fields": { "label": "y" } }),
+ gcs_location_update,
+ IGcsLocationDelete,
+ json!({ "on": { "d_tag": "gcs-a" } }),
+ IGcsLocationDelete::Rel(IGcsLocationFindOneRelArgs {
+ rel: GcsLocationFindManyRel::OnPlot(GcsLocationPlotArgs {
+ id: String::from("plot-1")
+ })
+ }),
+ gcs_location_delete
+);
+
+assert_rel_model_paths!(
+ media_image_scripted_region_paths,
+ IMediaImageCreate,
+ json!({
+ "file_path": "/img/a.jpg",
+ "mime_type": "image/jpeg",
+ "res_base": "https://cdn.example.com",
+ "res_path": "img/a.jpg"
+ }),
+ media_image_create,
+ IMediaImageFindMany,
+ json!({ "filter": { "id": "id-1" } }),
+ IMediaImageFindMany::Rel {
+ rel: MediaImageFindManyRel::OnTradeProduct(MediaImageTradeProductArgs {
+ id: String::from("tp-1")
+ })
+ },
+ media_image_find_many,
+ IMediaImageFindOne,
+ json!({ "on": { "id": "id-1" } }),
+ IMediaImageFindOne::Rel(IMediaImageFindOneRelArgs {
+ rel: MediaImageFindManyRel::OffTradeProduct(MediaImageTradeProductArgs {
+ id: String::from("tp-1")
+ })
+ }),
+ media_image_find_one,
+ IMediaImageUpdate,
+ json!({ "on": { "id": "id-1" }, "fields": { "label": "z" } }),
+ json!({ "on": { "file_path": "/img/a.jpg" }, "fields": { "label": "y" } }),
+ media_image_update,
+ IMediaImageDelete,
+ json!({ "on": { "file_path": "/img/a.jpg" } }),
+ IMediaImageDelete::Rel(IMediaImageFindOneRelArgs {
+ rel: MediaImageFindManyRel::OnTradeProduct(MediaImageTradeProductArgs {
+ id: String::from("tp-1")
+ })
+ }),
+ media_image_delete
+);
+
+assert_rel_model_paths!(
+ nostr_profile_scripted_region_paths,
+ INostrProfileCreate,
+ json!({ "public_key": hex64('d'), "profile_type": "farm", "name": "profile a" }),
+ nostr_profile_create,
+ INostrProfileFindMany,
+ json!({ "filter": { "id": "id-1" } }),
+ INostrProfileFindMany::Rel {
+ rel: NostrProfileFindManyRel::OnRelay(NostrProfileRelayArgs {
+ id: String::from("relay-1")
+ })
+ },
+ nostr_profile_find_many,
+ INostrProfileFindOne,
+ json!({ "on": { "id": "id-1" } }),
+ INostrProfileFindOne::Rel(INostrProfileFindOneRelArgs {
+ rel: NostrProfileFindManyRel::OffRelay(NostrProfileRelayArgs {
+ id: String::from("relay-1")
+ })
+ }),
+ nostr_profile_find_one,
+ INostrProfileUpdate,
+ json!({ "on": { "id": "id-1" }, "fields": { "name": "z" } }),
+ json!({ "on": { "public_key": hex64('d') }, "fields": { "name": "y" } }),
+ nostr_profile_update,
+ INostrProfileDelete,
+ json!({ "on": { "public_key": hex64('d') } }),
+ INostrProfileDelete::Rel(INostrProfileFindOneRelArgs {
+ rel: NostrProfileFindManyRel::OnRelay(NostrProfileRelayArgs {
+ id: String::from("relay-1")
+ })
+ }),
+ nostr_profile_delete
+);
+
+assert_rel_model_paths!(
+ nostr_relay_scripted_region_paths,
+ INostrRelayCreate,
+ json!({ "url": "wss://relay.example.com" }),
+ nostr_relay_create,
+ INostrRelayFindMany,
+ json!({ "filter": { "id": "id-1" } }),
+ INostrRelayFindMany::Rel {
+ rel: NostrRelayFindManyRel::OnProfile(NostrRelayProfileArgs {
+ public_key: hex64('d')
+ })
+ },
+ nostr_relay_find_many,
+ INostrRelayFindOne,
+ json!({ "on": { "id": "id-1" } }),
+ INostrRelayFindOne::Rel(INostrRelayFindOneRelArgs {
+ rel: NostrRelayFindManyRel::OffProfile(NostrRelayProfileArgs {
+ public_key: hex64('d')
+ })
+ }),
+ nostr_relay_find_one,
+ INostrRelayUpdate,
+ json!({ "on": { "id": "id-1" }, "fields": { "name": "z" } }),
+ json!({ "on": { "url": "wss://relay.example.com" }, "fields": { "name": "y" } }),
+ nostr_relay_update,
+ INostrRelayDelete,
+ json!({ "on": { "url": "wss://relay.example.com" } }),
+ INostrRelayDelete::Rel(INostrRelayFindOneRelArgs {
+ rel: NostrRelayFindManyRel::OnProfile(NostrRelayProfileArgs {
+ public_key: hex64('d')
+ })
+ }),
+ nostr_relay_delete
+);
+
+assert_trade_product_paths!(
+ trade_product_scripted_region_paths,
+ ITradeProductCreate,
+ json!({
+ "key": "product-a",
+ "category": "coffee",
+ "title": "coffee a",
+ "summary": "summary",
+ "process": "washed",
+ "lot": "lot-a",
+ "profile": "floral",
+ "year": 2024,
+ "qty_amt": 100,
+ "qty_unit": "kg",
+ "price_amt": 7.5,
+ "price_currency": "USD",
+ "price_qty_amt": 1,
+ "price_qty_unit": "kg"
+ }),
+ trade_product_create,
+ ITradeProductFindMany,
+ json!({ "filter": { "id": "id-1" } }),
+ trade_product_find_many,
+ ITradeProductFindOne,
+ json!({ "on": { "id": "id-1" } }),
+ trade_product_find_one,
+ ITradeProductUpdate,
+ json!({ "on": { "id": "id-1" }, "fields": { "title": "z" } }),
+ trade_product_update
+);