fix(query): preserve structured backend errors

This commit is contained in:
miracle authored and GitHub committed 2026-08-02 16:37:46 +08:00
1 parent 2e9dcdc26b
commit bcafc4a474
58 files changed
+4182 -554

No files matched your search

+8 -7
View File
@@ -472,6 +472,7 @@ fn user_shell_node_candidate() -> Option<NodeRuntimeCandidate> {
Some(NodeRuntimeCandidate { node_path })
}
#[cfg(not(windows))]
fn prefixed_output_path(output: &str, prefix: &str) -> Option<PathBuf> {
output
.lines()
@@ -834,7 +835,7 @@ fn path_string(path: &Path) -> String {
pub(crate) fn locate_command(command: &str) -> Option<String> {
#[cfg(windows)]
{
return locate_windows_command(command);
locate_windows_command(command)
}
#[cfg(not(windows))]
{
@@ -909,7 +910,7 @@ fn command_output(command: &str, args: &[&str]) -> Result<CommandOutput, String>
#[cfg(windows)]
{
return run_windows_command_candidates(command, args).or(direct);
run_windows_command_candidates(command, args).or(direct)
}
#[cfg(not(windows))]
@@ -986,7 +987,7 @@ fn windows_common_command_dirs() -> Vec<std::path::PathBuf> {
#[cfg(windows)]
fn run_command_through_user_shell(command: &str, args: &[&str]) -> Result<CommandOutput, String> {
let script = windows_command_script(command, args);
let mut output = run_command("powershell.exe", &["-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", &script])?;
let mut output = run_command("powershell.exe", ["-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", &script])?;
output.stdout = stdout_after_shell_marker(&output.stdout);
Ok(output)
}
@@ -1080,13 +1081,12 @@ mod tests {
#[cfg(windows)]
use super::first_windows_command_path;
#[cfg(not(windows))]
use super::{bash_login_script, NodeRuntimeCandidate};
use super::{bash_login_script, prefixed_output_path, NodeRuntimeCandidate};
use super::{
canonical_runtime_path, is_mcp_compatible_node_version, mcp_command_for_runtime, mcp_native_binary_path_for,
mcp_package, normalized_reported_path, npm_cli_candidates, parse_minimum_node_version, parse_node_version,
prefer_runtime, prefixed_output_path, require_managed_mcp_command, resolve_managed_mcp_command,
stdout_after_shell_marker, NodeRuntime, NodeVersion, MCP_MIN_NODE_VERSION_REQUIREMENT, MCP_PACKAGE_NAME,
SHELL_COMMAND_MARKER,
prefer_runtime, require_managed_mcp_command, resolve_managed_mcp_command, stdout_after_shell_marker,
NodeRuntime, NodeVersion, MCP_MIN_NODE_VERSION_REQUIREMENT, MCP_PACKAGE_NAME, SHELL_COMMAND_MARKER,
};
#[cfg(not(windows))]
use super::{shell_command_script, shell_quote};
@@ -1151,6 +1151,7 @@ mod tests {
}
#[test]
#[cfg(not(windows))]
fn prefixed_output_path_ignores_empty_values() {
let output = "node=/opt/node/bin/node\nmissing=\n";
+9 -6
View File
@@ -3,6 +3,7 @@ use std::time::Instant;
use tauri::{AppHandle, Emitter, State};
use crate::commands::connection::AppState;
use dbx_core::backend_error::BackendError;
use dbx_core::db;
use dbx_core::models::connection::DatabaseType;
use dbx_core::query_cancel::RunningTaskMetadata;
@@ -18,7 +19,8 @@ struct ExecuteMultiProgress {
success: bool,
execution_time_ms: u128,
affected_rows: u64,
error: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
error: Option<BackendError>,
}
#[tauri::command]
@@ -38,7 +40,7 @@ pub async fn execute_query(
client_session_id: Option<String>,
timeout_secs: Option<u64>,
execution_mode: Option<dbx_core::query::QueryExecutionMode>,
) -> Result<db::QueryResult, String> {
) -> Result<db::QueryResult, BackendError> {
let execution_id = execution_id.filter(|id| !id.trim().is_empty());
let registered_query = execution_id.as_ref().map(|id| {
state.running_queries.register_task(
@@ -48,7 +50,7 @@ pub async fn execute_query(
});
let cancel_token = registered_query.as_ref().map(|query| query.token());
dbx_core::query::execute_sql_statement_with_options(
dbx_core::query::execute_sql_statement_with_options_typed(
&state,
&connection_id,
&database,
@@ -69,6 +71,7 @@ pub async fn execute_query(
},
)
.await
.map_err(dbx_core::query::QueryExecutionError::into_backend_error)
}
#[tauri::command]
@@ -91,7 +94,7 @@ pub async fn execute_multi(
use_transaction: Option<bool>,
continue_on_error: Option<bool>,
execution_mode: Option<dbx_core::query::QueryExecutionMode>,
) -> Result<Vec<dbx_core::query::ExecuteMultiResult>, String> {
) -> Result<Vec<dbx_core::query::ExecuteMultiResult>, BackendError> {
let execution_id = execution_id.filter(|id| !id.trim().is_empty());
let registered_query = execution_id.as_ref().map(|id| {
state.running_queries.register_task(
@@ -130,7 +133,7 @@ pub async fn execute_multi(
schema
);
let result = dbx_core::query::execute_multi_core_with_options_for_client_and_progress(
let result = dbx_core::query::execute_multi_core_with_options_for_client_and_progress_typed(
&state,
&connection_id,
&database,
@@ -169,7 +172,7 @@ pub async fn execute_multi(
error
),
}
result
result.map_err(dbx_core::query::QueryExecutionError::into_backend_error)
}
#[tauri::command]