From d8fc286e94c8abaae80459b371c43fc043f65c9b Mon Sep 17 00:00:00 2001 From: Alex Groleau Date: Mon, 16 Mar 2026 19:39:24 -0400 Subject: [PATCH] better error dropping --- src/database/executors/pgrx.rs | 2 ++ src/drop.rs | 8 ++++++-- src/lib.rs | 3 +++ src/merger/mod.rs | 6 ++++++ src/queryer/mod.rs | 24 ++++++++++++++++++------ src/validator/mod.rs | 19 ++++++++++++++++--- 6 files changed, 51 insertions(+), 11 deletions(-) diff --git a/src/database/executors/pgrx.rs b/src/database/executors/pgrx.rs index 4bbcc7f..4954699 100644 --- a/src/database/executors/pgrx.rs +++ b/src/database/executors/pgrx.rs @@ -25,6 +25,7 @@ impl DatabaseExecutor for SpiExecutor { } Spi::connect(|client| { + pgrx::notice!("JSPG_SQL: {}", sql); match client.select(sql, Some(args_with_oid.len() as i64), &args_with_oid) { Ok(tup_table) => { let mut results = Vec::new(); @@ -53,6 +54,7 @@ impl DatabaseExecutor for SpiExecutor { } Spi::connect_mut(|client| { + pgrx::notice!("JSPG_SQL: {}", sql); match client.update(sql, Some(args_with_oid.len() as i64), &args_with_oid) { Ok(_) => Ok(()), Err(e) => Err(format!("SPI Execution Failure: {}", e)), diff --git a/src/drop.rs b/src/drop.rs index 2cd3317..eabbbf8 100644 --- a/src/drop.rs +++ b/src/drop.rs @@ -67,6 +67,10 @@ pub struct Error { #[derive(Debug, Serialize, Deserialize, Clone)] pub struct ErrorDetails { pub path: String, - // Extensions can be added here (package, cause, etc) - // For now, validator only provides path + #[serde(skip_serializing_if = "Option::is_none")] + pub cause: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub context: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub schema: Option, } diff --git a/src/lib.rs b/src/lib.rs index 8ed6a65..cbd72d8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,6 +31,9 @@ fn jspg_failure() -> JsonB { message: "JSPG extension has not been initialized via jspg_setup".to_string(), details: crate::drop::ErrorDetails { path: "".to_string(), + cause: None, + context: None, + schema: None, }, }; let drop = crate::drop::Drop::with_errors(vec![error]); diff --git a/src/merger/mod.rs b/src/merger/mod.rs index 7a67e4a..b55ab20 100644 --- a/src/merger/mod.rs +++ b/src/merger/mod.rs @@ -36,6 +36,9 @@ impl Merger { message: msg, details: crate::drop::ErrorDetails { path: "".to_string(), + cause: None, + context: None, + schema: None, }, }]); } @@ -49,6 +52,9 @@ impl Merger { message: format!("Executor Error in pre-ordered notify: {:?}", e), details: crate::drop::ErrorDetails { path: "".to_string(), + cause: None, + context: None, + schema: None, }, }]); } diff --git a/src/queryer/mod.rs b/src/queryer/mod.rs index e4c4e9d..8082d6e 100644 --- a/src/queryer/mod.rs +++ b/src/queryer/mod.rs @@ -32,9 +32,12 @@ impl Queryer { Err(msg) => { return crate::drop::Drop::with_errors(vec![crate::drop::Error { code: "FILTER_PARSE_FAILED".to_string(), - message: msg, + message: msg.clone(), details: crate::drop::ErrorDetails { - path: schema_id.to_string(), + path: "".to_string(), // filters apply to the root query + cause: Some(msg), + context: filters.map(|f| vec![f.to_string()]), + schema: Some(schema_id.to_string()), }, }]); } @@ -104,9 +107,12 @@ impl Queryer { } Err(e) => Err(crate::drop::Drop::with_errors(vec![crate::drop::Error { code: "QUERY_COMPILATION_FAILED".to_string(), - message: e, + message: e.clone(), details: crate::drop::ErrorDetails { - path: schema_id.to_string(), + path: "".to_string(), + cause: Some(e), + context: None, + schema: Some(schema_id.to_string()), }, }])), } @@ -130,14 +136,20 @@ impl Queryer { code: "QUERY_FAILED".to_string(), message: format!("Expected array from generic query, got: {:?}", other), details: crate::drop::ErrorDetails { - path: schema_id.to_string(), + path: "".to_string(), + cause: Some(format!("Expected array, got {}", other)), + context: Some(vec![sql.to_string()]), + schema: Some(schema_id.to_string()), }, }]), Err(e) => crate::drop::Drop::with_errors(vec![crate::drop::Error { code: "QUERY_FAILED".to_string(), message: format!("SPI error in queryer: {}", e), details: crate::drop::ErrorDetails { - path: schema_id.to_string(), + path: "".to_string(), + cause: Some(format!("SPI error in queryer: {}", e)), + context: Some(vec![sql.to_string()]), + schema: Some(schema_id.to_string()), }, }]), } diff --git a/src/validator/mod.rs b/src/validator/mod.rs index 6755c89..49dff47 100644 --- a/src/validator/mod.rs +++ b/src/validator/mod.rs @@ -67,7 +67,12 @@ impl Validator { .map(|e| crate::drop::Error { code: e.code, message: e.message, - details: crate::drop::ErrorDetails { path: e.path }, + details: crate::drop::ErrorDetails { + path: e.path, + cause: None, + context: None, + schema: None, + }, }) .collect(); crate::drop::Drop::with_errors(errors) @@ -76,7 +81,12 @@ impl Validator { Err(e) => crate::drop::Drop::with_errors(vec![crate::drop::Error { code: e.code, message: e.message, - details: crate::drop::ErrorDetails { path: e.path }, + details: crate::drop::ErrorDetails { + path: e.path, + cause: None, + context: None, + schema: None, + }, }]), } } else { @@ -84,7 +94,10 @@ impl Validator { code: "SCHEMA_NOT_FOUND".to_string(), message: format!("Schema {} not found", schema_id), details: crate::drop::ErrorDetails { - path: "".to_string(), + path: "/".to_string(), + cause: None, + context: None, + schema: None, }, }]) }