diesel/mariadb/connection.rs
1use crate::mariadb::Mariadb;
2
3/// A connection to a Mariadb database. Connection URLs should be in the form
4/// `mariadb://[user[:password]@]host/database_name[?unix_socket=socket-path]`
5///
6///* `host` can be an IP address or a hostname. If it is set to `localhost`, a connection
7/// will be attempted through the socket at `/tmp/mysql.sock`. If you want to connect to
8/// a local server via TCP (e.g. docker containers), use `0.0.0.0` or `127.0.0.1` instead.
9/// * `unix_socket` expects the path to the unix socket
10///
11/// Errors carry the SQLSTATE the server or client library reports in
12/// [`DatabaseErrorInformation::sqlstate`](crate::result::DatabaseErrorInformation::sqlstate),
13/// including custom codes raised with
14/// [`SIGNAL`](https://mariadb.com/docs/server/reference/sql-statements/programmatic-compound-statements/signal).
15/// The server reports `HY000` for errors without a specific SQLSTATE, as
16/// described at <https://mariadb.com/docs/server/reference/sql-statements/programmatic-compound-statements/programmatic-compound-statements-diagnostics/sqlstate>.
17/// [`sql_state`](crate::mysql_like::sql_state) names the codes.
18///
19/// # Supported loading model implementations
20///
21/// * [`DefaultLoadingMode`](crate::connection::DefaultLoadingMode)
22///
23/// As `MariadbConnection` only supports a single loading mode implementation
24/// it is **not required** to explicitly specify a loading mode
25/// when calling [`RunQueryDsl::load_iter()`](crate::query_dsl::RunQueryDsl::load_iter)
26/// or [`LoadConnection::load`](crate::connection::LoadConnection::load)
27///
28/// ## DefaultLoadingMode
29///
30/// `MariadbConnection` only supports a single loading mode, which loads
31/// values row by row from the result set.
32///
33/// ```rust,dejadoc
34/// # include!("../doctest_setup.rs");
35/// #
36/// # fn main() {
37/// # run_test().unwrap();
38/// # }
39/// #
40/// # fn run_test() -> QueryResult<()> {
41/// # use schema::users;
42/// # let connection = &mut establish_connection();
43/// use diesel::connection::DefaultLoadingMode;
44/// { // scope to restrict the lifetime of the iterator
45/// let iter1 = users::table.load_iter::<(i32, String), DefaultLoadingMode>(connection)?;
46///
47/// for r in iter1 {
48/// let (id, name) = r?;
49/// println!("Id: {} Name: {}", id, name);
50/// }
51/// }
52///
53/// // works without specifying the loading mode
54/// let iter2 = users::table.load_iter::<(i32, String), _>(connection)?;
55///
56/// for r in iter2 {
57/// let (id, name) = r?;
58/// println!("Id: {} Name: {}", id, name);
59/// }
60/// # Ok(())
61/// # }
62/// ```
63///
64/// This mode does **not support** creating
65/// multiple iterators using the same connection.
66///
67/// ```compile_fail,dejadoc
68/// # include!("../../doctest_setup.rs");
69/// #
70/// # fn main() {
71/// # run_test().unwrap();
72/// # }
73/// #
74/// # fn run_test() -> QueryResult<()> {
75/// # use schema::users;
76/// # let connection = &mut establish_connection();
77/// use diesel::connection::DefaultLoadingMode;
78///
79/// let iter1 = users::table.load_iter::<(i32, String), DefaultLoadingMode>(connection)?;
80/// let iter2 = users::table.load_iter::<(i32, String), DefaultLoadingMode>(connection)?;
81///
82/// for r in iter1 {
83/// let (id, name) = r?;
84/// println!("Id: {} Name: {}", id, name);
85/// }
86///
87/// for r in iter2 {
88/// let (id, name) = r?;
89/// println!("Id: {} Name: {}", id, name);
90/// }
91/// # Ok(())
92/// # }
93/// ```
94pub type MariadbConnection = crate::mysql_like::MysqlLikeConnection<Mariadb>;
95
96#[cfg(test)]
97mod tests {
98 extern crate dotenvy;
99
100 use super::*;
101 use std::env;
102
103 use crate::connection::Connection;
104 use crate::connection::SimpleConnection;
105 use crate::query_dsl::RunQueryDsl;
106
107 fn connection() -> MariadbConnection {
108 dotenvy::dotenv().ok();
109 let database_url = env::var("MARIADB_UNIT_TEST_DATABASE_URL")
110 .or_else(|_| env::var("MARIADB_DATABASE_URL"))
111 .or_else(|_| env::var("DATABASE_URL"))
112 .expect("DATABASE_URL must be set in order to run unit tests");
113 MariadbConnection::establish(&database_url).unwrap()
114 }
115
116 #[diesel_test_helper::test]
117 fn batch_execute_handles_single_queries_with_results() {
118 let connection = &mut connection();
119 assert!(connection.batch_execute("SELECT 1").is_ok());
120 assert!(connection.batch_execute("SELECT 1").is_ok());
121 }
122
123 #[diesel_test_helper::test]
124 fn batch_execute_handles_multi_queries_with_results() {
125 let connection = &mut connection();
126 let query = "SELECT 1; SELECT 2; SELECT 3;";
127 assert!(connection.batch_execute(query).is_ok());
128 assert!(connection.batch_execute(query).is_ok());
129 }
130
131 #[diesel_test_helper::test]
132 fn execute_handles_queries_which_return_results() {
133 let connection = &mut connection();
134 assert!(crate::sql_query("SELECT 1").execute(connection).is_ok());
135 assert!(crate::sql_query("SELECT 1").execute(connection).is_ok());
136 }
137
138 #[diesel_test_helper::test]
139 fn check_client_found_rows_flag() {
140 let conn = &mut crate::test_helpers::connection();
141 crate::sql_query("DROP TABLE IF EXISTS update_test CASCADE")
142 .execute(conn)
143 .unwrap();
144
145 crate::sql_query("CREATE TABLE update_test(id INTEGER PRIMARY KEY, num INTEGER NOT NULL)")
146 .execute(conn)
147 .unwrap();
148
149 crate::sql_query("INSERT INTO update_test(id, num) VALUES (1, 5)")
150 .execute(conn)
151 .unwrap();
152
153 let output = crate::sql_query("UPDATE update_test SET num = 5 WHERE id = 1")
154 .execute(conn)
155 .unwrap();
156
157 assert_eq!(output, 1);
158 }
159
160 #[crate::declare_sql_function]
161 extern "SQL" {
162 fn version() -> crate::sql_types::Text;
163 }
164
165 #[diesel_test_helper::test]
166 fn version_matches_the_server_reported_version() {
167 let connection = &mut connection();
168 let expected = connection.version().unwrap().to_string();
169 let reported = crate::select(version())
170 .get_result::<String>(connection)
171 .unwrap();
172 assert!(
173 reported.starts_with(&format!("{expected}-")),
174 "`{reported}` does not start with `{expected}-`"
175 );
176 }
177}