omni_dev/snowflake/
client.rs1pub mod config;
20pub mod error;
21pub mod row;
22
23mod auth;
24mod session;
25mod transport;
26
27use std::sync::Arc;
28
29pub use config::{AuthMethod, BrowserConfig, BrowserLaunch, SnowflakeClientConfig};
30pub use error::{Error, Result};
31pub use row::{rows_to_payload, value_to_json, Column, Row};
32pub use session::SnowflakeSession;
33
34use transport::Transport;
35
36pub struct SnowflakeClient {
38 transport: Arc<Transport>,
39 config: SnowflakeClientConfig,
40}
41
42impl SnowflakeClient {
43 pub fn new(config: SnowflakeClientConfig) -> Result<Self> {
50 let transport = Arc::new(Transport::new(&config.api_host(), config.http_timeout)?);
51 Ok(Self { transport, config })
52 }
53
54 #[must_use]
56 pub fn config(&self) -> &SnowflakeClientConfig {
57 &self.config
58 }
59
60 pub async fn create_session(&self) -> Result<SnowflakeSession> {
67 let AuthMethod::ExternalBrowser(browser) = &self.config.auth;
68 let tokens = auth::external_browser_login(&self.transport, &self.config, browser).await?;
69 Ok(SnowflakeSession::new(
70 Arc::clone(&self.transport),
71 tokens,
72 self.config.query_timeout,
73 ))
74 }
75}
76
77#[cfg(test)]
81#[allow(clippy::unwrap_used, clippy::expect_used)]
82pub(crate) fn test_session(base_url: &str, query_timeout: std::time::Duration) -> SnowflakeSession {
83 use std::time::Duration;
84 let url = url::Url::parse(base_url).unwrap().join("/").unwrap();
85 let transport =
86 Arc::new(transport::Transport::with_base_url(url, Duration::from_secs(5)).unwrap());
87 SnowflakeSession::new(
88 transport,
89 session::LoginTokens {
90 session_token: "test-sess".into(),
91 master_token: "test-mast".into(),
92 session_validity_secs: 3600,
93 master_validity_secs: 14_400,
94 },
95 query_timeout,
96 )
97}
98
99#[cfg(test)]
100#[allow(clippy::unwrap_used, clippy::expect_used)]
101mod tests {
102 use super::*;
103
104 #[test]
105 fn new_builds_a_client_and_exposes_its_config() {
106 let client = SnowflakeClient::new(SnowflakeClientConfig::external_browser("MyAcct", "me"))
107 .expect("a valid account resolves to a valid host");
108 assert_eq!(client.config().account, "MyAcct");
109 assert_eq!(client.config().user, "me");
110 assert_eq!(client.config().api_host(), "myacct.snowflakecomputing.com");
111 }
112
113 #[test]
114 fn new_rejects_an_invalid_host_override() {
115 let config = SnowflakeClientConfig {
116 host: Some("[".to_string()),
118 ..SnowflakeClientConfig::external_browser("acct", "me")
119 };
120 assert!(matches!(
121 SnowflakeClient::new(config),
122 Err(Error::Protocol(_))
123 ));
124 }
125}