use crate::client::InnerClient; use crate::codec::FrontendMessage; use crate::connection::{Request, RequestMessages}; use crate::types::{Oid, Type}; use crate::{Column, Error, Statement}; use fallible_iterator::FallibleIterator; use futures::StreamExt; use postgres_protocol::message::backend::Message; use postgres_protocol::message::frontend; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; static NEXT_ID: AtomicUsize = AtomicUsize::new(0); pub async fn prepare( client: Arc<InnerClient>, query: &str, types: &[Type], ) -> Result<Statement, Error> { let name = format!("s{}", NEXT_ID.fetch_add(1, Ordering::SeqCst)); let mut buf = vec![]; frontend::parse(&name, query, types.iter().map(Type::oid), &mut buf).map_err(Error::encode)?; frontend::describe(b'S', &name, &mut buf).map_err(Error::encode)?; frontend::sync(&mut buf); let mut responses = client.send(RequestMessages::Single(FrontendMessage::Raw(buf)))?; match responses.next().await? { Message::ParseComplete => {} _ => return Err(Error::unexpected_message()), } let parameter_description = match responses.next().await? { Message::ParameterDescription(body) => body, _ => return Err(Error::unexpected_message()), }; let row_description = match responses.next().await? { Message::RowDescription(body) => Some(body), Message::NoData => None, _ => return Err(Error::unexpected_message()), }; let mut parameters = vec![]; let mut it = parameter_description.parameters(); while let Some(oid) = it.next().map_err(Error::parse)? { let type_ = get_type(&client, oid).await?; parameters.push(type_); } let mut columns = vec![]; if let Some(row_description) = row_description { let mut it = row_description.fields(); while let Some(field) = it.next().map_err(Error::parse)? { let type_ = get_type(&client, field.type_oid()).await?; let column = Column::new(field.name().to_string(), type_); columns.push(column); } } Ok(Statement::new(&client, name, parameters, columns)) } async fn get_type(client: &InnerClient, oid: Oid) -> Result<Type, Error> { if let Some(type_) = Type::from_oid(oid) { return Ok(type_); } unimplemented!() }