1use crate::connection::Connection;
2use crate::error::Result;
3use bytes::Bytes;
4use std::sync::Arc;
5
6pub struct Client {
7 connection: Connection,
8}
9
10impl Client {
11 pub async fn connect(
12 addr: &str,
13 user: &str,
14 password: Option<&str>,
15 database: Option<&str>,
16 ) -> Result<Self> {
17 let connection = Connection::connect(addr, user, password, database).await?;
18 Ok(Self { connection })
19 }
20
21 pub async fn execute(&mut self, query: &str) -> Result<()> {
22 self.connection.execute(query).await
23 }
24
25 pub async fn query(&mut self, query: &str) -> Result<Vec<Row>> {
26 self.connection.query(query).await
27 }
28}
29
30#[derive(Debug, Clone)]
31pub struct Column {
32 pub name: String,
33 pub table_oid: u32,
34 pub column_id: i16,
35 pub type_oid: u32,
36 pub type_len: i16,
37 pub type_mod: i32,
38 pub format: i16,
39}
40
41use postgres_types::{FromSql, Type};
42
43pub struct Row {
44 pub columns: Arc<Vec<Column>>,
45 pub data: Vec<Option<Bytes>>,
46}
47
48impl Row {
49 pub fn get<'a, T: FromSql<'a>>(&'a self, index: usize) -> Result<T> {
50 let col = self.columns.get(index).ok_or_else(|| {
51 crate::error::Error::Parse(format!("Column index {} out of bounds", index))
52 })?;
53 let bytes = self.get_raw(index);
54
55 let ty = Type::from_oid(col.type_oid).unwrap_or(Type::UNKNOWN);
56
57 match bytes {
58 Some(b) => T::from_sql(&ty, b).map_err(|e| crate::error::Error::Parse(e.to_string())),
59 None => T::from_sql_null(&ty).map_err(|e| crate::error::Error::Parse(e.to_string())),
60 }
61 }
62
63 pub fn get_raw(&self, index: usize) -> Option<&Bytes> {
64 self.data.get(index).and_then(|opt| opt.as_ref())
65 }
66}