diff --git a/src/engine/duckdb/mod.rs b/src/engine/duckdb/mod.rs index 3ef9037..0bafbcc 100644 --- a/src/engine/duckdb/mod.rs +++ b/src/engine/duckdb/mod.rs @@ -39,7 +39,13 @@ pub struct DuckDbEngine; /// Default schema used when no `--schema` is provided. const DEFAULT_SCHEMA: &str = "main"; +// `DatabaseEngine` declares these methods as returning futures, so each impl must be +// `async` whether or not its body awaits. The DuckDB driver is synchronous, so all three +// methods here have no `.await` and trip `clippy::unused_async` -- a lint that cannot be +// satisfied without hand-rolling `impl Future` bodies purely to appease it. The +// `postgres` and `mysql` impls are unaffected because their drivers genuinely await. impl DatabaseEngine for DuckDbEngine { + #[allow(clippy::unused_async, clippy::unused_async_trait_impl)] async fn validate_connection(config: &ConnectionConfig) -> Result { let file_path = extract_file_path(config)?; let conn = open_connection(&file_path)?; @@ -60,6 +66,7 @@ impl DatabaseEngine for DuckDbEngine { }) } + #[allow(clippy::unused_async, clippy::unused_async_trait_impl)] async fn introspect( config: &ConnectionConfig, operation: &IntrospectOperation, @@ -97,6 +104,7 @@ impl DatabaseEngine for DuckDbEngine { Ok(result) } + #[allow(clippy::unused_async, clippy::unused_async_trait_impl)] async fn execute( config: &ConnectionConfig, query: &str, @@ -810,6 +818,11 @@ fn duckdb_value_to_json(value: &Value) -> serde_json::Value { Json::Object(obj) } Value::Union(inner) => duckdb_value_to_json(inner), + // `duckdb::types::Value` is #[non_exhaustive] as of duckdb 1.10505.0, so a + // wildcard is required. Rendering the Debug form keeps an unknown future + // variant VISIBLE in the JSON rather than silently nulling it out; the + // compiler's suggested `todo!()` would panic inside a live MCP server. + other => Json::String(format!("{other:?}")), } } diff --git a/src/engine/sqlite/mod.rs b/src/engine/sqlite/mod.rs index 038b50b..94d6d4b 100644 --- a/src/engine/sqlite/mod.rs +++ b/src/engine/sqlite/mod.rs @@ -31,7 +31,13 @@ use crate::error::{PlenumError, Result}; /// `SQLite` database engine implementation pub struct SqliteEngine; +// `DatabaseEngine` declares these methods as returning futures, so each impl must be +// `async` whether or not its body awaits. The SQLite driver is synchronous, so all three +// methods here have no `.await` and trip `clippy::unused_async` -- a lint that cannot be +// satisfied without hand-rolling `impl Future` bodies purely to appease it. The +// `postgres` and `mysql` impls are unaffected because their drivers genuinely await. impl DatabaseEngine for SqliteEngine { + #[allow(clippy::unused_async, clippy::unused_async_trait_impl)] async fn validate_connection(config: &ConnectionConfig) -> Result { // Validate config is for SQLite if config.engine != DatabaseType::SQLite { @@ -74,6 +80,7 @@ impl DatabaseEngine for SqliteEngine { }) } + #[allow(clippy::unused_async, clippy::unused_async_trait_impl)] async fn introspect( config: &ConnectionConfig, operation: &IntrospectOperation, @@ -149,6 +156,7 @@ impl DatabaseEngine for SqliteEngine { Ok(result) } + #[allow(clippy::unused_async, clippy::unused_async_trait_impl)] async fn execute( config: &ConnectionConfig, query: &str, diff --git a/src/main.rs b/src/main.rs index ec2d7c0..6748983 100644 --- a/src/main.rs +++ b/src/main.rs @@ -69,7 +69,7 @@ enum Commands { project_path: Option, /// Database engine - #[arg(long, value_parser = ["postgres", "mysql", "sqlite"])] + #[arg(long, value_parser = ["postgres", "mysql", "sqlite", "duckdb"])] engine: Option, /// Host (postgres/mysql) @@ -108,7 +108,7 @@ enum Commands { #[arg(long)] database: Option, - /// `SQLite` file path + /// `SQLite` / `DuckDB` file path #[arg(long)] file: Option, @@ -153,7 +153,7 @@ enum Commands { project_path: Option, /// Engine override - #[arg(long, value_parser = ["postgres", "mysql", "sqlite"])] + #[arg(long, value_parser = ["postgres", "mysql", "sqlite", "duckdb"])] engine: Option, /// Host override @@ -280,7 +280,7 @@ enum Commands { project_path: Option, /// Engine override - #[arg(long, value_parser = ["postgres", "mysql", "sqlite"])] + #[arg(long, value_parser = ["postgres", "mysql", "sqlite", "duckdb"])] engine: Option, /// Host override