Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Asyncronous Rust Mysql driver based on Tokio.

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT
NotificationsYou must be signed in to change notification settings

blackbeam/mysql_async

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Gitter

Build StatusAPI Documentation on docs.rs

mysql_async

Tokio based asynchronous MySql client library for The Rust Programming Language.

Installation

The library is hosted oncrates.io.

[dependencies]mysql_async ="<desired version>"

Crate Features

By default there are only two features enabled:

List Of Features

  • minimal – enables only necessary features (at the moment the only necessary featureisflate2 backend). Enables:

    • `flate2/zlib"

    Example:

    [dependencies]mysql_async = {version ="*",default-features =false,features = ["minimal"]}
  • minimal-rust - same asminimal but with rust-based flate2 backend. Enables:

    • flate2/rust_backend
  • default – enables the following set of features:

    • flate2/zlib
    • derive
  • default-rustls – default set of features with TLS viarustls/aws-lc-rs

  • default-rustls-ring – default set of features with TLS viarustls/ring

    Example:

    [dependencies]mysql_async = {version ="*",default-features =false,features = ["default-rustls"] }
  • native-tls-tls – enables TLS vianative-tls

    Example:

    [dependencies]mysql_async = {version ="*",default-features =false,features = ["minimal","native-tls-tls"] }
  • rustls-tls - enables rustls TLS backend with no provider. You should enable oneof existing providers usingaws-lc-rs orring features:

    Example:

    [dependencies]mysql_async = {version ="*",default-features =false,features = ["minimal-rust","rustls-tls","ring"] }
  • tracing – enables instrumentation viatracing package.

    Primary operations (query,prepare,exec) are instrumented atINFO level.Remaining operations, incl.get_conn, are instrumented atDEBUG level.Also atDEBUG, the SQL queries and parameters are added to thequery,prepareandexec spans. Also some internal queries are instrumented atTRACE level.

    Example:

    [dependencies]mysql_async = {version ="*",features = ["tracing"] }
  • binlog - enables binlog-related functionality. Enables:

    • `mysql_common/binlog"

