Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v22.0.0 release #305

Merged
merged 3 commits into from
Dec 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,18 @@ default = [
# It is necessary to choose one of `flate2` backends.
"flate2/zlib",

# set of enabled-by-default mysql_common features
"mysql_common/bigdecimal03",
"mysql_common/rust_decimal",
"mysql_common/time03",
"mysql_common/uuid",
"mysql_common/frunk",

# use global buffer pool by default
"buffer-pool",
]
rustls-tls = ["rustls", "webpki", "webpki-roots", "rustls-pemfile"]
buffer-pool = []
nightly = []

[dev-dependencies]
Expand Down
67 changes: 48 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,44 @@ assert_eq!(payments, selected_payments);
println!("Yay!");
```

### Crate Features

* crate's features:

* **native-tls** (enabled by default) – specifies `native-tls` as the TLS backend
(see the [SSL Support](#ssl-support) section)
* **rustls-tls** (disabled by default) – specifies `rustls` as the TLS backend
(see the [SSL Support](#ssl-support) section)
* **buffer-pool** (enabled by default) – enables buffer pooling
(see the [Buffer Pool](#buffer-pool) section)

* external features enabled by default:

* for the `flate2` crate (please consult `flate2` crate documentation for available features):

* **flate2/zlib** (necessary) – `zlib` backend is chosed by default.

* for the `mysql_common` crate (please consult `mysql_common` crate documentation for available features):

* **mysql_common/bigdecimal03** – the `bigdecimal03` is enabled by default
* **mysql_common/rust_decimal** – the `rust_decimal` is enabled by default
* **mysql_common/time03** – the `time03` is enabled by default
* **mysql_common/uuid** – the `uuid` is enabled by default
* **mysql_common/frunk** – the `frunk` is enabled by default

Please note, that you'll need to reenable external features if you are using `no-default-features = true`:

```toml
[dependencies]
# Lets say that we want to use the `rustls-tls` feature:
mysql = { version = "*", no-default-features = true, features = ["rustls-tls", "buffer-pool"] }
# Previous line disables default mysql features,
# so now we have to choose the flate2 backend (this is necessary),
# as well as the desired set of mysql_common features:
flate2 = { version = "*", no-default-features = true, features = ["zlib"] }
mysql_common = { version = "*", no-default-features = true, features = ["bigdecimal03", "time03", "uuid"]}
```

### API Documentation

Please refer to the [crate docs].
Expand Down Expand Up @@ -435,7 +473,7 @@ let structure: Deserialized<Example> = from_value(value);
assert_eq!(structure, Deserialized(Example { foo: 42 }));
```

#### `QueryResult`
#### [`QueryResult`]

It's an iterator over rows of a query result with support of multi-result sets. It's intended
for cases when you need full control during result set iteration. For other cases
Expand All @@ -444,7 +482,7 @@ the first result set and drop everything else.

This iterator is lazy so it won't read the result from server until you iterate over it.
MySql protocol is strictly sequential, so `Conn` will be mutably borrowed until the result
is fully consumed.
is fully consumed (please also look at [`QueryResult::iter`] docs).

