pub struct SqlCodeExecutor { /* private fields */ }Expand description
CodeExecutor adapter bridging the toolkit’s single-method
SqlConnector to the code-mode validate_code / execute_code flow.
§Re-derived for the single-method trait
The production reference (mcp-sql-server-core::SqlCodeModeHandler) is
written over a 2-method DatabaseConnector (execute_query /
execute_statement) and dispatches by crate::sql’s
QueryType. The toolkit’s SqlConnector exposes a SINGLE
SqlConnector::execute entry point, so this adapter collapses that
2-method dispatch into one connector.execute(sql, ¶ms) call regardless
of statement type — re-validating the SQL FIRST for defense-in-depth. The
execute_code variables input IS bound as named params (85-10 WR-02);
it is never silently dropped.
§Defense-in-depth re-validation (threat T-85-02-01)
Before touching the connector, SqlCodeExecutor::execute re-runs the
[code_mode] policy against the supplied SQL via the same
ValidationPipeline the validate_code tool used. The code-mode
framework already verified the approval token + code hash before calling
this method, but re-validation guards against a token issued for an
allowed statement being replayed with a different (e.g. mutating)
statement. A policy violation returns Err(ExecutionError::BackendError)
BEFORE the connector is reached — a config-driven server cannot bypass the
write/DDL guards (SC-3, threat T-85-02-02).
§Observable result shape (REVIEW FIX Codex MEDIUM #6b)
The production handler returns
{"columns": [...], "rows": [...], "rows_affected": N} because its
2-method connector surfaces columns + affected-row counts separately. The
toolkit’s SqlConnector::execute returns Vec<Value> (one JSON object
per row, keyed by column name) with no separate columns/rows_affected
channel, so this adapter mirrors production’s OBSERVABLE "rows" key:
{"rows": <values>}. The parity replay (Plan 06) only exercises
execute_code with an INVALID token (asserts failure), so this success
shape is not asserted by generated.yaml; mirroring production keeps the
executor correct for any future success-path scenario and for the direct
unit assertions in this crate.
Implementations§
Source§impl SqlCodeExecutor
impl SqlCodeExecutor
Sourcepub fn new(
connector: Arc<dyn SqlConnector>,
config: ServerConfig,
) -> Result<Self>
pub fn new( connector: Arc<dyn SqlConnector>, config: ServerConfig, ) -> Result<Self>
Construct an executor over connector, enforcing the [code_mode]
policy carried by config on every SqlCodeExecutor::execute call.
The ValidationPipeline is built ONCE here (85-10 IN-01) via
validation_pipeline_from_config, so the token_secret env var is
resolved a single time at construction rather than on every request.
§Errors
Returns every error from validation_pipeline_from_config — most
notably the R9 inline-secret rejection and the secret-resolution /
16-byte-minimum failures — so a misconfigured token_secret fails at
builder time, not first request.
Trait Implementations§
Source§impl CodeExecutor for SqlCodeExecutor
impl CodeExecutor for SqlCodeExecutor
Source§fn execute<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
code: &'life1 str,
variables: Option<&'life2 Value>,
) -> Pin<Box<dyn Future<Output = Result<Value, ExecutionError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn execute<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
code: &'life1 str,
variables: Option<&'life2 Value>,
) -> Pin<Box<dyn Future<Output = Result<Value, ExecutionError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Re-validate the SQL against the [code_mode] policy, then execute it via
the single-method SqlConnector::execute.
§Errors
Returns ExecutionError::BackendError when re-validation rejects the
statement (policy violation or parse failure) or when the connector
surfaces a crate::sql::ConnectorError. Connector error messages are
surfaced verbatim from the toolkit’s already-sanitized
ConnectorError Display (T-84-01-01 / threat T-85-02-04) — no raw
backend credentials are echoed.
Auto Trait Implementations§
impl Freeze for SqlCodeExecutor
impl !RefUnwindSafe for SqlCodeExecutor
impl Send for SqlCodeExecutor
impl Sync for SqlCodeExecutor
impl Unpin for SqlCodeExecutor
impl UnsafeUnpin for SqlCodeExecutor
impl !UnwindSafe for SqlCodeExecutor
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more