Skip to main content

diesel/mysql/
connection.rs

1use crate::mysql::Mysql;
2use crate::mysql_like::MysqlLikeConnection;
3
4/// A connection to a MySQL database. Connection URLs should be in the form
5/// `mysql://[user[:password]@]host/database_name[?unix_socket=socket-path&ssl_mode=SSL_MODE*&ssl_ca=/etc/ssl/certs/ca-certificates.crt&ssl_cert=/etc/ssl/certs/client-cert.crt&ssl_key=/etc/ssl/certs/client-key.crt]`
6///
7///* `host` can be an IP address or a hostname. If it is set to `localhost`, a connection
8///  will be attempted through the socket at `/tmp/mysql.sock`. If you want to connect to
9///  a local server via TCP (e.g. docker containers), use `0.0.0.0` or `127.0.0.1` instead.
10/// * `unix_socket` expects the path to the unix socket
11/// * `ssl_ca` accepts a path to the system's certificate roots
12/// * `ssl_cert` accepts a path to the client's certificate file
13/// * `ssl_key` accepts a path to the client's private key file
14/// * `ssl_mode` expects a value defined for MySQL client command option `--ssl-mode`
15///   See <https://dev.mysql.com/doc/refman/5.7/en/connection-options.html#option_general_ssl-mode>
16///
17/// # Supported loading model implementations
18///
19/// * [`DefaultLoadingMode`](crate::connection::DefaultLoadingMode)
20///
21/// As `MysqlConnection` only supports a single loading mode implementation
22/// it is **not required** to explicitly specify a loading mode
23/// when calling [`RunQueryDsl::load_iter()`](crate::query_dsl::RunQueryDsl::load_iter)
24/// or [`LoadConnection::load`](crate::connection::LoadConnection::load)
25///
26/// ## DefaultLoadingMode
27///
28/// `MysqlConnection` only supports a single loading mode, which loads
29/// values row by row from the result set.
30///
31/// ```rust
32/// # include!("../doctest_setup.rs");
33/// #
34/// # fn main() {
35/// #     run_test().unwrap();
36/// # }
37/// #
38/// # fn run_test() -> QueryResult<()> {
39/// #     use schema::users;
40/// #     let connection = &mut establish_connection();
41/// use diesel::connection::DefaultLoadingMode;
42/// {
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
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 MysqlConnection = MysqlLikeConnection<Mysql>;
94
95#[cfg(test)]
96mod tests {
97    extern crate dotenvy;
98
99    use super::*;
100    use crate::connection::Connection;
101    use crate::connection::SimpleConnection;
102    use crate::query_dsl::RunQueryDsl;
103    use std::env;
104
105    fn connection() -> MysqlConnection {
106        dotenvy::dotenv().ok();
107        let database_url = env::var("MYSQL_UNIT_TEST_DATABASE_URL")
108            .or_else(|_| env::var("MYSQL_DATABASE_URL"))
109            .or_else(|_| env::var("DATABASE_URL"))
110            .expect("DATABASE_URL must be set in order to run unit tests");
111        MysqlConnection::establish(&database_url).unwrap()
112    }
113
114    #[diesel_test_helper::test]
115    fn batch_execute_handles_single_queries_with_results() {
116        let connection = &mut connection();
117        assert!(connection.batch_execute("SELECT 1").is_ok());
118        assert!(connection.batch_execute("SELECT 1").is_ok());
119    }
120
121    #[diesel_test_helper::test]
122    fn batch_execute_handles_multi_queries_with_results() {
123        let connection = &mut connection();
124        let query = "SELECT 1; SELECT 2; SELECT 3;";
125        assert!(connection.batch_execute(query).is_ok());
126        assert!(connection.batch_execute(query).is_ok());
127    }
128
129    #[diesel_test_helper::test]
130    fn execute_handles_queries_which_return_results() {
131        let connection = &mut connection();
132        assert!(crate::sql_query("SELECT 1").execute(connection).is_ok());
133        assert!(crate::sql_query("SELECT 1").execute(connection).is_ok());
134    }
135
136    #[diesel_test_helper::test]
137    fn check_client_found_rows_flag() {
138        let conn = &mut crate::test_helpers::connection();
139        crate::sql_query("DROP TABLE IF EXISTS update_test CASCADE")
140            .execute(conn)
141            .unwrap();
142
143        crate::sql_query("CREATE TABLE update_test(id INTEGER PRIMARY KEY, num INTEGER NOT NULL)")
144            .execute(conn)
145            .unwrap();
146
147        crate::sql_query("INSERT INTO update_test(id, num) VALUES (1, 5)")
148            .execute(conn)
149            .unwrap();
150
151        let output = crate::sql_query("UPDATE update_test SET num = 5 WHERE id = 1")
152            .execute(conn)
153            .unwrap();
154
155        assert_eq!(output, 1);
156    }
157}