Skip to main content

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///
18/// # Supported loading model implementations
19///
20/// * [`DefaultLoadingMode`](crate::connection::DefaultLoadingMode)
21///
22/// As `MariadbConnection` only supports a single loading mode implementation
23/// it is **not required** to explicitly specify a loading mode
24/// when calling [`RunQueryDsl::load_iter()`](crate::query_dsl::RunQueryDsl::load_iter)
25/// or [`LoadConnection::load`](crate::connection::LoadConnection::load)
26///
27/// ## DefaultLoadingMode
28///
29/// `MariadbConnection` only supports a single loading mode, which loads
30/// values row by row from the result set.
31///
32/// ```rust,dejadoc
33/// # include!("../doctest_setup.rs");
34/// #
35/// # fn main() {
36/// #     run_test().unwrap();
37/// # }
38/// #
39/// # fn run_test() -> QueryResult<()> {
40/// #     use schema::users;
41/// #     let connection = &mut establish_connection();
42/// use diesel::connection::DefaultLoadingMode;
43/// { // scope to restrict the lifetime of the iterator
44///     let iter1 = users::table.load_iter::<(i32, String), DefaultLoadingMode>(connection)?;
45///
46///     for r in iter1 {
47///         let (id, name) = r?;
48///         println!("Id: {} Name: {}", id, name);
49///     }
50/// }
51///
52/// // works without specifying the loading mode
53/// let iter2 = users::table.load_iter::<(i32, String), _>(connection)?;
54///
55/// for r in iter2 {
56///     let (id, name) = r?;
57///     println!("Id: {} Name: {}", id, name);
58/// }
59/// #   Ok(())
60/// # }
61/// ```
62///
63/// This mode does **not support** creating
64/// multiple iterators using the same connection.
65///
66/// ```compile_fail,dejadoc
67/// # include!("../../doctest_setup.rs");
68/// #
69/// # fn main() {
70/// #     run_test().unwrap();
71/// # }
72/// #
73/// # fn run_test() -> QueryResult<()> {
74/// #     use schema::users;
75/// #     let connection = &mut establish_connection();
76/// use diesel::connection::DefaultLoadingMode;
77///
78/// let iter1 = users::table.load_iter::<(i32, String), DefaultLoadingMode>(connection)?;
79/// let iter2 = users::table.load_iter::<(i32, String), DefaultLoadingMode>(connection)?;
80///
81/// for r in iter1 {
82///     let (id, name) = r?;
83///     println!("Id: {} Name: {}", id, name);
84/// }
85///
86/// for r in iter2 {
87///     let (id, name) = r?;
88///     println!("Id: {} Name: {}", id, name);
89/// }
90/// #   Ok(())
91/// # }
92/// ```
93pub type MariadbConnection = crate::mysql_like::MysqlLikeConnection<Mariadb>;
94
95#[cfg(test)]
96mod tests {
97    extern crate dotenvy;
98
99    use super::*;
100    use std::env;
101
102    use crate::connection::Connection;
103    use crate::connection::SimpleConnection;
104    use crate::query_dsl::RunQueryDsl;
105
106    fn connection() -> MariadbConnection {
107        dotenvy::dotenv().ok();
108        let database_url = env::var("MARIADB_UNIT_TEST_DATABASE_URL")
109            .or_else(|_| env::var("MARIADB_DATABASE_URL"))
110            .or_else(|_| env::var("DATABASE_URL"))
111            .expect("DATABASE_URL must be set in order to run unit tests");
112        MariadbConnection::establish(&database_url).unwrap()
113    }
114
115    #[diesel_test_helper::test]
116    fn batch_execute_handles_single_queries_with_results() {
117        let connection = &mut connection();
118        assert!(connection.batch_execute("SELECT 1").is_ok());
119        assert!(connection.batch_execute("SELECT 1").is_ok());
120    }
121
122    #[diesel_test_helper::test]
123    fn batch_execute_handles_multi_queries_with_results() {
124        let connection = &mut connection();
125        let query = "SELECT 1; SELECT 2; SELECT 3;";
126        assert!(connection.batch_execute(query).is_ok());
127        assert!(connection.batch_execute(query).is_ok());
128    }
129
130    #[diesel_test_helper::test]
131    fn execute_handles_queries_which_return_results() {
132        let connection = &mut connection();
133        assert!(crate::sql_query("SELECT 1").execute(connection).is_ok());
134        assert!(crate::sql_query("SELECT 1").execute(connection).is_ok());
135    }
136
137    #[diesel_test_helper::test]
138    fn check_client_found_rows_flag() {
139        let conn = &mut crate::test_helpers::connection();
140        crate::sql_query("DROP TABLE IF EXISTS update_test CASCADE")
141            .execute(conn)
142            .unwrap();
143
144        crate::sql_query("CREATE TABLE update_test(id INTEGER PRIMARY KEY, num INTEGER NOT NULL)")
145            .execute(conn)
146            .unwrap();
147
148        crate::sql_query("INSERT INTO update_test(id, num) VALUES (1, 5)")
149            .execute(conn)
150            .unwrap();
151
152        let output = crate::sql_query("UPDATE update_test SET num = 5 WHERE id = 1")
153            .execute(conn)
154            .unwrap();
155
156        assert_eq!(output, 1);
157    }
158
159    #[crate::declare_sql_function]
160    extern "SQL" {
161        fn version() -> crate::sql_types::Text;
162    }
163
164    #[diesel_test_helper::test]
165    fn version_matches_the_server_reported_version() {
166        let connection = &mut connection();
167        let expected = connection.version().unwrap().to_string();
168        let reported = crate::select(version())
169            .get_result::<String>(connection)
170            .unwrap();
171        assert!(
172            reported.starts_with(&format!("{expected}-")),
173            "`{reported}` does not start with `{expected}-`"
174        );
175    }
176}