mirror of
https://github.com/launchbadge/sqlx
synced 2024-11-10 14:34:19 +00:00
feat(mysql): allow to connect with mysql driver without default behavor (#3037)
* feat(mysql): provide options to disable default connection settings after connecting * style(mysql): remove unecessary newlines and run rustfmt * feat(mysql): allow to pass a custom timezone to the database after connecting docs(mysql): improve docs for options set_names and no_engine_substitution
This commit is contained in:
parent
8c43b8c7bc
commit
27a49914ad
2 changed files with 92 additions and 13 deletions
|
@ -46,22 +46,36 @@ impl ConnectOptions for MySqlConnectOptions {
|
|||
|
||||
// https://mathiasbynens.be/notes/mysql-utf8mb4
|
||||
|
||||
let mut options = String::new();
|
||||
let mut sql_mode = Vec::new();
|
||||
if self.pipes_as_concat {
|
||||
options.push_str(r#"SET sql_mode=(SELECT CONCAT(@@sql_mode, ',PIPES_AS_CONCAT,NO_ENGINE_SUBSTITUTION')),"#);
|
||||
} else {
|
||||
options.push_str(
|
||||
r#"SET sql_mode=(SELECT CONCAT(@@sql_mode, ',NO_ENGINE_SUBSTITUTION')),"#,
|
||||
);
|
||||
sql_mode.push(r#"PIPES_AS_CONCAT"#);
|
||||
}
|
||||
if self.no_engine_subsitution {
|
||||
sql_mode.push(r#"NO_ENGINE_SUBSTITUTION"#);
|
||||
}
|
||||
options.push_str(r#"time_zone='+00:00',"#);
|
||||
options.push_str(&format!(
|
||||
r#"NAMES {} COLLATE {};"#,
|
||||
conn.stream.charset.as_str(),
|
||||
conn.stream.collation.as_str()
|
||||
));
|
||||
|
||||
conn.execute(&*options).await?;
|
||||
let mut options = Vec::new();
|
||||
if !sql_mode.is_empty() {
|
||||
options.push(format!(
|
||||
r#"sql_mode=(SELECT CONCAT(@@sql_mode, ',{}'))"#,
|
||||
sql_mode.join(",")
|
||||
));
|
||||
}
|
||||
if let Some(timezone) = &self.timezone {
|
||||
options.push(format!(r#"time_zone='{}'"#, timezone));
|
||||
}
|
||||
if self.set_names {
|
||||
options.push(format!(
|
||||
r#"NAMES {} COLLATE {}"#,
|
||||
conn.stream.charset.as_str(),
|
||||
conn.stream.collation.as_str()
|
||||
))
|
||||
}
|
||||
|
||||
if !options.is_empty() {
|
||||
conn.execute(&*format!(r#"SET {};"#, options.join(",")))
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(conn)
|
||||
})
|
||||
|
|
|
@ -77,6 +77,9 @@ pub struct MySqlConnectOptions {
|
|||
pub(crate) log_settings: LogSettings,
|
||||
pub(crate) pipes_as_concat: bool,
|
||||
pub(crate) enable_cleartext_plugin: bool,
|
||||
pub(crate) no_engine_subsitution: bool,
|
||||
pub(crate) timezone: Option<String>,
|
||||
pub(crate) set_names: bool,
|
||||
}
|
||||
|
||||
impl Default for MySqlConnectOptions {
|
||||
|
@ -105,6 +108,9 @@ impl MySqlConnectOptions {
|
|||
log_settings: Default::default(),
|
||||
pipes_as_concat: true,
|
||||
enable_cleartext_plugin: false,
|
||||
no_engine_subsitution: true,
|
||||
timezone: Some(String::from("+00:00")),
|
||||
set_names: true,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -333,6 +339,65 @@ impl MySqlConnectOptions {
|
|||
self.enable_cleartext_plugin = flag_val;
|
||||
self
|
||||
}
|
||||
|
||||
/// Flag that enables or disables the `NO_ENGINE_SUBSTITUTION` sql_mode setting after
|
||||
/// connection.
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// By default, this is `true` (`NO_ENGINE_SUBSTITUTION` is passed, forbidding engine
|
||||
/// substitution).
|
||||
///
|
||||
/// https://mariadb.com/kb/en/sql-mode/
|
||||
pub fn no_engine_subsitution(mut self, flag_val: bool) -> Self {
|
||||
self.no_engine_subsitution = flag_val;
|
||||
self
|
||||
}
|
||||
|
||||
/// If `Some`, sets the `time_zone` option to the given string after connecting to the database.
|
||||
///
|
||||
/// If `None`, no `time_zone` parameter is sent; the server timezone will be used instead.
|
||||
///
|
||||
/// Defaults to `Some(String::from("+00:00"))` to ensure all timestamps are in UTC.
|
||||
///
|
||||
/// ### Warning
|
||||
/// Changing this setting from its default will apply an unexpected skew to any
|
||||
/// `time::OffsetDateTime` or `chrono::DateTime<Utc>` value, whether passed as a parameter or
|
||||
/// decoded as a result. `TIMESTAMP` values are not encoded with their UTC offset in the MySQL
|
||||
/// protocol, so encoding and decoding of these types assumes the server timezone is *always*
|
||||
/// UTC.
|
||||
///
|
||||
/// If you are changing this option, ensure your application only uses
|
||||
/// `time::PrimitiveDateTime` or `chrono::NaiveDateTime` and that it does not assume these
|
||||
/// timestamps can be placed on a real timeline without applying the proper offset.
|
||||
pub fn timezone(mut self, value: impl Into<Option<String>>) -> Self {
|
||||
self.timezone = value.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// If enabled, `SET NAMES '{charset}' COLLATE '{collation}'` is passed with the values of
|
||||
/// [`.charset()`] and [`.collation()`] after connecting to the database.
|
||||
///
|
||||
/// This ensures the connection uses the specified character set and collation.
|
||||
///
|
||||
/// Enabled by default.
|
||||
///
|
||||
/// ### Warning
|
||||
/// If this is disabled and the default charset is not binary-compatible with UTF-8, query
|
||||
/// strings, column names and string values will likely not decode (or encode) correctly, which
|
||||
/// may result in unexpected errors or garbage outputs at runtime.
|
||||
///
|
||||
/// For proper functioning, you *must* ensure the server is using a binary-compatible charset,
|
||||
/// such as ASCII or Latin-1 (ISO 8859-1), and that you do not pass any strings containing
|
||||
/// codepoints not supported by said charset.
|
||||
///
|
||||
/// Instead of disabling this, you may also consider setting [`.charset()`] to a charset that
|
||||
/// is supported by your MySQL or MariaDB server version and compatible with UTF-8.
|
||||
pub fn set_names(mut self, flag_val: bool) -> Self {
|
||||
self.set_names = flag_val;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl MySqlConnectOptions {
|
||||
|
|
Loading…
Reference in a new issue