Skip to content

Commit a207c80

Browse files
committed
feat(core, mysql): expose MySQL connection options to sqlx.toml
1 parent 4893f83 commit a207c80

7 files changed

Lines changed: 91 additions & 6 deletions

File tree

sqlx-core/src/config/drivers.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,38 @@ pub struct Config {
4040
}
4141

4242
/// Configuration for the MySQL database driver.
43-
#[derive(Debug, Default)]
43+
#[derive(Debug)]
4444
#[cfg_attr(
4545
feature = "sqlx-toml",
4646
derive(serde::Deserialize),
4747
serde(default, rename_all = "kebab-case", deny_unknown_fields)
4848
)]
4949
pub struct MySqlConfig {
50-
// No fields implemented yet. This key is only used to validate parsing.
50+
/// Whether to enable the `PIPES_AS_CONCAT` connection setting
51+
///
52+
/// Defaults to `true`.
53+
///
54+
/// Some MySql databases such as PlanetScale error out with this connection setting
55+
/// so it needs to be set `false` in such cases.
56+
pub pipes_as_concat: bool,
57+
/// Whether to enable the `NO_ENGINE_SUBSTITUTION` sql_mode setting after connection.
58+
///
59+
/// Defaults to `true` (`NO_ENGINE_SUBSTITUTION` is passed, forbidding engine substitution.)
60+
///
61+
/// If not set, if the available storage engine specified by a `CREATE TABLE` is not available,
62+
/// a warning is given and the default storage engine is used instead.
63+
///
64+
/// <https://mariadb.com/kb/en/sql-mode/>
65+
pub no_engine_substitution: bool,
66+
}
67+
68+
impl Default for MySqlConfig {
69+
fn default() -> Self {
70+
Self {
71+
pipes_as_concat: true,
72+
no_engine_substitution: true,
73+
}
74+
}
5175
}
5276

5377
/// Configuration for the Postgres database driver.

sqlx-core/src/config/reference.toml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,20 @@ database-url-var = "FOO_DATABASE_URL"
2222

2323
# Configure MySQL databases in macros and sqlx-cli.
2424
[drivers.mysql]
25-
# No fields implemented yet. This key is only used to validate parsing.
25+
# Whether to enable the `PIPES_AS_CONCAT` connection setting
26+
#
27+
# Defaults to `true`.
28+
#
29+
# Some MySql databases such as PlanetScale error out with this connection setting
30+
# so it needs to be set `false` in such cases.
31+
pipes-as-concat = false
32+
# Whether to enable the `NO_ENGINE_SUBSTITUTION` sql_mode setting after connection.
33+
#
34+
# Defaults to `true` (`NO_ENGINE_SUBSTITUTION` is passed, forbidding engine substitution.)
35+
#
36+
# If not set, if the available storage engine specified by a `CREATE TABLE` is not available,
37+
# a warning is given and the default storage engine is used instead.
38+
no-engine-substitution = false
2639

2740
# Configure Postgres databases in macros and sqlx-cli.
2841
[drivers.postgres]

sqlx-core/src/config/tests.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ fn assert_common_config(config: &config::common::Config) {
1818
}
1919

2020
fn assert_drivers_config(config: &config::drivers::Config) {
21+
assert!(!config.mysql.pipes_as_concat);
22+
assert!(!config.mysql.no_engine_substitution);
23+
2124
assert_eq!(
2225
config.sqlite.unsafe_load_extensions,
2326
vec![

sqlx-core/src/connection.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,29 @@ pub trait Connection: Send {
179179
async move { Self::connect_with(&options?).await }
180180
}
181181

182+
/// UNSTABLE: for use with `sqlx-macros-core`
183+
///
184+
/// Establish a new database connection.
185+
///
186+
/// A value of [`Options`][Self::Options] is first parsed from the provided connection string.
187+
/// This parsing is database-specific.
188+
/// The option then gets updated with options from the sqlx.toml file as appropriate.
189+
#[doc(hidden)]
190+
#[inline]
191+
fn connect_with_driver_config(
192+
url: &str,
193+
driver_config: &config::drivers::Config,
194+
) -> impl Future<Output = Result<Self, Error>> + Send + 'static
195+
where
196+
Self: Sized,
197+
{
198+
let options = url
199+
.parse::<Self::Options>()
200+
.and_then(|options| options.__unstable_apply_driver_config(driver_config));
201+
202+
async move { Self::connect_with(&options?).await }
203+
}
204+
182205
/// Establish a new database connection with the provided options.
183206
fn connect_with(
184207
options: &Self::Options,

sqlx-macros-core/src/database/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ impl<DB: DatabaseExt> CachingDescribeBlocking<DB> {
5050
&self,
5151
query: &str,
5252
database_url: &str,
53-
_driver_config: &config::drivers::Config,
53+
driver_config: &config::drivers::Config,
5454
) -> sqlx_core::Result<Describe<DB>>
5555
where
5656
for<'a> &'a mut DB::Connection: Executor<'a, Database = DB>,
@@ -64,7 +64,10 @@ impl<DB: DatabaseExt> CachingDescribeBlocking<DB> {
6464
let conn = match cache.entry(database_url.to_string()) {
6565
hash_map::Entry::Occupied(hit) => hit.into_mut(),
6666
hash_map::Entry::Vacant(miss) => {
67-
let conn = miss.insert(DB::Connection::connect(database_url).await?);
67+
let conn = miss.insert(
68+
DB::Connection::connect_with_driver_config(database_url, driver_config)
69+
.await?,
70+
);
6871

6972
#[cfg(feature = "postgres")]
7073
if DB::NAME == sqlx_postgres::Postgres::NAME {

sqlx-mysql/src/options/connect.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::executor::Executor;
44
use crate::{MySqlConnectOptions, MySqlConnection};
55
use log::LevelFilter;
66
use sqlx_core::sql_str::AssertSqlSafe;
7-
use sqlx_core::Url;
7+
use sqlx_core::{config, Url};
88
use std::time::Duration;
99

1010
impl ConnectOptions for MySqlConnectOptions {
@@ -100,4 +100,11 @@ impl ConnectOptions for MySqlConnectOptions {
100100
self.log_settings.log_slow_statements(level, duration);
101101
self
102102
}
103+
104+
fn __unstable_apply_driver_config(
105+
self,
106+
config: &config::drivers::Config,
107+
) -> crate::Result<Self> {
108+
self.apply_driver_config(&config.mysql)
109+
}
103110
}

sqlx-mysql/src/options/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mod parse;
55
mod ssl_mode;
66

77
use crate::{connection::LogSettings, net::tls::CertificateInput};
8+
use sqlx_core::config;
89
pub use ssl_mode::MySqlSslMode;
910

1011
/// Options and flags which can be used to configure a MySQL connection.
@@ -414,6 +415,17 @@ impl MySqlConnectOptions {
414415
self.set_names = flag_val;
415416
self
416417
}
418+
419+
pub(crate) fn apply_driver_config(
420+
mut self,
421+
config: &config::drivers::MySqlConfig,
422+
) -> crate::Result<Self> {
423+
self = self
424+
.pipes_as_concat(config.pipes_as_concat)
425+
.no_engine_substitution(config.no_engine_substitution);
426+
427+
Ok(self)
428+
}
417429
}
418430

419431
impl MySqlConnectOptions {

0 commit comments

Comments
 (0)