1use std::{borrow::Cow, collections::HashMap, sync::Arc};
2
3use sqlx_core::{
4 column::ColumnIndex, database::Database, impl_statement_query, statement::Statement, Either,
5};
6
7use crate::{
8 arguments::ExaArguments, column::ExaColumn, database::Exasol, type_info::ExaTypeInfo,
9 SqlxError, SqlxResult,
10};
11
12#[derive(Debug, Clone)]
14pub struct ExaStatement<'q> {
15 pub(crate) sql: Cow<'q, str>,
16 pub(crate) metadata: ExaStatementMetadata,
17}
18
19#[derive(Debug, Clone)]
20pub struct ExaStatementMetadata {
21 pub columns: Arc<[ExaColumn]>,
22 pub column_names: HashMap<Arc<str>, usize>,
23 pub parameters: Arc<[ExaTypeInfo]>,
24}
25
26impl ExaStatementMetadata {
27 pub fn new(columns: Arc<[ExaColumn]>, parameters: Arc<[ExaTypeInfo]>) -> Self {
28 let mut column_names = HashMap::with_capacity(columns.len());
29
30 for (idx, col) in columns.as_ref().iter().enumerate() {
31 column_names.insert(col.name.clone(), idx);
32 }
33
34 Self {
35 columns,
36 column_names,
37 parameters,
38 }
39 }
40}
41
42impl<'q> Statement<'q> for ExaStatement<'q> {
43 type Database = Exasol;
44
45 fn to_owned(&self) -> <Self::Database as Database>::Statement<'static> {
46 ExaStatement {
47 sql: Cow::Owned(self.sql.clone().into_owned()),
48 metadata: self.metadata.clone(),
49 }
50 }
51
52 fn sql(&self) -> &str {
53 &self.sql
54 }
55
56 fn parameters(&self) -> Option<Either<&[<Self::Database as Database>::TypeInfo], usize>> {
57 Some(Either::Left(&self.metadata.parameters))
58 }
59
60 fn columns(&self) -> &[<Self::Database as Database>::Column] {
61 &self.metadata.columns
62 }
63
64 impl_statement_query!(ExaArguments);
65}
66
67impl ColumnIndex<ExaStatement<'_>> for &'_ str {
68 fn index(&self, statement: &ExaStatement<'_>) -> SqlxResult<usize> {
69 statement
70 .metadata
71 .column_names
72 .get(*self)
73 .ok_or_else(|| SqlxError::ColumnNotFound((*self).into()))
74 .copied()
75 }
76}