sentinel_driver/connection/
prepare.rs1use super::{frontend, BackendMessage, CacheMetrics, Connection, Error, Oid, Result, Statement};
2
3impl Connection {
4 pub async fn prepare(&mut self, sql: &str) -> Result<Statement> {
8 let stmt_name = format!("_sentinel_p{}", self.process_id);
9
10 frontend::parse(self.conn.write_buf(), &stmt_name, sql, &[]);
11 frontend::describe_statement(self.conn.write_buf(), &stmt_name);
12 frontend::sync(self.conn.write_buf());
13 self.conn.send().await?;
14
15 match self.conn.recv().await? {
17 BackendMessage::ParseComplete => {}
18 BackendMessage::ErrorResponse { fields } => {
19 self.drain_until_ready().await.ok();
20 return Err(Error::server(
21 fields.severity,
22 fields.code,
23 fields.message,
24 fields.detail,
25 fields.hint,
26 fields.position,
27 ));
28 }
29 other => {
30 return Err(Error::protocol(format!(
31 "expected ParseComplete, got {other:?}"
32 )))
33 }
34 }
35
36 let param_oids = match self.conn.recv().await? {
38 BackendMessage::ParameterDescription { oids } => {
39 oids.into_iter().map(Oid::from).collect()
40 }
41 other => {
42 return Err(Error::protocol(format!(
43 "expected ParameterDescription, got {other:?}"
44 )))
45 }
46 };
47
48 let columns = match self.conn.recv().await? {
50 BackendMessage::RowDescription { fields } => Some(fields),
51 BackendMessage::NoData => None,
52 other => {
53 return Err(Error::protocol(format!(
54 "expected RowDescription/NoData, got {other:?}"
55 )))
56 }
57 };
58
59 self.drain_until_ready().await?;
61
62 Ok(Statement::new(
63 stmt_name,
64 sql.to_string(),
65 param_oids,
66 columns,
67 ))
68 }
69
70 pub fn register_statement(&mut self, name: &str, statement: Statement) {
72 self.stmt_cache.register(name, statement);
73 }
74
75 pub fn cache_metrics(&self) -> &CacheMetrics {
77 self.stmt_cache.metrics()
78 }
79}