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}