Proxied features (see`mysql_common`` fatures)

  • derive – enablesmysql_common/derive feature
  • chrono = enablesmysql_common/chrono feature
  • time = enablesmysql_common/time feature
  • bigdecimal = enablesmysql_common/bigdecimal feature
  • rust_decimal = enablesmysql_common/rust_decimal feature
  • frunk = enablesmysql_common/frunk feature

TLS/SSL Support

SSL support comes in two flavors:

  1. Based on native-tls – this is the default option, that usually works without pitfalls(see thenative-tls-tls crate feature).

  2. Based on rustls – TLS backend written in Rust (see therustls-tls crate feature).

    Please also note a few things about rustls:

    • it will fail if you'll try to connect to the server by its IP address,hostname is required;
    • it, most likely, won't work on windows, at least with default server certs,generated by the MySql installer.

Connection URL parameters

There is a set of url-parameters supported by the driver (see documentation on [Opts]).

Example

use mysql_async::prelude::*;#[derive(Debug,PartialEq,Eq,Clone)]structPayment{customer_id:i32,amount:i32,account_name:Option<String>,}#[tokio::main]asyncfnmain() ->Result<()>{let payments =vec![Payment{ customer_id:1, amount:2, account_name:None},Payment{ customer_id:3, amount:4, account_name:Some("foo".into())},Payment{ customer_id:5, amount:6, account_name:None},Payment{ customer_id:7, amount:8, account_name:None},Payment{ customer_id:9, amount:10, account_name:Some("bar".into())},];let database_url =/* ... */    #get_opts();let pool = mysql_async::Pool::new(database_url);letmut conn = pool.get_conn().await?;// Create a temporary tabler"CREATE TEMPORARY TABLE payment (        customer_id int not null,        amount int not null,        account_name text    )".ignore(&mut conn).await?;// Save paymentsr"INSERT INTO payment (customer_id, amount, account_name)      VALUES (:customer_id, :amount, :account_name)".with(payments.iter().map(|payment|params!{"customer_id" => payment.customer_id,"amount" => payment.amount,"account_name" => payment.account_name.as_ref(),})).batch(&mut conn).await?;// Load payments from the database. Type inference will work here.let loaded_payments ="SELECT customer_id, amount, account_name FROM payment".with(()).map(&mut conn, |(customer_id, amount, account_name)|Payment{ customer_id, amount, account_name}).await?;// Dropped connection will go to the pooldrop(conn);// The Pool must be disconnected explicitly because// it's an asynchronous operation.    pool.disconnect().await?;assert_eq!(loaded_payments, payments);// the async fn returns Result, soOk(())}

Pool

The [Pool] structure is an asynchronous connection pool.

Please note:

  • [Pool] is a smart pointer – each clone will point to the same pool instance.
  • [Pool] isSend + Sync + 'static – feel free to pass it around.
  • use [Pool::disconnect] to gracefuly close the pool.
  • ⚠️ [Pool::new] is lazy and won't assert server availability.

Transaction

[Conn::start_transaction] is a wrapper, that starts withSTART TRANSACTIONand ends withCOMMIT orROLLBACK.

Dropped transaction will be implicitly rolled back if it wasn't explicitlycommitted or rolled back. Note that this behaviour will be triggered by a pool(on conn drop) or by the next query, i.e. may be delayed.

API won't allow you to run nested transactions because some statements causesan implicit commit (START TRANSACTION is one of them), so this behavioris chosen as less error prone.

Value

This enumeration represents the raw value of a MySql cell. Library offers conversion betweenValue and different rust types viaFromValue trait described below.

FromValue trait

This trait is reexported frommysql_common create. Please refer to itscrate docs for the list of supported conversions.

Trait offers conversion in two flavours:

  • from_value(Value) -> T - convenient, but panicking conversion.

    Note, that for any variant ofValue there exist a type, that fully covers its domain,i.e. for any variant ofValue there existT: FromValue such thatfrom_value will neverpanic. This means, that if your database schema is known, than it's possible to write yourapplication using onlyfrom_value with no fear of runtime panic.

    Also note, that some convertions may fail even though the type seem sufficient,e.g. in case of invalid dates (seesql mode).

  • from_value_opt(Value) -> Option<T> - non-panicking, but less convenient conversion.

    This function is useful to probe conversion in cases, where source database schemais unknown.

MySql query protocols

Text protocol

MySql text protocol is implemented in the set ofQueryable::query* methodsand in the [prelude::Query] trait if query is [prelude::AsQuery].It's useful when your query doesn't have parameters.

Note: All values of a text protocol result set will be encoded as strings by the server,sofrom_value conversion may lead to additional parsing costs.

Binary protocol and prepared statements.

MySql binary protocol is implemented in the set ofexec* methods,defined on the [prelude::Queryable] trait and in the [prelude::Query]trait if query is [QueryWithParams]. Prepared statements is the only way topass rust value to the MySql server. MySql uses? symbol as a parameter placeholder.

Note: it's only possible to use parameters where a single MySql valueis expected, i.e. you can't execute something likeSELECT ... WHERE id IN ?with a vector as a parameter. You'll need to build a query that looks likeSELECT ... WHERE id IN (?, ?, ...) and to pass each vector element asa parameter.

Named parameters

MySql itself doesn't have named parameters support, so it's implemented on the client side.One should use:name as a placeholder syntax for a named parameter. Named parameters usesthe following naming convention:

  • parameter name must start with either_ ora..z
  • parameter name may continue with_,a..z and0..9

Note: this rules mean that, say, the statmentSELECT :fooBar will be translatedtoSELECT ?Bar so please be careful.

Named parameters may be repeated within the statement, e.gSELECT :foo, :foo will requirea single named parameterfoo that will be repeated on the corresponding positions duringstatement execution.

One should use theparams! macro to build parameters for execution.

Note: Positional and named parameters can't be mixed within the single statement.

Statements

In MySql each prepared statement belongs to a particular connection and can't be executedon another connection. Trying to do so will lead to an error. The driver won't tie statementto its connection in any way, but one can look on to the connection id, containedin the [Statement] structure.

LOCAL INFILE Handlers

Warning: You should be aware ofSecurity Considerations for LOAD DATA LOCAL.

There are two flavors of LOCAL INFILE handlers –global andlocal.

I case of a LOCAL INFILE request from the server the driver will try to find a handler for it:

  1. It'll try to uselocal handler installed on the connection, if any;
  2. It'll try to useglobal handler, specified via [OptsBuilder::local_infile_handler],if any;
  3. It will emit [LocalInfileError::NoHandler] if no handlers found.

The purpose of a handler (local orglobal) is to return [InfileData].

Global LOCAL INFILE handler

See [prelude::GlobalHandler].

Simply speaking theglobal handler is an async function that takes a file name (as&[u8])and returnsResult<InfileData>.

You can set it up using [OptsBuilder::local_infile_handler]. Server will use it if there is nolocal handler installed for the connection. This handler might be called multiple times.

Examles:

  1. [WhiteListFsHandler] is aglobal handler.
  2. EveryT: Fn(&[u8]) -> BoxFuture<'static, Result<InfileData, LocalInfileError>>is aglobal handler.

Local LOCAL INFILE handler.

Simply speaking thelocal handler is a future, that returnsResult<InfileData>.

This is a one-time handler – it's consumed after use. You can set it up using[Conn::set_infile_handler]. This handler have priority overglobal handler.

Worth noting:

  1. impl Drop for Conn will clearlocal handler, i.e. handler will be removed whenconnection is returned to aPool.
  2. [Conn::reset] will clearlocal handler.

Example:

#let pool = mysql_async::Pool::new(database_url);letmut conn = pool.get_conn().await?;"CREATE TEMPORARY TABLE tmp (id INT, val TEXT)".ignore(&mut conn).await?;// We are going to call `LOAD DATA LOCAL` so let's setup a one-time handler.conn.set_infile_handler(asyncmove{// We need to return a stream of `io::Result<Bytes>`Ok(stream::iter([Bytes::from("1,a\r\n"),Bytes::from("2,b\r\n3,c")]).map(Ok).boxed())});let result =r#"LOAD DATA LOCAL INFILE 'whatever'    INTO TABLE `tmp`    FIELDS TERMINATED BY ',' ENCLOSED BY '\"'    LINES TERMINATED BY '\r\n'"#.ignore(&mut conn).await;match result{Ok(()) =>(),Err(Error::Server(ref err))if err.code ==1148 =>{// The used command is not allowed with this MySQL versionreturnOk(());},Err(Error::Server(ref err))if err.code ==3948 =>{// Loading local data is disabled;// this must be enabled on both the client and the serverreturnOk(());}    e @Err(_) => e.unwrap(),}// Now let's verify the resultlet result:Vec<(u32,String)> = conn.query("SELECT * FROM tmp ORDER BY id ASC").await?;assert_eq!(    result,    vec![(1,"a".into()),(2,"b".into()),(3,"c".into())]);drop(conn);pool.disconnect().await?;

Testing

Tests uses followin environment variables:

  • DATABASE_URL – defaults tomysql://root:password@127.0.0.1:3307/mysql
  • COMPRESS – set to1 ortrue to enable compression for tests
  • SSL – set to1 ortrue to enable TLS for tests

You can run a test server using doker. Please note that params relatedto max allowed packet, local-infile and binary logging are requiredto properly run tests (please refer toazure-pipelines.yml):

docker run -d --name container \    -v`pwd`:/root \    -p 3307:3306 \    -e MYSQL_ROOT_PASSWORD=password \    mysql:8.0 \    --max-allowed-packet=36700160 \    --local-infile \    --log-bin=mysql-bin \    --log-slave-updates \    --gtid_mode=ON \    --enforce_gtid_consistency=ON \    --server-id=1

Change log

Availablehere

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionallysubmitted for inclusion in the work by you, as defined in the Apache-2.0license, shall be dual licensed as above, without any additional terms orconditions.

About

Asyncronous Rust Mysql driver based on Tokio.

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Packages

No packages published

Languages


[8]ページ先頭

©2009-2025 Movatter.jp