tank_core/
executor.rs

1use crate::{
2    AsQuery, Driver, Entity, Query, QueryResult, Result, RowLabeled, RowsAffected,
3    stream::{Stream, StreamExt, TryStreamExt},
4    writer::SqlWriter,
5};
6use std::future::Future;
7
8/// Async query executor bound to a concrete `Driver`.
9///
10/// Responsibilities:
11/// - Translate high-level operations into driver queries
12/// - Stream results without buffering the entire result set (if possible)
13/// - Provide ergonomic helpers for common patterns
14///
15/// Implementors typically wrap a connection or pooled handle.
16pub trait Executor: Send + Sized {
17    /// Associated driver.
18    type Driver: Driver;
19
20    fn accepts_multiple_statements(&self) -> bool {
21        true
22    }
23
24    /// Driver instance.
25    fn driver(&self) -> &Self::Driver;
26
27    /// Prepare a query for later execution.
28    fn prepare(
29        &mut self,
30        query: String,
31    ) -> impl Future<Output = Result<Query<Self::Driver>>> + Send;
32
33    /// Run a query, streaming `QueryResult` items.
34    fn run<'s>(
35        &'s mut self,
36        query: impl AsQuery<Self::Driver> + 's,
37    ) -> impl Stream<Item = Result<QueryResult>> + Send;
38
39    /// Stream only labeled rows (filters non-row results).
40    fn fetch<'s>(
41        &'s mut self,
42        query: impl AsQuery<Self::Driver> + 's,
43    ) -> impl Stream<Item = Result<RowLabeled>> + Send {
44        self.run(query).filter_map(|v| async move {
45            match v {
46                Ok(QueryResult::Row(v)) => Some(Ok(v)),
47                Err(e) => Some(Err(e)),
48                _ => None,
49            }
50        })
51    }
52
53    /// Execute and aggregate affected rows.
54    fn execute<'s>(
55        &'s mut self,
56        query: impl AsQuery<Self::Driver> + 's,
57    ) -> impl Future<Output = Result<RowsAffected>> + Send {
58        self.run(query)
59            .filter_map(|v| async move {
60                match v {
61                    Ok(QueryResult::Affected(v)) => Some(Ok(v)),
62                    Err(e) => Some(Err(e)),
63                    _ => None,
64                }
65            })
66            .try_collect()
67    }
68
69    /// Insert many entities efficiently.
70    fn append<'a, E, It>(
71        &mut self,
72        entities: It,
73    ) -> impl Future<Output = Result<RowsAffected>> + Send
74    where
75        E: Entity + 'a,
76        It: IntoIterator<Item = &'a E> + Send,
77        <It as IntoIterator>::IntoIter: Send,
78    {
79        let mut query = String::new();
80        self.driver()
81            .sql_writer()
82            .write_insert(&mut query, entities, false);
83        self.execute(query)
84    }
85}