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