diff --git a/sqlx-core/src/mysql/collation.rs b/sqlx-core/src/mysql/collation.rs new file mode 100644 index 00000000..7b35f430 --- /dev/null +++ b/sqlx-core/src/mysql/collation.rs @@ -0,0 +1,896 @@ +use crate::error::Error; +use std::str::FromStr; + +#[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 { + 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, +} + +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 { + 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())); + } + }) + } +} diff --git a/sqlx-core/src/mysql/connection/establish.rs b/sqlx-core/src/mysql/connection/establish.rs index 0127f2bd..c84d6db3 100644 --- a/sqlx-core/src/mysql/connection/establish.rs +++ b/sqlx-core/src/mysql/connection/establish.rs @@ -3,7 +3,7 @@ use bytes::Bytes; use crate::common::StatementCache; use crate::error::Error; use crate::mysql::connection::{ - tls, MySqlStream, COLLATE_UTF8MB4_UNICODE_CI, COLLATE_UTF8_UNICODE_CI, MAX_PACKET_SIZE, + tls, MySqlStream, MAX_PACKET_SIZE, }; use crate::mysql::protocol::connect::{ AuthSwitchRequest, AuthSwitchResponse, Handshake, HandshakeResponse, @@ -70,14 +70,8 @@ impl MySqlConnection { None }; - let char_set = if stream.server_version >= (5, 5, 3) { - COLLATE_UTF8MB4_UNICODE_CI - } else { - COLLATE_UTF8_UNICODE_CI - }; - stream.write_packet(HandshakeResponse { - char_set, + collation: stream.collation as u8, max_packet_size: MAX_PACKET_SIZE, username: &options.username, database: options.database.as_deref(), diff --git a/sqlx-core/src/mysql/connection/mod.rs b/sqlx-core/src/mysql/connection/mod.rs index d4314361..3e371ff1 100644 --- a/sqlx-core/src/mysql/connection/mod.rs +++ b/sqlx-core/src/mysql/connection/mod.rs @@ -12,6 +12,7 @@ use crate::ext::ustr::UStr; use crate::mysql::protocol::statement::StmtClose; use crate::mysql::protocol::text::{Ping, Quit}; use crate::mysql::{MySql, MySqlColumn, MySqlConnectOptions}; +use crate::transaction::Transaction; mod auth; mod establish; @@ -19,12 +20,8 @@ mod executor; mod stream; mod tls; -use crate::transaction::Transaction; pub(crate) use stream::{Busy, MySqlStream}; -pub(crate) const COLLATE_UTF8_UNICODE_CI: u8 = 192; -pub(crate) const COLLATE_UTF8MB4_UNICODE_CI: u8 = 224; - const MAX_PACKET_SIZE: u32 = 1024; /// A connection to a MySQL database. diff --git a/sqlx-core/src/mysql/connection/stream.rs b/sqlx-core/src/mysql/connection/stream.rs index 59bfbee1..1ea50182 100644 --- a/sqlx-core/src/mysql/connection/stream.rs +++ b/sqlx-core/src/mysql/connection/stream.rs @@ -7,6 +7,7 @@ use crate::io::{BufStream, Decode, Encode}; use crate::mysql::io::MySqlBufExt; use crate::mysql::protocol::response::{EofPacket, ErrPacket, OkPacket, Status}; use crate::mysql::protocol::{Capabilities, Packet}; +use crate::mysql::collation::{CharSet, Collation}; use crate::mysql::{MySqlConnectOptions, MySqlDatabaseError}; use crate::net::{MaybeTlsStream, Socket}; @@ -16,6 +17,8 @@ pub struct MySqlStream { pub(super) capabilities: Capabilities, pub(crate) sequence_id: u8, pub(crate) busy: Busy, + pub(crate) charset: CharSet, + pub(crate) collation: Collation, } #[derive(Debug, PartialEq, Eq)] @@ -31,6 +34,9 @@ pub(crate) enum Busy { impl MySqlStream { pub(super) async fn connect(options: &MySqlConnectOptions) -> Result { + let charset: CharSet = options.charset.parse()?; + let collation: Collation = options.collation.as_deref().map(|collation| collation.parse()).transpose()?.unwrap_or_else(|| charset.default_collation()); + let socket = match options.socket { Some(ref path) => Socket::connect_uds(path).await?, None => Socket::connect_tcp(&options.host, options.port).await?, @@ -58,6 +64,8 @@ impl MySqlStream { capabilities, server_version: (0, 0, 0), sequence_id: 0, + collation, + charset, stream: BufStream::new(MaybeTlsStream::Raw(socket)), }) } diff --git a/sqlx-core/src/mysql/connection/tls.rs b/sqlx-core/src/mysql/connection/tls.rs index 25694432..4627779a 100644 --- a/sqlx-core/src/mysql/connection/tls.rs +++ b/sqlx-core/src/mysql/connection/tls.rs @@ -41,7 +41,7 @@ async fn upgrade(stream: &mut MySqlStream, options: &MySqlConnectOptions) -> Res stream.write_packet(SslRequest { max_packet_size: super::MAX_PACKET_SIZE, - char_set: super::COLLATE_UTF8MB4_UNICODE_CI, + collation: stream.collation as u8, }); stream.flush().await?; diff --git a/sqlx-core/src/mysql/mod.rs b/sqlx-core/src/mysql/mod.rs index fb2f0dde..cbb407b6 100644 --- a/sqlx-core/src/mysql/mod.rs +++ b/sqlx-core/src/mysql/mod.rs @@ -9,6 +9,7 @@ mod error; mod io; mod options; mod protocol; +mod collation; mod row; mod transaction; mod type_info; diff --git a/sqlx-core/src/mysql/options/connect.rs b/sqlx-core/src/mysql/options/connect.rs index 05111b27..5799a7f8 100644 --- a/sqlx-core/src/mysql/options/connect.rs +++ b/sqlx-core/src/mysql/options/connect.rs @@ -42,14 +42,7 @@ impl ConnectOptions for MySqlConnectOptions { let mut options = String::new(); options.push_str(r#"SET sql_mode=(SELECT CONCAT(@@sql_mode, ',PIPES_AS_CONCAT,NO_ENGINE_SUBSTITUTION')),"#); options.push_str(r#"time_zone='+00:00',"#); - - let char_set = if conn.stream.server_version >= (5, 5, 3) { - "utf8mb4" - } else { - "utf8" - }; - - options.push_str(&format!(r#"NAMES {0} COLLATE {0}_unicode_ci;"#, char_set)); + options.push_str(&format!(r#"NAMES {} COLLATE {};"#, conn.stream.charset.as_str(), conn.stream.collation.as_str())); conn.execute(&*options).await?; diff --git a/sqlx-core/src/mysql/options/mod.rs b/sqlx-core/src/mysql/options/mod.rs index 3c940a36..eb55e658 100644 --- a/sqlx-core/src/mysql/options/mod.rs +++ b/sqlx-core/src/mysql/options/mod.rs @@ -63,6 +63,8 @@ pub struct MySqlConnectOptions { pub(crate) ssl_mode: MySqlSslMode, pub(crate) ssl_ca: Option, pub(crate) statement_cache_capacity: usize, + pub(crate) charset: String, + pub(crate) collation: Option, } impl Default for MySqlConnectOptions { @@ -81,6 +83,8 @@ impl MySqlConnectOptions { username: String::from("root"), password: None, database: None, + charset: String::from("utf8mb4"), + collation: None, ssl_mode: MySqlSslMode::Preferred, ssl_ca: None, statement_cache_capacity: 100, @@ -174,4 +178,22 @@ impl MySqlConnectOptions { self.statement_cache_capacity = capacity; self } + + /// Sets the character set for the connection. + /// + /// 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`. + pub fn charset(mut self, charset: &str) -> Self { + self.charset = charset.to_owned(); + self + } + + /// Sets the collation for the connection. + /// + /// The default collation is derived from the `charset`. Normally, you should only have to set + /// the `charset`. + pub fn collation(mut self, collation: &str) -> Self { + self.collation = Some(collation.to_owned()); + self + } } diff --git a/sqlx-core/src/mysql/options/parse.rs b/sqlx-core/src/mysql/options/parse.rs index 2c311e0a..c7ecb3ab 100644 --- a/sqlx-core/src/mysql/options/parse.rs +++ b/sqlx-core/src/mysql/options/parse.rs @@ -42,6 +42,14 @@ impl FromStr for MySqlConnectOptions { options = options.ssl_ca(&*value); } + "charset" => { + options = options.charset(&*value); + } + + "collation" => { + options = options.collation(&*value); + } + "statement-cache-capacity" => { options = options.statement_cache_capacity(value.parse().map_err(Error::config)?); diff --git a/sqlx-core/src/mysql/protocol/connect/handshake_response.rs b/sqlx-core/src/mysql/protocol/connect/handshake_response.rs index 3503ec44..22933006 100644 --- a/sqlx-core/src/mysql/protocol/connect/handshake_response.rs +++ b/sqlx-core/src/mysql/protocol/connect/handshake_response.rs @@ -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 character set for the connection - pub char_set: u8, + /// Default collation for the connection + pub collation: u8, /// Name of the SQL account which client wants to log in pub username: &'a str, @@ -37,7 +37,7 @@ impl Encode<'_, Capabilities> for HandshakeResponse<'_> { // NOTE: Half of this packet is identical to the SSL Request packet SslRequest { max_packet_size: self.max_packet_size, - char_set: self.char_set, + collation: self.collation, } .encode_with(buf, capabilities); diff --git a/sqlx-core/src/mysql/protocol/connect/ssl_request.rs b/sqlx-core/src/mysql/protocol/connect/ssl_request.rs index 8b927be5..5f0c2d89 100644 --- a/sqlx-core/src/mysql/protocol/connect/ssl_request.rs +++ b/sqlx-core/src/mysql/protocol/connect/ssl_request.rs @@ -7,14 +7,14 @@ use crate::mysql::protocol::Capabilities; #[derive(Debug)] pub struct SslRequest { pub max_packet_size: u32, - pub char_set: u8, + pub collation: u8, } impl Encode<'_, Capabilities> for SslRequest { fn encode_with(&self, buf: &mut Vec, capabilities: Capabilities) { buf.extend(&(capabilities.bits() as u32).to_le_bytes()); buf.extend(&self.max_packet_size.to_le_bytes()); - buf.push(self.char_set); + buf.push(self.collation); // reserved: string<19> buf.extend(&[0_u8; 19]); diff --git a/sqlx-core/src/mysql/types/str.rs b/sqlx-core/src/mysql/types/str.rs index 2e6a8764..5f76a9b1 100644 --- a/sqlx-core/src/mysql/types/str.rs +++ b/sqlx-core/src/mysql/types/str.rs @@ -1,22 +1,25 @@ use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; -use crate::mysql::connection::{COLLATE_UTF8MB4_UNICODE_CI, COLLATE_UTF8_UNICODE_CI}; use crate::mysql::io::MySqlBufMutExt; use crate::mysql::protocol::text::{ColumnFlags, ColumnType}; use crate::mysql::{MySql, MySqlTypeInfo, MySqlValueRef}; use crate::types::Type; +const COLLATE_UTF8_UNICODE_CI: u16 = 192; +const COLLATE_UTF8MB4_UNICODE_CI: u16 = 224; + impl Type for str { fn type_info() -> MySqlTypeInfo { MySqlTypeInfo { - r#type: ColumnType::VarString, // VARCHAR - char_set: 224, // utf8mb4_unicode_ci + r#type: ColumnType::VarString, // VARCHAR + char_set: COLLATE_UTF8MB4_UNICODE_CI, // utf8mb4_unicode_ci flags: ColumnFlags::empty(), } } fn compatible(ty: &MySqlTypeInfo) -> bool { + // TODO: Support more collations being returned from SQL? matches!( ty.r#type, ColumnType::VarChar diff --git a/tests/docker.py b/tests/docker.py index 3881fc10..b4cdadd6 100644 --- a/tests/docker.py +++ b/tests/docker.py @@ -29,7 +29,7 @@ def start_database(driver, database, cwd): time.sleep(30) # determine appropriate port for driver - if driver.startswith("mysql"): + if driver.startswith("mysql") or driver.startswith("mariadb"): port = 3306 elif driver.startswith("postgres"): @@ -56,7 +56,7 @@ def start_database(driver, database, cwd): port = int(res.stdout[1:-2].decode()) # construct appropriate database URL - if driver.startswith("mysql"): + if driver.startswith("mysql") or driver.startswith("mariadb"): return f"mysql://root:password@127.0.0.1:{port}/{database}" elif driver.startswith("postgres"):