earl_protocol_sql/
executor.rs1use anyhow::{Result, bail};
2use serde_json::Value;
3
4use earl_core::{ExecutionContext, ProtocolExecutor, RawExecutionResult};
5
6use crate::PreparedSqlQuery;
7
8pub async fn execute_sql_once(
10 data: &PreparedSqlQuery,
11 ctx: &ExecutionContext,
12) -> Result<RawExecutionResult> {
13 let result = crate::sandbox::execute_query(
14 &data.connection_url,
15 &data.query,
16 &data.params,
17 data.read_only,
18 data.max_rows,
19 ctx.transport.timeout,
20 )
21 .await;
22
23 let rows = match result {
25 Ok(rows) => rows,
26 Err(err) => {
27 let redacted_msg = ctx.redactor.redact(&format!("{err:#}"));
28 bail!("SQL query failed: {redacted_msg}");
29 }
30 };
31
32 let result_value = Value::Array(rows.into_iter().map(Value::Object).collect());
33 let body = serde_json::to_vec(&result_value)?;
34
35 Ok(RawExecutionResult {
36 status: 0,
37 url: "sql://query".into(),
38 body,
39 content_type: Some("application/json".to_string()),
40 })
41}
42
43pub struct SqlExecutor;
45
46impl ProtocolExecutor for SqlExecutor {
47 type PreparedData = PreparedSqlQuery;
48
49 async fn execute(
50 &mut self,
51 data: &PreparedSqlQuery,
52 ctx: &ExecutionContext,
53 ) -> anyhow::Result<RawExecutionResult> {
54 execute_sql_once(data, ctx).await
55 }
56}