dynoxide/actions/
batch_execute_statement.rs1use crate::errors::{DynoxideError, Result};
2use crate::partiql;
3use crate::storage_backend::StorageBackend;
4use crate::types::{AttributeValue, Item};
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Default, Deserialize)]
8pub struct BatchExecuteStatementRequest {
9 #[serde(rename = "Statements")]
10 pub statements: Vec<BatchStatementRequest>,
11}
12
13#[derive(Debug, Default, Deserialize)]
14pub struct BatchStatementRequest {
15 #[serde(rename = "Statement")]
16 pub statement: String,
17 #[serde(rename = "Parameters", default)]
18 pub parameters: Option<Vec<AttributeValue>>,
19}
20
21#[derive(Debug, Default, Serialize)]
22pub struct BatchExecuteStatementResponse {
23 #[serde(rename = "Responses")]
24 pub responses: Vec<BatchStatementResponse>,
25}
26
27#[derive(Debug, Default, Serialize)]
28pub struct BatchStatementResponse {
29 #[serde(rename = "Error", skip_serializing_if = "Option::is_none")]
30 pub error: Option<BatchStatementError>,
31 #[serde(rename = "Item", skip_serializing_if = "Option::is_none")]
32 pub item: Option<Item>,
33}
34
35#[derive(Debug, Default, Serialize)]
36pub struct BatchStatementError {
37 #[serde(rename = "Code")]
38 pub code: String,
39 #[serde(rename = "Message")]
40 pub message: String,
41}
42
43pub async fn execute<S: StorageBackend>(
44 storage: &S,
45 request: BatchExecuteStatementRequest,
46) -> Result<BatchExecuteStatementResponse> {
47 if request.statements.is_empty() {
48 return Err(DynoxideError::ValidationException(
49 "1 validation error detected: Value '[]' at 'statements' failed to satisfy constraint: Member must have length greater than or equal to 1".to_string(),
50 ));
51 }
52
53 if request.statements.len() > 25 {
54 return Err(DynoxideError::ValidationException(
55 "Too many statements in BatchExecuteStatement; limit is 25".to_string(),
56 ));
57 }
58
59 let mut responses = Vec::with_capacity(request.statements.len());
60
61 for stmt_req in &request.statements {
62 let parsed = partiql::parser::parse(&stmt_req.statement);
63
64 let response = match parsed {
65 Err(e) => BatchStatementResponse {
66 error: Some(BatchStatementError {
67 code: "ValidationException".to_string(),
68 message: format!("Statement wasn't well formed, got error: {e}"),
69 }),
70 item: None,
71 },
72 Ok(stmt) => {
73 let params = stmt_req.parameters.as_deref().unwrap_or_default();
74 match partiql::executor::execute(storage, &stmt, params, None).await {
75 Ok(Some(items)) => {
76 BatchStatementResponse {
78 error: None,
79 item: items.into_iter().next(),
80 }
81 }
82 Ok(None) => BatchStatementResponse {
83 error: None,
84 item: None,
85 },
86 Err(e) => BatchStatementResponse {
87 error: Some(BatchStatementError {
88 code: e.short_error_code().to_string(),
89 message: e.to_string(),
90 }),
91 item: None,
92 },
93 }
94 }
95 };
96
97 responses.push(response);
98 }
99
100 Ok(BatchExecuteStatementResponse { responses })
101}