1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
use std::collections::HashMap;
use std::sync::Arc;

use pgwire::api::auth::ServerParameterProvider;
use pgwire::api::{ClientInfo, MakeHandler};
use tokio::net::TcpListener;

use super::auth_source::DataClotAuthSource;
use super::make_handler::{MakeDataClotStartupHandler, MakePostgresBackend};

pub struct DataClotParameterProvider {
    version: &'static str,
}

impl DataClotParameterProvider {
    fn new() -> Self {
        Self {
            version: env!("CARGO_PKG_VERSION"),
        }
    }
}

impl ServerParameterProvider for DataClotParameterProvider {
    fn server_parameters<C>(&self, _client: &C) -> Option<HashMap<String, String>>
    where
        C: ClientInfo,
    {
        Some(HashMap::from([
            ("server_version".to_owned(), self.version.to_owned()),
            ("server_encoding".to_owned(), "UTF8".to_owned()),
            ("client_encoding".to_owned(), "UTF8".to_owned()),
            ("DateStyle".to_owned(), "ISO YMD".to_owned()),
            ("integer_datetimes".to_owned(), "on".to_owned()),
        ]))
    }
}

pub async fn server(tcp_addr: String) {
    let listener = TcpListener::bind(&tcp_addr).await.unwrap();

    let authenticator = Arc::new(MakeDataClotStartupHandler::new(
        Arc::new(DataClotAuthSource),
        Arc::new(DataClotParameterProvider::new()),
    ));
    let processor = Arc::new(MakePostgresBackend::new());

    loop {
        let (incoming_socket, _) = listener.accept().await.unwrap();
        let authenticator_ref = authenticator.make();
        let processor_ref = processor.make();

        tokio::spawn(async move {
            pgwire::tokio::process_socket(
                incoming_socket,
                None,
                authenticator_ref,
                processor_ref.clone(),
                processor_ref,
            )
            .await
        });
    }
}