sqlx_rqlite/options/connect.rs
1use crate::rqlite;
2use crate::connection::RqliteConnection;
3use crate::options::RqliteConnectOptions;
4
5use futures_core::future::BoxFuture;
6use log::LevelFilter;
7use sqlx_core::connection::ConnectOptions;
8use sqlx_core::error::Error;
9//use sqlx_core::executor::Executor;
10//use std::fmt::Write;
11use percent_encoding::percent_decode_str;
12use std::str::FromStr;
13use std::time::Duration;
14use url::Url;
15
16impl ConnectOptions for RqliteConnectOptions {
17 type Connection = RqliteConnection;
18 // borrowed from sqlx-mysql
19 fn from_url(url: &Url) -> Result<Self, Error> {
20 let mut options = rqlite::ConnectOptions::default();
21 if let Some(host) = url.host_str() {
22 options.host = host.into();
23 }
24
25 if let Some(port) = url.port() {
26 options.port = port;
27 }
28
29 let username = url.username();
30 if !username.is_empty() {
31 options.user = Some(
32 percent_decode_str(username)
33 .decode_utf8()
34 .map_err(Error::config)?
35 .to_string(),
36 );
37 }
38
39 if let Some(password) = url.password() {
40 options.pass = Some(
41 percent_decode_str(password)
42 .decode_utf8()
43 .map_err(Error::config)?
44 .to_string(),
45 );
46 }
47 /*
48 let path = url.path().trim_start_matches('/');
49 if !path.is_empty() {
50 options = options.database(path);
51 }
52 */
53 for (key, value) in url.query_pairs().into_iter() {
54 match &*key {
55 "ssl"=> {
56 if value == "yes" || value == "1" {
57 options.scheme=rqlite::Scheme::HTTPS;
58 }
59 }
60 "ssl-insecure"=> {
61 if value == "yes" || value == "1" {
62 options.scheme=rqlite::Scheme::HTTPS;
63 options.accept_invalid_cert=true;
64 }
65 }
66 _=>{}
67 }
68 }
69 Ok(Self { inner: options })
70 }
71 fn to_url_lossy(&self) -> Url {
72 self.build_url()
73 }
74
75 fn connect(&self) -> BoxFuture<'_, Result<Self::Connection, Error>>
76 where
77 Self::Connection: Sized,
78 {
79 Box::pin(async move {
80 let conn = RqliteConnection::establish(self).await?;
81 /*
82 // After the connection is established, we initialize by configuring a few
83 // connection parameters
84
85 // https://mariadb.com/kb/en/sql-mode/
86
87 // PIPES_AS_CONCAT - Allows using the pipe character (ASCII 124) as string concatenation operator.
88 // This means that "A" || "B" can be used in place of CONCAT("A", "B").
89
90 // NO_ENGINE_SUBSTITUTION - If not set, if the available storage engine specified by a CREATE TABLE is
91 // not available, a warning is given and the default storage
92 // engine is used instead.
93
94 // NO_ZERO_DATE - Don't allow '0000-00-00'. This is invalid in Rust.
95
96 // NO_ZERO_IN_DATE - Don't allow 'YYYY-00-00'. This is invalid in Rust.
97
98 // --
99
100 // Setting the time zone allows us to assume that the output
101 // from a TIMESTAMP field is UTC
102
103 // --
104
105 // https://mathiasbynens.be/notes/mysql-utf8mb4
106
107 let mut sql_mode = Vec::new();
108 if self.pipes_as_concat {
109 sql_mode.push(r#"PIPES_AS_CONCAT"#);
110 }
111 if self.no_engine_subsitution {
112 sql_mode.push(r#"NO_ENGINE_SUBSTITUTION"#);
113 }
114
115 let mut options = Vec::new();
116 if !sql_mode.is_empty() {
117 options.push(format!(
118 r#"sql_mode=(SELECT CONCAT(@@sql_mode, ',{}'))"#,
119 sql_mode.join(",")
120 ));
121 }
122 if let Some(timezone) = &self.timezone {
123 options.push(format!(r#"time_zone='{}'"#, timezone));
124 }
125 if self.set_names {
126 options.push(format!(
127 r#"NAMES {} COLLATE {}"#,
128 conn.stream.charset.as_str(),
129 conn.stream.collation.as_str()
130 ))
131 }
132
133 if !options.is_empty() {
134 conn.execute(&*format!(r#"SET {};"#, options.join(",")))
135 .await?;
136 }
137 */
138 Ok(conn)
139 })
140 }
141
142 fn log_statements(self, _level: LevelFilter) -> Self {
143 //self.log_settings.log_statements(level);
144 self
145 }
146
147 fn log_slow_statements(self, _level: LevelFilter, _duration: Duration) -> Self {
148 //self.log_settings.log_slow_statements(level, duration);
149 self
150 }
151}
152
153impl FromStr for RqliteConnectOptions {
154 type Err = Error;
155
156 fn from_str(s: &str) -> Result<Self, Error> {
157 let url: Url = s.parse().map_err(Error::config)?;
158 Self::from_url(&url)
159 }
160}