1use std::borrow::Cow;
6use std::sync::Arc;
7
8use either::Either;
9use sqlx_core::HashMap;
10use sqlx_core::column::ColumnIndex;
11use sqlx_core::error::Error;
12use sqlx_core::statement::Statement;
13
14use crate::column::SpgColumn;
15use crate::database::Spg;
16use crate::type_info::SpgTypeInfo;
17
18#[derive(Debug, Clone)]
27pub struct SpgStatement<'q> {
28 pub(crate) sql: Cow<'q, str>,
29 pub(crate) inner: Option<Arc<spg_embedded::Statement>>,
33 pub(crate) columns: Arc<Vec<SpgColumn>>,
34 pub(crate) by_name: Arc<HashMap<String, usize>>,
35}
36
37impl<'q> SpgStatement<'q> {
38 #[must_use]
42 pub fn unparsed(sql: impl Into<Cow<'q, str>>) -> Self {
43 Self {
44 sql: sql.into(),
45 inner: None,
46 columns: Arc::new(Vec::new()),
47 by_name: Arc::new(HashMap::new()),
48 }
49 }
50}
51
52impl<'q> Statement<'q> for SpgStatement<'q> {
53 type Database = Spg;
54
55 fn to_owned(&self) -> SpgStatement<'static> {
56 SpgStatement {
57 sql: Cow::Owned(self.sql.clone().into_owned()),
58 inner: self.inner.clone(),
59 columns: Arc::clone(&self.columns),
60 by_name: Arc::clone(&self.by_name),
61 }
62 }
63
64 fn sql(&self) -> &str {
65 &self.sql
66 }
67
68 fn parameters(&self) -> Option<Either<&[SpgTypeInfo], usize>> {
69 None
74 }
75
76 fn columns(&self) -> &[SpgColumn] {
77 &self.columns
78 }
79
80 fn query(&self) -> sqlx_core::query::Query<'_, Spg, crate::SpgArguments<'_>> {
81 sqlx_core::query::query_statement(self)
82 }
83
84 fn query_with<'s, A>(&'s self, arguments: A) -> sqlx_core::query::Query<'s, Spg, A>
85 where
86 A: sqlx_core::arguments::IntoArguments<'s, Spg>,
87 {
88 sqlx_core::query::query_statement_with(self, arguments)
89 }
90
91 fn query_as<O>(&self) -> sqlx_core::query_as::QueryAs<'_, Spg, O, crate::SpgArguments<'_>>
92 where
93 O: for<'r> sqlx_core::from_row::FromRow<'r, crate::SpgRow>,
94 {
95 sqlx_core::query_as::query_statement_as(self)
96 }
97
98 fn query_as_with<'s, O, A>(
99 &'s self,
100 arguments: A,
101 ) -> sqlx_core::query_as::QueryAs<'s, Spg, O, A>
102 where
103 O: for<'r> sqlx_core::from_row::FromRow<'r, crate::SpgRow>,
104 A: sqlx_core::arguments::IntoArguments<'s, Spg>,
105 {
106 sqlx_core::query_as::query_statement_as_with(self, arguments)
107 }
108
109 fn query_scalar<O>(
110 &self,
111 ) -> sqlx_core::query_scalar::QueryScalar<'_, Spg, O, crate::SpgArguments<'_>>
112 where
113 (O,): for<'r> sqlx_core::from_row::FromRow<'r, crate::SpgRow>,
114 {
115 sqlx_core::query_scalar::query_statement_scalar(self)
116 }
117
118 fn query_scalar_with<'s, O, A>(
119 &'s self,
120 arguments: A,
121 ) -> sqlx_core::query_scalar::QueryScalar<'s, Spg, O, A>
122 where
123 (O,): for<'r> sqlx_core::from_row::FromRow<'r, crate::SpgRow>,
124 A: sqlx_core::arguments::IntoArguments<'s, Spg>,
125 {
126 sqlx_core::query_scalar::query_statement_scalar_with(self, arguments)
127 }
128}
129
130impl ColumnIndex<SpgStatement<'_>> for &str {
131 fn index(&self, stmt: &SpgStatement<'_>) -> Result<usize, Error> {
132 stmt.by_name
133 .get(*self)
134 .copied()
135 .ok_or_else(|| Error::ColumnNotFound((*self).to_string()))
136 }
137}
138
139impl ColumnIndex<SpgStatement<'_>> for usize {
140 fn index(&self, stmt: &SpgStatement<'_>) -> Result<usize, Error> {
141 if *self >= stmt.columns.len() {
142 return Err(Error::ColumnIndexOutOfBounds {
143 index: *self,
144 len: stmt.columns.len(),
145 });
146 }
147 Ok(*self)
148 }
149}