1use crate::pool::ConnectionFactory;
2use crate::postgres_client::statements::{PreparedQuery, Statement};
3use crate::postgres_client::PostgresClient;
4use crate::protocol::{
5 BackendMessage, FieldDescription, FrontendMessage, RowDescription, ValueFormat,
6};
7use crate::types::EnumTypeRegistry;
8use crate::{
9 protocol, ElefantClientError, FromSql, FromSqlBinary, FromSqlBinaryOwned, FromSqlRowOwned,
10 FromSqlText, FromSqlTextOwned, ToSql,
11};
12use std::borrow::Cow;
13use std::marker::PhantomData;
14use std::rc::Rc;
15use std::sync::Arc;
16use tracing::{debug, trace};
17
18#[macro_export]
19macro_rules! reborrow_until_polonius {
20 ($e:expr) => {
21 unsafe {
22 &mut *(($e) as *mut _)
26 }
27 };
28}
29
30impl<F: ConnectionFactory> PostgresClient<F> {
31 pub async fn query(
33 &mut self,
34 query: &(impl Statement + ?Sized),
35 parameters: &[&dyn ToSql],
36 ) -> Result<QueryResult<'_, F>, ElefantClientError> {
37 let prepared = query.prepare(self).await?;
38 prepared.execute(self, parameters).await
39 }
40
41 pub async fn query_simple(
43 &mut self,
44 query: &str,
45 ) -> Result<SimpleQueryResult<'_, F>, ElefantClientError> {
46 self.start_new_query().await?;
47 self.connection
48 .write_frontend_message(&FrontendMessage::Query(protocol::Query {
49 query: Cow::Borrowed(query),
50 }))
51 .await?;
52 self.connection.flush().await?;
53
54 Ok(SimpleQueryResult::new(self, None))
55 }
56
57 pub async fn prepare_query(
58 &mut self,
59 query: &str,
60 ) -> Result<PreparedQuery, ElefantClientError> {
61 self.prepared_query_counter += 1;
62
63 let name = format!("elefant_prepared_query_{}", self.prepared_query_counter);
64
65 self.prepare_with_name(query, Some(name)).await
66 }
67
68 pub(crate) async fn prepare_with_name(
69 &mut self,
70 query: &str,
71 name: Option<String>,
72 ) -> Result<PreparedQuery, ElefantClientError> {
73 self.start_new_query().await?;
74
75 let destination = name
76 .as_ref()
77 .map(|n| Cow::Borrowed(n.as_ref()))
78 .unwrap_or(Cow::Borrowed(""));
79
80 self.connection
81 .write_frontend_message(&FrontendMessage::Parse(protocol::Parse {
82 destination: destination.clone(),
83 query: Cow::Borrowed(query),
84 parameter_types: vec![],
85 }))
86 .await?;
87
88 self.connection
89 .write_frontend_message(&FrontendMessage::Describe(protocol::Describe {
90 name: destination,
91 target: protocol::DescribeTarget::Statement,
92 }))
93 .await?;
94 self.connection
95 .write_frontend_message(&FrontendMessage::Flush)
96 .await?;
97 self.connection.flush().await?;
98
99 let msg = self.read_next_backend_message().await?;
100
101 match msg {
102 BackendMessage::ParseComplete => {
103 trace!("Parse complete");
104 }
105 BackendMessage::ErrorResponse(er) => {
106 return Err(ElefantClientError::PostgresError(format!("{er:?}")));
107 }
108 _ => {
109 return Err(ElefantClientError::UnexpectedBackendMessage(format!(
110 "{msg:?}"
111 )));
112 }
113 }
114
115 let parameter_description = {
116 let msg = self.read_next_backend_message().await?;
117
118 match msg {
119 BackendMessage::ParameterDescription(pd) => pd,
120 BackendMessage::ErrorResponse(er) => {
121 return Err(ElefantClientError::PostgresError(format!("{er:?}")));
122 }
123 _ => {
124 return Err(ElefantClientError::UnexpectedBackendMessage(format!(
125 "{msg:?}"
126 )));
127 }
128 }
129 };
130
131 let row_description = {
132 let msg = self.read_next_backend_message().await?;
133
134 match msg {
135 BackendMessage::RowDescription(rd) => {
136 PreparedQueryResult::RowDescription(RowDescription {
137 fields: rd
138 .fields
139 .iter()
140 .map(|f| FieldDescription {
141 name: f.name.clone(),
142 format: ValueFormat::Binary,
143 data_type_oid: f.data_type_oid,
144 data_type_size: f.data_type_size,
145 type_modifier: f.type_modifier,
146 table_oid: f.table_oid,
147 column_attribute_number: f.column_attribute_number,
148 })
149 .collect(),
150 })
151 }
152 BackendMessage::NoData => PreparedQueryResult::NoData,
153 BackendMessage::ErrorResponse(er) => {
154 return Err(ElefantClientError::PostgresError(format!("{er:?}")));
155 }
156 _ => {
157 return Err(ElefantClientError::UnexpectedBackendMessage(format!(
158 "{msg:?}"
159 )));
160 }
161 }
162 };
163
164 self.ready_for_query = true;
165
166 Ok(PreparedQuery::new(
167 name,
168 self.client_id,
169 parameter_description,
170 row_description,
171 ))
172 }
173}
174
175pub(crate) enum PreparedQueryResult {
176 RowDescription(protocol::RowDescription),
177 NoData,
178}
179
180pub struct QueryResultBase<'postgres_client, F: ConnectionFactory> {
182 client: &'postgres_client mut PostgresClient<F>,
183 prepared_query_result: Option<Rc<PreparedQueryResult>>,
184}
185
186pub struct QueryResult<'postgres_client, F: ConnectionFactory> {
188 base: QueryResultBase<'postgres_client, F>,
189}
190
191pub struct SimpleQueryResult<'postgres_client, F: ConnectionFactory> {
193 base: QueryResultBase<'postgres_client, F>,
194}
195
196impl<'postgres_client, F: ConnectionFactory> QueryResultBase<'postgres_client, F> {
197 pub(crate) fn new(
198 client: &'postgres_client mut PostgresClient<F>,
199 prepared_query_result: Option<Rc<PreparedQueryResult>>,
200 ) -> Self {
201 Self {
202 client,
203 prepared_query_result,
204 }
205 }
206
207 pub async fn next_result_set<'query_result>(
208 &'query_result mut self,
209 ) -> Result<QueryResultSet<'postgres_client, 'query_result, F>, ElefantClientError> {
210 if let Some(prepared) = self.prepared_query_result.take() {
211 self.prepared_query_result = Some(Rc::new(PreparedQueryResult::NoData));
212 return match prepared.as_ref() {
213 PreparedQueryResult::RowDescription(rd) => {
214 let client: &mut PostgresClient<F> = reborrow_until_polonius!(self.client);
215 let registry = client.enum_registry.clone();
216 Ok(QueryResultSet::RowDescriptionReceived(RowResultReader {
217 client,
218 row_description: rd.clone(),
219 enum_registry: registry,
220 query_result_res: PhantomData,
221 }))
222 }
223 PreparedQueryResult::NoData => Ok(QueryResultSet::QueryProcessingComplete),
224 };
225 }
226
227 loop {
228 let client: &mut PostgresClient<F> = reborrow_until_polonius!(self.client);
229 let msg = client.read_next_backend_message().await?;
230
231 match msg {
232 BackendMessage::CommandComplete(cc) => {
233 debug!("Command complete: {:?}", cc);
234 }
235 BackendMessage::RowDescription(rd) => {
236 let registry = client.enum_registry.clone();
237 return Ok(QueryResultSet::RowDescriptionReceived(RowResultReader {
238 client,
239 row_description: rd,
240 enum_registry: registry,
241 query_result_res: PhantomData,
242 }));
243 }
244 BackendMessage::DataRow(dr) => {
245 return Err(ElefantClientError::UnexpectedBackendMessage(format!(
246 "Received DataRow without receiving a RowDescription: {dr:?}"
247 )));
248 }
249 BackendMessage::EmptyQueryResponse => {
250 debug!("Empty query response");
251 }
252 BackendMessage::ErrorResponse(er) => {
253 return Err(ElefantClientError::PostgresError(format!("{er:?}")));
254 }
255 BackendMessage::ReadyForQuery(rfq) => {
256 self.client.ready_for_query = true;
257 self.client.current_transaction_status = rfq.current_transaction_status;
258 return Ok(QueryResultSet::QueryProcessingComplete);
259 }
260 _ => {
261 return Err(ElefantClientError::UnexpectedBackendMessage(format!(
262 "{msg:?}"
263 )));
264 }
265 }
266 }
267 }
268}
269
270impl<'postgres_client, F: ConnectionFactory> QueryResult<'postgres_client, F> {
272 pub(crate) fn new(
273 client: &'postgres_client mut PostgresClient<F>,
274 prepared_query_result: Option<Rc<PreparedQueryResult>>,
275 ) -> Self {
276 Self {
277 base: QueryResultBase::new(client, prepared_query_result),
278 }
279 }
280
281 pub async fn next_result_set<'query_result>(
282 &'query_result mut self,
283 ) -> Result<QueryResultSet<'postgres_client, 'query_result, F>, ElefantClientError> {
284 self.base.next_result_set().await
285 }
286
287 pub async fn collect_to_vec<T>(mut self) -> Result<Vec<T>, ElefantClientError>
288 where
289 T: FromSqlRowOwned,
290 {
291 let mut results = Vec::new();
292 loop {
293 match self.next_result_set().await? {
294 QueryResultSet::QueryProcessingComplete => return Ok(results),
295 QueryResultSet::RowDescriptionReceived(reader) => {
296 results.extend(reader.collect_to_vec::<T>().await?);
297 }
298 }
299 }
300 }
301
302 pub async fn collect_single_column_to_vec<T>(mut self) -> Result<Vec<T>, ElefantClientError>
303 where
304 T: FromSqlBinaryOwned,
305 {
306 let mut results = Vec::new();
307 loop {
308 match self.next_result_set().await? {
309 QueryResultSet::QueryProcessingComplete => return Ok(results),
310 QueryResultSet::RowDescriptionReceived(mut row_result_reader) => {
311 while let Some(row) = row_result_reader.next_row().await? {
312 results.push(row.get_binary(0)?);
313 }
314 }
315 }
316 }
317 }
318}
319
320impl<'postgres_client, F: ConnectionFactory> SimpleQueryResult<'postgres_client, F> {
322 pub(crate) fn new(
323 client: &'postgres_client mut PostgresClient<F>,
324 prepared_query_result: Option<Rc<PreparedQueryResult>>,
325 ) -> Self {
326 Self {
327 base: QueryResultBase::new(client, prepared_query_result),
328 }
329 }
330
331 pub async fn next_result_set<'query_result>(
332 &'query_result mut self,
333 ) -> Result<QueryResultSet<'postgres_client, 'query_result, F>, ElefantClientError> {
334 self.base.next_result_set().await
335 }
336
337 pub async fn collect_to_vec<T>(mut self) -> Result<Vec<T>, ElefantClientError>
338 where
339 T: FromSqlRowOwned,
340 {
341 let mut results = Vec::new();
342 loop {
343 match self.next_result_set().await? {
344 QueryResultSet::QueryProcessingComplete => return Ok(results),
345 QueryResultSet::RowDescriptionReceived(reader) => {
346 results.extend(reader.collect_to_vec::<T>().await?);
347 }
348 }
349 }
350 }
351
352 pub async fn collect_next_to_vec<T: FromSqlRowOwned>(
357 &mut self,
358 ) -> Result<Vec<T>, ElefantClientError> {
359 match self.next_result_set().await? {
360 QueryResultSet::RowDescriptionReceived(reader) => Ok(reader.collect_to_vec().await?),
361 QueryResultSet::QueryProcessingComplete => {
362 Err(ElefantClientError::BatchQueryUnexpectedEnd)
363 }
364 }
365 }
366
367 pub async fn collect_single_column_to_vec<T>(mut self) -> Result<Vec<T>, ElefantClientError>
368 where
369 T: FromSqlTextOwned,
370 {
371 let mut results = Vec::new();
372 loop {
373 match self.next_result_set().await? {
374 QueryResultSet::QueryProcessingComplete => return Ok(results),
375 QueryResultSet::RowDescriptionReceived(mut row_result_reader) => {
376 while let Some(row) = row_result_reader.next_row().await? {
377 results.push(row.get_text(0)?);
378 }
379 }
380 }
381 }
382 }
383}
384
385pub enum QueryResultSet<'postgres_client, 'query_result_set, F: ConnectionFactory> {
386 QueryProcessingComplete,
387 RowDescriptionReceived(RowResultReader<'postgres_client, 'query_result_set, F>),
388}
389
390pub struct RowResultReader<'postgres_client, 'query_result_set, F: ConnectionFactory> {
391 client: &'postgres_client mut PostgresClient<F>,
392 row_description: RowDescription,
393 enum_registry: Arc<EnumTypeRegistry>,
394 query_result_res: PhantomData<&'query_result_set QueryResult<'postgres_client, F>>,
396}
397
398impl<'postgres_client, 'query_result_set, F: ConnectionFactory>
399 RowResultReader<'postgres_client, 'query_result_set, F>
400{
401 pub async fn next_row<'row_result_reader>(
402 &'row_result_reader mut self,
403 ) -> Result<Option<PostgresDataRow<'postgres_client, 'row_result_reader>>, ElefantClientError>
404 {
405 let client: &mut PostgresClient<F> = reborrow_until_polonius!(self.client);
406 let msg = client.read_next_backend_message().await?;
407
408 match msg {
409 BackendMessage::DataRow(dr) => Ok(Some(PostgresDataRow {
410 row_description: &self.row_description,
411 data_row: dr,
412 enum_registry: &self.enum_registry,
413 })),
414 BackendMessage::CommandComplete(cc) => {
415 debug!("Command complete: {:?}", cc);
416 Ok(None)
417 }
418 BackendMessage::ReadyForQuery(rfq) => {
419 self.client.ready_for_query = true;
420 self.client.current_transaction_status = rfq.current_transaction_status;
421 Ok(None)
422 }
423 BackendMessage::ErrorResponse(er) => {
424 Err(ElefantClientError::PostgresError(format!("{er:?}")))
425 }
426 _ => Err(ElefantClientError::UnexpectedBackendMessage(format!(
427 "{msg:?}"
428 ))),
429 }
430 }
431
432 pub async fn collect_to_vec<T>(mut self) -> Result<Vec<T>, ElefantClientError>
433 where
434 T: FromSqlRowOwned,
435 {
436 let mut results = Vec::new();
437 while let Some(row) = self.next_row().await? {
438 results.push(T::from_sql_row(&row)?);
439 }
440 Ok(results)
441 }
442}
443
444pub struct PostgresDataRow<'postgres_client, 'row_result_reader> {
445 row_description: &'row_result_reader RowDescription,
446 data_row: protocol::DataRow<'postgres_client>,
447 enum_registry: &'row_result_reader EnumTypeRegistry,
448}
449
450impl<'postgres_client> PostgresDataRow<'postgres_client, '_> {
451 pub fn get_some_bytes(&self) -> &[Option<&[u8]>] {
452 &self.data_row.values
453 }
454
455 pub fn get<T>(&self, index: usize) -> Result<T, ElefantClientError>
456 where
457 T: FromSql<'postgres_client>,
458 {
459 let field = &self.row_description.fields[index];
460
461 if !T::accepts_with_registry(field, self.enum_registry) {
462 return Err(ElefantClientError::UnsupportedFieldType {
463 postgres_field: field.clone(),
464 desired_rust_type: std::any::type_name::<T>(),
465 });
466 }
467
468 if let Some(raw) = self.data_row.values[index] {
469 let value = match field.format {
470 ValueFormat::Text => {
471 let raw_str = std::str::from_utf8(raw).map_err(|e| {
472 ElefantClientError::IoError(std::io::Error::new(
473 std::io::ErrorKind::InvalidData,
474 e,
475 ))
476 })?;
477 T::from_sql_text(raw_str, field).map_err(|e| {
478 ElefantClientError::DataTypeParseError {
479 original_error: e,
480 column_index: index,
481 }
482 })?
483 }
484 ValueFormat::Binary => T::from_sql_binary(raw, field).map_err(|e| {
485 ElefantClientError::DataTypeParseError {
486 original_error: e,
487 column_index: index,
488 }
489 })?,
490 };
491
492 Ok(value)
493 } else {
494 T::from_null(field)
495 }
496 }
497
498 pub fn get_binary<T>(&self, index: usize) -> Result<T, ElefantClientError>
500 where
501 T: FromSqlBinary<'postgres_client>,
502 {
503 let field = &self.row_description.fields[index];
504
505 if !T::accepts_with_registry(field, self.enum_registry) {
506 return Err(ElefantClientError::UnsupportedFieldType {
507 postgres_field: field.clone(),
508 desired_rust_type: std::any::type_name::<T>(),
509 });
510 }
511
512 if let Some(raw) = self.data_row.values[index] {
513 let value = T::from_sql_binary(raw, field).map_err(|e| {
514 ElefantClientError::DataTypeParseError {
515 original_error: e,
516 column_index: index,
517 }
518 })?;
519 Ok(value)
520 } else {
521 T::from_null(field)
522 }
523 }
524
525 pub fn get_text<T>(&self, index: usize) -> Result<T, ElefantClientError>
527 where
528 T: FromSqlText<'postgres_client>,
529 {
530 let field = &self.row_description.fields[index];
531
532 if !T::accepts_with_registry(field, self.enum_registry) {
533 return Err(ElefantClientError::UnsupportedFieldType {
534 postgres_field: field.clone(),
535 desired_rust_type: std::any::type_name::<T>(),
536 });
537 }
538
539 if let Some(raw) = self.data_row.values[index] {
540 let raw_str = std::str::from_utf8(raw).map_err(|e| {
541 ElefantClientError::IoError(std::io::Error::new(std::io::ErrorKind::InvalidData, e))
542 })?;
543 let value = T::from_sql_text(raw_str, field).map_err(|e| {
544 ElefantClientError::DataTypeParseError {
545 original_error: e,
546 column_index: index,
547 }
548 })?;
549 Ok(value)
550 } else {
551 T::from_null(field)
552 }
553 }
554
555 pub fn column_count(&self) -> usize {
556 self.row_description.fields.len()
557 }
558
559 pub fn require_columns(&self, count: usize) -> Result<(), ElefantClientError> {
560 if self.column_count() < count {
561 return Err(ElefantClientError::NotEnoughColumns {
562 desired: count,
563 actual: self.column_count(),
564 });
565 }
566 Ok(())
567 }
568}