```rust
use mysql::*;
Expand All @@ -456,7 +494,7 @@ let mut conn = Conn::new(get_opts())?;
let mut result = conn.query_iter("SELECT 1, 2; SELECT 3, 3.14;")?;

let mut sets = 0;
while let Some(result_set) = result.current_set() {
while let Some(result_set) = result.iter() {
sets += 1;

println!("Result set columns: {:?}", result_set.columns());
Expand Down Expand Up @@ -637,15 +675,14 @@ that helps to avoid allocations for basic scenarios. You can control it's charac
the following environment variables:

* `RUST_MYSQL_BUFFER_POOL_CAP` (defaults to 128) – controls the pool capacity. Dropped buffer will
be immediately deallocated if the pool is full.

**Note:** it might be the case, that you don't need the pooling (say you are using jemalloc).
It's possible to disable the pool by setting the `RUST_MYSQL_BUFFER_POOL_CAP` environment
variable to `0`.
be immediately deallocated if the pool is full. Set it to `0` to disable the pool at runtime.

* `RUST_MYSQL_BUFFER_SIZE_CAP` (defaults to 4MiB) – controls the maximum capacity of a buffer
stored in the pool. Capacity of a dropped buffer will be shrinked to this value when buffer
is returning to the pool.
is returned to the pool.

To completely disable the pool (say you are using jemalloc) please remove the `buffer-pool` feature
from the set of default crate features (see the [Crate Features](#crate-features) section).

#### `BinQuery` and `BatchQuery` traits.

Expand Down Expand Up @@ -725,17 +762,9 @@ SSL support comes in two flavors:
1. Based on **native-tls** – this is the default option, that usually works without pitfalls
(see the `native-tls` crate feature).
2. Based on **rustls** – TLS backend written in Rust. Please use the `rustls-tls` crate feature
to enable:

```toml
[dependencies]
mysql = { version = "*", no-default-features = true, features = ["rustls-tls"] }
# Please note, that the previous line disables default mysql features,
# so now we have to choose the flate2 backend (this is necessary):
flate2 = { version = "1.0", no-default-features = true, features = ["zlib"] }
```
to enable it (see the [Crate Features](#crate-features) section).

Please also note a few things about this backend:
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
Expand Down
25 changes: 25 additions & 0 deletions src/buffer_pool/disabled.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#![cfg(not(feature = "buffer-pool"))]

use std::ops::Deref;

#[derive(Debug)]
#[repr(transparent)]
pub struct Buffer(Vec<u8>);

impl AsMut<Vec<u8>> for Buffer {
fn as_mut(&mut self) -> &mut Vec<u8> {
&mut self.0
}
}

impl Deref for Buffer {
type Target = [u8];

fn deref(&self) -> &Self::Target {
self.0.deref()
}
}

pub const fn get_buffer() -> Buffer {
Buffer(Vec::new())
}
32 changes: 17 additions & 15 deletions src/buffer_pool.rs → src/buffer_pool/enabled.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,36 @@
// Copyright (c) 2021 Anatoly Ikorsky
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.
#![cfg(feature = "buffer-pool")]

use crossbeam::queue::ArrayQueue;
use once_cell::sync::Lazy;

use std::{mem::replace, ops::Deref, sync::Arc};

const DEFAULT_MYSQL_BUFFER_POOL_CAP: usize = 128;
const DEFAULT_MYSQL_BUFFER_SIZE_CAP: usize = 4 * 1024 * 1024;

static BUFFER_POOL: Lazy<Arc<BufferPool>> = Lazy::new(|| Default::default());

#[inline(always)]
pub fn get_buffer() -> Buffer {
BUFFER_POOL.get()
}

#[derive(Debug)]
struct Inner {
buffer_cap: usize,
pool: ArrayQueue<Vec<u8>>,
}

impl Inner {
fn get(self: &Arc<Self>) -> PooledBuf {
fn get(self: &Arc<Self>) -> Buffer {
let mut buf = self.pool.pop().unwrap_or_default();

// SAFETY:
// 1. OK – 0 is always within capacity
// 2. OK - nothing to initialize
unsafe { buf.set_len(0) }

PooledBuf(buf, Some(self.clone()))
Buffer(buf, Some(self.clone()))
}

fn put(&self, mut buf: Vec<u8>) {
Expand Down Expand Up @@ -61,10 +63,10 @@ impl BufferPool {
}))
}

pub fn get(self: &Arc<Self>) -> PooledBuf {
pub fn get(self: &Arc<Self>) -> Buffer {
match self.0 {
Some(ref inner) => inner.get(),
None => PooledBuf(Vec::new(), None),
None => Buffer(Vec::new(), None),
}
}
}
Expand All @@ -76,23 +78,23 @@ impl Default for BufferPool {
}

#[derive(Debug)]
pub struct PooledBuf(Vec<u8>, Option<Arc<Inner>>);
pub struct Buffer(Vec<u8>, Option<Arc<Inner>>);

impl AsMut<Vec<u8>> for PooledBuf {
impl AsMut<Vec<u8>> for Buffer {
fn as_mut(&mut self) -> &mut Vec<u8> {
&mut self.0
}
}

impl Deref for PooledBuf {
impl Deref for Buffer {
type Target = [u8];

fn deref(&self) -> &Self::Target {
self.0.deref()
}
}

impl Drop for PooledBuf {
impl Drop for Buffer {
fn drop(&mut self) {
if let Some(ref inner) = self.1 {
inner.put(replace(&mut self.0, vec![]));
Expand Down
16 changes: 16 additions & 0 deletions src/buffer_pool/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (c) 2021 Anatoly Ikorsky
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

mod disabled;
mod enabled;

#[cfg(feature = "buffer-pool")]
pub use enabled::{get_buffer, Buffer};

#[cfg(not(feature = "buffer-pool"))]
pub use disabled::{get_buffer, Buffer};
20 changes: 10 additions & 10 deletions src/conn/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ use std::{
};

use crate::{
buffer_pool::PooledBuf,
buffer_pool::{get_buffer, Buffer},
conn::{
local_infile::LocalInfile,
pool::{Pool, PooledConn},
Expand Down Expand Up @@ -410,9 +410,9 @@ impl Conn {
Ok(())
}

fn read_packet(&mut self) -> Result<PooledBuf> {
fn read_packet(&mut self) -> Result<Buffer> {
loop {
let mut buffer = crate::BUFFER_POOL.get();
let mut buffer = get_buffer();
if !self.stream_mut().next_packet(buffer.as_mut())? {
return Err(
io::Error::new(io::ErrorKind::BrokenPipe, "server disconnected").into(),
Expand Down Expand Up @@ -441,7 +441,7 @@ impl Conn {
}

fn write_struct<T: MySerialize>(&mut self, s: &T) -> Result<()> {
let mut buf = crate::BUFFER_POOL.get();
let mut buf = get_buffer();
s.serialize(buf.as_mut());
self.write_packet(&mut &*buf)
}
Expand All @@ -462,7 +462,7 @@ impl Conn {

fn handle_ok<'a, T: OkPacketKind>(
&mut self,
buffer: &'a PooledBuf,
buffer: &'a Buffer,
) -> crate::Result<OkPacket<'a>> {
let ok = ParseBuf(&**buffer)
.parse::<OkPacketDeserializer<T>>(self.0.capability_flags)?
Expand Down Expand Up @@ -652,7 +652,7 @@ impl Conn {
Some(self.connect_attrs().clone()),
);

let mut buf = crate::BUFFER_POOL.get();
let mut buf = get_buffer();
handshake_response.serialize(buf.as_mut());
self.write_packet(&mut &*buf)
}
Expand Down Expand Up @@ -771,7 +771,7 @@ impl Conn {
}

fn write_command_raw<T: MySerialize>(&mut self, cmd: &T) -> Result<()> {
let mut buf = crate::BUFFER_POOL.get();
let mut buf = get_buffer();
cmd.serialize(buf.as_mut());
self.reset_seq_id();
debug_assert!(buf.len() > 0);
Expand All @@ -780,7 +780,7 @@ impl Conn {
}

fn write_command(&mut self, cmd: Command, data: &[u8]) -> Result<()> {
let mut buf = crate::BUFFER_POOL.get();
let mut buf = get_buffer();
buf.as_mut().put_u8(cmd as u8);
buf.as_mut().extend_from_slice(data);

Expand Down Expand Up @@ -1713,7 +1713,7 @@ mod test {
)
.unwrap();

while let Some(result) = query_result.current_set() {
while let Some(result) = query_result.iter() {
result.affected_rows();
}
}
Expand Down Expand Up @@ -1752,7 +1752,7 @@ mod test {
}
let mut result = conn.query_iter("SELECT 1; SELECT 2; SELECT 3;").unwrap();
let mut i = 0;
while let Some(result_set) = result.current_set() {
while let Some(result_set) = result.iter() {
i += 1;
for row in result_set {
match i {
Expand Down
2 changes: 1 addition & 1 deletion src/conn/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ where
let params = params.into();
let meta = conn._execute(&*statement, params)?;
let mut query_result = QueryResult::<Binary>::new((&mut *conn).into(), meta);
while let Some(result_set) = query_result.current_set() {
while let Some(result_set) = query_result.iter() {
for row in result_set {
row?;
}
Expand Down
Loading