mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-12-29 21:00:54 +00:00
breaking(mysql): assume all non-binary collations compatible with str (#3924)
cc https://github.com/launchbadge/sqlx/pull/3400#issuecomment-3041035104 comment in `sqlx-mysql/src/collation.rs` for explanation fixes #3200 fixes #3387 fixes #3390 fixes #3409
This commit is contained in:
parent
469f22788e
commit
a3aa942a78
12
.github/workflows/sqlx.yml
vendored
12
.github/workflows/sqlx.yml
vendored
@ -419,7 +419,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
matrix:
|
||||
mariadb: [ verylatest, 11_4, 10_11, 10_4 ]
|
||||
mariadb: [ verylatest, 11_8, 11_4, 10_11, 10_6 ]
|
||||
runtime: [ async-std, tokio ]
|
||||
tls: [ native-tls, rustls-aws-lc-rs, rustls-ring, none ]
|
||||
needs: check
|
||||
@ -446,7 +446,7 @@ jobs:
|
||||
env:
|
||||
DATABASE_URL: mysql://root:password@localhost:3306/sqlx
|
||||
SQLX_OFFLINE_DIR: .sqlx
|
||||
RUSTFLAGS: --cfg mariadb_${{ matrix.mariadb }}
|
||||
RUSTFLAGS: --cfg mariadb="${{ matrix.mariadb }}"
|
||||
|
||||
# Run the `test-attr` test again to cover cleanup.
|
||||
- run: >
|
||||
@ -457,7 +457,7 @@ jobs:
|
||||
env:
|
||||
DATABASE_URL: mysql://root:password@localhost:3306/sqlx
|
||||
SQLX_OFFLINE_DIR: .sqlx
|
||||
RUSTFLAGS: --cfg mariadb_${{ matrix.mariadb }}
|
||||
RUSTFLAGS: --cfg mariadb="${{ matrix.mariadb }}"
|
||||
|
||||
# Remove test artifacts
|
||||
- run: cargo clean -p sqlx
|
||||
@ -471,7 +471,7 @@ jobs:
|
||||
env:
|
||||
SQLX_OFFLINE: true
|
||||
SQLX_OFFLINE_DIR: .sqlx
|
||||
RUSTFLAGS: -D warnings --cfg mariadb_${{ matrix.mariadb }}
|
||||
RUSTFLAGS: -D warnings --cfg mariadb="${{ matrix.mariadb }}"
|
||||
|
||||
# Test macros in offline mode (still needs DATABASE_URL to run)
|
||||
- run: >
|
||||
@ -483,7 +483,7 @@ jobs:
|
||||
DATABASE_URL: mysql://root:password@localhost:3306/sqlx
|
||||
SQLX_OFFLINE: true
|
||||
SQLX_OFFLINE_DIR: .sqlx
|
||||
RUSTFLAGS: --cfg mariadb_${{ matrix.mariadb }}
|
||||
RUSTFLAGS: --cfg mariadb="${{ matrix.mariadb }}"
|
||||
|
||||
# client SSL authentication
|
||||
|
||||
@ -500,4 +500,4 @@ jobs:
|
||||
--features any,mysql,macros,migrate,_unstable-all-types,runtime-${{ matrix.runtime }},tls-${{ matrix.tls }}
|
||||
env:
|
||||
DATABASE_URL: mysql://root@localhost:3306/sqlx?sslmode=verify_ca&ssl-ca=.%2Ftests%2Fcerts%2Fca.crt&ssl-key=.%2Ftests%2Fcerts%2Fkeys%2Fclient.key&ssl-cert=.%2Ftests%2Fcerts%2Fclient.crt
|
||||
RUSTFLAGS: --cfg mariadb_${{ matrix.mariadb }}
|
||||
RUSTFLAGS: --cfg mariadb="${{ matrix.mariadb }}"
|
||||
|
||||
12
Cargo.lock
generated
12
Cargo.lock
generated
@ -772,9 +772,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.26"
|
||||
version = "4.5.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783"
|
||||
checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@ -782,9 +782,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.26"
|
||||
version = "4.5.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121"
|
||||
checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@ -804,9 +804,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.24"
|
||||
version = "4.5.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c"
|
||||
checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
|
||||
@ -210,6 +210,9 @@ cast_sign_loss = 'deny'
|
||||
# See `clippy.toml`
|
||||
disallowed_methods = 'deny'
|
||||
|
||||
[lints.rust]
|
||||
unexpected_cfgs = { level = 'warn', check-cfg = ['cfg(mariadb, values(any()))'] }
|
||||
|
||||
#
|
||||
# Any
|
||||
#
|
||||
|
||||
@ -240,11 +240,11 @@ impl RawSql {
|
||||
///
|
||||
/// Otherwise, you might want to add `LIMIT 1` to your query.
|
||||
#[inline]
|
||||
pub async fn fetch_optional<'e, E, DB>(self, executor: E) -> crate::Result<DB::Row>
|
||||
pub async fn fetch_optional<'e, E, DB>(self, executor: E) -> crate::Result<Option<DB::Row>>
|
||||
where
|
||||
DB: Database,
|
||||
E: Executor<'e, Database = DB>,
|
||||
{
|
||||
executor.fetch_one(self).await
|
||||
executor.fetch_optional(self).await
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,900 +1,49 @@
|
||||
use crate::error::Error;
|
||||
use std::str::FromStr;
|
||||
// One of several questionable design decisions in MySQL is the choice to conflate
|
||||
// *how stored data is sorted* with the character encoding used over the wire.
|
||||
//
|
||||
// The documentation for `Protocol::HandshakeResponse41` implies that
|
||||
// the lower 8 bits of the collation ID may be used to uniquely identify the character set:
|
||||
// https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_connection_phase_packets_protocol_handshake_response.html
|
||||
//
|
||||
// However, this isn't at _all_ true in practice. Collation IDs are assigned without any apparent
|
||||
// rhyme or reason, mostly just sequential with unexplained gaps. Masking the collation ID with 0xFF
|
||||
// doesn't actually tell you anything meaningful, except obviously for collation IDs under 256
|
||||
// which just gives you the same collation ID again.
|
||||
//
|
||||
// Hanlon's razor would suggest they just forgot that they told clients they could do this.
|
||||
// Occam's razor suggests no one ever bothers to set the connection charset/collation this way,
|
||||
// and they all just default to `latin1_swedish_ci` (8), `utf8mb4_general_ci` (45),
|
||||
// or `utf8mb4_0900_ai_ci` (255).
|
||||
//
|
||||
// This would seem to mean that if we want to be *sure* of the character encoding of a given column,
|
||||
// we have to reference the _full_ catalog of collations. Because new ones are added occasionally,
|
||||
// we can't just assume a collation we don't recognize is UTF-8 as that's not always the case.
|
||||
//
|
||||
// This is especially true when we include MariaDB because they've started creating
|
||||
// their *own* collations, and even character sets, separately from MySQL.
|
||||
//
|
||||
// Awesome, right?
|
||||
//
|
||||
// However, as long as `character_set_client` and `character_set_results` are set correctly,
|
||||
// we can assume that any non-binary collation is a valid string, because the server will transcode.
|
||||
// As it turns out, the collation specified in the `Protocol::ColumnDefinition`
|
||||
// is *purely* informational. It has no bearing on what's sent over the wire except for `binary` (63),
|
||||
// which is never transcoded.
|
||||
//
|
||||
// So at the end of the day, none of this matters anyway! To know if a column is a string or not,
|
||||
// we merely need to check if it's not `binary` (63). If the protocol was just a *bit*
|
||||
// better documented, it would have saved me literally six hours spent figuring this out.
|
||||
//
|
||||
// Thanks, MySQL.
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub(crate) enum CharSet {
|
||||
armscii8,
|
||||
ascii,
|
||||
big5,
|
||||
binary,
|
||||
cp1250,
|
||||
cp1251,
|
||||
cp1256,
|
||||
cp1257,
|
||||
cp850,
|
||||
cp852,
|
||||
cp866,
|
||||
cp932,
|
||||
dec8,
|
||||
eucjpms,
|
||||
euckr,
|
||||
gb18030,
|
||||
gb2312,
|
||||
gbk,
|
||||
geostd8,
|
||||
greek,
|
||||
hebrew,
|
||||
hp8,
|
||||
keybcs2,
|
||||
koi8r,
|
||||
koi8u,
|
||||
latin1,
|
||||
latin2,
|
||||
latin5,
|
||||
latin7,
|
||||
macce,
|
||||
macroman,
|
||||
sjis,
|
||||
swe7,
|
||||
tis620,
|
||||
ucs2,
|
||||
ujis,
|
||||
utf16,
|
||||
utf16le,
|
||||
utf32,
|
||||
utf8,
|
||||
utf8mb4,
|
||||
}
|
||||
|
||||
impl CharSet {
|
||||
pub(crate) fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
CharSet::armscii8 => "armscii8",
|
||||
CharSet::ascii => "ascii",
|
||||
CharSet::big5 => "big5",
|
||||
CharSet::binary => "binary",
|
||||
CharSet::cp1250 => "cp1250",
|
||||
CharSet::cp1251 => "cp1251",
|
||||
CharSet::cp1256 => "cp1256",
|
||||
CharSet::cp1257 => "cp1257",
|
||||
CharSet::cp850 => "cp850",
|
||||
CharSet::cp852 => "cp852",
|
||||
CharSet::cp866 => "cp866",
|
||||
CharSet::cp932 => "cp932",
|
||||
CharSet::dec8 => "dec8",
|
||||
CharSet::eucjpms => "eucjpms",
|
||||
CharSet::euckr => "euckr",
|
||||
CharSet::gb18030 => "gb18030",
|
||||
CharSet::gb2312 => "gb2312",
|
||||
CharSet::gbk => "gbk",
|
||||
CharSet::geostd8 => "geostd8",
|
||||
CharSet::greek => "greek",
|
||||
CharSet::hebrew => "hebrew",
|
||||
CharSet::hp8 => "hp8",
|
||||
CharSet::keybcs2 => "keybcs2",
|
||||
CharSet::koi8r => "koi8r",
|
||||
CharSet::koi8u => "koi8u",
|
||||
CharSet::latin1 => "latin1",
|
||||
CharSet::latin2 => "latin2",
|
||||
CharSet::latin5 => "latin5",
|
||||
CharSet::latin7 => "latin7",
|
||||
CharSet::macce => "macce",
|
||||
CharSet::macroman => "macroman",
|
||||
CharSet::sjis => "sjis",
|
||||
CharSet::swe7 => "swe7",
|
||||
CharSet::tis620 => "tis620",
|
||||
CharSet::ucs2 => "ucs2",
|
||||
CharSet::ujis => "ujis",
|
||||
CharSet::utf16 => "utf16",
|
||||
CharSet::utf16le => "utf16le",
|
||||
CharSet::utf32 => "utf32",
|
||||
CharSet::utf8 => "utf8",
|
||||
CharSet::utf8mb4 => "utf8mb4",
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn default_collation(&self) -> Collation {
|
||||
match self {
|
||||
CharSet::armscii8 => Collation::armscii8_general_ci,
|
||||
CharSet::ascii => Collation::ascii_general_ci,
|
||||
CharSet::big5 => Collation::big5_chinese_ci,
|
||||
CharSet::binary => Collation::binary,
|
||||
CharSet::cp1250 => Collation::cp1250_general_ci,
|
||||
CharSet::cp1251 => Collation::cp1251_general_ci,
|
||||
CharSet::cp1256 => Collation::cp1256_general_ci,
|
||||
CharSet::cp1257 => Collation::cp1257_general_ci,
|
||||
CharSet::cp850 => Collation::cp850_general_ci,
|
||||
CharSet::cp852 => Collation::cp852_general_ci,
|
||||
CharSet::cp866 => Collation::cp866_general_ci,
|
||||
CharSet::cp932 => Collation::cp932_japanese_ci,
|
||||
CharSet::dec8 => Collation::dec8_swedish_ci,
|
||||
CharSet::eucjpms => Collation::eucjpms_japanese_ci,
|
||||
CharSet::euckr => Collation::euckr_korean_ci,
|
||||
CharSet::gb18030 => Collation::gb18030_chinese_ci,
|
||||
CharSet::gb2312 => Collation::gb2312_chinese_ci,
|
||||
CharSet::gbk => Collation::gbk_chinese_ci,
|
||||
CharSet::geostd8 => Collation::geostd8_general_ci,
|
||||
CharSet::greek => Collation::greek_general_ci,
|
||||
CharSet::hebrew => Collation::hebrew_general_ci,
|
||||
CharSet::hp8 => Collation::hp8_english_ci,
|
||||
CharSet::keybcs2 => Collation::keybcs2_general_ci,
|
||||
CharSet::koi8r => Collation::koi8r_general_ci,
|
||||
CharSet::koi8u => Collation::koi8u_general_ci,
|
||||
CharSet::latin1 => Collation::latin1_swedish_ci,
|
||||
CharSet::latin2 => Collation::latin2_general_ci,
|
||||
CharSet::latin5 => Collation::latin5_turkish_ci,
|
||||
CharSet::latin7 => Collation::latin7_general_ci,
|
||||
CharSet::macce => Collation::macce_general_ci,
|
||||
CharSet::macroman => Collation::macroman_general_ci,
|
||||
CharSet::sjis => Collation::sjis_japanese_ci,
|
||||
CharSet::swe7 => Collation::swe7_swedish_ci,
|
||||
CharSet::tis620 => Collation::tis620_thai_ci,
|
||||
CharSet::ucs2 => Collation::ucs2_general_ci,
|
||||
CharSet::ujis => Collation::ujis_japanese_ci,
|
||||
CharSet::utf16 => Collation::utf16_general_ci,
|
||||
CharSet::utf16le => Collation::utf16le_general_ci,
|
||||
CharSet::utf32 => Collation::utf32_general_ci,
|
||||
CharSet::utf8 => Collation::utf8_unicode_ci,
|
||||
CharSet::utf8mb4 => Collation::utf8mb4_unicode_ci,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for CharSet {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(char_set: &str) -> Result<Self, Self::Err> {
|
||||
Ok(match char_set {
|
||||
"armscii8" => CharSet::armscii8,
|
||||
"ascii" => CharSet::ascii,
|
||||
"big5" => CharSet::big5,
|
||||
"binary" => CharSet::binary,
|
||||
"cp1250" => CharSet::cp1250,
|
||||
"cp1251" => CharSet::cp1251,
|
||||
"cp1256" => CharSet::cp1256,
|
||||
"cp1257" => CharSet::cp1257,
|
||||
"cp850" => CharSet::cp850,
|
||||
"cp852" => CharSet::cp852,
|
||||
"cp866" => CharSet::cp866,
|
||||
"cp932" => CharSet::cp932,
|
||||
"dec8" => CharSet::dec8,
|
||||
"eucjpms" => CharSet::eucjpms,
|
||||
"euckr" => CharSet::euckr,
|
||||
"gb18030" => CharSet::gb18030,
|
||||
"gb2312" => CharSet::gb2312,
|
||||
"gbk" => CharSet::gbk,
|
||||
"geostd8" => CharSet::geostd8,
|
||||
"greek" => CharSet::greek,
|
||||
"hebrew" => CharSet::hebrew,
|
||||
"hp8" => CharSet::hp8,
|
||||
"keybcs2" => CharSet::keybcs2,
|
||||
"koi8r" => CharSet::koi8r,
|
||||
"koi8u" => CharSet::koi8u,
|
||||
"latin1" => CharSet::latin1,
|
||||
"latin2" => CharSet::latin2,
|
||||
"latin5" => CharSet::latin5,
|
||||
"latin7" => CharSet::latin7,
|
||||
"macce" => CharSet::macce,
|
||||
"macroman" => CharSet::macroman,
|
||||
"sjis" => CharSet::sjis,
|
||||
"swe7" => CharSet::swe7,
|
||||
"tis620" => CharSet::tis620,
|
||||
"ucs2" => CharSet::ucs2,
|
||||
"ujis" => CharSet::ujis,
|
||||
"utf16" => CharSet::utf16,
|
||||
"utf16le" => CharSet::utf16le,
|
||||
"utf32" => CharSet::utf32,
|
||||
"utf8" => CharSet::utf8,
|
||||
"utf8mb4" => CharSet::utf8mb4,
|
||||
|
||||
_ => {
|
||||
return Err(Error::Configuration(
|
||||
format!("unsupported MySQL charset: {char_set}").into(),
|
||||
));
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[repr(u8)]
|
||||
pub(crate) enum Collation {
|
||||
armscii8_bin = 64,
|
||||
armscii8_general_ci = 32,
|
||||
ascii_bin = 65,
|
||||
ascii_general_ci = 11,
|
||||
big5_bin = 84,
|
||||
big5_chinese_ci = 1,
|
||||
binary = 63,
|
||||
cp1250_bin = 66,
|
||||
cp1250_croatian_ci = 44,
|
||||
cp1250_czech_cs = 34,
|
||||
cp1250_general_ci = 26,
|
||||
cp1250_polish_ci = 99,
|
||||
cp1251_bin = 50,
|
||||
cp1251_bulgarian_ci = 14,
|
||||
cp1251_general_ci = 51,
|
||||
cp1251_general_cs = 52,
|
||||
cp1251_ukrainian_ci = 23,
|
||||
cp1256_bin = 67,
|
||||
cp1256_general_ci = 57,
|
||||
cp1257_bin = 58,
|
||||
cp1257_general_ci = 59,
|
||||
cp1257_lithuanian_ci = 29,
|
||||
cp850_bin = 80,
|
||||
cp850_general_ci = 4,
|
||||
cp852_bin = 81,
|
||||
cp852_general_ci = 40,
|
||||
cp866_bin = 68,
|
||||
cp866_general_ci = 36,
|
||||
cp932_bin = 96,
|
||||
cp932_japanese_ci = 95,
|
||||
dec8_bin = 69,
|
||||
dec8_swedish_ci = 3,
|
||||
eucjpms_bin = 98,
|
||||
eucjpms_japanese_ci = 97,
|
||||
euckr_bin = 85,
|
||||
euckr_korean_ci = 19,
|
||||
gb18030_bin = 249,
|
||||
gb18030_chinese_ci = 248,
|
||||
gb18030_unicode_520_ci = 250,
|
||||
gb2312_bin = 86,
|
||||
gb2312_chinese_ci = 24,
|
||||
gbk_bin = 87,
|
||||
gbk_chinese_ci = 28,
|
||||
geostd8_bin = 93,
|
||||
geostd8_general_ci = 92,
|
||||
greek_bin = 70,
|
||||
greek_general_ci = 25,
|
||||
hebrew_bin = 71,
|
||||
hebrew_general_ci = 16,
|
||||
hp8_bin = 72,
|
||||
hp8_english_ci = 6,
|
||||
keybcs2_bin = 73,
|
||||
keybcs2_general_ci = 37,
|
||||
koi8r_bin = 74,
|
||||
koi8r_general_ci = 7,
|
||||
koi8u_bin = 75,
|
||||
koi8u_general_ci = 22,
|
||||
latin1_bin = 47,
|
||||
latin1_danish_ci = 15,
|
||||
latin1_general_ci = 48,
|
||||
latin1_general_cs = 49,
|
||||
latin1_german1_ci = 5,
|
||||
latin1_german2_ci = 31,
|
||||
latin1_spanish_ci = 94,
|
||||
latin1_swedish_ci = 8,
|
||||
latin2_bin = 77,
|
||||
latin2_croatian_ci = 27,
|
||||
latin2_czech_cs = 2,
|
||||
latin2_general_ci = 9,
|
||||
latin2_hungarian_ci = 21,
|
||||
latin5_bin = 78,
|
||||
latin5_turkish_ci = 30,
|
||||
latin7_bin = 79,
|
||||
latin7_estonian_cs = 20,
|
||||
latin7_general_ci = 41,
|
||||
latin7_general_cs = 42,
|
||||
macce_bin = 43,
|
||||
macce_general_ci = 38,
|
||||
macroman_bin = 53,
|
||||
macroman_general_ci = 39,
|
||||
sjis_bin = 88,
|
||||
sjis_japanese_ci = 13,
|
||||
swe7_bin = 82,
|
||||
swe7_swedish_ci = 10,
|
||||
tis620_bin = 89,
|
||||
tis620_thai_ci = 18,
|
||||
ucs2_bin = 90,
|
||||
ucs2_croatian_ci = 149,
|
||||
ucs2_czech_ci = 138,
|
||||
ucs2_danish_ci = 139,
|
||||
ucs2_esperanto_ci = 145,
|
||||
ucs2_estonian_ci = 134,
|
||||
ucs2_general_ci = 35,
|
||||
ucs2_general_mysql500_ci = 159,
|
||||
ucs2_german2_ci = 148,
|
||||
ucs2_hungarian_ci = 146,
|
||||
ucs2_icelandic_ci = 129,
|
||||
ucs2_latvian_ci = 130,
|
||||
ucs2_lithuanian_ci = 140,
|
||||
ucs2_persian_ci = 144,
|
||||
ucs2_polish_ci = 133,
|
||||
ucs2_roman_ci = 143,
|
||||
ucs2_romanian_ci = 131,
|
||||
ucs2_sinhala_ci = 147,
|
||||
ucs2_slovak_ci = 141,
|
||||
ucs2_slovenian_ci = 132,
|
||||
ucs2_spanish_ci = 135,
|
||||
ucs2_spanish2_ci = 142,
|
||||
ucs2_swedish_ci = 136,
|
||||
ucs2_turkish_ci = 137,
|
||||
ucs2_unicode_520_ci = 150,
|
||||
ucs2_unicode_ci = 128,
|
||||
ucs2_vietnamese_ci = 151,
|
||||
ujis_bin = 91,
|
||||
ujis_japanese_ci = 12,
|
||||
utf16_bin = 55,
|
||||
utf16_croatian_ci = 122,
|
||||
utf16_czech_ci = 111,
|
||||
utf16_danish_ci = 112,
|
||||
utf16_esperanto_ci = 118,
|
||||
utf16_estonian_ci = 107,
|
||||
utf16_general_ci = 54,
|
||||
utf16_german2_ci = 121,
|
||||
utf16_hungarian_ci = 119,
|
||||
utf16_icelandic_ci = 102,
|
||||
utf16_latvian_ci = 103,
|
||||
utf16_lithuanian_ci = 113,
|
||||
utf16_persian_ci = 117,
|
||||
utf16_polish_ci = 106,
|
||||
utf16_roman_ci = 116,
|
||||
utf16_romanian_ci = 104,
|
||||
utf16_sinhala_ci = 120,
|
||||
utf16_slovak_ci = 114,
|
||||
utf16_slovenian_ci = 105,
|
||||
utf16_spanish_ci = 108,
|
||||
utf16_spanish2_ci = 115,
|
||||
utf16_swedish_ci = 109,
|
||||
utf16_turkish_ci = 110,
|
||||
utf16_unicode_520_ci = 123,
|
||||
utf16_unicode_ci = 101,
|
||||
utf16_vietnamese_ci = 124,
|
||||
utf16le_bin = 62,
|
||||
utf16le_general_ci = 56,
|
||||
utf32_bin = 61,
|
||||
utf32_croatian_ci = 181,
|
||||
utf32_czech_ci = 170,
|
||||
utf32_danish_ci = 171,
|
||||
utf32_esperanto_ci = 177,
|
||||
utf32_estonian_ci = 166,
|
||||
utf32_general_ci = 60,
|
||||
utf32_german2_ci = 180,
|
||||
utf32_hungarian_ci = 178,
|
||||
utf32_icelandic_ci = 161,
|
||||
utf32_latvian_ci = 162,
|
||||
utf32_lithuanian_ci = 172,
|
||||
utf32_persian_ci = 176,
|
||||
utf32_polish_ci = 165,
|
||||
utf32_roman_ci = 175,
|
||||
utf32_romanian_ci = 163,
|
||||
utf32_sinhala_ci = 179,
|
||||
utf32_slovak_ci = 173,
|
||||
utf32_slovenian_ci = 164,
|
||||
utf32_spanish_ci = 167,
|
||||
utf32_spanish2_ci = 174,
|
||||
utf32_swedish_ci = 168,
|
||||
utf32_turkish_ci = 169,
|
||||
utf32_unicode_520_ci = 182,
|
||||
utf32_unicode_ci = 160,
|
||||
utf32_vietnamese_ci = 183,
|
||||
utf8_bin = 83,
|
||||
utf8_croatian_ci = 213,
|
||||
utf8_czech_ci = 202,
|
||||
utf8_danish_ci = 203,
|
||||
utf8_esperanto_ci = 209,
|
||||
utf8_estonian_ci = 198,
|
||||
utf8_general_ci = 33,
|
||||
utf8_general_mysql500_ci = 223,
|
||||
utf8_german2_ci = 212,
|
||||
utf8_hungarian_ci = 210,
|
||||
utf8_icelandic_ci = 193,
|
||||
utf8_latvian_ci = 194,
|
||||
utf8_lithuanian_ci = 204,
|
||||
utf8_persian_ci = 208,
|
||||
utf8_polish_ci = 197,
|
||||
utf8_roman_ci = 207,
|
||||
utf8_romanian_ci = 195,
|
||||
utf8_sinhala_ci = 211,
|
||||
utf8_slovak_ci = 205,
|
||||
utf8_slovenian_ci = 196,
|
||||
utf8_spanish_ci = 199,
|
||||
utf8_spanish2_ci = 206,
|
||||
utf8_swedish_ci = 200,
|
||||
utf8_tolower_ci = 76,
|
||||
utf8_turkish_ci = 201,
|
||||
utf8_unicode_520_ci = 214,
|
||||
utf8_unicode_ci = 192,
|
||||
utf8_vietnamese_ci = 215,
|
||||
utf8mb4_0900_ai_ci = 255,
|
||||
utf8mb4_bin = 46,
|
||||
utf8mb4_croatian_ci = 245,
|
||||
utf8mb4_czech_ci = 234,
|
||||
utf8mb4_danish_ci = 235,
|
||||
utf8mb4_esperanto_ci = 241,
|
||||
utf8mb4_estonian_ci = 230,
|
||||
utf8mb4_general_ci = 45,
|
||||
utf8mb4_german2_ci = 244,
|
||||
utf8mb4_hungarian_ci = 242,
|
||||
utf8mb4_icelandic_ci = 225,
|
||||
utf8mb4_latvian_ci = 226,
|
||||
utf8mb4_lithuanian_ci = 236,
|
||||
utf8mb4_persian_ci = 240,
|
||||
utf8mb4_polish_ci = 229,
|
||||
utf8mb4_roman_ci = 239,
|
||||
utf8mb4_romanian_ci = 227,
|
||||
utf8mb4_sinhala_ci = 243,
|
||||
utf8mb4_slovak_ci = 237,
|
||||
utf8mb4_slovenian_ci = 228,
|
||||
utf8mb4_spanish_ci = 231,
|
||||
utf8mb4_spanish2_ci = 238,
|
||||
utf8mb4_swedish_ci = 232,
|
||||
utf8mb4_turkish_ci = 233,
|
||||
utf8mb4_unicode_520_ci = 246,
|
||||
utf8mb4_unicode_ci = 224,
|
||||
utf8mb4_vietnamese_ci = 247,
|
||||
}
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "offline", derive(serde::Deserialize, serde::Serialize))]
|
||||
pub struct Collation(pub u16);
|
||||
|
||||
impl Collation {
|
||||
pub(crate) fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Collation::armscii8_bin => "armscii8_bin",
|
||||
Collation::armscii8_general_ci => "armscii8_general_ci",
|
||||
Collation::ascii_bin => "ascii_bin",
|
||||
Collation::ascii_general_ci => "ascii_general_ci",
|
||||
Collation::big5_bin => "big5_bin",
|
||||
Collation::big5_chinese_ci => "big5_chinese_ci",
|
||||
Collation::binary => "binary",
|
||||
Collation::cp1250_bin => "cp1250_bin",
|
||||
Collation::cp1250_croatian_ci => "cp1250_croatian_ci",
|
||||
Collation::cp1250_czech_cs => "cp1250_czech_cs",
|
||||
Collation::cp1250_general_ci => "cp1250_general_ci",
|
||||
Collation::cp1250_polish_ci => "cp1250_polish_ci",
|
||||
Collation::cp1251_bin => "cp1251_bin",
|
||||
Collation::cp1251_bulgarian_ci => "cp1251_bulgarian_ci",
|
||||
Collation::cp1251_general_ci => "cp1251_general_ci",
|
||||
Collation::cp1251_general_cs => "cp1251_general_cs",
|
||||
Collation::cp1251_ukrainian_ci => "cp1251_ukrainian_ci",
|
||||
Collation::cp1256_bin => "cp1256_bin",
|
||||
Collation::cp1256_general_ci => "cp1256_general_ci",
|
||||
Collation::cp1257_bin => "cp1257_bin",
|
||||
Collation::cp1257_general_ci => "cp1257_general_ci",
|
||||
Collation::cp1257_lithuanian_ci => "cp1257_lithuanian_ci",
|
||||
Collation::cp850_bin => "cp850_bin",
|
||||
Collation::cp850_general_ci => "cp850_general_ci",
|
||||
Collation::cp852_bin => "cp852_bin",
|
||||
Collation::cp852_general_ci => "cp852_general_ci",
|
||||
Collation::cp866_bin => "cp866_bin",
|
||||
Collation::cp866_general_ci => "cp866_general_ci",
|
||||
Collation::cp932_bin => "cp932_bin",
|
||||
Collation::cp932_japanese_ci => "cp932_japanese_ci",
|
||||
Collation::dec8_bin => "dec8_bin",
|
||||
Collation::dec8_swedish_ci => "dec8_swedish_ci",
|
||||
Collation::eucjpms_bin => "eucjpms_bin",
|
||||
Collation::eucjpms_japanese_ci => "eucjpms_japanese_ci",
|
||||
Collation::euckr_bin => "euckr_bin",
|
||||
Collation::euckr_korean_ci => "euckr_korean_ci",
|
||||
Collation::gb18030_bin => "gb18030_bin",
|
||||
Collation::gb18030_chinese_ci => "gb18030_chinese_ci",
|
||||
Collation::gb18030_unicode_520_ci => "gb18030_unicode_520_ci",
|
||||
Collation::gb2312_bin => "gb2312_bin",
|
||||
Collation::gb2312_chinese_ci => "gb2312_chinese_ci",
|
||||
Collation::gbk_bin => "gbk_bin",
|
||||
Collation::gbk_chinese_ci => "gbk_chinese_ci",
|
||||
Collation::geostd8_bin => "geostd8_bin",
|
||||
Collation::geostd8_general_ci => "geostd8_general_ci",
|
||||
Collation::greek_bin => "greek_bin",
|
||||
Collation::greek_general_ci => "greek_general_ci",
|
||||
Collation::hebrew_bin => "hebrew_bin",
|
||||
Collation::hebrew_general_ci => "hebrew_general_ci",
|
||||
Collation::hp8_bin => "hp8_bin",
|
||||
Collation::hp8_english_ci => "hp8_english_ci",
|
||||
Collation::keybcs2_bin => "keybcs2_bin",
|
||||
Collation::keybcs2_general_ci => "keybcs2_general_ci",
|
||||
Collation::koi8r_bin => "koi8r_bin",
|
||||
Collation::koi8r_general_ci => "koi8r_general_ci",
|
||||
Collation::koi8u_bin => "koi8u_bin",
|
||||
Collation::koi8u_general_ci => "koi8u_general_ci",
|
||||
Collation::latin1_bin => "latin1_bin",
|
||||
Collation::latin1_danish_ci => "latin1_danish_ci",
|
||||
Collation::latin1_general_ci => "latin1_general_ci",
|
||||
Collation::latin1_general_cs => "latin1_general_cs",
|
||||
Collation::latin1_german1_ci => "latin1_german1_ci",
|
||||
Collation::latin1_german2_ci => "latin1_german2_ci",
|
||||
Collation::latin1_spanish_ci => "latin1_spanish_ci",
|
||||
Collation::latin1_swedish_ci => "latin1_swedish_ci",
|
||||
Collation::latin2_bin => "latin2_bin",
|
||||
Collation::latin2_croatian_ci => "latin2_croatian_ci",
|
||||
Collation::latin2_czech_cs => "latin2_czech_cs",
|
||||
Collation::latin2_general_ci => "latin2_general_ci",
|
||||
Collation::latin2_hungarian_ci => "latin2_hungarian_ci",
|
||||
Collation::latin5_bin => "latin5_bin",
|
||||
Collation::latin5_turkish_ci => "latin5_turkish_ci",
|
||||
Collation::latin7_bin => "latin7_bin",
|
||||
Collation::latin7_estonian_cs => "latin7_estonian_cs",
|
||||
Collation::latin7_general_ci => "latin7_general_ci",
|
||||
Collation::latin7_general_cs => "latin7_general_cs",
|
||||
Collation::macce_bin => "macce_bin",
|
||||
Collation::macce_general_ci => "macce_general_ci",
|
||||
Collation::macroman_bin => "macroman_bin",
|
||||
Collation::macroman_general_ci => "macroman_general_ci",
|
||||
Collation::sjis_bin => "sjis_bin",
|
||||
Collation::sjis_japanese_ci => "sjis_japanese_ci",
|
||||
Collation::swe7_bin => "swe7_bin",
|
||||
Collation::swe7_swedish_ci => "swe7_swedish_ci",
|
||||
Collation::tis620_bin => "tis620_bin",
|
||||
Collation::tis620_thai_ci => "tis620_thai_ci",
|
||||
Collation::ucs2_bin => "ucs2_bin",
|
||||
Collation::ucs2_croatian_ci => "ucs2_croatian_ci",
|
||||
Collation::ucs2_czech_ci => "ucs2_czech_ci",
|
||||
Collation::ucs2_danish_ci => "ucs2_danish_ci",
|
||||
Collation::ucs2_esperanto_ci => "ucs2_esperanto_ci",
|
||||
Collation::ucs2_estonian_ci => "ucs2_estonian_ci",
|
||||
Collation::ucs2_general_ci => "ucs2_general_ci",
|
||||
Collation::ucs2_general_mysql500_ci => "ucs2_general_mysql500_ci",
|
||||
Collation::ucs2_german2_ci => "ucs2_german2_ci",
|
||||
Collation::ucs2_hungarian_ci => "ucs2_hungarian_ci",
|
||||
Collation::ucs2_icelandic_ci => "ucs2_icelandic_ci",
|
||||
Collation::ucs2_latvian_ci => "ucs2_latvian_ci",
|
||||
Collation::ucs2_lithuanian_ci => "ucs2_lithuanian_ci",
|
||||
Collation::ucs2_persian_ci => "ucs2_persian_ci",
|
||||
Collation::ucs2_polish_ci => "ucs2_polish_ci",
|
||||
Collation::ucs2_roman_ci => "ucs2_roman_ci",
|
||||
Collation::ucs2_romanian_ci => "ucs2_romanian_ci",
|
||||
Collation::ucs2_sinhala_ci => "ucs2_sinhala_ci",
|
||||
Collation::ucs2_slovak_ci => "ucs2_slovak_ci",
|
||||
Collation::ucs2_slovenian_ci => "ucs2_slovenian_ci",
|
||||
Collation::ucs2_spanish_ci => "ucs2_spanish_ci",
|
||||
Collation::ucs2_spanish2_ci => "ucs2_spanish2_ci",
|
||||
Collation::ucs2_swedish_ci => "ucs2_swedish_ci",
|
||||
Collation::ucs2_turkish_ci => "ucs2_turkish_ci",
|
||||
Collation::ucs2_unicode_520_ci => "ucs2_unicode_520_ci",
|
||||
Collation::ucs2_unicode_ci => "ucs2_unicode_ci",
|
||||
Collation::ucs2_vietnamese_ci => "ucs2_vietnamese_ci",
|
||||
Collation::ujis_bin => "ujis_bin",
|
||||
Collation::ujis_japanese_ci => "ujis_japanese_ci",
|
||||
Collation::utf16_bin => "utf16_bin",
|
||||
Collation::utf16_croatian_ci => "utf16_croatian_ci",
|
||||
Collation::utf16_czech_ci => "utf16_czech_ci",
|
||||
Collation::utf16_danish_ci => "utf16_danish_ci",
|
||||
Collation::utf16_esperanto_ci => "utf16_esperanto_ci",
|
||||
Collation::utf16_estonian_ci => "utf16_estonian_ci",
|
||||
Collation::utf16_general_ci => "utf16_general_ci",
|
||||
Collation::utf16_german2_ci => "utf16_german2_ci",
|
||||
Collation::utf16_hungarian_ci => "utf16_hungarian_ci",
|
||||
Collation::utf16_icelandic_ci => "utf16_icelandic_ci",
|
||||
Collation::utf16_latvian_ci => "utf16_latvian_ci",
|
||||
Collation::utf16_lithuanian_ci => "utf16_lithuanian_ci",
|
||||
Collation::utf16_persian_ci => "utf16_persian_ci",
|
||||
Collation::utf16_polish_ci => "utf16_polish_ci",
|
||||
Collation::utf16_roman_ci => "utf16_roman_ci",
|
||||
Collation::utf16_romanian_ci => "utf16_romanian_ci",
|
||||
Collation::utf16_sinhala_ci => "utf16_sinhala_ci",
|
||||
Collation::utf16_slovak_ci => "utf16_slovak_ci",
|
||||
Collation::utf16_slovenian_ci => "utf16_slovenian_ci",
|
||||
Collation::utf16_spanish_ci => "utf16_spanish_ci",
|
||||
Collation::utf16_spanish2_ci => "utf16_spanish2_ci",
|
||||
Collation::utf16_swedish_ci => "utf16_swedish_ci",
|
||||
Collation::utf16_turkish_ci => "utf16_turkish_ci",
|
||||
Collation::utf16_unicode_520_ci => "utf16_unicode_520_ci",
|
||||
Collation::utf16_unicode_ci => "utf16_unicode_ci",
|
||||
Collation::utf16_vietnamese_ci => "utf16_vietnamese_ci",
|
||||
Collation::utf16le_bin => "utf16le_bin",
|
||||
Collation::utf16le_general_ci => "utf16le_general_ci",
|
||||
Collation::utf32_bin => "utf32_bin",
|
||||
Collation::utf32_croatian_ci => "utf32_croatian_ci",
|
||||
Collation::utf32_czech_ci => "utf32_czech_ci",
|
||||
Collation::utf32_danish_ci => "utf32_danish_ci",
|
||||
Collation::utf32_esperanto_ci => "utf32_esperanto_ci",
|
||||
Collation::utf32_estonian_ci => "utf32_estonian_ci",
|
||||
Collation::utf32_general_ci => "utf32_general_ci",
|
||||
Collation::utf32_german2_ci => "utf32_german2_ci",
|
||||
Collation::utf32_hungarian_ci => "utf32_hungarian_ci",
|
||||
Collation::utf32_icelandic_ci => "utf32_icelandic_ci",
|
||||
Collation::utf32_latvian_ci => "utf32_latvian_ci",
|
||||
Collation::utf32_lithuanian_ci => "utf32_lithuanian_ci",
|
||||
Collation::utf32_persian_ci => "utf32_persian_ci",
|
||||
Collation::utf32_polish_ci => "utf32_polish_ci",
|
||||
Collation::utf32_roman_ci => "utf32_roman_ci",
|
||||
Collation::utf32_romanian_ci => "utf32_romanian_ci",
|
||||
Collation::utf32_sinhala_ci => "utf32_sinhala_ci",
|
||||
Collation::utf32_slovak_ci => "utf32_slovak_ci",
|
||||
Collation::utf32_slovenian_ci => "utf32_slovenian_ci",
|
||||
Collation::utf32_spanish_ci => "utf32_spanish_ci",
|
||||
Collation::utf32_spanish2_ci => "utf32_spanish2_ci",
|
||||
Collation::utf32_swedish_ci => "utf32_swedish_ci",
|
||||
Collation::utf32_turkish_ci => "utf32_turkish_ci",
|
||||
Collation::utf32_unicode_520_ci => "utf32_unicode_520_ci",
|
||||
Collation::utf32_unicode_ci => "utf32_unicode_ci",
|
||||
Collation::utf32_vietnamese_ci => "utf32_vietnamese_ci",
|
||||
Collation::utf8_bin => "utf8_bin",
|
||||
Collation::utf8_croatian_ci => "utf8_croatian_ci",
|
||||
Collation::utf8_czech_ci => "utf8_czech_ci",
|
||||
Collation::utf8_danish_ci => "utf8_danish_ci",
|
||||
Collation::utf8_esperanto_ci => "utf8_esperanto_ci",
|
||||
Collation::utf8_estonian_ci => "utf8_estonian_ci",
|
||||
Collation::utf8_general_ci => "utf8_general_ci",
|
||||
Collation::utf8_general_mysql500_ci => "utf8_general_mysql500_ci",
|
||||
Collation::utf8_german2_ci => "utf8_german2_ci",
|
||||
Collation::utf8_hungarian_ci => "utf8_hungarian_ci",
|
||||
Collation::utf8_icelandic_ci => "utf8_icelandic_ci",
|
||||
Collation::utf8_latvian_ci => "utf8_latvian_ci",
|
||||
Collation::utf8_lithuanian_ci => "utf8_lithuanian_ci",
|
||||
Collation::utf8_persian_ci => "utf8_persian_ci",
|
||||
Collation::utf8_polish_ci => "utf8_polish_ci",
|
||||
Collation::utf8_roman_ci => "utf8_roman_ci",
|
||||
Collation::utf8_romanian_ci => "utf8_romanian_ci",
|
||||
Collation::utf8_sinhala_ci => "utf8_sinhala_ci",
|
||||
Collation::utf8_slovak_ci => "utf8_slovak_ci",
|
||||
Collation::utf8_slovenian_ci => "utf8_slovenian_ci",
|
||||
Collation::utf8_spanish_ci => "utf8_spanish_ci",
|
||||
Collation::utf8_spanish2_ci => "utf8_spanish2_ci",
|
||||
Collation::utf8_swedish_ci => "utf8_swedish_ci",
|
||||
Collation::utf8_tolower_ci => "utf8_tolower_ci",
|
||||
Collation::utf8_turkish_ci => "utf8_turkish_ci",
|
||||
Collation::utf8_unicode_520_ci => "utf8_unicode_520_ci",
|
||||
Collation::utf8_unicode_ci => "utf8_unicode_ci",
|
||||
Collation::utf8_vietnamese_ci => "utf8_vietnamese_ci",
|
||||
Collation::utf8mb4_0900_ai_ci => "utf8mb4_0900_ai_ci",
|
||||
Collation::utf8mb4_bin => "utf8mb4_bin",
|
||||
Collation::utf8mb4_croatian_ci => "utf8mb4_croatian_ci",
|
||||
Collation::utf8mb4_czech_ci => "utf8mb4_czech_ci",
|
||||
Collation::utf8mb4_danish_ci => "utf8mb4_danish_ci",
|
||||
Collation::utf8mb4_esperanto_ci => "utf8mb4_esperanto_ci",
|
||||
Collation::utf8mb4_estonian_ci => "utf8mb4_estonian_ci",
|
||||
Collation::utf8mb4_general_ci => "utf8mb4_general_ci",
|
||||
Collation::utf8mb4_german2_ci => "utf8mb4_german2_ci",
|
||||
Collation::utf8mb4_hungarian_ci => "utf8mb4_hungarian_ci",
|
||||
Collation::utf8mb4_icelandic_ci => "utf8mb4_icelandic_ci",
|
||||
Collation::utf8mb4_latvian_ci => "utf8mb4_latvian_ci",
|
||||
Collation::utf8mb4_lithuanian_ci => "utf8mb4_lithuanian_ci",
|
||||
Collation::utf8mb4_persian_ci => "utf8mb4_persian_ci",
|
||||
Collation::utf8mb4_polish_ci => "utf8mb4_polish_ci",
|
||||
Collation::utf8mb4_roman_ci => "utf8mb4_roman_ci",
|
||||
Collation::utf8mb4_romanian_ci => "utf8mb4_romanian_ci",
|
||||
Collation::utf8mb4_sinhala_ci => "utf8mb4_sinhala_ci",
|
||||
Collation::utf8mb4_slovak_ci => "utf8mb4_slovak_ci",
|
||||
Collation::utf8mb4_slovenian_ci => "utf8mb4_slovenian_ci",
|
||||
Collation::utf8mb4_spanish_ci => "utf8mb4_spanish_ci",
|
||||
Collation::utf8mb4_spanish2_ci => "utf8mb4_spanish2_ci",
|
||||
Collation::utf8mb4_swedish_ci => "utf8mb4_swedish_ci",
|
||||
Collation::utf8mb4_turkish_ci => "utf8mb4_turkish_ci",
|
||||
Collation::utf8mb4_unicode_520_ci => "utf8mb4_unicode_520_ci",
|
||||
Collation::utf8mb4_unicode_ci => "utf8mb4_unicode_ci",
|
||||
Collation::utf8mb4_vietnamese_ci => "utf8mb4_vietnamese_ci",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handshake packet have only 1 byte for collation_id.
|
||||
// So we can't use collations with ID > 255.
|
||||
impl FromStr for Collation {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(collation: &str) -> Result<Self, Self::Err> {
|
||||
Ok(match collation {
|
||||
"big5_chinese_ci" => Collation::big5_chinese_ci,
|
||||
"swe7_swedish_ci" => Collation::swe7_swedish_ci,
|
||||
"utf16_unicode_ci" => Collation::utf16_unicode_ci,
|
||||
"utf16_icelandic_ci" => Collation::utf16_icelandic_ci,
|
||||
"utf16_latvian_ci" => Collation::utf16_latvian_ci,
|
||||
"utf16_romanian_ci" => Collation::utf16_romanian_ci,
|
||||
"utf16_slovenian_ci" => Collation::utf16_slovenian_ci,
|
||||
"utf16_polish_ci" => Collation::utf16_polish_ci,
|
||||
"utf16_estonian_ci" => Collation::utf16_estonian_ci,
|
||||
"utf16_spanish_ci" => Collation::utf16_spanish_ci,
|
||||
"utf16_swedish_ci" => Collation::utf16_swedish_ci,
|
||||
"ascii_general_ci" => Collation::ascii_general_ci,
|
||||
"utf16_turkish_ci" => Collation::utf16_turkish_ci,
|
||||
"utf16_czech_ci" => Collation::utf16_czech_ci,
|
||||
"utf16_danish_ci" => Collation::utf16_danish_ci,
|
||||
"utf16_lithuanian_ci" => Collation::utf16_lithuanian_ci,
|
||||
"utf16_slovak_ci" => Collation::utf16_slovak_ci,
|
||||
"utf16_spanish2_ci" => Collation::utf16_spanish2_ci,
|
||||
"utf16_roman_ci" => Collation::utf16_roman_ci,
|
||||
"utf16_persian_ci" => Collation::utf16_persian_ci,
|
||||
"utf16_esperanto_ci" => Collation::utf16_esperanto_ci,
|
||||
"utf16_hungarian_ci" => Collation::utf16_hungarian_ci,
|
||||
"ujis_japanese_ci" => Collation::ujis_japanese_ci,
|
||||
"utf16_sinhala_ci" => Collation::utf16_sinhala_ci,
|
||||
"utf16_german2_ci" => Collation::utf16_german2_ci,
|
||||
"utf16_croatian_ci" => Collation::utf16_croatian_ci,
|
||||
"utf16_unicode_520_ci" => Collation::utf16_unicode_520_ci,
|
||||
"utf16_vietnamese_ci" => Collation::utf16_vietnamese_ci,
|
||||
"ucs2_unicode_ci" => Collation::ucs2_unicode_ci,
|
||||
"ucs2_icelandic_ci" => Collation::ucs2_icelandic_ci,
|
||||
"sjis_japanese_ci" => Collation::sjis_japanese_ci,
|
||||
"ucs2_latvian_ci" => Collation::ucs2_latvian_ci,
|
||||
"ucs2_romanian_ci" => Collation::ucs2_romanian_ci,
|
||||
"ucs2_slovenian_ci" => Collation::ucs2_slovenian_ci,
|
||||
"ucs2_polish_ci" => Collation::ucs2_polish_ci,
|
||||
"ucs2_estonian_ci" => Collation::ucs2_estonian_ci,
|
||||
"ucs2_spanish_ci" => Collation::ucs2_spanish_ci,
|
||||
"ucs2_swedish_ci" => Collation::ucs2_swedish_ci,
|
||||
"ucs2_turkish_ci" => Collation::ucs2_turkish_ci,
|
||||
"ucs2_czech_ci" => Collation::ucs2_czech_ci,
|
||||
"ucs2_danish_ci" => Collation::ucs2_danish_ci,
|
||||
"cp1251_bulgarian_ci" => Collation::cp1251_bulgarian_ci,
|
||||
"ucs2_lithuanian_ci" => Collation::ucs2_lithuanian_ci,
|
||||
"ucs2_slovak_ci" => Collation::ucs2_slovak_ci,
|
||||
"ucs2_spanish2_ci" => Collation::ucs2_spanish2_ci,
|
||||
"ucs2_roman_ci" => Collation::ucs2_roman_ci,
|
||||
"ucs2_persian_ci" => Collation::ucs2_persian_ci,
|
||||
"ucs2_esperanto_ci" => Collation::ucs2_esperanto_ci,
|
||||
"ucs2_hungarian_ci" => Collation::ucs2_hungarian_ci,
|
||||
"ucs2_sinhala_ci" => Collation::ucs2_sinhala_ci,
|
||||
"ucs2_german2_ci" => Collation::ucs2_german2_ci,
|
||||
"ucs2_croatian_ci" => Collation::ucs2_croatian_ci,
|
||||
"latin1_danish_ci" => Collation::latin1_danish_ci,
|
||||
"ucs2_unicode_520_ci" => Collation::ucs2_unicode_520_ci,
|
||||
"ucs2_vietnamese_ci" => Collation::ucs2_vietnamese_ci,
|
||||
"ucs2_general_mysql500_ci" => Collation::ucs2_general_mysql500_ci,
|
||||
"hebrew_general_ci" => Collation::hebrew_general_ci,
|
||||
"utf32_unicode_ci" => Collation::utf32_unicode_ci,
|
||||
"utf32_icelandic_ci" => Collation::utf32_icelandic_ci,
|
||||
"utf32_latvian_ci" => Collation::utf32_latvian_ci,
|
||||
"utf32_romanian_ci" => Collation::utf32_romanian_ci,
|
||||
"utf32_slovenian_ci" => Collation::utf32_slovenian_ci,
|
||||
"utf32_polish_ci" => Collation::utf32_polish_ci,
|
||||
"utf32_estonian_ci" => Collation::utf32_estonian_ci,
|
||||
"utf32_spanish_ci" => Collation::utf32_spanish_ci,
|
||||
"utf32_swedish_ci" => Collation::utf32_swedish_ci,
|
||||
"utf32_turkish_ci" => Collation::utf32_turkish_ci,
|
||||
"utf32_czech_ci" => Collation::utf32_czech_ci,
|
||||
"utf32_danish_ci" => Collation::utf32_danish_ci,
|
||||
"utf32_lithuanian_ci" => Collation::utf32_lithuanian_ci,
|
||||
"utf32_slovak_ci" => Collation::utf32_slovak_ci,
|
||||
"utf32_spanish2_ci" => Collation::utf32_spanish2_ci,
|
||||
"utf32_roman_ci" => Collation::utf32_roman_ci,
|
||||
"utf32_persian_ci" => Collation::utf32_persian_ci,
|
||||
"utf32_esperanto_ci" => Collation::utf32_esperanto_ci,
|
||||
"utf32_hungarian_ci" => Collation::utf32_hungarian_ci,
|
||||
"utf32_sinhala_ci" => Collation::utf32_sinhala_ci,
|
||||
"tis620_thai_ci" => Collation::tis620_thai_ci,
|
||||
"utf32_german2_ci" => Collation::utf32_german2_ci,
|
||||
"utf32_croatian_ci" => Collation::utf32_croatian_ci,
|
||||
"utf32_unicode_520_ci" => Collation::utf32_unicode_520_ci,
|
||||
"utf32_vietnamese_ci" => Collation::utf32_vietnamese_ci,
|
||||
"euckr_korean_ci" => Collation::euckr_korean_ci,
|
||||
"utf8_unicode_ci" => Collation::utf8_unicode_ci,
|
||||
"utf8_icelandic_ci" => Collation::utf8_icelandic_ci,
|
||||
"utf8_latvian_ci" => Collation::utf8_latvian_ci,
|
||||
"utf8_romanian_ci" => Collation::utf8_romanian_ci,
|
||||
"utf8_slovenian_ci" => Collation::utf8_slovenian_ci,
|
||||
"utf8_polish_ci" => Collation::utf8_polish_ci,
|
||||
"utf8_estonian_ci" => Collation::utf8_estonian_ci,
|
||||
"utf8_spanish_ci" => Collation::utf8_spanish_ci,
|
||||
"latin2_czech_cs" => Collation::latin2_czech_cs,
|
||||
"latin7_estonian_cs" => Collation::latin7_estonian_cs,
|
||||
"utf8_swedish_ci" => Collation::utf8_swedish_ci,
|
||||
"utf8_turkish_ci" => Collation::utf8_turkish_ci,
|
||||
"utf8_czech_ci" => Collation::utf8_czech_ci,
|
||||
"utf8_danish_ci" => Collation::utf8_danish_ci,
|
||||
"utf8_lithuanian_ci" => Collation::utf8_lithuanian_ci,
|
||||
"utf8_slovak_ci" => Collation::utf8_slovak_ci,
|
||||
"utf8_spanish2_ci" => Collation::utf8_spanish2_ci,
|
||||
"utf8_roman_ci" => Collation::utf8_roman_ci,
|
||||
"utf8_persian_ci" => Collation::utf8_persian_ci,
|
||||
"utf8_esperanto_ci" => Collation::utf8_esperanto_ci,
|
||||
"latin2_hungarian_ci" => Collation::latin2_hungarian_ci,
|
||||
"utf8_hungarian_ci" => Collation::utf8_hungarian_ci,
|
||||
"utf8_sinhala_ci" => Collation::utf8_sinhala_ci,
|
||||
"utf8_german2_ci" => Collation::utf8_german2_ci,
|
||||
"utf8_croatian_ci" => Collation::utf8_croatian_ci,
|
||||
"utf8_unicode_520_ci" => Collation::utf8_unicode_520_ci,
|
||||
"utf8_vietnamese_ci" => Collation::utf8_vietnamese_ci,
|
||||
"koi8u_general_ci" => Collation::koi8u_general_ci,
|
||||
"utf8_general_mysql500_ci" => Collation::utf8_general_mysql500_ci,
|
||||
"utf8mb4_unicode_ci" => Collation::utf8mb4_unicode_ci,
|
||||
"utf8mb4_icelandic_ci" => Collation::utf8mb4_icelandic_ci,
|
||||
"utf8mb4_latvian_ci" => Collation::utf8mb4_latvian_ci,
|
||||
"utf8mb4_romanian_ci" => Collation::utf8mb4_romanian_ci,
|
||||
"utf8mb4_slovenian_ci" => Collation::utf8mb4_slovenian_ci,
|
||||
"utf8mb4_polish_ci" => Collation::utf8mb4_polish_ci,
|
||||
"cp1251_ukrainian_ci" => Collation::cp1251_ukrainian_ci,
|
||||
"utf8mb4_estonian_ci" => Collation::utf8mb4_estonian_ci,
|
||||
"utf8mb4_spanish_ci" => Collation::utf8mb4_spanish_ci,
|
||||
"utf8mb4_swedish_ci" => Collation::utf8mb4_swedish_ci,
|
||||
"utf8mb4_turkish_ci" => Collation::utf8mb4_turkish_ci,
|
||||
"utf8mb4_czech_ci" => Collation::utf8mb4_czech_ci,
|
||||
"utf8mb4_danish_ci" => Collation::utf8mb4_danish_ci,
|
||||
"utf8mb4_lithuanian_ci" => Collation::utf8mb4_lithuanian_ci,
|
||||
"utf8mb4_slovak_ci" => Collation::utf8mb4_slovak_ci,
|
||||
"utf8mb4_spanish2_ci" => Collation::utf8mb4_spanish2_ci,
|
||||
"utf8mb4_roman_ci" => Collation::utf8mb4_roman_ci,
|
||||
"gb2312_chinese_ci" => Collation::gb2312_chinese_ci,
|
||||
"utf8mb4_persian_ci" => Collation::utf8mb4_persian_ci,
|
||||
"utf8mb4_esperanto_ci" => Collation::utf8mb4_esperanto_ci,
|
||||
"utf8mb4_hungarian_ci" => Collation::utf8mb4_hungarian_ci,
|
||||
"utf8mb4_sinhala_ci" => Collation::utf8mb4_sinhala_ci,
|
||||
"utf8mb4_german2_ci" => Collation::utf8mb4_german2_ci,
|
||||
"utf8mb4_croatian_ci" => Collation::utf8mb4_croatian_ci,
|
||||
"utf8mb4_unicode_520_ci" => Collation::utf8mb4_unicode_520_ci,
|
||||
"utf8mb4_vietnamese_ci" => Collation::utf8mb4_vietnamese_ci,
|
||||
"gb18030_chinese_ci" => Collation::gb18030_chinese_ci,
|
||||
"gb18030_bin" => Collation::gb18030_bin,
|
||||
"greek_general_ci" => Collation::greek_general_ci,
|
||||
"gb18030_unicode_520_ci" => Collation::gb18030_unicode_520_ci,
|
||||
"utf8mb4_0900_ai_ci" => Collation::utf8mb4_0900_ai_ci,
|
||||
"cp1250_general_ci" => Collation::cp1250_general_ci,
|
||||
"latin2_croatian_ci" => Collation::latin2_croatian_ci,
|
||||
"gbk_chinese_ci" => Collation::gbk_chinese_ci,
|
||||
"cp1257_lithuanian_ci" => Collation::cp1257_lithuanian_ci,
|
||||
"dec8_swedish_ci" => Collation::dec8_swedish_ci,
|
||||
"latin5_turkish_ci" => Collation::latin5_turkish_ci,
|
||||
"latin1_german2_ci" => Collation::latin1_german2_ci,
|
||||
"armscii8_general_ci" => Collation::armscii8_general_ci,
|
||||
"utf8_general_ci" => Collation::utf8_general_ci,
|
||||
"cp1250_czech_cs" => Collation::cp1250_czech_cs,
|
||||
"ucs2_general_ci" => Collation::ucs2_general_ci,
|
||||
"cp866_general_ci" => Collation::cp866_general_ci,
|
||||
"keybcs2_general_ci" => Collation::keybcs2_general_ci,
|
||||
"macce_general_ci" => Collation::macce_general_ci,
|
||||
"macroman_general_ci" => Collation::macroman_general_ci,
|
||||
"cp850_general_ci" => Collation::cp850_general_ci,
|
||||
"cp852_general_ci" => Collation::cp852_general_ci,
|
||||
"latin7_general_ci" => Collation::latin7_general_ci,
|
||||
"latin7_general_cs" => Collation::latin7_general_cs,
|
||||
"macce_bin" => Collation::macce_bin,
|
||||
"cp1250_croatian_ci" => Collation::cp1250_croatian_ci,
|
||||
"utf8mb4_general_ci" => Collation::utf8mb4_general_ci,
|
||||
"utf8mb4_bin" => Collation::utf8mb4_bin,
|
||||
"latin1_bin" => Collation::latin1_bin,
|
||||
"latin1_general_ci" => Collation::latin1_general_ci,
|
||||
"latin1_general_cs" => Collation::latin1_general_cs,
|
||||
"latin1_german1_ci" => Collation::latin1_german1_ci,
|
||||
"cp1251_bin" => Collation::cp1251_bin,
|
||||
"cp1251_general_ci" => Collation::cp1251_general_ci,
|
||||
"cp1251_general_cs" => Collation::cp1251_general_cs,
|
||||
"macroman_bin" => Collation::macroman_bin,
|
||||
"utf16_general_ci" => Collation::utf16_general_ci,
|
||||
"utf16_bin" => Collation::utf16_bin,
|
||||
"utf16le_general_ci" => Collation::utf16le_general_ci,
|
||||
"cp1256_general_ci" => Collation::cp1256_general_ci,
|
||||
"cp1257_bin" => Collation::cp1257_bin,
|
||||
"cp1257_general_ci" => Collation::cp1257_general_ci,
|
||||
"hp8_english_ci" => Collation::hp8_english_ci,
|
||||
"utf32_general_ci" => Collation::utf32_general_ci,
|
||||
"utf32_bin" => Collation::utf32_bin,
|
||||
"utf16le_bin" => Collation::utf16le_bin,
|
||||
"binary" => Collation::binary,
|
||||
"armscii8_bin" => Collation::armscii8_bin,
|
||||
"ascii_bin" => Collation::ascii_bin,
|
||||
"cp1250_bin" => Collation::cp1250_bin,
|
||||
"cp1256_bin" => Collation::cp1256_bin,
|
||||
"cp866_bin" => Collation::cp866_bin,
|
||||
"dec8_bin" => Collation::dec8_bin,
|
||||
"koi8r_general_ci" => Collation::koi8r_general_ci,
|
||||
"greek_bin" => Collation::greek_bin,
|
||||
"hebrew_bin" => Collation::hebrew_bin,
|
||||
"hp8_bin" => Collation::hp8_bin,
|
||||
"keybcs2_bin" => Collation::keybcs2_bin,
|
||||
"koi8r_bin" => Collation::koi8r_bin,
|
||||
"koi8u_bin" => Collation::koi8u_bin,
|
||||
"utf8_tolower_ci" => Collation::utf8_tolower_ci,
|
||||
"latin2_bin" => Collation::latin2_bin,
|
||||
"latin5_bin" => Collation::latin5_bin,
|
||||
"latin7_bin" => Collation::latin7_bin,
|
||||
"latin1_swedish_ci" => Collation::latin1_swedish_ci,
|
||||
"cp850_bin" => Collation::cp850_bin,
|
||||
"cp852_bin" => Collation::cp852_bin,
|
||||
"swe7_bin" => Collation::swe7_bin,
|
||||
"utf8_bin" => Collation::utf8_bin,
|
||||
"big5_bin" => Collation::big5_bin,
|
||||
"euckr_bin" => Collation::euckr_bin,
|
||||
"gb2312_bin" => Collation::gb2312_bin,
|
||||
"gbk_bin" => Collation::gbk_bin,
|
||||
"sjis_bin" => Collation::sjis_bin,
|
||||
"tis620_bin" => Collation::tis620_bin,
|
||||
"latin2_general_ci" => Collation::latin2_general_ci,
|
||||
"ucs2_bin" => Collation::ucs2_bin,
|
||||
"ujis_bin" => Collation::ujis_bin,
|
||||
"geostd8_general_ci" => Collation::geostd8_general_ci,
|
||||
"geostd8_bin" => Collation::geostd8_bin,
|
||||
"latin1_spanish_ci" => Collation::latin1_spanish_ci,
|
||||
"cp932_japanese_ci" => Collation::cp932_japanese_ci,
|
||||
"cp932_bin" => Collation::cp932_bin,
|
||||
"eucjpms_japanese_ci" => Collation::eucjpms_japanese_ci,
|
||||
"eucjpms_bin" => Collation::eucjpms_bin,
|
||||
"cp1250_polish_ci" => Collation::cp1250_polish_ci,
|
||||
|
||||
_ => {
|
||||
return Err(Error::Configuration(
|
||||
format!("unsupported MySQL collation: {collation}").into(),
|
||||
));
|
||||
}
|
||||
})
|
||||
}
|
||||
/// Collation used for all non-string data.
|
||||
pub const BINARY: Self = Collation(63);
|
||||
|
||||
/// Most broadly supported UTF-8 collation.
|
||||
pub const UTF8MB4_GENERAL_CI: Self = Collation(45);
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
use bytes::buf::Buf;
|
||||
use bytes::Bytes;
|
||||
|
||||
use crate::collation::{CharSet, Collation};
|
||||
use crate::common::StatementCache;
|
||||
use crate::connection::{tls, MySqlConnectionInner, MySqlStream, MAX_PACKET_SIZE};
|
||||
use crate::error::Error;
|
||||
@ -37,20 +36,10 @@ impl MySqlConnection {
|
||||
|
||||
struct DoHandshake<'a> {
|
||||
options: &'a MySqlConnectOptions,
|
||||
charset: CharSet,
|
||||
collation: Collation,
|
||||
}
|
||||
|
||||
impl<'a> DoHandshake<'a> {
|
||||
fn new(options: &'a MySqlConnectOptions) -> Result<Self, Error> {
|
||||
let charset: CharSet = options.charset.parse()?;
|
||||
let collation: Collation = options
|
||||
.collation
|
||||
.as_deref()
|
||||
.map(|collation| collation.parse())
|
||||
.transpose()?
|
||||
.unwrap_or_else(|| charset.default_collation());
|
||||
|
||||
if options.enable_cleartext_plugin
|
||||
&& matches!(
|
||||
options.ssl_mode,
|
||||
@ -60,21 +49,13 @@ impl<'a> DoHandshake<'a> {
|
||||
log::warn!("Security warning: sending cleartext passwords without requiring SSL");
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
options,
|
||||
charset,
|
||||
collation,
|
||||
})
|
||||
Ok(Self { options })
|
||||
}
|
||||
|
||||
async fn do_handshake<S: Socket>(self, socket: S) -> Result<MySqlStream, Error> {
|
||||
let DoHandshake {
|
||||
options,
|
||||
charset,
|
||||
collation,
|
||||
} = self;
|
||||
let DoHandshake { options } = self;
|
||||
|
||||
let mut stream = MySqlStream::with_socket(charset, collation, options, socket);
|
||||
let mut stream = MySqlStream::with_socket(options, socket);
|
||||
|
||||
// https://dev.mysql.com/doc/internals/en/connection-phase.html
|
||||
// https://mariadb.com/kb/en/connection/
|
||||
@ -125,7 +106,7 @@ impl<'a> DoHandshake<'a> {
|
||||
};
|
||||
|
||||
stream.write_packet(HandshakeResponse {
|
||||
collation: stream.collation as u8,
|
||||
charset: super::INITIAL_CHARSET,
|
||||
max_packet_size: MAX_PACKET_SIZE,
|
||||
username: &options.username,
|
||||
database: options.database.as_deref(),
|
||||
|
||||
@ -5,6 +5,7 @@ pub(crate) use sqlx_core::connection::*;
|
||||
use sqlx_core::sql_str::SqlSafeStr;
|
||||
pub(crate) use stream::{MySqlStream, Waiting};
|
||||
|
||||
use crate::collation::Collation;
|
||||
use crate::common::StatementCache;
|
||||
use crate::error::Error;
|
||||
use crate::protocol::response::Status;
|
||||
@ -22,6 +23,13 @@ mod tls;
|
||||
|
||||
const MAX_PACKET_SIZE: u32 = 1024;
|
||||
|
||||
/// The charset parameter sent in the `Protocol::HandshakeResponse41` packet.
|
||||
///
|
||||
/// This becomes the default if `set_names = false`,
|
||||
/// and also ensures that any error messages returned before `SET NAMES` are encoded correctly.
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
const INITIAL_CHARSET: u8 = Collation::UTF8MB4_GENERAL_CI.0 as u8;
|
||||
|
||||
/// A connection to a MySQL database.
|
||||
pub struct MySqlConnection {
|
||||
pub(crate) inner: Box<MySqlConnectionInner>,
|
||||
|
||||
@ -3,7 +3,6 @@ use std::ops::{Deref, DerefMut};
|
||||
|
||||
use bytes::{Buf, Bytes, BytesMut};
|
||||
|
||||
use crate::collation::{CharSet, Collation};
|
||||
use crate::error::Error;
|
||||
use crate::io::MySqlBufExt;
|
||||
use crate::io::{ProtocolDecode, ProtocolEncode};
|
||||
@ -19,8 +18,6 @@ pub struct MySqlStream<S = Box<dyn Socket>> {
|
||||
pub(super) capabilities: Capabilities,
|
||||
pub(crate) sequence_id: u8,
|
||||
pub(crate) waiting: VecDeque<Waiting>,
|
||||
pub(crate) charset: CharSet,
|
||||
pub(crate) collation: Collation,
|
||||
pub(crate) is_tls: bool,
|
||||
}
|
||||
|
||||
@ -34,12 +31,7 @@ pub(crate) enum Waiting {
|
||||
}
|
||||
|
||||
impl<S: Socket> MySqlStream<S> {
|
||||
pub(crate) fn with_socket(
|
||||
charset: CharSet,
|
||||
collation: Collation,
|
||||
options: &MySqlConnectOptions,
|
||||
socket: S,
|
||||
) -> Self {
|
||||
pub(crate) fn with_socket(options: &MySqlConnectOptions, socket: S) -> Self {
|
||||
let mut capabilities = Capabilities::PROTOCOL_41
|
||||
| Capabilities::IGNORE_SPACE
|
||||
| Capabilities::DEPRECATE_EOF
|
||||
@ -62,8 +54,6 @@ impl<S: Socket> MySqlStream<S> {
|
||||
capabilities,
|
||||
server_version: (0, 0, 0),
|
||||
sequence_id: 0,
|
||||
collation,
|
||||
charset,
|
||||
socket: BufferedSocket::new(socket),
|
||||
is_tls: false,
|
||||
}
|
||||
@ -222,8 +212,6 @@ impl<S: Socket> MySqlStream<S> {
|
||||
capabilities: self.capabilities,
|
||||
sequence_id: self.sequence_id,
|
||||
waiting: self.waiting,
|
||||
charset: self.charset,
|
||||
collation: self.collation,
|
||||
is_tls: self.is_tls,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use crate::collation::{CharSet, Collation};
|
||||
use crate::connection::{MySqlStream, Waiting};
|
||||
use crate::error::Error;
|
||||
use crate::net::tls::TlsConfig;
|
||||
@ -13,8 +12,6 @@ struct MapStream {
|
||||
capabilities: Capabilities,
|
||||
sequence_id: u8,
|
||||
waiting: VecDeque<Waiting>,
|
||||
charset: CharSet,
|
||||
collation: Collation,
|
||||
}
|
||||
|
||||
pub(super) async fn maybe_upgrade<S: Socket>(
|
||||
@ -71,7 +68,7 @@ pub(super) async fn maybe_upgrade<S: Socket>(
|
||||
// Request TLS upgrade
|
||||
stream.write_packet(SslRequest {
|
||||
max_packet_size: super::MAX_PACKET_SIZE,
|
||||
collation: stream.collation as u8,
|
||||
charset: super::INITIAL_CHARSET,
|
||||
})?;
|
||||
|
||||
stream.flush().await?;
|
||||
@ -84,8 +81,6 @@ pub(super) async fn maybe_upgrade<S: Socket>(
|
||||
capabilities: stream.capabilities,
|
||||
sequence_id: stream.sequence_id,
|
||||
waiting: stream.waiting,
|
||||
charset: stream.charset,
|
||||
collation: stream.collation,
|
||||
},
|
||||
)
|
||||
.await
|
||||
@ -101,8 +96,6 @@ impl WithSocket for MapStream {
|
||||
capabilities: self.capabilities,
|
||||
sequence_id: self.sequence_id,
|
||||
waiting: self.waiting,
|
||||
charset: self.charset,
|
||||
collation: self.collation,
|
||||
is_tls: true,
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,15 +64,23 @@ impl ConnectOptions for MySqlConnectOptions {
|
||||
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.inner.stream.charset.as_str(),
|
||||
conn.inner.stream.collation.as_str()
|
||||
))
|
||||
// As it turns out, we don't _have_ to set a collation if we don't want to.
|
||||
// We can let the server choose the default collation for the charset.
|
||||
let set_names = if let Some(collation) = &self.collation {
|
||||
format!(r#"NAMES {} COLLATE {collation}"#, self.charset,)
|
||||
} else {
|
||||
// Leaves the default collation up to the server,
|
||||
// but ensures statements and results are encoded using the proper charset.
|
||||
format!("NAMES {}", self.charset)
|
||||
};
|
||||
|
||||
options.push(set_names);
|
||||
}
|
||||
|
||||
if !options.is_empty() {
|
||||
|
||||
@ -301,16 +301,24 @@ impl MySqlConnectOptions {
|
||||
///
|
||||
/// The default character set is `utf8mb4`. This is supported from MySQL 5.5.3.
|
||||
/// If you need to connect to an older version, we recommend you to change this to `utf8`.
|
||||
///
|
||||
/// Implies [`.set_names(true)`][Self::set_names()].
|
||||
pub fn charset(mut self, charset: &str) -> Self {
|
||||
self.set_names = true;
|
||||
charset.clone_into(&mut self.charset);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the collation for the connection.
|
||||
///
|
||||
/// The default collation is derived from the `charset`. Normally, you should only have to set
|
||||
/// the `charset`.
|
||||
/// The default collation is derived on the server from the `charset`, if set.
|
||||
/// Normally, you should only have to set the `charset`.
|
||||
///
|
||||
/// If setting this, it is recommended to also set [`charset`][Self::charset()].
|
||||
///
|
||||
/// Implies [`.set_names(true)`][Self::set_names()].
|
||||
pub fn collation(mut self, collation: &str) -> Self {
|
||||
self.set_names = true;
|
||||
self.collation = Some(collation.to_owned());
|
||||
self
|
||||
}
|
||||
@ -381,8 +389,9 @@ impl MySqlConnectOptions {
|
||||
self
|
||||
}
|
||||
|
||||
/// If enabled, `SET NAMES '{charset}' COLLATE '{collation}'` is passed with the values of
|
||||
/// [`.charset()`] and [`.collation()`] after connecting to the database.
|
||||
/// If enabled, [`.charset()`] and [`.collation()`] are set with the appropriate command.
|
||||
///
|
||||
/// If only `.charset()`
|
||||
///
|
||||
/// This ensures the connection uses the specified character set and collation.
|
||||
///
|
||||
@ -399,6 +408,8 @@ impl MySqlConnectOptions {
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// [`.charset`]: Self::charset()
|
||||
pub fn set_names(mut self, flag_val: bool) -> Self {
|
||||
self.set_names = flag_val;
|
||||
self
|
||||
|
||||
@ -14,8 +14,8 @@ pub struct HandshakeResponse<'a> {
|
||||
/// Max size of a command packet that the client wants to send to the server
|
||||
pub max_packet_size: u32,
|
||||
|
||||
/// Default collation for the connection
|
||||
pub collation: u8,
|
||||
/// Default charset (collation ID < 256) for the connection
|
||||
pub charset: u8,
|
||||
|
||||
/// Name of the SQL account which client wants to log in
|
||||
pub username: &'a str,
|
||||
@ -41,7 +41,7 @@ impl ProtocolEncode<'_, Capabilities> for HandshakeResponse<'_> {
|
||||
// NOTE: Half of this packet is identical to the SSL Request packet
|
||||
SslRequest {
|
||||
max_packet_size: self.max_packet_size,
|
||||
collation: self.collation,
|
||||
charset: self.charset,
|
||||
}
|
||||
.encode_with(buf, context)?;
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ use crate::protocol::Capabilities;
|
||||
#[derive(Debug)]
|
||||
pub struct SslRequest {
|
||||
pub max_packet_size: u32,
|
||||
pub collation: u8,
|
||||
pub charset: u8,
|
||||
}
|
||||
|
||||
impl ProtocolEncode<'_, Capabilities> for SslRequest {
|
||||
@ -16,7 +16,7 @@ impl ProtocolEncode<'_, Capabilities> for SslRequest {
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
buf.extend(&(context.bits() as u32).to_le_bytes());
|
||||
buf.extend(&self.max_packet_size.to_le_bytes());
|
||||
buf.push(self.collation);
|
||||
buf.push(self.charset);
|
||||
|
||||
// reserved: string<19>
|
||||
buf.extend(&[0_u8; 19]);
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
use std::str;
|
||||
|
||||
use bitflags::bitflags;
|
||||
use bytes::{Buf, Bytes};
|
||||
|
||||
use crate::collation::Collation;
|
||||
use crate::error::Error;
|
||||
use crate::io::MySqlBufExt;
|
||||
use crate::io::ProtocolDecode;
|
||||
use crate::protocol::Capabilities;
|
||||
use bitflags::bitflags;
|
||||
use bytes::{Buf, Bytes};
|
||||
|
||||
// https://dev.mysql.com/doc/dev/mysql-server/8.0.12/group__group__cs__column__definition__flags.html
|
||||
|
||||
@ -110,8 +110,7 @@ pub(crate) struct ColumnDefinition {
|
||||
table: Bytes,
|
||||
alias: Bytes,
|
||||
name: Bytes,
|
||||
#[allow(unused)]
|
||||
pub(crate) collation: u16,
|
||||
pub(crate) collation: Collation,
|
||||
pub(crate) max_size: u32,
|
||||
pub(crate) r#type: ColumnType,
|
||||
pub(crate) flags: ColumnFlags,
|
||||
@ -162,7 +161,7 @@ impl ProtocolDecode<'_, Capabilities> for ColumnDefinition {
|
||||
table,
|
||||
alias,
|
||||
name,
|
||||
collation,
|
||||
collation: Collation(collation),
|
||||
max_size,
|
||||
r#type: ColumnType::try_from_u16(type_id)?,
|
||||
flags: ColumnFlags::from_bits_truncate(flags),
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
|
||||
pub(crate) use sqlx_core::type_info::*;
|
||||
|
||||
use crate::collation::Collation;
|
||||
use crate::protocol::text::{ColumnDefinition, ColumnFlags, ColumnType};
|
||||
pub(crate) use sqlx_core::type_info::*;
|
||||
|
||||
/// Type information for a MySql type.
|
||||
#[derive(Debug, Clone)]
|
||||
@ -10,6 +10,7 @@ use crate::protocol::text::{ColumnDefinition, ColumnFlags, ColumnType};
|
||||
pub struct MySqlTypeInfo {
|
||||
pub(crate) r#type: ColumnType,
|
||||
pub(crate) flags: ColumnFlags,
|
||||
pub(crate) collation: Collation,
|
||||
|
||||
// [max_size] for integer types, this is (M) in BIT(M) or TINYINT(M)
|
||||
#[cfg_attr(feature = "offline", serde(default))]
|
||||
@ -21,6 +22,7 @@ impl MySqlTypeInfo {
|
||||
Self {
|
||||
r#type: ty,
|
||||
flags: ColumnFlags::BINARY,
|
||||
collation: Collation::BINARY,
|
||||
max_size: None,
|
||||
}
|
||||
}
|
||||
@ -38,6 +40,7 @@ impl MySqlTypeInfo {
|
||||
Self {
|
||||
r#type: ColumnType::String,
|
||||
flags: ColumnFlags::ENUM,
|
||||
collation: Collation::UTF8MB4_GENERAL_CI,
|
||||
max_size: None,
|
||||
}
|
||||
}
|
||||
@ -60,6 +63,7 @@ impl MySqlTypeInfo {
|
||||
Self {
|
||||
r#type: column.r#type,
|
||||
flags: column.flags,
|
||||
collation: column.collation,
|
||||
max_size: Some(column.max_size),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use crate::collation::Collation;
|
||||
use crate::decode::Decode;
|
||||
use crate::encode::{Encode, IsNull};
|
||||
use crate::error::BoxDynError;
|
||||
@ -9,9 +10,10 @@ use crate::{
|
||||
|
||||
impl Type<MySql> for bool {
|
||||
fn type_info() -> MySqlTypeInfo {
|
||||
// MySQL has no actual `BOOLEAN` type, the type is an alias of `TINYINT(1)`
|
||||
// MySQL has no actual `BOOLEAN` type, the type is an alias of `[UNSIGNED] TINYINT(1)`
|
||||
MySqlTypeInfo {
|
||||
flags: ColumnFlags::BINARY | ColumnFlags::UNSIGNED,
|
||||
collation: Collation::BINARY,
|
||||
max_size: Some(1),
|
||||
r#type: ColumnType::Tiny,
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ use std::borrow::Cow;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::collation::Collation;
|
||||
use crate::decode::Decode;
|
||||
use crate::encode::{Encode, IsNull};
|
||||
use crate::error::BoxDynError;
|
||||
@ -15,6 +16,8 @@ impl Type<MySql> for str {
|
||||
MySqlTypeInfo {
|
||||
r#type: ColumnType::VarString, // VARCHAR
|
||||
flags: ColumnFlags::empty(),
|
||||
// Doesn't matter because we never send this.
|
||||
collation: Collation::UTF8MB4_GENERAL_CI,
|
||||
max_size: None,
|
||||
}
|
||||
}
|
||||
@ -31,7 +34,13 @@ impl Type<MySql> for str {
|
||||
| ColumnType::String
|
||||
| ColumnType::VarString
|
||||
| ColumnType::Enum
|
||||
) && !ty.flags.contains(ColumnFlags::BINARY)
|
||||
)
|
||||
// Any collation that *isn't* `binary` generally indicates string data.
|
||||
// The actual collation used for storage doesn't matter,
|
||||
// because the server will transcode to the charset we specify.
|
||||
//
|
||||
// See comment in `src/collation.rs` for details.
|
||||
&& ty.collation != Collation::BINARY
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use crate::collation::Collation;
|
||||
use crate::decode::Decode;
|
||||
use crate::encode::{Encode, IsNull};
|
||||
use crate::error::BoxDynError;
|
||||
@ -10,6 +11,7 @@ fn uint_type_info(ty: ColumnType) -> MySqlTypeInfo {
|
||||
MySqlTypeInfo {
|
||||
r#type: ty,
|
||||
flags: ColumnFlags::BINARY | ColumnFlags::UNSIGNED,
|
||||
collation: Collation::BINARY,
|
||||
max_size: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,15 +58,43 @@ services:
|
||||
MYSQL_DATABASE: sqlx
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: 1
|
||||
|
||||
#
|
||||
# MariaDB 10.11, 10.6, 10.5, 10.4
|
||||
# MariaDB
|
||||
# Testing will be dropped when Community Support ends.
|
||||
# https://mariadb.org/about/#maintenance-policy
|
||||
#
|
||||
|
||||
# EOL: 2028/06/04 (sooner than 11.4 for some reason)
|
||||
mariadb_11_8:
|
||||
image: mariadb:11.8
|
||||
volumes:
|
||||
- "./mysql/setup.sql:/docker-entrypoint-initdb.d/setup.sql:z"
|
||||
- "./mysql/setup-mariadb.sql:/docker-entrypoint-initdb.d/setup-mariadb.sql:z"
|
||||
ports:
|
||||
- 3306
|
||||
environment:
|
||||
MARIADB_ROOT_PASSWORD: password
|
||||
MARIADB_DATABASE: sqlx
|
||||
|
||||
mariadb_11_8_client_ssl:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: mysql/Dockerfile
|
||||
args:
|
||||
IMAGE: mariadb:11.8
|
||||
volumes:
|
||||
- "./mysql/setup.sql:/docker-entrypoint-initdb.d/setup.sql:z"
|
||||
- "./mysql/setup-mariadb.sql:/docker-entrypoint-initdb.d/setup-mariadb.sql:z"
|
||||
ports:
|
||||
- 3306
|
||||
environment:
|
||||
MARIADB_DATABASE: sqlx
|
||||
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: 1
|
||||
|
||||
# EOL: 2029/05/29
|
||||
mariadb_11_4:
|
||||
image: mariadb:11.4
|
||||
volumes:
|
||||
- "./mysql/setup.sql:/docker-entrypoint-initdb.d/setup.sql:z"
|
||||
- "./mysql/setup-mariadb.sql:/docker-entrypoint-initdb.d/setup-mariadb.sql:z"
|
||||
ports:
|
||||
- 3306
|
||||
environment:
|
||||
@ -81,16 +109,19 @@ services:
|
||||
IMAGE: mariadb:11.4
|
||||
volumes:
|
||||
- "./mysql/setup.sql:/docker-entrypoint-initdb.d/setup.sql:z"
|
||||
- "./mysql/setup-mariadb.sql:/docker-entrypoint-initdb.d/setup-mariadb.sql:z"
|
||||
ports:
|
||||
- 3306
|
||||
environment:
|
||||
MARIADB_DATABASE: sqlx
|
||||
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: 1
|
||||
|
||||
# EOL: 2028/02/16
|
||||
mariadb_10_11:
|
||||
image: mariadb:10.11
|
||||
volumes:
|
||||
- "./mysql/setup.sql:/docker-entrypoint-initdb.d/setup.sql:z"
|
||||
- "./mysql/setup-mariadb.sql:/docker-entrypoint-initdb.d/setup-mariadb.sql:z"
|
||||
ports:
|
||||
- 3306
|
||||
environment:
|
||||
@ -105,16 +136,20 @@ services:
|
||||
IMAGE: mariadb:10.11
|
||||
volumes:
|
||||
- "./mysql/setup.sql:/docker-entrypoint-initdb.d/setup.sql:z"
|
||||
- "./mysql/setup-mariadb.sql:/docker-entrypoint-initdb.d/setup-mariadb.sql:z"
|
||||
ports:
|
||||
- 3306
|
||||
environment:
|
||||
MARIADB_DATABASE: sqlx
|
||||
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: 1
|
||||
|
||||
# EOL: 2026/07/06
|
||||
mariadb_10_6:
|
||||
image: mariadb:10.6
|
||||
volumes:
|
||||
- "./mysql/setup.sql:/docker-entrypoint-initdb.d/setup.sql:z"
|
||||
# UUID support was not added until 10.10
|
||||
# - "./mysql/setup-mariadb.sql:/docker-entrypoint-initdb.d/setup-mariadb.sql:z"
|
||||
ports:
|
||||
- 3306
|
||||
environment:
|
||||
@ -129,54 +164,8 @@ services:
|
||||
IMAGE: mariadb:10.6
|
||||
volumes:
|
||||
- "./mysql/setup.sql:/docker-entrypoint-initdb.d/setup.sql:z"
|
||||
ports:
|
||||
- 3306
|
||||
environment:
|
||||
MARIADB_DATABASE: sqlx
|
||||
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: 1
|
||||
|
||||
mariadb_10_5:
|
||||
image: mariadb:10.5
|
||||
volumes:
|
||||
- "./mysql/setup.sql:/docker-entrypoint-initdb.d/setup.sql:z"
|
||||
ports:
|
||||
- 3306
|
||||
environment:
|
||||
MARIADB_ROOT_PASSWORD: password
|
||||
MARIADB_DATABASE: sqlx
|
||||
|
||||
mariadb_10_5_client_ssl:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: mysql/Dockerfile
|
||||
args:
|
||||
IMAGE: mariadb:10.5
|
||||
volumes:
|
||||
- "./mysql/setup.sql:/docker-entrypoint-initdb.d/setup.sql:z"
|
||||
ports:
|
||||
- 3306
|
||||
environment:
|
||||
MARIADB_DATABASE: sqlx
|
||||
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: 1
|
||||
|
||||
mariadb_10_4:
|
||||
image: mariadb:10.4
|
||||
volumes:
|
||||
- "./mysql/setup.sql:/docker-entrypoint-initdb.d/setup.sql:z"
|
||||
ports:
|
||||
- 3306
|
||||
environment:
|
||||
MARIADB_ROOT_PASSWORD: password
|
||||
MARIADB_DATABASE: sqlx
|
||||
|
||||
mariadb_10_4_client_ssl:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: mysql/Dockerfile
|
||||
args:
|
||||
IMAGE: mariadb:10.4
|
||||
volumes:
|
||||
- "./mysql/setup.sql:/docker-entrypoint-initdb.d/setup.sql:z"
|
||||
# UUID support was not added until 10.10
|
||||
# - "./mysql/setup-mariadb.sql:/docker-entrypoint-initdb.d/setup-mariadb.sql:z"
|
||||
ports:
|
||||
- 3306
|
||||
environment:
|
||||
@ -189,6 +178,7 @@ services:
|
||||
image: quay.io/mariadb-foundation/mariadb-devel:verylatest
|
||||
volumes:
|
||||
- "./mysql/setup.sql:/docker-entrypoint-initdb.d/setup.sql:z"
|
||||
- "./mysql/setup-mariadb.sql:/docker-entrypoint-initdb.d/setup-mariadb.sql:z"
|
||||
ports:
|
||||
- 3306
|
||||
environment:
|
||||
@ -203,6 +193,7 @@ services:
|
||||
IMAGE: quay.io/mariadb-foundation/mariadb-devel:verylatest
|
||||
volumes:
|
||||
- "./mysql/setup.sql:/docker-entrypoint-initdb.d/setup.sql:z"
|
||||
- "./mysql/setup-mariadb.sql:/docker-entrypoint-initdb.d/setup-mariadb.sql:z"
|
||||
ports:
|
||||
- 3306
|
||||
environment:
|
||||
|
||||
@ -555,4 +555,34 @@ async fn test_from_row_json_try_from_attr() -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(all(mariadb, not(mariadb = "10_6"), feature = "time"))]
|
||||
#[sqlx_macros::test]
|
||||
async fn test_uuid_is_compatible_mariadb() -> anyhow::Result<()> {
|
||||
use sqlx::types::time::OffsetDateTime;
|
||||
use sqlx::types::Uuid;
|
||||
|
||||
struct Tweet {
|
||||
id: Uuid,
|
||||
text: String,
|
||||
created_at: OffsetDateTime,
|
||||
owner_id: Option<Uuid>,
|
||||
}
|
||||
|
||||
let mut conn = new::<MySql>().await?;
|
||||
|
||||
sqlx::query!("INSERT INTO tweet_with_uuid(text) VALUES ('Hello, world!')")
|
||||
.execute(&mut conn)
|
||||
.await?;
|
||||
|
||||
let tweets: Vec<Tweet> = sqlx::query_as!(Tweet, "SELECT * FROM tweet_with_uuid")
|
||||
.fetch_all(&mut conn)
|
||||
.await?;
|
||||
|
||||
assert_eq!(tweets.len(), 1);
|
||||
|
||||
assert_eq!(tweets[0].text, "Hello, world!");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// we don't emit bind parameter type-checks for MySQL so testing the overrides is redundant
|
||||
|
||||
@ -605,3 +605,34 @@ async fn select_statement_count(conn: &mut MySqlConnection) -> Result<i64, sqlx:
|
||||
.fetch_one(conn)
|
||||
.await
|
||||
}
|
||||
|
||||
#[sqlx_macros::test]
|
||||
async fn issue_3200() -> anyhow::Result<()> {
|
||||
let mut conn = new::<MySql>().await?;
|
||||
|
||||
sqlx::raw_sql(
|
||||
"\
|
||||
CREATE TABLE IF NOT EXISTS users
|
||||
(
|
||||
`id` BIGINT AUTO_INCREMENT,
|
||||
`username` VARCHAR(128) NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
",
|
||||
)
|
||||
.execute(&mut conn)
|
||||
.await?;
|
||||
|
||||
let result = sqlx::raw_sql(
|
||||
"\
|
||||
SET @myvar := 'test@test.com';
|
||||
select id from users where username = @myvar;
|
||||
",
|
||||
)
|
||||
.fetch_optional(&mut conn)
|
||||
.await?;
|
||||
|
||||
assert!(result.is_none(), "{result:?}");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
10
tests/mysql/setup-mariadb.sql
Normal file
10
tests/mysql/setup-mariadb.sql
Normal file
@ -0,0 +1,10 @@
|
||||
-- additional SQL to execute for MariaDB databases
|
||||
|
||||
CREATE TABLE tweet_with_uuid
|
||||
(
|
||||
-- UUID is only a bespoke datatype in MariaDB.
|
||||
id UUID PRIMARY KEY DEFAULT UUID(),
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
text TEXT NOT NULL,
|
||||
owner_id UUID
|
||||
);
|
||||
Loading…
x
Reference in New Issue
Block a user