Skip to main content

teaql_data_service/
lib.rs

1#![allow(async_fn_in_trait)]
2
3use std::time::SystemTime;
4use teaql_core::{
5    DeleteCommand, InsertCommand, RecoverCommand, UpdateCommand, SelectQuery, TraceNode, Record,
6};
7
8#[derive(Debug, Clone, Default)]
9pub struct DataServiceCapabilities {
10    pub query: bool,
11    pub mutation: bool,
12    pub transaction: bool,
13    pub schema: bool,
14    pub id_generation: bool,
15    pub batch_mutation: bool,
16    pub returning: bool,
17}
18
19#[derive(Debug, Clone)]
20pub struct QueryRequest {
21    pub query: SelectQuery,
22    pub trace_chain: Vec<TraceNode>,
23    pub comment: Option<String>,
24}
25
26#[derive(Debug, Clone)]
27pub struct QueryResult {
28    pub rows: Vec<Record>,
29    pub metadata: ExecutionMetadata,
30}
31
32#[derive(Debug, Clone)]
33pub enum MutationRequest {
34    Insert(InsertCommand),
35    Update(UpdateCommand),
36    Delete(DeleteCommand),
37    Recover(RecoverCommand),
38    Batch(Vec<MutationRequest>),
39}
40
41impl MutationRequest {
42    pub fn trace_chain(&self) -> &[teaql_core::TraceNode] {
43        match self {
44            MutationRequest::Insert(cmd) => &cmd.trace_chain,
45            MutationRequest::Update(cmd) => &cmd.trace_chain,
46            MutationRequest::Delete(cmd) => &cmd.trace_chain,
47            MutationRequest::Recover(cmd) => &cmd.trace_chain,
48            MutationRequest::Batch(_) => &[], // Batch traces are per-item
49        }
50    }
51
52    pub fn comment(&self) -> Option<&str> {
53        match self {
54            MutationRequest::Insert(cmd) => cmd.trace_chain.last().map(|n| n.comment.as_str()),
55            MutationRequest::Update(cmd) => cmd.trace_chain.last().map(|n| n.comment.as_str()),
56            MutationRequest::Delete(cmd) => cmd.trace_chain.last().map(|n| n.comment.as_str()),
57            MutationRequest::Recover(cmd) => cmd.trace_chain.last().map(|n| n.comment.as_str()),
58            MutationRequest::Batch(_) => None,
59        }
60    }
61}
62
63#[derive(Debug, Clone)]
64pub struct MutationResult {
65    pub affected_rows: u64,
66    pub generated_values: Record,
67    pub metadata: ExecutionMetadata,
68}
69
70#[derive(Debug, Clone, Copy, PartialEq, Eq)]
71pub enum DataServiceOperation {
72    Query,
73    Insert,
74    Update,
75    Delete,
76    Recover,
77    Batch,
78    Schema,
79}
80
81#[derive(Debug, Clone)]
82pub struct ExecutionMetadata {
83    pub backend: String,
84    pub operation: DataServiceOperation,
85    pub started_at: SystemTime,
86    pub ended_at: SystemTime,
87    pub affected_rows: Option<u64>,
88    pub result_count: Option<usize>,
89    pub trace_chain: Vec<TraceNode>,
90    pub comment: Option<String>,
91    pub backend_request_id: Option<String>,
92    pub debug_query: Option<String>,
93}
94
95pub trait DataServiceExecutor {
96    type Error: std::error::Error + Send + Sync + 'static;
97
98    fn capabilities(&self) -> DataServiceCapabilities;
99}
100
101pub trait QueryExecutor: DataServiceExecutor {
102    fn query(&self, request: QueryRequest) -> impl std::future::Future<Output = Result<QueryResult, Self::Error>> + Send;
103}
104
105/// Result of a single streaming chunk.
106#[derive(Debug, Clone)]
107pub struct StreamChunk {
108    pub rows: Vec<Record>,
109    pub chunk_index: usize,
110    pub is_last: bool,
111}
112
113/// Streaming query executor. Returns rows in chunks rather than all at once.
114pub trait StreamQueryExecutor: DataServiceExecutor {
115    fn query_stream(
116        &self,
117        request: QueryRequest,
118        chunk_size: usize,
119    ) -> impl std::future::Future<Output = Result<Vec<StreamChunk>, Self::Error>> + Send;
120}
121
122pub trait MutationExecutor: DataServiceExecutor {
123    fn mutate(&self, request: MutationRequest) -> impl std::future::Future<Output = Result<MutationResult, Self::Error>> + Send;
124}
125
126pub trait TransactionExecutor: DataServiceExecutor {
127    type Tx<'a>: QueryExecutor<Error = Self::Error>
128        + MutationExecutor<Error = Self::Error>
129        + Transaction<Error = Self::Error>
130    where
131        Self: 'a;
132
133    fn begin(&self) -> impl std::future::Future<Output = Result<Self::Tx<'_>, Self::Error>> + Send;
134}
135
136pub trait Transaction {
137    type Error: std::error::Error + Send + Sync + 'static;
138
139    fn commit(self) -> impl std::future::Future<Output = Result<(), Self::Error>> + Send;
140    fn rollback(self) -> impl std::future::Future<Output = Result<(), Self::Error>> + Send;
141}
142
143#[derive(Debug, Clone)]
144pub struct SchemaRequest {
145    pub entity_name: String,
146}
147
148#[derive(Debug, Clone)]
149pub struct SchemaResult {
150    pub changed: bool,
151}
152
153pub trait SchemaExecutor: DataServiceExecutor {
154    fn ensure_schema(&self, request: SchemaRequest) -> impl std::future::Future<Output = Result<SchemaResult, Self::Error>> + Send;
155}
156
157pub trait IdGeneratorExecutor: DataServiceExecutor {
158    fn next_id(&self, entity: &str) -> impl std::future::Future<Output = Result<u64, Self::Error>> + Send;
159}
160
161pub trait SchemaProvider: Send + Sync {
162    fn get_entity(&self, name: &str) -> Option<std::sync::Arc<teaql_core::EntityDescriptor>>;
163}