diff --git a/sqlx-core/src/config/drivers.rs b/sqlx-core/src/config/drivers.rs index c3416541cd..dd5452fb5a 100644 --- a/sqlx-core/src/config/drivers.rs +++ b/sqlx-core/src/config/drivers.rs @@ -40,14 +40,38 @@ pub struct Config { } /// Configuration for the MySQL database driver. -#[derive(Debug, Default)] +#[derive(Debug)] #[cfg_attr( feature = "sqlx-toml", derive(serde::Deserialize), serde(default, rename_all = "kebab-case", deny_unknown_fields) )] pub struct MySqlConfig { - // No fields implemented yet. This key is only used to validate parsing. + /// Whether to enable the `PIPES_AS_CONCAT` connection setting + /// + /// Defaults to `true`. + /// + /// Some MySql databases such as PlanetScale error out with this connection setting + /// so it needs to be set `false` in such cases. + pub pipes_as_concat: bool, + /// Whether to enable the `NO_ENGINE_SUBSTITUTION` sql_mode setting after connection. + /// + /// Defaults to `true` (`NO_ENGINE_SUBSTITUTION` is passed, forbidding engine substitution.) + /// + /// If not set, if the available storage engine specified by a `CREATE TABLE` is not available, + /// a warning is given and the default storage engine is used instead. + /// + /// + pub no_engine_substitution: bool, +} + +impl Default for MySqlConfig { + fn default() -> Self { + Self { + pipes_as_concat: true, + no_engine_substitution: true, + } + } } /// Configuration for the Postgres database driver. diff --git a/sqlx-core/src/config/reference.toml b/sqlx-core/src/config/reference.toml index 618ac23c91..3585f740f8 100644 --- a/sqlx-core/src/config/reference.toml +++ b/sqlx-core/src/config/reference.toml @@ -22,7 +22,20 @@ database-url-var = "FOO_DATABASE_URL" # Configure MySQL databases in macros and sqlx-cli. [drivers.mysql] -# No fields implemented yet. This key is only used to validate parsing. +# Whether to enable the `PIPES_AS_CONCAT` connection setting +# +# Defaults to `true`. +# +# Some MySql databases such as PlanetScale error out with this connection setting +# so it needs to be set `false` in such cases. +pipes-as-concat = false +# Whether to enable the `NO_ENGINE_SUBSTITUTION` sql_mode setting after connection. +# +# Defaults to `true` (`NO_ENGINE_SUBSTITUTION` is passed, forbidding engine substitution.) +# +# If not set, if the available storage engine specified by a `CREATE TABLE` is not available, +# a warning is given and the default storage engine is used instead. +no-engine-substitution = false # Configure Postgres databases in macros and sqlx-cli. [drivers.postgres] diff --git a/sqlx-core/src/config/tests.rs b/sqlx-core/src/config/tests.rs index d01b859e46..4f1ee36535 100644 --- a/sqlx-core/src/config/tests.rs +++ b/sqlx-core/src/config/tests.rs @@ -18,6 +18,9 @@ fn assert_common_config(config: &config::common::Config) { } fn assert_drivers_config(config: &config::drivers::Config) { + assert!(!config.mysql.pipes_as_concat); + assert!(!config.mysql.no_engine_substitution); + assert_eq!( config.sqlite.unsafe_load_extensions, vec![ diff --git a/sqlx-core/src/connection.rs b/sqlx-core/src/connection.rs index b5f8138b2b..c7208bce9d 100644 --- a/sqlx-core/src/connection.rs +++ b/sqlx-core/src/connection.rs @@ -179,6 +179,29 @@ pub trait Connection: Send { async move { Self::connect_with(&options?).await } } + /// UNSTABLE: for use with `sqlx-macros-core` + /// + /// Establish a new database connection. + /// + /// A value of [`Options`][Self::Options] is first parsed from the provided connection string. + /// This parsing is database-specific. + /// The option then gets updated with options from the sqlx.toml file as appropriate. + #[doc(hidden)] + #[inline] + fn connect_with_driver_config( + url: &str, + driver_config: &config::drivers::Config, + ) -> impl Future> + Send + 'static + where + Self: Sized, + { + let options = url + .parse::() + .and_then(|options| options.__unstable_apply_driver_config(driver_config)); + + async move { Self::connect_with(&options?).await } + } + /// Establish a new database connection with the provided options. fn connect_with( options: &Self::Options, diff --git a/sqlx-macros-core/src/database/mod.rs b/sqlx-macros-core/src/database/mod.rs index 0885b3cca8..d1bd1c02ed 100644 --- a/sqlx-macros-core/src/database/mod.rs +++ b/sqlx-macros-core/src/database/mod.rs @@ -50,7 +50,7 @@ impl CachingDescribeBlocking { &self, query: &str, database_url: &str, - _driver_config: &config::drivers::Config, + driver_config: &config::drivers::Config, ) -> sqlx_core::Result> where for<'a> &'a mut DB::Connection: Executor<'a, Database = DB>, @@ -64,7 +64,10 @@ impl CachingDescribeBlocking { let conn = match cache.entry(database_url.to_string()) { hash_map::Entry::Occupied(hit) => hit.into_mut(), hash_map::Entry::Vacant(miss) => { - let conn = miss.insert(DB::Connection::connect(database_url).await?); + let conn = miss.insert( + DB::Connection::connect_with_driver_config(database_url, driver_config) + .await?, + ); #[cfg(feature = "postgres")] if DB::NAME == sqlx_postgres::Postgres::NAME { diff --git a/sqlx-mysql/src/options/connect.rs b/sqlx-mysql/src/options/connect.rs index f3b0492781..4f91756d15 100644 --- a/sqlx-mysql/src/options/connect.rs +++ b/sqlx-mysql/src/options/connect.rs @@ -4,7 +4,7 @@ use crate::executor::Executor; use crate::{MySqlConnectOptions, MySqlConnection}; use log::LevelFilter; use sqlx_core::sql_str::AssertSqlSafe; -use sqlx_core::Url; +use sqlx_core::{config, Url}; use std::time::Duration; impl ConnectOptions for MySqlConnectOptions { @@ -100,4 +100,11 @@ impl ConnectOptions for MySqlConnectOptions { self.log_settings.log_slow_statements(level, duration); self } + + fn __unstable_apply_driver_config( + self, + config: &config::drivers::Config, + ) -> crate::Result { + self.apply_driver_config(&config.mysql) + } } diff --git a/sqlx-mysql/src/options/mod.rs b/sqlx-mysql/src/options/mod.rs index 421bfb700e..bfcfb2d9d5 100644 --- a/sqlx-mysql/src/options/mod.rs +++ b/sqlx-mysql/src/options/mod.rs @@ -5,6 +5,7 @@ mod parse; mod ssl_mode; use crate::{connection::LogSettings, net::tls::CertificateInput}; +use sqlx_core::config; pub use ssl_mode::MySqlSslMode; /// Options and flags which can be used to configure a MySQL connection. @@ -414,6 +415,17 @@ impl MySqlConnectOptions { self.set_names = flag_val; self } + + pub(crate) fn apply_driver_config( + mut self, + config: &config::drivers::MySqlConfig, + ) -> crate::Result { + self = self + .pipes_as_concat(config.pipes_as_concat) + .no_engine_substitution(config.no_engine_substitution); + + Ok(self) + } } impl MySqlConnectOptions {