mysql/
lib.rs

1// Copyright (c) 2020 rust-mysql-simple contributors
2//
3// Licensed under the Apache License, Version 2.0
4// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
5// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. All files in the project carrying such notice may not be copied,
7// modified, or distributed except according to those terms.
8
9//! This crate offers:
10//!
11//! *   MySql database driver in pure rust;
12//! *   connection pool.
13//!
14//! Features:
15//!
16//! *   macOS, Windows and Linux support;
17//! *   TLS support via **nativetls** or **rustls** (see the [SSL Support](#ssl-support) section);
18//! *   MySql text protocol support, i.e. support of simple text queries and text result sets;
19//! *   MySql binary protocol support, i.e. support of prepared statements and binary result sets;
20//! *   support of multi-result sets;
21//! *   support of named parameters for prepared statements (see the [Named Parameters](#named-parameters) section);
22//! *   optional per-connection cache of prepared statements (see the [Statement Cache](#statement-cache) section);
23//! *   buffer pool (see the [Buffer Pool](#buffer-pool) section);
24//! *   support of MySql packets larger than 2^24;
25//! *   support of Unix sockets and Windows named pipes;
26//! *   support of custom LOCAL INFILE handlers;
27//! *   support of MySql protocol compression;
28//! *   support of auth plugins:
29//!     *   **mysql_native_password** - for MySql prior to v8;
30//!     *   **caching_sha2_password** - for MySql v8 and higher.
31//!
32//! ## Installation
33//!
34//! Put the desired version of the crate into the `dependencies` section of your `Cargo.toml`:
35//!
36//! ```toml
37//! [dependencies]
38//! mysql = "*"
39//! ```
40//!
41//! ## Example
42//!
43//! ```rust
44//! use mysql::*;
45//! use mysql::prelude::*;
46//!
47//! #[derive(Debug, PartialEq, Eq)]
48//! struct Payment {
49//!     customer_id: i32,
50//!     amount: i32,
51//!     account_name: Option<String>,
52//! }
53//!
54//! # def_get_opts!();
55//!
56//! fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
57//!     let url = "mysql://root:password@localhost:3307/db_name";
58//!     # Opts::try_from(url)?;
59//!     # let url = get_opts();
60//!     let pool = Pool::new(url)?;
61//!
62//!     let mut conn = pool.get_conn()?;
63//!
64//!     // Let's create a table for payments.
65//!     conn.query_drop(
66//!         r"CREATE TEMPORARY TABLE payment (
67//!             customer_id int not null,
68//!             amount int not null,
69//!             account_name text
70//!         )")?;
71//!
72//!     let payments = vec![
73//!         Payment { customer_id: 1, amount: 2, account_name: None },
74//!         Payment { customer_id: 3, amount: 4, account_name: Some("foo".into()) },
75//!         Payment { customer_id: 5, amount: 6, account_name: None },
76//!         Payment { customer_id: 7, amount: 8, account_name: None },
77//!         Payment { customer_id: 9, amount: 10, account_name: Some("bar".into()) },
78//!     ];
79//!
80//!     // Now let's insert payments to the database
81//!     conn.exec_batch(
82//!         r"INSERT INTO payment (customer_id, amount, account_name)
83//!           VALUES (:customer_id, :amount, :account_name)",
84//!         payments.iter().map(|p| params! {
85//!             "customer_id" => p.customer_id,
86//!             "amount" => p.amount,
87//!             "account_name" => &p.account_name,
88//!         })
89//!     )?;
90//!
91//!     // Let's select payments from database. Type inference should do the trick here.
92//!     let selected_payments = conn
93//!         .query_map(
94//!             "SELECT customer_id, amount, account_name from payment",
95//!             |(customer_id, amount, account_name)| {
96//!                 Payment { customer_id, amount, account_name }
97//!             },
98//!         )?;
99//!
100//!     // Let's make sure, that `payments` equals to `selected_payments`.
101//!     // Mysql gives no guaranties on order of returned rows
102//!     // without `ORDER BY`, so assume we are lucky.
103//!     assert_eq!(payments, selected_payments);
104//!     println!("Yay!");
105//!
106//!     Ok(())
107//! }
108//! ```
109//!
110//! ## Crate Features
111//!
112//! * feature sets:
113//!
114//!     *   **default** – includes default `mysql_common` features, `native-tls`, `buffer-pool`
115//!         and `flate2/zlib`
116//!     *   **default-rustls** - same as `default` but with `rustls-tls` instead of `native-tls`
117//!     *   **minimal** - includes `flate2/zlib`
118//!
119//! * crate's features:
120//!
121//!     *   **native-tls** (enabled by default) – specifies `native-tls` as the TLS backend
122//!         (see the [SSL Support](#ssl-support) section)
123//!     *   **rustls-tls** (disabled by default) – specifies `rustls` as the TLS backend
124//!         (see the [SSL Support](#ssl-support) section)
125//!     *   **buffer-pool** (enabled by default) – enables buffer pooling
126//!         (see the [Buffer Pool](#buffer-pool) section)
127//!
128//! * external features enabled by default:
129//!
130//!     * for the `flate2` crate (please consult `flate2` crate documentation for available features):
131//!
132//!         *   **flate2/zlib** (necessary) – `zlib` backend is chosed by default.
133//!
134//!     * for the `mysql_common` crate (please consult `mysql_common` crate documentation for available features):
135//!
136//!         *   **mysql_common/bigdecimal03** – the `bigdecimal03` is enabled by default
137//!         *   **mysql_common/rust_decimal** – the `rust_decimal` is enabled by default
138//!         *   **mysql_common/time03** – the `time03` is enabled by default
139//!         *   **mysql_common/uuid** – the `uuid` is enabled by default
140//!         *   **mysql_common/frunk** – the `frunk` is enabled by default
141//!
142//! Please note, that you'll need to reenable required features if you are using `default-features = false`:
143//!
144//! ```toml
145//! [dependencies]
146//! # Lets say that we want to use the `rustls-tls` feature:
147//! mysql = { version = "*", default-features = false, features = ["minimal", "rustls-tls"] }
148//! # Previous line disables default mysql features,
149//! # so now we need to choose desired mysql_common features:
150//! mysql_common = { version = "*", default-features = false, features = ["bigdecimal03", "time03", "uuid"]}
151//! ```
152//!
153//! ## API Documentation
154//!
155//! Please refer to the [crate docs].
156//!
157//! ## Basic structures
158//!
159//! ### `Opts`
160//!
161//! This structure holds server host name, client username/password and other settings,
162//! that controls client behavior.
163//!
164//! #### URL-based connection string
165//!
166//! Note, that you can use URL-based connection string as a source of an `Opts` instance.
167//! URL schema must be `mysql`. Host, port and credentials, as well as query parameters,
168//! should be given in accordance with the RFC 3986.
169//!
170//! Examples:
171//!
172//! ```rust
173//! # mysql::doctest_wrapper!(__result, {
174//! # use mysql::Opts;
175//! let _ = Opts::from_url("mysql://localhost/some_db")?;
176//! let _ = Opts::from_url("mysql://[::1]/some_db")?;
177//! let _ = Opts::from_url("mysql://user:pass%20word@127.0.0.1:3307/some_db?")?;
178//! # });
179//! ```
180//!
181//! Supported URL parameters (for the meaning of each field please refer to the docs on `Opts`
182//! structure in the create API docs):
183//!
184//! *   `prefer_socket: true | false` - defines the value of the same field in the `Opts` structure;
185//! *   `tcp_keepalive_time_ms: u32` - defines the value (in milliseconds)
186//!     of the `tcp_keepalive_time` field in the `Opts` structure;
187//! *   `tcp_keepalive_probe_interval_secs: u32` - defines the value
188//!     of the `tcp_keepalive_probe_interval_secs` field in the `Opts` structure;
189//! *   `tcp_keepalive_probe_count: u32` - defines the value
190//!     of the `tcp_keepalive_probe_count` field in the `Opts` structure;
191//! *   `tcp_connect_timeout_ms: u64` - defines the value (in milliseconds)
192//!     of the `tcp_connect_timeout` field in the `Opts` structure;
193//! *   `tcp_user_timeout_ms` - defines the value (in milliseconds)
194//!     of the `tcp_user_timeout` field in the `Opts` structure;
195//! *   `stmt_cache_size: u32` - defines the value of the same field in the `Opts` structure;
196//! *   `compress` - defines the value of the same field in the `Opts` structure.
197//!     Supported value are:
198//!     *  `true` - enables compression with the default compression level;
199//!     *  `fast` - enables compression with "fast" compression level;
200//!     *  `best` - enables compression with "best" compression level;
201//!     *  `1`..`9` - enables compression with the given compression level.
202//! *   `socket` - socket path on UNIX, or pipe name on Windows.
203//!
204//! ### `OptsBuilder`
205//!
206//! It's a convenient builder for the `Opts` structure. It defines setters for fields
207//! of the `Opts` structure.
208//!
209//! ```no_run
210//! # mysql::doctest_wrapper!(__result, {
211//! # use mysql::*;
212//! let opts = OptsBuilder::new()
213//!     .user(Some("foo"))
214//!     .db_name(Some("bar"));
215//! let _ = Conn::new(opts)?;
216//! # });
217//! ```
218//!
219//! ### `Conn`
220//!
221//! This structure represents an active MySql connection. It also holds statement cache
222//! and metadata for the last result set.
223//!
224//! Conn's destructor will gracefully disconnect it from the server.
225//!
226//! ### `Transaction`
227//!
228//! It's a simple wrapper on top of a routine, that starts with `START TRANSACTION`
229//! and ends with `COMMIT` or `ROLLBACK`.
230//!
231//! ```
232//! # mysql::doctest_wrapper!(__result, {
233//! use mysql::*;
234//! use mysql::prelude::*;
235//!
236//! let pool = Pool::new(get_opts())?;
237//! let mut conn = pool.get_conn()?;
238//!
239//! let mut tx = conn.start_transaction(TxOpts::default())?;
240//! tx.query_drop("CREATE TEMPORARY TABLE tmp (TEXT a)")?;
241//! tx.exec_drop("INSERT INTO tmp (a) VALUES (?)", ("foo",))?;
242//! let val: Option<String> = tx.query_first("SELECT a from tmp")?;
243//! assert_eq!(val.unwrap(), "foo");
244//! // Note, that transaction will be rolled back implicitly on Drop, if not committed.
245//! tx.rollback();
246//!
247//! let val: Option<String> = conn.query_first("SELECT a from tmp")?;
248//! assert_eq!(val, None);
249//! # });
250//! ```
251//!
252//! ### `Pool`
253//!
254//! It's a reference to a connection pool, that can be cloned and shared between threads.
255//!
256//! ```
257//! # mysql::doctest_wrapper!(__result, {
258//! use mysql::*;
259//! use mysql::prelude::*;
260//!
261//! use std::thread::spawn;
262//!
263//! let pool = Pool::new(get_opts())?;
264//!
265//! let handles = (0..4).map(|i| {
266//!     spawn({
267//!         let pool = pool.clone();
268//!         move || {
269//!             let mut conn = pool.get_conn()?;
270//!             conn.exec_first::<u32, _, _>("SELECT ? * 10", (i,))
271//!                 .map(Option::unwrap)
272//!         }
273//!     })
274//! });
275//!
276//! let result: Result<Vec<u32>> = handles.map(|handle| handle.join().unwrap()).collect();
277//!
278//! assert_eq!(result.unwrap(), vec![0, 10, 20, 30]);
279//! # });
280//! ```
281//!
282//! ### `Statement`
283//!
284//! Statement, actually, is just an identifier coupled with statement metadata, i.e an information
285//! about its parameters and columns. Internally the `Statement` structure also holds additional
286//! data required to support named parameters (see bellow).
287//!
288//! ```
289//! # mysql::doctest_wrapper!(__result, {
290//! use mysql::*;
291//! use mysql::prelude::*;
292//!
293//! let pool = Pool::new(get_opts())?;
294//! let mut conn = pool.get_conn()?;
295//!
296//! let stmt = conn.prep("DO ?")?;
297//!
298//! // The prepared statement will return no columns.
299//! assert!(stmt.columns().is_empty());
300//!
301//! // The prepared statement have one parameter.
302//! let param = stmt.params().get(0).unwrap();
303//! assert_eq!(param.schema_str(), "");
304//! assert_eq!(param.table_str(), "");
305//! assert_eq!(param.name_str(), "?");
306//! # });
307//! ```
308//!
309//! ### `Value`
310//!
311//! This enumeration represents the raw value of a MySql cell. Library offers conversion between
312//! `Value` and different rust types via `FromValue` trait described below.
313//!
314//! #### `FromValue` trait
315//!
316//! This trait is reexported from **mysql_common** create. Please refer to its
317//! [crate docs][mysql_common docs] for the list of supported conversions.
318//!
319//! Trait offers conversion in two flavours:
320//!
321//! *   `from_value(Value) -> T` - convenient, but panicking conversion.
322//!
323//!     Note, that for any variant of `Value` there exist a type, that fully covers its domain,
324//!     i.e. for any variant of `Value` there exist `T: FromValue` such that `from_value` will never
325//!     panic. This means, that if your database schema is known, than it's possible to write your
326//!     application using only `from_value` with no fear of runtime panic.
327//!
328//! *   `from_value_opt(Value) -> Option<T>` - non-panicking, but less convenient conversion.
329//!
330//!     This function is useful to probe conversion in cases, where source database schema
331//!     is unknown.
332//!
333//! ```
334//! # mysql::doctest_wrapper!(__result, {
335//! use mysql::*;
336//! use mysql::prelude::*;
337//!
338//! let via_test_protocol: u32 = from_value(Value::Bytes(b"65536".to_vec()));
339//! let via_bin_protocol: u32 = from_value(Value::UInt(65536));
340//! assert_eq!(via_test_protocol, via_bin_protocol);
341//!
342//! let unknown_val = // ...
343//! # Value::Time(false, 10, 2, 30, 0, 0);
344//!
345//! // Maybe it is a float?
346//! let unknown_val = match from_value_opt::<f64>(unknown_val) {
347//!     Ok(float) => {
348//!         println!("A float value: {}", float);
349//!         return Ok(());
350//!     }
351//!     Err(FromValueError(unknown_val)) => unknown_val,
352//! };
353//!
354//! // Or a string?
355//! let unknown_val = match from_value_opt::<String>(unknown_val) {
356//!     Ok(string) => {
357//!         println!("A string value: {}", string);
358//!         return Ok(());
359//!     }
360//!     Err(FromValueError(unknown_val)) => unknown_val,
361//! };
362//!
363//! // Screw this, I'll simply match on it
364//! match unknown_val {
365//!     val @ Value::NULL => {
366//!         println!("An empty value: {:?}", from_value::<Option<u8>>(val))
367//!     },
368//!     val @ Value::Bytes(..) => {
369//!         // It's non-utf8 bytes, since we already tried to convert it to String
370//!         println!("Bytes: {:?}", from_value::<Vec<u8>>(val))
371//!     }
372//!     val @ Value::Int(..) => {
373//!         println!("A signed integer: {}", from_value::<i64>(val))
374//!     }
375//!     val @ Value::UInt(..) => {
376//!         println!("An unsigned integer: {}", from_value::<u64>(val))
377//!     }
378//!     Value::Float(..) => unreachable!("already tried"),
379//!     val @ Value::Double(..) => {
380//!         println!("A double precision float value: {}", from_value::<f64>(val))
381//!     }
382//!     val @ Value::Date(..) => {
383//!         use time::PrimitiveDateTime;
384//!         println!("A date value: {}", from_value::<PrimitiveDateTime>(val))
385//!     }
386//!     val @ Value::Time(..) => {
387//!         use std::time::Duration;
388//!         println!("A time value: {:?}", from_value::<Duration>(val))
389//!     }
390//! }
391//! # });
392//! ```
393//!
394//! ### `Row`
395//!
396//! Internally `Row` is a vector of `Value`s, that also allows indexing by a column name/offset,
397//! and stores row metadata. Library offers conversion between `Row` and sequences of Rust types
398//! via `FromRow` trait described below.
399//!
400//! #### `FromRow` trait
401//!
402//! This trait is reexported from **mysql_common** create. Please refer to its
403//! [crate docs][mysql_common docs] for the list of supported conversions.
404//!
405//! This conversion is based on the `FromValue` and so comes in two similar flavours:
406//!
407//! *   `from_row(Row) -> T` - same as `from_value`, but for rows;
408//! *   `from_row_opt(Row) -> Option<T>` - same as `from_value_opt`, but for rows.
409//!
410//! [`Queryable`](#queryable)
411//! trait offers implicit conversion for rows of a query result,
412//! that is based on this trait.
413//!
414//! ```
415//! # mysql::doctest_wrapper!(__result, {
416//! use mysql::*;
417//! use mysql::prelude::*;
418//!
419//! let mut conn = Conn::new(get_opts())?;
420//!
421//! // Single-column row can be converted to a singular value:
422//! let val: Option<String> = conn.query_first("SELECT 'foo'")?;
423//! assert_eq!(val.unwrap(), "foo");
424//!
425//! // Example of a mutli-column row conversion to an inferred type:
426//! let row = conn.query_first("SELECT 255, 256")?;
427//! assert_eq!(row, Some((255u8, 256u16)));
428//!
429//! // The FromRow trait does not support to-tuple conversion for rows with more than 12 columns,
430//! // but you can do this by hand using row indexing or `Row::take` method:
431//! let row: Row = conn.exec_first("select 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12", ())?.unwrap();
432//! for i in 0..row.len() {
433//!     assert_eq!(row[i], Value::Int(i as i64));
434//! }
435//!
436//! // Another way to handle wide rows is to use HList (requires `mysql_common/frunk` feature)
437//! use frunk::{HList, hlist, hlist_pat};
438//! let query = "select 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15";
439//! type RowType = HList!(u8, u16, u32, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8);
440//! let first_three_columns = conn.query_map(query, |row: RowType| {
441//!     // do something with the row (see the `frunk` crate documentation)
442//!     let hlist_pat![c1, c2, c3, ...] = row;
443//!     (c1, c2, c3)
444//! });
445//! assert_eq!(first_three_columns.unwrap(), vec![(0_u8, 1_u16, 2_u32)]);
446//!
447//! // Some unknown row
448//! let row: Row = conn.query_first(
449//!     // ...
450//!     # "SELECT 255, Null",
451//! )?.unwrap();
452//!
453//! for column in row.columns_ref() {
454//!     // Cells in a row can be indexed by numeric index or by column name
455//!     let column_value = &row[column.name_str().as_ref()];
456//!
457//!     println!(
458//!         "Column {} of type {:?} with value {:?}",
459//!         column.name_str(),
460//!         column.column_type(),
461//!         column_value,
462//!     );
463//! }
464//! # });
465//! ```
466//!
467//! ### `Params`
468//!
469//! Represents parameters of a prepared statement, but this type won't appear directly in your code
470//! because binary protocol API will ask for `T: Into<Params>`, where `Into<Params>` is implemented:
471//!
472//! *   for tuples of `Into<Value>` types up to arity 12;
473//!
474//!     **Note:** singular tuple requires extra comma, e.g. `("foo",)`;
475//!
476//! *   for `IntoIterator<Item: Into<Value>>` for cases, when your statement takes more
477//!     than 12 parameters;
478//! *   for named parameters representation (the value of the `params!` macro, described below).
479//!
480//! ```
481//! # mysql::doctest_wrapper!(__result, {
482//! use mysql::*;
483//! use mysql::prelude::*;
484//!
485//! let mut conn = Conn::new(get_opts())?;
486//!
487//! // Singular tuple requires extra comma:
488//! let row: Option<u8> = conn.exec_first("SELECT ?", (0,))?;
489//! assert_eq!(row.unwrap(), 0);
490//!
491//! // More than 12 parameters:
492//! let row: Option<u8> = conn.exec_first(
493//!     "SELECT CONVERT(? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ?, UNSIGNED)",
494//!     (0..16).collect::<Vec<_>>(),
495//! )?;
496//! assert_eq!(row.unwrap(), 120);
497//! # });
498//! ```
499//!
500//! **Note:** Please refer to the [**mysql_common** crate docs][mysql_common docs] for the list
501//! of types, that implements `Into<Value>`.
502//!
503//! #### `Serialized`, `Deserialized`
504//!
505//! Wrapper structures for cases, when you need to provide a value for a JSON cell,
506//! or when you need to parse JSON cell as a struct.
507//!
508//! ```rust
509//! # #[macro_use] extern crate serde_derive;
510//! # mysql::doctest_wrapper!(__result, {
511//! use mysql::*;
512//! use mysql::prelude::*;
513//!
514//! /// Serializable structure.
515//! #[derive(Debug, PartialEq, Serialize, Deserialize)]
516//! struct Example {
517//!     foo: u32,
518//! }
519//!
520//! // Value::from for Serialized will emit json string.
521//! let value = Value::from(Serialized(Example { foo: 42 }));
522//! assert_eq!(value, Value::Bytes(br#"{"foo":42}"#.to_vec()));
523//!
524//! // from_value for Deserialized will parse json string.
525//! let structure: Deserialized<Example> = from_value(value);
526//! assert_eq!(structure, Deserialized(Example { foo: 42 }));
527//! # });
528//! ```
529//!
530//! ### [`QueryResult`]
531//!
532//! It's an iterator over rows of a query result with support of multi-result sets. It's intended
533//! for cases when you need full control during result set iteration. For other cases
534//! [`Queryable`](#queryable) provides a set of methods that will immediately consume
535//! the first result set and drop everything else.
536//!
537//! This iterator is lazy so it won't read the result from server until you iterate over it.
538//! MySql protocol is strictly sequential, so `Conn` will be mutably borrowed until the result
539//! is fully consumed (please also look at [`QueryResult::iter`] docs).
540//!
541//! ```rust
542//! # #[macro_use] extern crate serde_derive;
543//! # mysql::doctest_wrapper!(__result, {
544//! use mysql::*;
545//! use mysql::prelude::*;
546//!
547//! let mut conn = Conn::new(get_opts())?;
548//!
549//! // This query will emit two result sets.
550//! let mut result = conn.query_iter("SELECT 1, 2; SELECT 3, 3.14;")?;
551//!
552//! let mut sets = 0;
553//! while let Some(result_set) = result.iter() {
554//!     sets += 1;
555//!
556//!     println!("Result set columns: {:?}", result_set.columns());
557//!     println!(
558//!         "Result set meta: {}, {:?}, {} {}",
559//!         result_set.affected_rows(),
560//!         result_set.last_insert_id(),
561//!         result_set.warnings(),
562//!         result_set.info_str(),
563//!     );
564//!
565//!     for row in result_set {
566//!         match sets {
567//!             1 => {
568//!                 // First result set will contain two numbers.
569//!                 assert_eq!((1_u8, 2_u8), from_row(row?));
570//!             }
571//!             2 => {
572//!                 // Second result set will contain a number and a float.
573//!                 assert_eq!((3_u8, 3.14), from_row(row?));
574//!             }
575//!             _ => unreachable!(),
576//!         }
577//!     }
578//! }
579//!
580//! assert_eq!(sets, 2);
581//! # });
582//! ```
583//!
584//! ## Text protocol
585//!
586//! MySql text protocol is implemented in the set of `Queryable::query*` methods. It's useful when your
587//! query doesn't have parameters.
588//!
589//! **Note:** All values of a text protocol result set will be encoded as strings by the server,
590//! so `from_value` conversion may lead to additional parsing costs.
591//!
592//! Examples:
593//!
594//! ```rust
595//! # mysql::doctest_wrapper!(__result, {
596//! # use mysql::*;
597//! # use mysql::prelude::*;
598//! let pool = Pool::new(get_opts())?;
599//! let val = pool.get_conn()?.query_first("SELECT POW(2, 16)")?;
600//!
601//! // Text protocol returns bytes even though the result of POW
602//! // is actually a floating point number.
603//! assert_eq!(val, Some(Value::Bytes("65536".as_bytes().to_vec())));
604//! # });
605//! ```
606//!
607//! ### The `TextQuery` trait.
608//!
609//! The `TextQuery` trait covers the set of `Queryable::query*` methods from the perspective
610//! of a query, i.e. `TextQuery` is something, that can be performed if suitable connection
611//! is given. Suitable connections are:
612//!
613//! *   `&Pool`
614//! *   `Conn`
615//! *   `PooledConn`
616//! *   `&mut Conn`
617//! *   `&mut PooledConn`
618//! *   `&mut Transaction`
619//!
620//! The unique characteristic of this trait, is that you can give away the connection
621//! and thus produce `QueryResult` that satisfies `'static`:
622//!
623//! ```rust
624//! # mysql::doctest_wrapper!(__result, {
625//! use mysql::*;
626//! use mysql::prelude::*;
627//!
628//! fn iter(pool: &Pool) -> Result<impl Iterator<Item=Result<u32>>> {
629//!     let result = "SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3".run(pool)?;
630//!     Ok(result.map(|row| row.map(from_row)))
631//! }
632//!
633//! let pool = Pool::new(get_opts())?;
634//!
635//! let it = iter(&pool)?;
636//!
637//! assert_eq!(it.collect::<Result<Vec<u32>>>()?, vec![1, 2, 3]);
638//! # });
639//! ```
640//!
641//! ## Binary protocol and prepared statements.
642//!
643//! MySql binary protocol is implemented in `prep`, `close` and the set of `exec*` methods,
644//! defined on the [`Queryable`](#queryable) trait. Prepared statements is the only way to
645//! pass rust value to the MySql server. MySql uses `?` symbol as a parameter placeholder
646//! and it's only possible to use parameters where a single MySql value is expected.
647//! For example:
648//!
649//! ```rust
650//! # mysql::doctest_wrapper!(__result, {
651//! # use mysql::*;
652//! # use mysql::prelude::*;
653//! let pool = Pool::new(get_opts())?;
654//! let val = pool.get_conn()?.exec_first("SELECT POW(?, ?)", (2, 16))?;
655//!
656//! assert_eq!(val, Some(Value::Double(65536.0)));
657//! # });
658//! ```
659//!
660//! ### Statements
661//!
662//! In MySql each prepared statement belongs to a particular connection and can't be executed
663//! on another connection. Trying to do so will lead to an error. The driver won't tie statement
664//! to its connection in any way, but one can look on to the connection id, contained
665//!  in the `Statement` structure.
666//!
667//! ```rust
668//! # mysql::doctest_wrapper!(__result, {
669//! # use mysql::*;
670//! # use mysql::prelude::*;
671//! let pool = Pool::new(get_opts())?;
672//!
673//! let mut conn_1 = pool.get_conn()?;
674//! let mut conn_2 = pool.get_conn()?;
675//!
676//! let stmt_1 = conn_1.prep("SELECT ?")?;
677//!
678//! // stmt_1 is for the conn_1, ..
679//! assert!(stmt_1.connection_id() == conn_1.connection_id());
680//! assert!(stmt_1.connection_id() != conn_2.connection_id());
681//!
682//! // .. so stmt_1 will execute only on conn_1
683//! assert!(conn_1.exec_drop(&stmt_1, ("foo",)).is_ok());
684//! assert!(conn_2.exec_drop(&stmt_1, ("foo",)).is_err());
685//! # });
686//! ```
687//!
688//! ### Statement cache
689//!
690//! `Conn` will manage the cache of prepared statements on the client side, so subsequent calls
691//! to prepare with the same statement won't lead to a client-server roundtrip. Cache size
692//! for each connection is determined by the `stmt_cache_size` field of the `Opts` structure.
693//! Statements, that are out of this boundary will be closed in LRU order.
694//!
695//! Statement cache is completely disabled if `stmt_cache_size` is zero.
696//!
697//! **Caveats:**
698//!
699//! *   disabled statement cache means, that you have to close statements yourself using
700//!     `Conn::close`, or they'll exhaust server limits/resources;
701//!
702//! *   you should be aware of the [`max_prepared_stmt_count`][max_prepared_stmt_count]
703//!     option of the MySql server. If the number of active connections times the value
704//!     of `stmt_cache_size` is greater, than you could receive an error while prepareing
705//!     another statement.
706//!
707//! ### Named parameters
708//!
709//! MySql itself doesn't have named parameters support, so it's implemented on the client side.
710//! One should use `:name` as a placeholder syntax for a named parameter. Named parameters uses
711//! the following naming convention:
712//!
713//! * parameter name must start with either `_` or `a..z`
714//! * parameter name may continue with `_`, `a..z` and `0..9`
715//!
716//! Named parameters may be repeated within the statement, e.g `SELECT :foo, :foo` will require
717//! a single named parameter `foo` that will be repeated on the corresponding positions during
718//! statement execution.
719//!
720//! One should use the `params!` macro to build parameters for execution.
721//!
722//! **Note:** Positional and named parameters can't be mixed within the single statement.
723//!
724//! Examples:
725//!
726//! ```rust
727//! # mysql::doctest_wrapper!(__result, {
728//! # use mysql::*;
729//! # use mysql::prelude::*;
730//! let pool = Pool::new(get_opts())?;
731//!
732//! let mut conn = pool.get_conn()?;
733//! let stmt = conn.prep("SELECT :foo, :bar, :foo")?;
734//!
735//! let foo = 42;
736//!
737//! let val_13 = conn.exec_first(&stmt, params! { "foo" => 13, "bar" => foo })?.unwrap();
738//! // Short syntax is available when param name is the same as variable name:
739//! let val_42 = conn.exec_first(&stmt, params! { foo, "bar" => 13 })?.unwrap();
740//!
741//! assert_eq!((foo, 13, foo), val_42);
742//! assert_eq!((13, foo, 13), val_13);
743//! # });
744//! ```
745//!
746//! ### Buffer pool
747//!
748//! Crate uses the global lock-free buffer pool for the purpose of IO and data serialization/deserialization,
749//! that helps to avoid allocations for basic scenarios. You can control it's characteristics using
750//! the following environment variables:
751//!
752//! *   `RUST_MYSQL_BUFFER_POOL_CAP` (defaults to 128) – controls the pool capacity. Dropped buffer will
753//!     be immediately deallocated if the pool is full. Set it to `0` to disable the pool at runtime.
754//!
755//! *   `RUST_MYSQL_BUFFER_SIZE_CAP` (defaults to 4MiB) – controls the maximum capacity of a buffer
756//!     stored in the pool. Capacity of a dropped buffer will be shrunk to this value when buffer
757//!     is returned to the pool.
758//!
759//! To completely disable the pool (say you are using jemalloc) please remove the `buffer-pool` feature
760//! from the set of default crate features (see the [Crate Features](#crate-features) section).
761//!
762//! ### `BinQuery` and `BatchQuery` traits.
763//!
764//! `BinQuery` and `BatchQuery` traits covers the set of `Queryable::exec*` methods from
765//! the perspective of a query, i.e. `BinQuery` is something, that can be performed if suitable
766//! connection is given (see [`TextQuery`](#the-textquery-trat) section for the list
767//! of suitable connections).
768//!
769//! As with the [`TextQuery`](#the-textquery-trait) you can give away the connection and acquire
770//! `QueryResult` that satisfies `'static`.
771//!
772//! `BinQuery` is for prepared statements, and prepared statements requires a set of parameters,
773//! so `BinQuery` is implemented for `QueryWithParams` structure, that can be acquired, using
774//! `WithParams` trait.
775//!
776//! Example:
777//!
778//! ```rust
779//! # mysql::doctest_wrapper!(__result, {
780//! use mysql::*;
781//! use mysql::prelude::*;
782//!
783//! let pool = Pool::new(get_opts())?;
784//!
785//! let result: Option<(u8, u8, u8)> = "SELECT ?, ?, ?"
786//!     .with((1, 2, 3)) // <- WithParams::with will construct an instance of QueryWithParams
787//!     .first(&pool)?;  // <- QueryWithParams is executed on the given pool
788//!
789//! assert_eq!(result.unwrap(), (1, 2, 3));
790//! # });
791//! ```
792//!
793//! The `BatchQuery` trait is a helper for batch statement execution. It's implemented for
794//! `QueryWithParams` where parameters is an iterator over parameters:
795//!
796//! ```rust
797//! # mysql::doctest_wrapper!(__result, {
798//! use mysql::*;
799//! use mysql::prelude::*;
800//!
801//! let pool = Pool::new(get_opts())?;
802//! let mut conn = pool.get_conn()?;
803//!
804//! "CREATE TEMPORARY TABLE batch (x INT)".run(&mut conn)?;
805//! "INSERT INTO batch (x) VALUES (?)"
806//!     .with((0..3).map(|x| (x,))) // <- QueryWithParams constructed with an iterator
807//!     .batch(&mut conn)?;         // <- batch execution is preformed here
808//!
809//! let result: Vec<u8> = "SELECT x FROM batch".fetch(conn)?;
810//!
811//! assert_eq!(result, vec![0, 1, 2]);
812//! # });
813//! ```
814//!
815//! ### `Queryable`
816//!
817//! The `Queryable` trait defines common methods for `Conn`, `PooledConn` and `Transaction`.
818//! The set of basic methods consts of:
819//!
820//! *   `query_iter` - basic methods to execute text query and get `QueryResult`;
821//! *   `prep` - basic method to prepare a statement;
822//! *   `exec_iter` - basic method to execute statement and get `QueryResult`;
823//! *   `close` - basic method to close the statement;
824//!
825//! The trait also defines the set of helper methods, that is based on basic methods.
826//! These methods will consume only the first result set, other result sets will be dropped:
827//!
828//! *   `{query|exec}` - to collect the result into a `Vec<T: FromRow>`;
829//! *   `{query|exec}_first` - to get the first `T: FromRow`, if any;
830//! *   `{query|exec}_map` - to map each `T: FromRow` to some `U`;
831//! *   `{query|exec}_fold` - to fold the set of `T: FromRow` to a single value;
832//! *   `{query|exec}_drop` - to immediately drop the result.
833//!
834//! The trait also defines the `exec_batch` function, which is a helper for batch statement
835//! execution.
836//!
837//! ## SSL Support
838//!
839//! SSL support comes in two flavors:
840//!
841//! 1.  Based on **native-tls** – this is the default option, that usually works without pitfalls
842//!     (see the `native-tls` crate feature).
843//! 2.  Based on **rustls** – TLS backend written in Rust. Please use the `rustls-tls` crate feature
844//!     to enable it (see the [Crate Features](#crate-features) section).
845//!
846//!     Please also note a few things about **rustls**:
847//!
848//!     *   it will fail if you'll try to connect to the server by its IP address, hostname is required;
849//!     *   it, most likely, won't work on windows, at least with default server certs, generated by the
850//!         MySql installer.
851//!
852//! [crate docs]: https://docs.rs/mysql
853//! [mysql_common docs]: https://docs.rs/mysql_common
854//! [max_prepared_stmt_count]: https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_max_prepared_stmt_count
855//!
856
857#![cfg_attr(feature = "nightly", feature(test))]
858#[cfg(feature = "nightly")]
859extern crate test;
860
861use mysql_common as myc;
862pub extern crate serde;
863pub extern crate serde_json;
864#[cfg(test)]
865#[macro_use]
866extern crate serde_derive;
867
868mod buffer_pool;
869mod conn;
870pub mod error;
871mod io;
872
873#[doc(inline)]
874pub use crate::myc::constants as consts;
875
876#[doc(inline)]
877pub use crate::myc::packets::{binlog_request::BinlogRequest, BinlogDumpFlags};
878
879pub mod binlog {
880    #[doc(inline)]
881    pub use crate::myc::binlog::consts::*;
882
883    #[doc(inline)]
884    pub use crate::myc::binlog::{events, jsonb, jsondiff, row, value};
885}
886
887#[cfg(any(feature = "native-tls", feature = "rustls-tls"))]
888#[doc(inline)]
889pub use crate::conn::opts::ClientIdentity;
890
891#[doc(inline)]
892pub use crate::myc::packets::{session_state_change, SessionStateInfo};
893
894#[doc(inline)]
895pub use crate::conn::local_infile::{LocalInfile, LocalInfileHandler};
896#[doc(inline)]
897pub use crate::conn::opts::SslOpts;
898#[doc(inline)]
899pub use crate::conn::opts::{Opts, OptsBuilder, DEFAULT_STMT_CACHE_SIZE};
900#[doc(inline)]
901pub use crate::conn::pool::{Pool, PooledConn};
902#[doc(inline)]
903pub use crate::conn::query::QueryWithParams;
904#[doc(inline)]
905pub use crate::conn::query_result::{Binary, QueryResult, ResultSet, SetColumns, Text};
906#[doc(inline)]
907pub use crate::conn::stmt::Statement;
908#[doc(inline)]
909pub use crate::conn::transaction::{AccessMode, IsolationLevel, Transaction, TxOpts};
910#[doc(inline)]
911pub use crate::conn::{binlog_stream::BinlogStream, Conn};
912#[doc(inline)]
913pub use crate::error::{DriverError, Error, MySqlError, Result, ServerError, UrlError};
914#[doc(inline)]
915pub use crate::myc::packets::Column;
916#[doc(inline)]
917pub use crate::myc::params::Params;
918#[doc(inline)]
919pub use crate::myc::proto::codec::Compression;
920#[doc(inline)]
921pub use crate::myc::row::convert::{from_row, from_row_opt, FromRowError};
922#[doc(inline)]
923pub use crate::myc::row::Row;
924#[doc(inline)]
925pub use crate::myc::value::convert::{from_value, from_value_opt, FromValueError};
926#[doc(inline)]
927pub use crate::myc::value::json::{Deserialized, Serialized};
928#[doc(inline)]
929pub use crate::myc::value::Value;
930
931pub mod prelude {
932    #[doc(inline)]
933    pub use crate::conn::query::{BatchQuery, BinQuery, TextQuery, WithParams};
934    #[doc(inline)]
935    pub use crate::conn::queryable::{AsStatement, Queryable};
936    #[doc(inline)]
937    pub use crate::myc::row::convert::FromRow;
938    #[doc(inline)]
939    pub use crate::myc::row::ColumnIndex;
940    #[doc(inline)]
941    pub use crate::myc::value::convert::{ConvIr, FromValue, ToValue};
942
943    /// Trait for protocol markers [`crate::Binary`] and [`crate::Text`].
944    pub trait Protocol: crate::conn::query_result::Protocol {}
945    impl Protocol for crate::Binary {}
946    impl Protocol for crate::Text {}
947}
948
949#[doc(inline)]
950pub use crate::myc::params;
951
952#[doc(hidden)]
953#[macro_export]
954macro_rules! def_database_url {
955    () => {
956        if let Ok(url) = std::env::var("DATABASE_URL") {
957            let opts = $crate::Opts::from_url(&url).expect("DATABASE_URL invalid");
958            if opts
959                .get_db_name()
960                .expect("a database name is required")
961                .is_empty()
962            {
963                panic!("database name is empty");
964            }
965            url
966        } else {
967            "mysql://root:password@localhost:3307/mysql".into()
968        }
969    };
970}
971
972#[doc(hidden)]
973#[macro_export]
974macro_rules! def_get_opts {
975    () => {
976        pub fn test_ssl() -> bool {
977            let ssl = std::env::var("SSL").ok().unwrap_or("false".into());
978            ssl == "true" || ssl == "1"
979        }
980
981        pub fn test_compression() -> bool {
982            let compress = std::env::var("COMPRESS").ok().unwrap_or("false".into());
983            compress == "true" || compress == "1"
984        }
985
986        pub fn get_opts() -> $crate::OptsBuilder {
987            let database_url = $crate::def_database_url!();
988            let mut builder =
989                $crate::OptsBuilder::from_opts($crate::Opts::from_url(&*database_url).unwrap())
990                    .init(vec!["SET GLOBAL sql_mode = 'TRADITIONAL'"]);
991            if test_compression() {
992                builder = builder.compress(Some(Default::default()));
993            }
994            if test_ssl() {
995                let ssl_opts = $crate::SslOpts::default()
996                    .with_danger_skip_domain_validation(true)
997                    .with_danger_accept_invalid_certs(true);
998                builder = builder.prefer_socket(false).ssl_opts(ssl_opts);
999            }
1000            builder
1001        }
1002    };
1003}
1004
1005#[doc(hidden)]
1006#[macro_export]
1007macro_rules! doctest_wrapper {
1008    ($body:block) => {
1009        fn fun() {
1010            $crate::def_get_opts!();
1011            $body;
1012        }
1013        fun()
1014    };
1015    (__result, $body:block) => {
1016        fn fun() -> std::result::Result<(), Box<dyn std::error::Error>> {
1017            $crate::def_get_opts!();
1018            Ok($body)
1019        }
1020        fun()
1021    };
1022}
1023
1024#[cfg(test)]
1025mod test_misc {
1026    use lazy_static::lazy_static;
1027
1028    use crate::{def_database_url, def_get_opts};
1029
1030    #[allow(dead_code)]
1031    fn error_should_implement_send_and_sync() {
1032        fn _dummy<T: Send + Sync>(_: T) {}
1033        _dummy(crate::error::Error::FromValueError(crate::Value::NULL));
1034    }
1035
1036    lazy_static! {
1037        pub static ref DATABASE_URL: String = def_database_url!();
1038    }
1039
1040    def_get_opts!();
1041}