76个稳定版本 (24个主要版本)
25.0.1 | 2024年5月21日 |
---|---|
25.0.0 | 2024年3月18日 |
24.0.0 | 2023年5月17日 |
23.0.1 | 2022年12月10日 |
0.0.2 |
|
#204 在 数据库接口
每月下载量32,174
用于 149 个Crate (直接使用110个)
400KB
7.5K SLoC
mysql
此crate提供
- 纯Rust实现的MySQL数据库驱动;
- 连接池。
特性
- 支持macOS、Windows和Linux;
- 通过 nativetls 或 rustls 支持TLS(见SSL支持部分);
- 支持MySQL文本协议,即支持简单的文本查询和文本结果集;
- 支持MySQL二进制协议,即支持预处理语句和二进制结果集;
- 支持多结果集;
- 支持预处理语句的命名参数(见命名参数部分);
- 支持每个连接的预处理语句缓存(见语句缓存部分);
- 支持缓冲池(见缓冲池部分);
- 支持大于2^24的MySQL数据包;
- 支持Unix套接字和Windows命名管道;
- 支持自定义LOCAL INFILE处理器;
- 支持MySQL协议压缩;
- 支持认证插件
- mysql_native_password - 用于MySQL版本v8之前;
- caching_sha2_password - 用于MySQL版本v8及以上;
- mysql_clear_password - 可选(见
Opts::get_enable_cleartext_plugin
)。
安装
将所需版本的crate放入您的Cargo.toml
文件的dependencies
部分。
[dependencies]
mysql = "*"
示例
use mysql::*;
use mysql::prelude::*;
#[derive(Debug, PartialEq, Eq)]
struct Payment {
customer_id: i32,
amount: i32,
account_name: Option<String>,
}
fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
let url = "mysql://root:password@localhost:3307/db_name";
# Opts::try_from(url)?;
# let url = get_opts();
let pool = Pool::new(url)?;
let mut conn = pool.get_conn()?;
// Let's create a table for payments.
conn.query_drop(
r"CREATE TEMPORARY TABLE payment (
customer_id int not null,
amount int not null,
account_name text
)")?;
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()) },
];
// Now let's insert payments to the database
conn.exec_batch(
r"INSERT INTO payment (customer_id, amount, account_name)
VALUES (:customer_id, :amount, :account_name)",
payments.iter().map(|p| params! {
"customer_id" => p.customer_id,
"amount" => p.amount,
"account_name" => &p.account_name,
})
)?;
// Let's select payments from database. Type inference should do the trick here.
let selected_payments = conn
.query_map(
"SELECT customer_id, amount, account_name from payment",
|(customer_id, amount, account_name)| {
Payment { customer_id, amount, account_name }
},
)?;
// Let's make sure, that `payments` equals to `selected_payments`.
// Mysql gives no guaranties on order of returned rows
// without `ORDER BY`, so assume we are lucky.
assert_eq!(payments, selected_payments);
println!("Yay!");
Ok(())
}
Crate特性
-
特性集
- 默认 – 包括默认的
mysql_common
特性,native-tls
,buffer-pool
,flate2/zlib
和derive
。 - default-rustls - 与
default
相同,但使用rustls-tls
代替native-tls
,以及使用flate2/rust_backend
代替flate2/zlib
- minimal - 包含
flate2/zlib
- 默认 – 包括默认的
-
crate 的功能
-
默认启用的外部功能
-
对于
flate2
crate(请参阅flate2
crate 文档以获取可用功能)- flate2/zlib(必需)- 默认选择
zlib
后端。
- flate2/zlib(必需)- 默认选择
-
对于
mysql_common
crate(请参阅mysql_common
crate 文档以获取可用功能)- mysql_common/bigdecimal03 – 默认启用
bigdecimal03
- mysql_common/rust_decimal – 默认启用
rust_decimal
- mysql_common/time03 – 默认启用
time03
- mysql_common/uuid – 默认启用
uuid
- mysql_common/frunk – 默认启用
frunk
- mysql_common/bigdecimal03 – 默认启用
-
请注意,如果您使用 default-features = false
,则需要重新启用所需的功能
[dependencies]
# Lets say that we want to use the `rustls-tls` feature:
mysql = { version = "*", default-features = false, features = ["minimal", "rustls-tls"] }
# Previous line disables default mysql features,
# so now we need to choose desired mysql_common features:
mysql_common = { version = "*", default-features = false, features = ["bigdecimal03", "time03", "uuid"]}
API 文档
请参阅 crate 文档。
基本结构
Opts
此结构包含服务器主机名、客户端用户名/密码和其他设置,用于控制客户端行为。
基于 URL 的连接字符串
请注意,您可以使用基于 URL 的连接字符串作为 Opts
实例的来源。URL 方案必须是 mysql
。主机、端口、凭证以及查询参数应按照 RFC 3986 给出。
示例
let _ = Opts::from_url("mysql://127.0.0.1/some_db")?;
let _ = Opts::from_url("mysql://[::1]/some_db")?;
let _ = Opts::from_url("mysql://user:pass%[email protected]:3307/some_db?")?;
支持的 URL 参数(有关每个字段的含义,请参阅创建 API 文档中 Opts
结构的文档)
user: string
– MySql 客户端用户名password: string
– MySql 客户端密码;db_name: string
– MySql 数据库名;host: Host
– MySql 服务器主机名/ip;port: u16
– MySql 服务器端口;pool_min: usize
– 见PoolConstraints::min
;pool_max: usize
– 见PoolConstraints::max
;prefer_socket: true | false
- 请参阅Opts::get_prefer_socket
;tcp_keepalive_time_ms: u32
- 定义了结构体Opts
中tcp_keepalive_time
字段的值(以毫秒为单位);tcp_keepalive_probe_interval_secs: u32
- 定义了结构体Opts
中tcp_keepalive_probe_interval_secs
字段的值;tcp_keepalive_probe_count: u32
- 定义了结构体Opts
中tcp_keepalive_probe_count
字段的值;tcp_connect_timeout_ms: u64
- 定义了结构体Opts
中tcp_connect_timeout
字段的值(以毫秒为单位);tcp_user_timeout_ms
- 定义了结构体Opts
中tcp_user_timeout
字段的值(以毫秒为单位);stmt_cache_size: u32
- 定义了结构体Opts
中相同字段的值;enable_cleartext_plugin
– 请参阅Opts::get_enable_cleartext_plugin
;secure_auth
– 请参阅Opts::get_secure_auth
;reset_connection
– 请参阅PoolOpts::reset_connection
;check_health
– 请参阅PoolOpts::check_health
;compress
- 定义了结构体Opts
中相同字段的值。支持值有true
- 启用默认压缩级别的压缩;fast
- 启用“快速”压缩级别的压缩;best
- 启用“最佳”压缩级别的压缩;1
..9
- 启用指定压缩级别的压缩。
socket
- UNIX上的套接字路径,或在Windows上的管道名称。
OptsBuilder
它是 Opts
结构体的便捷构建器。它为 Opts
结构体的字段定义了设置器。
let opts = OptsBuilder::new()
.user(Some("foo"))
.db_name(Some("bar"));
let _ = Conn::new(opts)?;
Conn
此结构体代表一个活动的 MySql 连接。它还持有语句缓存和最后结果集的元数据。
Conn 的析构函数将优雅地将其从服务器断开连接。
Transaction
它是围绕一个例程的简单包装,该例程以 START TRANSACTION
开始,并以 COMMIT
或 ROLLBACK
结束。
use mysql::*;
use mysql::prelude::*;
let pool = Pool::new(get_opts())?;
let mut conn = pool.get_conn()?;
let mut tx = conn.start_transaction(TxOpts::default())?;
tx.query_drop("CREATE TEMPORARY TABLE tmp (TEXT a)")?;
tx.exec_drop("INSERT INTO tmp (a) VALUES (?)", ("foo",))?;
let val: Option<String> = tx.query_first("SELECT a from tmp")?;
assert_eq!(val.unwrap(), "foo");
// Note, that transaction will be rolled back implicitly on Drop, if not committed.
tx.rollback();
let val: Option<String> = conn.query_first("SELECT a from tmp")?;
assert_eq!(val, None);
Pool
它是对连接池的引用,可以被克隆并在线程之间共享。
use mysql::*;
use mysql::prelude::*;
use std::thread::spawn;
let pool = Pool::new(get_opts())?;
let handles = (0..4).map(|i| {
spawn({
let pool = pool.clone();
move || {
let mut conn = pool.get_conn()?;
conn.exec_first::<u32, _, _>("SELECT ? * 10", (i,))
.map(Option::unwrap)
}
})
});
let result: Result<Vec<u32>> = handles.map(|handle| handle.join().unwrap()).collect();
assert_eq!(result.unwrap(), vec![0, 10, 20, 30]);
Statement
语句实际上只是一个标识符与语句元数据的组合,即关于其参数和列的信息。在内部,Statement
结构还包含支持命名参数所需的其他数据(见下文)。
use mysql::*;
use mysql::prelude::*;
let pool = Pool::new(get_opts())?;
let mut conn = pool.get_conn()?;
let stmt = conn.prep("DO ?")?;
// The prepared statement will return no columns.
assert!(stmt.columns().is_empty());
// The prepared statement have one parameter.
let param = stmt.params().get(0).unwrap();
assert_eq!(param.schema_str(), "");
assert_eq!(param.table_str(), "");
assert_eq!(param.name_str(), "?");
值
此枚举表示MySQL单元格的原始值。库提供通过以下描述的FromValue
特质在Value
和不同的Rust类型之间的转换。
FromValue
特质
此特质从mysql_common
创建中重新导出。请参阅其crate文档以获取支持的转换列表。
特质提供两种转换方式
-
from_value(Value) -> T
- 方便,但会抛出恐慌的转换。注意,对于
Value
的任何变体,都存在一个完全涵盖其域的类型,即对于Value
的任何变体,都存在T: FromValue
,使得from_value
永远不会恐慌。这意味着,如果您的数据库模式已知,那么可以编写只使用from_value
的应用程序,而无需担心运行时恐慌。 -
from_value_opt(Value) -> Option<T>
- 非抛出恐慌,但不太方便的转换。此函数在源数据库模式未知的情况下进行转换试探非常有用。
use mysql::*;
use mysql::prelude::*;
let via_test_protocol: u32 = from_value(Value::Bytes(b"65536".to_vec()));
let via_bin_protocol: u32 = from_value(Value::UInt(65536));
assert_eq!(via_test_protocol, via_bin_protocol);
let unknown_val = // ...
// Maybe it is a float?
let unknown_val = match from_value_opt::<f64>(unknown_val) {
Ok(float) => {
println!("A float value: {}", float);
return Ok(());
}
Err(FromValueError(unknown_val)) => unknown_val,
};
// Or a string?
let unknown_val = match from_value_opt::<String>(unknown_val) {
Ok(string) => {
println!("A string value: {}", string);
return Ok(());
}
Err(FromValueError(unknown_val)) => unknown_val,
};
// Screw this, I'll simply match on it
match unknown_val {
val @ Value::NULL => {
println!("An empty value: {:?}", from_value::<Option<u8>>(val))
},
val @ Value::Bytes(..) => {
// It's non-utf8 bytes, since we already tried to convert it to String
println!("Bytes: {:?}", from_value::<Vec<u8>>(val))
}
val @ Value::Int(..) => {
println!("A signed integer: {}", from_value::<i64>(val))
}
val @ Value::UInt(..) => {
println!("An unsigned integer: {}", from_value::<u64>(val))
}
Value::Float(..) => unreachable!("already tried"),
val @ Value::Double(..) => {
println!("A double precision float value: {}", from_value::<f64>(val))
}
val @ Value::Date(..) => {
use time::PrimitiveDateTime;
println!("A date value: {}", from_value::<PrimitiveDateTime>(val))
}
val @ Value::Time(..) => {
use std::time::Duration;
println!("A time value: {:?}", from_value::<Duration>(val))
}
}
行
内部,Row
是Value
的向量,它还允许通过列名/偏移量进行索引,并存储行元数据。库提供通过以下描述的FromRow
特质在Row
和Rust类型序列之间的转换。
FromRow
特质
此特质从mysql_common
创建中重新导出。请参阅其crate文档以获取支持的转换列表。
这种转换基于FromValue
,因此有两种类似的口味
from_row(Row) -> T
- 与from_value
相同,但用于行;from_row_opt(Row) -> Option<T>
- 与from_value_opt
相同,但用于行。
Queryable
特质提供基于此特质的查询结果行的隐式转换。
use mysql::*;
use mysql::prelude::*;
let mut conn = Conn::new(get_opts())?;
// Single-column row can be converted to a singular value:
let val: Option<String> = conn.query_first("SELECT 'foo'")?;
assert_eq!(val.unwrap(), "foo");
// Example of a mutli-column row conversion to an inferred type:
let row = conn.query_first("SELECT 255, 256")?;
assert_eq!(row, Some((255u8, 256u16)));
// The FromRow trait does not support to-tuple conversion for rows with more than 12 columns,
// but you can do this by hand using row indexing or `Row::take` method:
let row: Row = conn.exec_first("select 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12", ())?.unwrap();
for i in 0..row.len() {
assert_eq!(row[i], Value::Int(i as i64));
}
// Another way to handle wide rows is to use HList (requires `mysql_common/frunk` feature)
use frunk::{HList, hlist, hlist_pat};
let query = "select 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15";
type RowType = HList!(u8, u16, u32, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8);
let first_three_columns = conn.query_map(query, |row: RowType| {
// do something with the row (see the `frunk` crate documentation)
let hlist_pat![c1, c2, c3, ...] = row;
(c1, c2, c3)
});
assert_eq!(first_three_columns.unwrap(), vec![(0_u8, 1_u16, 2_u32)]);
// Some unknown row
let row: Row = conn.query_first(
// ...
# "SELECT 255, Null",
)?.unwrap();
for column in row.columns_ref() {
// Cells in a row can be indexed by numeric index or by column name
let column_value = &row[column.name_str().as_ref()];
println!(
"Column {} of type {:?} with value {:?}",
column.name_str(),
column.column_type(),
column_value,
);
}
参数
表示预编译语句的参数,但此类型不会直接出现在您的代码中,因为二进制协议API将请求T: Into<Params>
,其中实现了Into<Params>
-
对于
Into<Value>
类型的元组,最多可到12个参数;注意:单个元组需要一个额外的逗号,例如
("foo",)
; -
对于当你的语句包含超过12个参数的情况,使用
IntoIterator<Item: Into<Value>>
。 -
对于命名参数的表示(下面将描述的
params!
宏的值)。
use mysql::*;
use mysql::prelude::*;
let mut conn = Conn::new(get_opts())?;
// Singular tuple requires extra comma:
let row: Option<u8> = conn.exec_first("SELECT ?", (0,))?;
assert_eq!(row.unwrap(), 0);
// More than 12 parameters:
let row: Option<u8> = conn.exec_first(
"SELECT CONVERT(? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ?, UNSIGNED)",
(0..16).collect::<Vec<_>>(),
)?;
assert_eq!(row.unwrap(), 120);
注意:请参考mysql_common crate文档以获取实现Into<Value>
的类型列表。
Serialized
,Deserialized
用于当你需要为JSON单元格提供一个值,或者当你需要将JSON单元格解析为结构体的情况的包装结构。
use mysql::*;
use mysql::prelude::*;
/// Serializable structure.
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Example {
foo: u32,
}
// Value::from for Serialized will emit json string.
let value = Value::from(Serialized(Example { foo: 42 }));
assert_eq!(value, Value::Bytes(br#"{"foo":42}"#.to_vec()));
// from_value for Deserialized will parse json string.
let structure: Deserialized<Example> = from_value(value);
assert_eq!(structure, Deserialized(Example { foo: 42 }));
QueryResult
它是查询结果行的迭代器,支持多结果集。它适用于需要在整个结果集迭代过程中进行完全控制的场景。对于其他情况,Queryable
提供了一系列方法,这些方法将立即消耗第一个结果集并丢弃其他所有内容。
此迭代器是惰性的,因此它不会在迭代之前从服务器读取结果。MySql协议是严格顺序的,所以Conn
将可变借用直到结果完全消耗完毕(请参阅QueryResult::iter
文档)。
use mysql::*;
use mysql::prelude::*;
let mut conn = Conn::new(get_opts())?;
// This query will emit two result sets.
let mut result = conn.query_iter("SELECT 1, 2; SELECT 3, 3.14;")?;
let mut sets = 0;
while let Some(result_set) = result.iter() {
sets += 1;
println!("Result set columns: {:?}", result_set.columns());
println!(
"Result set meta: {}, {:?}, {} {}",
result_set.affected_rows(),
result_set.last_insert_id(),
result_set.warnings(),
result_set.info_str(),
);
for row in result_set {
match sets {
1 => {
// First result set will contain two numbers.
assert_eq!((1_u8, 2_u8), from_row(row?));
}
2 => {
// Second result set will contain a number and a float.
assert_eq!((3_u8, 3.14), from_row(row?));
}
_ => unreachable!(),
}
}
}
assert_eq!(sets, 2);
文本协议
MySql文本协议在Queryable::query*
方法集中实现。当你查询没有参数时,它非常有用。
注意:服务器将文本协议结果集中的所有值都编码为字符串,因此from_value
转换可能会导致额外的解析成本。
示例
let pool = Pool::new(get_opts())?;
let val = pool.get_conn()?.query_first("SELECT POW(2, 16)")?;
// Text protocol returns bytes even though the result of POW
// is actually a floating point number.
assert_eq!(val, Some(Value::Bytes("65536".as_bytes().to_vec())));
TextQuery
特质。
TextQuery
特质涵盖了从查询的角度看Queryable::query*
方法集,即TextQuery
是在给定了适当的连接后可以执行的操作。合适的连接包括
&Pool
Conn
PooledConn
&mutConn
&mutPooledConn
&mutTransaction
此特质的独特之处在于,你可以放弃连接,从而产生满足'static
的QueryResult
。
use mysql::*;
use mysql::prelude::*;
fn iter(pool: &Pool) -> Result<impl Iterator<Item=Result<u32>>> {
let result = "SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3".run(pool)?;
Ok(result.map(|row| row.map(from_row)))
}
let pool = Pool::new(get_opts())?;
let it = iter(&pool)?;
assert_eq!(it.collect::<Result<Vec<u32>>>()?, vec![1, 2, 3]);
二进制协议和预编译语句。
MySql二进制协议在prep
、close
和定义在Queryable
特质上的exec*
方法集中实现。预编译语句是将Rust值传递给MySql服务器的唯一方式。MySql使用?
符号作为参数占位符,并且只能在期望单个MySql值的位置使用参数。例如
let pool = Pool::new(get_opts())?;
let val = pool.get_conn()?.exec_first("SELECT POW(?, ?)", (2, 16))?;
assert_eq!(val, Some(Value::Double(65536.0)));
语句
在MySql中,每个预编译语句都属于特定的连接,并且不能在另一个连接上执行。尝试这样做会导致错误。驱动程序不会以任何方式将语句与其连接绑定,但可以查看包含在Statement
结构中的连接ID。
let pool = Pool::new(get_opts())?;
let mut conn_1 = pool.get_conn()?;
let mut conn_2 = pool.get_conn()?;
let stmt_1 = conn_1.prep("SELECT ?")?;
// stmt_1 is for the conn_1, ..
assert!(stmt_1.connection_id() == conn_1.connection_id());
assert!(stmt_1.connection_id() != conn_2.connection_id());
// .. so stmt_1 will execute only on conn_1
assert!(conn_1.exec_drop(&stmt_1, ("foo",)).is_ok());
assert!(conn_2.exec_drop(&stmt_1, ("foo",)).is_err());
语句缓存
注意
语句缓存仅适用于
- 原始
Conn
- 对于
PooledConn
- 在其生命周期内,如果
PoolOpts::reset_connection
设置为true
- 在包装的
Conn
的生命周期内,如果PoolOpts::reset_connection
设置为false
- 在其生命周期内,如果
描述
Conn
将在客户端管理预编译语句的缓存,因此使用相同语句的后续调用不会导致客户端-服务器往返。每个连接的缓存大小由 Opts
结构中的 stmt_cache_size
字段确定。超出此边界的语句将按 LRU 顺序关闭。
如果 stmt_cache_size
为零,则完全禁用语句缓存。
注意事项
-
禁用语句缓存意味着您必须自己使用
Conn::close
关闭语句,否则它们会耗尽服务器限制/资源; -
您应该注意 MySql 服务器的
max_prepared_stmt_count
选项。如果活动连接数乘以stmt_cache_size
的值大于该值,则在准备另一个语句时可能会收到错误。
命名参数
MySql 本身不支持命名参数,因此在客户端实现。应使用 :name
作为命名参数的占位符语法。命名参数使用以下命名约定
- 参数名称必须以
_
或a..z
开头 - 参数名称可以继续使用
_
、a..z
和0..9
命名参数可以在语句中重复,例如 SELECT :foo, :foo
需要一个名为 foo
的命名参数,该参数将在语句执行期间在相应位置重复。
应使用 params!
宏来构建执行参数。
注意:在单个语句中不能混合使用位置参数和命名参数。
示例
let pool = Pool::new(get_opts())?;
let mut conn = pool.get_conn()?;
let stmt = conn.prep("SELECT :foo, :bar, :foo")?;
let foo = 42;
let val_13 = conn.exec_first(&stmt, params! { "foo" => 13, "bar" => foo })?.unwrap();
// Short syntax is available when param name is the same as variable name:
let val_42 = conn.exec_first(&stmt, params! { foo, "bar" => 13 })?.unwrap();
assert_eq!((foo, 13, foo), val_42);
assert_eq!((13, foo, 13), val_13);
缓冲池
该框架使用全局无锁缓冲池用于 I/O 和数据序列化/反序列化,有助于避免基本场景下的分配。您可以使用以下环境变量来控制其特征
-
RUST_MYSQL_BUFFER_POOL_CAP
(默认为 128)- 控制池容量。如果池已满,则丢弃的缓冲区将被立即分配。将其设置为0
以在运行时禁用池。 -
RUST_MYSQL_BUFFER_SIZE_CAP
(默认为 4MiB)- 控制存储在池中的缓冲区的最大容量。当缓冲区返回池时,丢弃的缓冲区容量将缩小到此值。
要完全禁用池(例如您正在使用jemalloc),请从默认crate功能集中移除buffer-pool
功能(请参阅Crate Features部分)。
BinQuery
和BatchQuery
特质。
BinQuery
和BatchQuery
特质涵盖了从查询的角度来看的Queryable::exec*
方法集合,即BinQuery
是某种在给定合适的连接时可以执行的操作(请参阅TextQuery
部分以获取合适连接的列表)。
与TextQuery
类似,您可以提供连接并获取满足'static
的QueryResult
。
BinQuery
用于预编译语句,而预编译语句需要一组参数,因此BinQuery
是为QueryWithParams
结构实现的,该结构可以通过使用WithParams
特质来获取。
示例
use mysql::*;
use mysql::prelude::*;
let pool = Pool::new(get_opts())?;
let result: Option<(u8, u8, u8)> = "SELECT ?, ?, ?"
.with((1, 2, 3)) // <- WithParams::with will construct an instance of QueryWithParams
.first(&pool)?; // <- QueryWithParams is executed on the given pool
assert_eq!(result.unwrap(), (1, 2, 3));
BatchQuery
特质是批量语句执行的辅助工具。它在QueryWithParams
上实现,其中参数是参数的迭代器。
use mysql::*;
use mysql::prelude::*;
let pool = Pool::new(get_opts())?;
let mut conn = pool.get_conn()?;
"CREATE TEMPORARY TABLE batch (x INT)".run(&mut conn)?;
"INSERT INTO batch (x) VALUES (?)"
.with((0..3).map(|x| (x,))) // <- QueryWithParams constructed with an iterator
.batch(&mut conn)?; // <- batch execution is preformed here
let result: Vec<u8> = "SELECT x FROM batch".fetch(conn)?;
assert_eq!(result, vec![0, 1, 2]);
Queryable
Queryable
特质定义了Conn
、PooledConn
和Transaction
的共同方法。基本方法集合包括:
query_iter
- 执行文本查询并获取QueryResult
的基本方法;prep
- 预编译语句的基本方法;exec_iter
- 执行语句并获取QueryResult
的基本方法;close
- 关闭语句的基本方法;
该特质还定义了一系列基于基本方法的辅助方法。这些方法将仅消耗第一个结果集,其他结果集将被丢弃
{query|exec}
- 将结果收集到Vec<T: FromRow>
中;{query|exec}_first
- 获取第一个T: FromRow
,如果有的话;{query|exec}_map
- 将每个T: FromRow
映射到某个U
;{query|exec}_fold
- 将T: FromRow
的集合折叠为单个值;{query|exec}_drop
- 立即丢弃结果。
该特质还定义了exec_batch
函数,它是批量语句执行的辅助工具。
SSL支持
SSL支持有两种形式
-
基于 native-tls – 这是默认选项,通常无需担心问题(参见
native-tls
仓库特性)。 -
基于 rustls – 使用 Rust 编写的 TLS 后端。请使用
rustls-tls
仓库特性来启用它(参见仓库特性部分)。请注意关于 rustls 的几点
- 如果您尝试通过 IP 地址连接到服务器,它将失败;需要主机名;
- 它很可能在 Windows 上无法正常工作,至少在使用默认服务器证书的情况下,这些证书是由 MySQL 安装程序生成的。
更新日志
在此处可找到
许可证
许可协议为以下之一
- Apache License,版本 2.0,(LICENSE-APACHE 或 https://www.apache.org/licenses/LICENSE-2.0)
- MIT 许可证 (LICENSE-MIT 或 https://opensource.org/licenses/MIT)
任选其一。
贡献
除非您明确声明,否则您提交的任何贡献,只要它有意提交以包含在作品中,根据 Apache-2.0 许可证定义,都应按上述方式双许可,无需任何额外条款或条件。
依赖关系
~13–29MB
~491K SLoC