├── .gitignore ├── Cargo.toml ├── scripts └── test.sh ├── CHANGELOG.md ├── .github └── workflows │ └── ci.yml ├── src ├── pool.rs └── lib.rs ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled files 2 | *.o 3 | *.so 4 | *.rlib 5 | *.dll 6 | 7 | # Executables 8 | *.exe 9 | .idea/ 10 | # Generated by Cargo 11 | /target/ 12 | /Cargo.lock 13 | 14 | .idea/workspace.xml 15 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "r2d2_mysql" 3 | version = "25.0.0" 4 | authors = ["outersky "] 5 | license = "MIT" 6 | description = "MySQL support for the r2d2 connection pool" 7 | repository = "https://github.com/outersky/r2d2-mysql" 8 | keywords = ["mysql", "sql", "pool", "database", "r2d2"] 9 | edition = "2021" 10 | rust-version = "1.70" 11 | 12 | [dependencies] 13 | r2d2 = "0.8.9" 14 | mysql = "25" 15 | -------------------------------------------------------------------------------- /scripts/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eEuxo pipefail 4 | 5 | DATABASE_NAME="rust_mysql_test" 6 | export DATABASE_URL="mysql://root@localhost:3306/${DATABASE_NAME}" 7 | 8 | # Assume no root password and create database 9 | mysql -uroot -e "CREATE DATABASE ${DATABASE_NAME}" 10 | 11 | # Run the tests! 12 | cargo test 13 | 14 | # Clean up after ourselves and drop the database 15 | mysql -uroot -e "DROP DATABASE ${DATABASE_NAME}" 16 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Unreleased 4 | 5 | ## 25.0.0 6 | 7 | - Update `mysql` dependency to `25`. 8 | - Minimum supported Rust version (MSRV) is now 1.70 to align with `mysql` dependency. 9 | 10 | ## 24.0.0 11 | 12 | - Update `mysql` dependency to `24`. 13 | - Remove deprecated `MysqlConnectionManager` type alias. 14 | - Minimum supported Rust version (MSRV) is now 1.65 due to transitive dependencies. 15 | 16 | ## 23.0.0 17 | 18 | - Update `mysql` dependency to `23`. 19 | - Rename `MysqlConnectionManager` to `MySqlConnectionManager`. The old name remains available under a deprecated type alias. 20 | - Hide `pool` module. 21 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | types: [opened, synchronize, reopened] 6 | push: 7 | branches: [master] 8 | 9 | jobs: 10 | test: 11 | strategy: 12 | fail-fast: false 13 | matrix: 14 | version: 15 | - { name: msrv, version: 1.70.0 } 16 | - { name: stable, version: stable } 17 | - { name: nightly, version: nightly } 18 | 19 | name: tests / ${{ matrix.version.name }} 20 | runs-on: ubuntu-latest 21 | 22 | steps: 23 | - uses: actions/checkout@v3 24 | 25 | - name: Install Rust (${{ matrix.version.name }}) 26 | uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 27 | with: 28 | toolchain: ${{ matrix.version.version }} 29 | 30 | - name: Setup MySQL 31 | uses: mirromutth/mysql-action@v1.1 32 | with: 33 | mysql user: 'ci' 34 | mysql password: 'ci' 35 | 36 | - run: cargo test 37 | env: 38 | DATABASE_URL: mysql://ci:ci@127.0.0.1:3306 39 | -------------------------------------------------------------------------------- /src/pool.rs: -------------------------------------------------------------------------------- 1 | //! Connection manager implementation for MySQL connections. 2 | //! 3 | //! See [`MySqlConnectionManager`]. 4 | 5 | use mysql::{error::Error, Conn, Opts, OptsBuilder}; 6 | 7 | /// An [`r2d2`] connection manager for [`mysql`] connections. 8 | #[derive(Clone, Debug)] 9 | pub struct MySqlConnectionManager { 10 | params: Opts, 11 | } 12 | 13 | impl MySqlConnectionManager { 14 | /// Constructs a new MySQL connection manager from `params`. 15 | pub fn new(params: OptsBuilder) -> MySqlConnectionManager { 16 | MySqlConnectionManager { 17 | params: Opts::from(params), 18 | } 19 | } 20 | } 21 | 22 | impl r2d2::ManageConnection for MySqlConnectionManager { 23 | type Connection = Conn; 24 | type Error = Error; 25 | 26 | fn connect(&self) -> Result { 27 | Conn::new(self.params.clone()) 28 | } 29 | 30 | fn is_valid(&self, conn: &mut Conn) -> Result<(), Error> { 31 | conn.ping() 32 | } 33 | 34 | fn has_broken(&self, conn: &mut Conn) -> bool { 35 | self.is_valid(conn).is_err() 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 outersky 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # r2d2_mysql 2 | 3 | > [`mysql`](https://github.com/blackbeam/rust-mysql-simple) support library for the [`r2d2`](https://github.com/sfackler/r2d2) connection pool. 4 | 5 | [![crates.io](https://img.shields.io/crates/v/r2d2_mysql?label=latest)](https://crates.io/crates/r2d2_mysql) 6 | [![Documentation](https://docs.rs/r2d2_mysql/badge.svg?version=24)](https://docs.rs/r2d2_mysql/24) 7 | ![Version](https://img.shields.io/badge/rustc-1.59+-ab6000.svg) 8 | ![License](https://img.shields.io/crates/l/r2d2_mysql.svg) 9 | [![Download](https://img.shields.io/crates/d/r2d2_mysql.svg)](https://crates.io/crates/r2d2_mysql) 10 | 11 | ## Install 12 | 13 | Include `r2d2_mysql` in the `[dependencies]` section of your `Cargo.toml`: 14 | 15 | ```toml 16 | [dependencies] 17 | r2d2_mysql = "24" 18 | ``` 19 | 20 | ## Usage 21 | 22 | ```rust 23 | use std::{env, sync::Arc, thread}; 24 | 25 | use r2d2_mysql::{ 26 | mysql::{prelude::*, Opts, OptsBuilder}, 27 | r2d2, MySqlConnectionManager, 28 | }; 29 | 30 | fn main() { 31 | let url = env::var("DATABASE_URL").unwrap(); 32 | let opts = Opts::from_url(&url).unwrap(); 33 | let builder = OptsBuilder::from_opts(opts); 34 | let manager = MySqlConnectionManager::new(builder); 35 | let pool = Arc::new(r2d2::Pool::builder().max_size(4).build(manager).unwrap()); 36 | 37 | let mut tasks = vec![]; 38 | 39 | for _ in 0..3 { 40 | let pool = pool.clone(); 41 | let th = thread::spawn(move || { 42 | let mut conn = pool.get().expect("error getting connection from pool"); 43 | 44 | let _ = conn 45 | .query("SELECT version()") 46 | .map(|rows: Vec| rows.is_empty()) 47 | .expect("error executing query"); 48 | }); 49 | 50 | tasks.push(th); 51 | } 52 | 53 | for th in tasks { 54 | let _ = th.join(); 55 | } 56 | } 57 | ``` 58 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! MySQL support for the [`r2d2`] connection pool (Rust). 2 | //! 3 | //! # Examples 4 | //! ``` 5 | //! use std::{env, sync::Arc, thread}; 6 | //! 7 | //! use r2d2_mysql::{ 8 | //! mysql::{prelude::*, Opts, OptsBuilder}, 9 | //! r2d2, MySqlConnectionManager, 10 | //! }; 11 | //! 12 | //! let url = env::var("DATABASE_URL").unwrap(); 13 | //! let opts = Opts::from_url(&url).unwrap(); 14 | //! let builder = OptsBuilder::from_opts(opts); 15 | //! let manager = MySqlConnectionManager::new(builder); 16 | //! let pool = Arc::new(r2d2::Pool::builder().max_size(4).build(manager).unwrap()); 17 | //! 18 | //! let mut tasks = vec![]; 19 | //! 20 | //! for _ in 0..3 { 21 | //! let pool = pool.clone(); 22 | //! let th = thread::spawn(move || { 23 | //! let mut conn = pool.get().expect("error getting connection from pool"); 24 | //! 25 | //! let _ = conn 26 | //! .query("SELECT version()") 27 | //! .map(|rows: Vec| rows.is_empty()) 28 | //! .expect("error executing query"); 29 | //! }); 30 | //! 31 | //! tasks.push(th); 32 | //! } 33 | //! 34 | //! for th in tasks { 35 | //! let _ = th.join(); 36 | //! } 37 | //! ``` 38 | 39 | pub use mysql; 40 | pub use r2d2; 41 | 42 | mod pool; 43 | pub use self::pool::MySqlConnectionManager; 44 | 45 | #[cfg(test)] 46 | mod test { 47 | use std::{env, sync::Arc, thread}; 48 | 49 | use mysql::{prelude::*, Opts, OptsBuilder}; 50 | 51 | use super::MySqlConnectionManager; 52 | 53 | #[test] 54 | fn query_pool() { 55 | let url = env::var("DATABASE_URL").unwrap(); 56 | let opts = Opts::from_url(&url).unwrap(); 57 | let builder = OptsBuilder::from_opts(opts); 58 | let manager = MySqlConnectionManager::new(builder); 59 | let pool = Arc::new(r2d2::Pool::builder().max_size(4).build(manager).unwrap()); 60 | 61 | let mut tasks = vec![]; 62 | 63 | for _ in 0..3 { 64 | let pool = pool.clone(); 65 | let th = thread::spawn(move || { 66 | let mut conn = pool.get().expect("error getting connection from pool"); 67 | 68 | let _ = conn 69 | .query("SELECT version()") 70 | .map(|rows: Vec| rows.is_empty()) 71 | .expect("error executing query"); 72 | }); 73 | 74 | tasks.push(th); 75 | } 76 | 77 | for th in tasks { 78 | let _ = th.join(); 79 | } 80 | } 81 | } 82 | --------------------------------------------------------------------------------