1use std::future;
2
3use futures_core::future::BoxFuture;
4use futures_core::stream::BoxStream;
5use futures_util::{stream, FutureExt, StreamExt, TryFutureExt};
6use sqlx_core::describe::Describe;
7use sqlx_core::error::Error;
8use sqlx_core::executor::{Execute, Executor};
9use sqlx_core::sql_str::SqlStr;
10use sqlx_core::Either;
11
12use crate::error::unsupported;
13use crate::{
14 js, Do, DoArguments, DoConnection, DoQueryResult, DoRow, DoStatement, DoTransaction, DoTypeInfo,
15};
16
17macro_rules! impl_executor {
26 ($ty:ty) => {
27 impl<'c> Executor<'c> for &'c $ty {
28 type Database = Do;
29
30 fn execute<'e, 'q: 'e, E>(self, query: E) -> BoxFuture<'e, Result<DoQueryResult, Error>>
32 where
33 'c: 'e,
34 E: 'q + Execute<'q, Do>,
35 {
36 async move {
37 let (sql, arguments) = take(query)?;
38 js::run(&self.sql, sql.as_str(), arguments_of(arguments.as_ref()))
39 }
40 .boxed()
41 }
42
43 fn execute_many<'e, 'q: 'e, E>(
44 self,
45 query: E,
46 ) -> BoxStream<'e, Result<DoQueryResult, Error>>
47 where
48 'c: 'e,
49 E: 'q + Execute<'q, Do>,
50 {
51 stream::once(self.execute(query)).boxed()
52 }
53
54 fn fetch_many<'e, 'q: 'e, E>(
57 self,
58 query: E,
59 ) -> BoxStream<'e, Result<Either<DoQueryResult, DoRow>, Error>>
60 where
61 'c: 'e,
62 E: 'q + Execute<'q, Do>,
63 {
64 async move {
65 let (sql, arguments) = take(query)?;
66 js::fetch(
67 &self.sql,
68 sql.as_str(),
69 arguments_of(arguments.as_ref()),
70 None,
71 )
72 .map(|(rows, _)| rows)
73 }
74 .map_ok(|rows| stream::iter(rows.into_iter().map(|row| Ok(Either::Right(row)))))
75 .try_flatten_stream()
76 .boxed()
77 }
78
79 fn fetch_optional<'e, 'q: 'e, E>(
80 self,
81 query: E,
82 ) -> BoxFuture<'e, Result<Option<DoRow>, Error>>
83 where
84 'c: 'e,
85 E: 'q + Execute<'q, Do>,
86 {
87 async move {
88 let (sql, arguments) = take(query)?;
89 let (rows, _) = js::fetch(
90 &self.sql,
91 sql.as_str(),
92 arguments_of(arguments.as_ref()),
93 Some(1),
94 )?;
95 Ok(rows.into_iter().next())
96 }
97 .boxed()
98 }
99
100 fn prepare_with<'e>(
101 self,
102 sql: SqlStr,
103 _parameters: &'e [DoTypeInfo],
104 ) -> BoxFuture<'e, Result<DoStatement, Error>>
105 where
106 'c: 'e,
107 {
108 future::ready(Ok(DoStatement { sql })).boxed()
109 }
110
111 fn describe<'e>(self, _sql: SqlStr) -> BoxFuture<'e, Result<Describe<Do>, Error>>
115 where
116 'c: 'e,
117 {
118 future::ready(Err(unsupported("statements cannot be described"))).boxed()
119 }
120 }
121
122 impl<'c> Executor<'c> for &'c mut $ty {
126 type Database = Do;
127
128 fn execute<'e, 'q: 'e, E>(self, query: E) -> BoxFuture<'e, Result<DoQueryResult, Error>>
129 where
130 'c: 'e,
131 E: 'q + Execute<'q, Do>,
132 {
133 (&*self).execute(query)
134 }
135
136 fn execute_many<'e, 'q: 'e, E>(
137 self,
138 query: E,
139 ) -> BoxStream<'e, Result<DoQueryResult, Error>>
140 where
141 'c: 'e,
142 E: 'q + Execute<'q, Do>,
143 {
144 (&*self).execute_many(query)
145 }
146
147 fn fetch_many<'e, 'q: 'e, E>(
148 self,
149 query: E,
150 ) -> BoxStream<'e, Result<Either<DoQueryResult, DoRow>, Error>>
151 where
152 'c: 'e,
153 E: 'q + Execute<'q, Do>,
154 {
155 (&*self).fetch_many(query)
156 }
157
158 fn fetch_optional<'e, 'q: 'e, E>(
159 self,
160 query: E,
161 ) -> BoxFuture<'e, Result<Option<DoRow>, Error>>
162 where
163 'c: 'e,
164 E: 'q + Execute<'q, Do>,
165 {
166 (&*self).fetch_optional(query)
167 }
168
169 fn prepare_with<'e>(
170 self,
171 sql: SqlStr,
172 parameters: &'e [DoTypeInfo],
173 ) -> BoxFuture<'e, Result<DoStatement, Error>>
174 where
175 'c: 'e,
176 {
177 (&*self).prepare_with(sql, parameters)
178 }
179
180 fn describe<'e>(self, sql: SqlStr) -> BoxFuture<'e, Result<Describe<Do>, Error>>
181 where
182 'c: 'e,
183 {
184 (&*self).describe(sql)
185 }
186 }
187 };
188}
189
190impl_executor!(DoConnection);
191impl_executor!(DoTransaction);
192
193fn take<'q, E>(mut query: E) -> Result<(SqlStr, Option<DoArguments>), Error>
195where
196 E: Execute<'q, Do>,
197{
198 let arguments = query.take_arguments().map_err(Error::Encode)?;
199 Ok((query.sql(), arguments))
200}
201
202fn arguments_of(arguments: Option<&DoArguments>) -> &[crate::DoArgumentValue] {
203 arguments.map_or(&[][..], DoArguments::values)
204}