diff --git a/sqlx-mysql/src/collation.rs b/sqlx-mysql/src/collation.rs index 46a3a3f90c..163d03e6d1 100644 --- a/sqlx-mysql/src/collation.rs +++ b/sqlx-mysql/src/collation.rs @@ -135,7 +135,7 @@ impl CharSet { 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::utf8 => Collation::utf8mb3_unicode_ci, CharSet::utf8mb4 => Collation::utf8mb4_unicode_ci, } } @@ -197,7 +197,8 @@ impl FromStr for CharSet { } } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug, PartialEq)] +#[cfg_attr(feature = "offline", derive(serde::Serialize, serde::Deserialize))] #[allow(non_camel_case_types)] #[repr(u8)] pub(crate) enum Collation { @@ -370,34 +371,34 @@ pub(crate) enum Collation { 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, + utf8mb3_bin = 83, + utf8mb3_croatian_ci = 213, + utf8mb3_czech_ci = 202, + utf8mb3_danish_ci = 203, + utf8mb3_esperanto_ci = 209, + utf8mb3_estonian_ci = 198, + utf8mb3_general_ci = 33, + utf8mb3_general_mysql500_ci = 223, + utf8mb3_german2_ci = 212, + utf8mb3_hungarian_ci = 210, + utf8mb3_icelandic_ci = 193, + utf8mb3_latvian_ci = 194, + utf8mb3_lithuanian_ci = 204, + utf8mb3_persian_ci = 208, + utf8mb3_polish_ci = 197, + utf8mb3_roman_ci = 207, + utf8mb3_romanian_ci = 195, + utf8mb3_sinhala_ci = 211, + utf8mb3_slovak_ci = 205, + utf8mb3_slovenian_ci = 196, + utf8mb3_spanish_ci = 199, + utf8mb3_spanish2_ci = 206, + utf8mb3_swedish_ci = 200, + utf8mb3_tolower_ci = 76, + utf8mb3_turkish_ci = 201, + utf8mb3_unicode_520_ci = 214, + utf8mb3_unicode_ci = 192, + utf8mb3_vietnamese_ci = 215, utf8mb4_0900_ai_ci = 255, utf8mb4_bin = 46, utf8mb4_croatian_ci = 245, @@ -425,6 +426,68 @@ pub(crate) enum Collation { utf8mb4_unicode_520_ci = 246, utf8mb4_unicode_ci = 224, utf8mb4_vietnamese_ci = 247, + // utf8mb4_de_pb_0900_ai_ci =256 , + // utf8mb4_is_0900_ai_ci =257 , + // utf8mb4_lv_0900_ai_ci =258 , + // utf8mb4_ro_0900_ai_ci =259 , + // utf8mb4_sl_0900_ai_ci =260 , + // utf8mb4_pl_0900_ai_ci =261 , + // utf8mb4_et_0900_ai_ci =262 , + // utf8mb4_es_0900_ai_ci =263 , + // utf8mb4_sv_0900_ai_ci =264 , + // utf8mb4_tr_0900_ai_ci =265 , + // utf8mb4_cs_0900_ai_ci =266 , + // utf8mb4_da_0900_ai_ci =267 , + // utf8mb4_lt_0900_ai_ci =268 , + // utf8mb4_sk_0900_ai_ci =269 , + // utf8mb4_es_trad_0900_ai_ci =270 , + // utf8mb4_la_0900_ai_ci =271 , + // utf8mb4_eo_0900_ai_ci =273 , + // utf8mb4_hu_0900_ai_ci =274 , + // utf8mb4_hr_0900_ai_ci =275 , + // utf8mb4_vi_0900_ai_ci =277 , + // utf8mb4_0900_as_cs =278 , + // utf8mb4_de_pb_0900_as_cs =279 , + // utf8mb4_is_0900_as_cs =280 , + // utf8mb4_lv_0900_as_cs =281 , + // utf8mb4_ro_0900_as_cs =282 , + // utf8mb4_sl_0900_as_cs =283 , + // utf8mb4_pl_0900_as_cs =284 , + // utf8mb4_et_0900_as_cs =285 , + // utf8mb4_es_0900_as_cs =286 , + // utf8mb4_sv_0900_as_cs =287 , + // utf8mb4_tr_0900_as_cs =288 , + // utf8mb4_cs_0900_as_cs =289 , + // utf8mb4_da_0900_as_cs =290 , + // utf8mb4_lt_0900_as_cs =291 , + // utf8mb4_sk_0900_as_cs =292 , + // utf8mb4_es_trad_0900_as_cs =293 , + // utf8mb4_la_0900_as_cs =294 , + // utf8mb4_eo_0900_as_cs =296 , + // utf8mb4_hu_0900_as_cs =297 , + // utf8mb4_hr_0900_as_cs =298 , + // utf8mb4_vi_0900_as_cs =300 , + // utf8mb4_ja_0900_as_cs =303 , + // utf8mb4_ja_0900_as_cs_ks =304 , + // utf8mb4_0900_as_ci =305 , + // utf8mb4_ru_0900_ai_ci =306 , + // utf8mb4_ru_0900_as_cs =307 , + // utf8mb4_zh_0900_as_cs =308 , + // utf8mb4_0900_bin =309 , + // utf8mb4_nb_0900_ai_ci =310 , + // utf8mb4_nb_0900_as_cs =311 , + // utf8mb4_nn_0900_ai_ci =312 , + // utf8mb4_nn_0900_as_cs =313 , + // utf8mb4_sr_latn_0900_ai_ci =314 , + // utf8mb4_sr_latn_0900_as_cs =315 , + // utf8mb4_bs_0900_ai_ci =316 , + // utf8mb4_bs_0900_as_cs =317 , + // utf8mb4_bg_0900_ai_ci =318 , + // utf8mb4_bg_0900_as_cs =319 , + // utf8mb4_gl_0900_ai_ci =320 , + // utf8mb4_gl_0900_as_cs =321 , + // utf8mb4_mn_cyrl_0900_ai_ci =322 , + // utf8mb4_mn_cyrl_0900_as_cs =323 , } impl Collation { @@ -599,34 +662,34 @@ impl Collation { 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::utf8mb3_bin => "utf8mb3_bin", + Collation::utf8mb3_croatian_ci => "utf8mb3_croatian_ci", + Collation::utf8mb3_czech_ci => "utf8mb3_czech_ci", + Collation::utf8mb3_danish_ci => "utf8mb3_danish_ci", + Collation::utf8mb3_esperanto_ci => "utf8mb3_esperanto_ci", + Collation::utf8mb3_estonian_ci => "utf8mb3_estonian_ci", + Collation::utf8mb3_general_ci => "utf8mb3_general_ci", + Collation::utf8mb3_general_mysql500_ci => "utf8mb3_general_mysql500_ci", + Collation::utf8mb3_german2_ci => "utf8mb3_german2_ci", + Collation::utf8mb3_hungarian_ci => "utf8mb3_hungarian_ci", + Collation::utf8mb3_icelandic_ci => "utf8mb3_icelandic_ci", + Collation::utf8mb3_latvian_ci => "utf8mb3_latvian_ci", + Collation::utf8mb3_lithuanian_ci => "utf8mb3_lithuanian_ci", + Collation::utf8mb3_persian_ci => "utf8mb3_persian_ci", + Collation::utf8mb3_polish_ci => "utf8mb3_polish_ci", + Collation::utf8mb3_roman_ci => "utf8mb3_roman_ci", + Collation::utf8mb3_romanian_ci => "utf8mb3_romanian_ci", + Collation::utf8mb3_sinhala_ci => "utf8mb3_sinhala_ci", + Collation::utf8mb3_slovak_ci => "utf8mb3_slovak_ci", + Collation::utf8mb3_slovenian_ci => "utf8mb3_slovenian_ci", + Collation::utf8mb3_spanish_ci => "utf8mb3_spanish_ci", + Collation::utf8mb3_spanish2_ci => "utf8mb3_spanish2_ci", + Collation::utf8mb3_swedish_ci => "utf8mb3_swedish_ci", + Collation::utf8mb3_tolower_ci => "utf8mb3_tolower_ci", + Collation::utf8mb3_turkish_ci => "utf8mb3_turkish_ci", + Collation::utf8mb3_unicode_520_ci => "utf8mb3_unicode_520_ci", + Collation::utf8mb3_unicode_ci => "utf8mb3_unicode_ci", + Collation::utf8mb3_vietnamese_ci => "utf8mb3_vietnamese_ci", Collation::utf8mb4_0900_ai_ci => "utf8mb4_0900_ai_ci", Collation::utf8mb4_bin => "utf8mb4_bin", Collation::utf8mb4_croatian_ci => "utf8mb4_croatian_ci", @@ -748,35 +811,35 @@ impl FromStr for Collation { "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, + "utf8mb3_unicode_ci" => Collation::utf8mb3_unicode_ci, + "utf8mb3_icelandic_ci" => Collation::utf8mb3_icelandic_ci, + "utf8mb3_latvian_ci" => Collation::utf8mb3_latvian_ci, + "utf8mb3_romanian_ci" => Collation::utf8mb3_romanian_ci, + "utf8mb3_slovenian_ci" => Collation::utf8mb3_slovenian_ci, + "utf8mb3_polish_ci" => Collation::utf8mb3_polish_ci, + "utf8mb3_estonian_ci" => Collation::utf8mb3_estonian_ci, + "utf8mb3_spanish_ci" => Collation::utf8mb3_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, + "utf8mb3_swedish_ci" => Collation::utf8mb3_swedish_ci, + "utf8mb3_turkish_ci" => Collation::utf8mb3_turkish_ci, + "utf8mb3_czech_ci" => Collation::utf8mb3_czech_ci, + "utf8mb3_danish_ci" => Collation::utf8mb3_danish_ci, + "utf8mb3_lithuanian_ci" => Collation::utf8mb3_lithuanian_ci, + "utf8mb3_slovak_ci" => Collation::utf8mb3_slovak_ci, + "utf8mb3_spanish2_ci" => Collation::utf8mb3_spanish2_ci, + "utf8mb3_roman_ci" => Collation::utf8mb3_roman_ci, + "utf8mb3_persian_ci" => Collation::utf8mb3_persian_ci, + "utf8mb3_esperanto_ci" => Collation::utf8mb3_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, + "utf8mb3_hungarian_ci" => Collation::utf8mb3_hungarian_ci, + "utf8mb3_sinhala_ci" => Collation::utf8mb3_sinhala_ci, + "utf8mb3_german2_ci" => Collation::utf8mb3_german2_ci, + "utf8mb3_croatian_ci" => Collation::utf8mb3_croatian_ci, + "utf8mb3_unicode_520_ci" => Collation::utf8mb3_unicode_520_ci, + "utf8mb3_vietnamese_ci" => Collation::utf8mb3_vietnamese_ci, "koi8u_general_ci" => Collation::koi8u_general_ci, - "utf8_general_mysql500_ci" => Collation::utf8_general_mysql500_ci, + "utf8mb3_general_mysql500_ci" => Collation::utf8mb3_general_mysql500_ci, "utf8mb4_unicode_ci" => Collation::utf8mb4_unicode_ci, "utf8mb4_icelandic_ci" => Collation::utf8mb4_icelandic_ci, "utf8mb4_latvian_ci" => Collation::utf8mb4_latvian_ci, @@ -816,7 +879,7 @@ impl FromStr for Collation { "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, + "utf8mb3_general_ci" => Collation::utf8mb3_general_ci, "cp1250_czech_cs" => Collation::cp1250_czech_cs, "ucs2_general_ci" => Collation::ucs2_general_ci, "cp866_general_ci" => Collation::cp866_general_ci, @@ -863,7 +926,7 @@ impl FromStr for Collation { "keybcs2_bin" => Collation::keybcs2_bin, "koi8r_bin" => Collation::koi8r_bin, "koi8u_bin" => Collation::koi8u_bin, - "utf8_tolower_ci" => Collation::utf8_tolower_ci, + "utf8mb3_tolower_ci" => Collation::utf8mb3_tolower_ci, "latin2_bin" => Collation::latin2_bin, "latin5_bin" => Collation::latin5_bin, "latin7_bin" => Collation::latin7_bin, @@ -871,7 +934,7 @@ impl FromStr for Collation { "cp850_bin" => Collation::cp850_bin, "cp852_bin" => Collation::cp852_bin, "swe7_bin" => Collation::swe7_bin, - "utf8_bin" => Collation::utf8_bin, + "utf8mb3_bin" => Collation::utf8mb3_bin, "big5_bin" => Collation::big5_bin, "euckr_bin" => Collation::euckr_bin, "gb2312_bin" => Collation::gb2312_bin, @@ -898,3 +961,303 @@ impl FromStr for Collation { }) } } + +// https://dev.mysql.com/doc/refman/8.4/en/adding-collation-choosing-id.html +// SELECT ID, COLLATION_NAME FROM INFORMATION_SCHEMA.COLLATIONS ORDER BY ID; +impl TryFrom for Collation { + type Error = sqlx_core::Error; + fn try_from(collation: u16) -> Result { + match collation { + 1 => Ok(Collation::big5_chinese_ci), + 2 => Ok(Collation::latin2_czech_cs), + 3 => Ok(Collation::dec8_swedish_ci), + 4 => Ok(Collation::cp850_general_ci), + 5 => Ok(Collation::latin1_german1_ci), + 6 => Ok(Collation::hp8_english_ci), + 7 => Ok(Collation::koi8r_general_ci), + 8 => Ok(Collation::latin1_swedish_ci), + 9 => Ok(Collation::latin2_general_ci), + 10 => Ok(Collation::swe7_swedish_ci), + 11 => Ok(Collation::ascii_general_ci), + 12 => Ok(Collation::ujis_japanese_ci), + 13 => Ok(Collation::sjis_japanese_ci), + 14 => Ok(Collation::cp1251_bulgarian_ci), + 15 => Ok(Collation::latin1_danish_ci), + 16 => Ok(Collation::hebrew_general_ci), + 18 => Ok(Collation::tis620_thai_ci), + 19 => Ok(Collation::euckr_korean_ci), + 20 => Ok(Collation::latin7_estonian_cs), + 21 => Ok(Collation::latin2_hungarian_ci), + 22 => Ok(Collation::koi8u_general_ci), + 23 => Ok(Collation::cp1251_ukrainian_ci), + 24 => Ok(Collation::gb2312_chinese_ci), + 25 => Ok(Collation::greek_general_ci), + 26 => Ok(Collation::cp1250_general_ci), + 27 => Ok(Collation::latin2_croatian_ci), + 28 => Ok(Collation::gbk_chinese_ci), + 29 => Ok(Collation::cp1257_lithuanian_ci), + 30 => Ok(Collation::latin5_turkish_ci), + 31 => Ok(Collation::latin1_german2_ci), + 32 => Ok(Collation::armscii8_general_ci), + 33 => Ok(Collation::utf8mb3_general_ci), + 34 => Ok(Collation::cp1250_czech_cs), + 35 => Ok(Collation::ucs2_general_ci), + 36 => Ok(Collation::cp866_general_ci), + 37 => Ok(Collation::keybcs2_general_ci), + 38 => Ok(Collation::macce_general_ci), + 39 => Ok(Collation::macroman_general_ci), + 40 => Ok(Collation::cp852_general_ci), + 41 => Ok(Collation::latin7_general_ci), + 42 => Ok(Collation::latin7_general_cs), + 43 => Ok(Collation::macce_bin), + 44 => Ok(Collation::cp1250_croatian_ci), + 45 => Ok(Collation::utf8mb4_general_ci), + 46 => Ok(Collation::utf8mb4_bin), + 47 => Ok(Collation::latin1_bin), + 48 => Ok(Collation::latin1_general_ci), + 49 => Ok(Collation::latin1_general_cs), + 50 => Ok(Collation::cp1251_bin), + 51 => Ok(Collation::cp1251_general_ci), + 52 => Ok(Collation::cp1251_general_cs), + 53 => Ok(Collation::macroman_bin), + 54 => Ok(Collation::utf16_general_ci), + 55 => Ok(Collation::utf16_bin), + 56 => Ok(Collation::utf16le_general_ci), + 57 => Ok(Collation::cp1256_general_ci), + 58 => Ok(Collation::cp1257_bin), + 59 => Ok(Collation::cp1257_general_ci), + 60 => Ok(Collation::utf32_general_ci), + 61 => Ok(Collation::utf32_bin), + 62 => Ok(Collation::utf16le_bin), + 63 => Ok(Collation::binary), + 64 => Ok(Collation::armscii8_bin), + 65 => Ok(Collation::ascii_bin), + 66 => Ok(Collation::cp1250_bin), + 67 => Ok(Collation::cp1256_bin), + 68 => Ok(Collation::cp866_bin), + 69 => Ok(Collation::dec8_bin), + 70 => Ok(Collation::greek_bin), + 71 => Ok(Collation::hebrew_bin), + 72 => Ok(Collation::hp8_bin), + 73 => Ok(Collation::keybcs2_bin), + 74 => Ok(Collation::koi8r_bin), + 75 => Ok(Collation::koi8u_bin), + 76 => Ok(Collation::utf8mb3_tolower_ci), + 77 => Ok(Collation::latin2_bin), + 78 => Ok(Collation::latin5_bin), + 79 => Ok(Collation::latin7_bin), + 80 => Ok(Collation::cp850_bin), + 81 => Ok(Collation::cp852_bin), + 82 => Ok(Collation::swe7_bin), + 83 => Ok(Collation::utf8mb3_bin), + 84 => Ok(Collation::big5_bin), + 85 => Ok(Collation::euckr_bin), + 86 => Ok(Collation::gb2312_bin), + 87 => Ok(Collation::gbk_bin), + 88 => Ok(Collation::sjis_bin), + 89 => Ok(Collation::tis620_bin), + 90 => Ok(Collation::ucs2_bin), + 91 => Ok(Collation::ujis_bin), + 92 => Ok(Collation::geostd8_general_ci), + 93 => Ok(Collation::geostd8_bin), + 94 => Ok(Collation::latin1_spanish_ci), + 95 => Ok(Collation::cp932_japanese_ci), + 96 => Ok(Collation::cp932_bin), + 97 => Ok(Collation::eucjpms_japanese_ci), + 98 => Ok(Collation::eucjpms_bin), + 99 => Ok(Collation::cp1250_polish_ci), + 101 => Ok(Collation::utf16_unicode_ci), + 102 => Ok(Collation::utf16_icelandic_ci), + 103 => Ok(Collation::utf16_latvian_ci), + 104 => Ok(Collation::utf16_romanian_ci), + 105 => Ok(Collation::utf16_slovenian_ci), + 106 => Ok(Collation::utf16_polish_ci), + 107 => Ok(Collation::utf16_estonian_ci), + 108 => Ok(Collation::utf16_spanish_ci), + 109 => Ok(Collation::utf16_swedish_ci), + 110 => Ok(Collation::utf16_turkish_ci), + 111 => Ok(Collation::utf16_czech_ci), + 112 => Ok(Collation::utf16_danish_ci), + 113 => Ok(Collation::utf16_lithuanian_ci), + 114 => Ok(Collation::utf16_slovak_ci), + 115 => Ok(Collation::utf16_spanish2_ci), + 116 => Ok(Collation::utf16_roman_ci), + 117 => Ok(Collation::utf16_persian_ci), + 118 => Ok(Collation::utf16_esperanto_ci), + 119 => Ok(Collation::utf16_hungarian_ci), + 120 => Ok(Collation::utf16_sinhala_ci), + 121 => Ok(Collation::utf16_german2_ci), + 122 => Ok(Collation::utf16_croatian_ci), + 123 => Ok(Collation::utf16_unicode_520_ci), + 124 => Ok(Collation::utf16_vietnamese_ci), + 128 => Ok(Collation::ucs2_unicode_ci), + 129 => Ok(Collation::ucs2_icelandic_ci), + 130 => Ok(Collation::ucs2_latvian_ci), + 131 => Ok(Collation::ucs2_romanian_ci), + 132 => Ok(Collation::ucs2_slovenian_ci), + 133 => Ok(Collation::ucs2_polish_ci), + 134 => Ok(Collation::ucs2_estonian_ci), + 135 => Ok(Collation::ucs2_spanish_ci), + 136 => Ok(Collation::ucs2_swedish_ci), + 137 => Ok(Collation::ucs2_turkish_ci), + 138 => Ok(Collation::ucs2_czech_ci), + 139 => Ok(Collation::ucs2_danish_ci), + 140 => Ok(Collation::ucs2_lithuanian_ci), + 141 => Ok(Collation::ucs2_slovak_ci), + 142 => Ok(Collation::ucs2_spanish2_ci), + 143 => Ok(Collation::ucs2_roman_ci), + 144 => Ok(Collation::ucs2_persian_ci), + 145 => Ok(Collation::ucs2_esperanto_ci), + 146 => Ok(Collation::ucs2_hungarian_ci), + 147 => Ok(Collation::ucs2_sinhala_ci), + 148 => Ok(Collation::ucs2_german2_ci), + 149 => Ok(Collation::ucs2_croatian_ci), + 150 => Ok(Collation::ucs2_unicode_520_ci), + 151 => Ok(Collation::ucs2_vietnamese_ci), + 159 => Ok(Collation::ucs2_general_mysql500_ci), + 160 => Ok(Collation::utf32_unicode_ci), + 161 => Ok(Collation::utf32_icelandic_ci), + 162 => Ok(Collation::utf32_latvian_ci), + 163 => Ok(Collation::utf32_romanian_ci), + 164 => Ok(Collation::utf32_slovenian_ci), + 165 => Ok(Collation::utf32_polish_ci), + 166 => Ok(Collation::utf32_estonian_ci), + 167 => Ok(Collation::utf32_spanish_ci), + 168 => Ok(Collation::utf32_swedish_ci), + 169 => Ok(Collation::utf32_turkish_ci), + 170 => Ok(Collation::utf32_czech_ci), + 171 => Ok(Collation::utf32_danish_ci), + 172 => Ok(Collation::utf32_lithuanian_ci), + 173 => Ok(Collation::utf32_slovak_ci), + 174 => Ok(Collation::utf32_spanish2_ci), + 175 => Ok(Collation::utf32_roman_ci), + 176 => Ok(Collation::utf32_persian_ci), + 177 => Ok(Collation::utf32_esperanto_ci), + 178 => Ok(Collation::utf32_hungarian_ci), + 179 => Ok(Collation::utf32_sinhala_ci), + 180 => Ok(Collation::utf32_german2_ci), + 181 => Ok(Collation::utf32_croatian_ci), + 182 => Ok(Collation::utf32_unicode_520_ci), + 183 => Ok(Collation::utf32_vietnamese_ci), + 192 => Ok(Collation::utf8mb3_unicode_ci), + 193 => Ok(Collation::utf8mb3_icelandic_ci), + 194 => Ok(Collation::utf8mb3_latvian_ci), + 195 => Ok(Collation::utf8mb3_romanian_ci), + 196 => Ok(Collation::utf8mb3_slovenian_ci), + 197 => Ok(Collation::utf8mb3_polish_ci), + 198 => Ok(Collation::utf8mb3_estonian_ci), + 199 => Ok(Collation::utf8mb3_spanish_ci), + 200 => Ok(Collation::utf8mb3_swedish_ci), + 201 => Ok(Collation::utf8mb3_turkish_ci), + 202 => Ok(Collation::utf8mb3_czech_ci), + 203 => Ok(Collation::utf8mb3_danish_ci), + 204 => Ok(Collation::utf8mb3_lithuanian_ci), + 205 => Ok(Collation::utf8mb3_slovak_ci), + 206 => Ok(Collation::utf8mb3_spanish2_ci), + 207 => Ok(Collation::utf8mb3_roman_ci), + 208 => Ok(Collation::utf8mb3_persian_ci), + 209 => Ok(Collation::utf8mb3_esperanto_ci), + 210 => Ok(Collation::utf8mb3_hungarian_ci), + 211 => Ok(Collation::utf8mb3_sinhala_ci), + 212 => Ok(Collation::utf8mb3_german2_ci), + 213 => Ok(Collation::utf8mb3_croatian_ci), + 214 => Ok(Collation::utf8mb3_unicode_520_ci), + 215 => Ok(Collation::utf8mb3_vietnamese_ci), + 223 => Ok(Collation::utf8mb3_general_mysql500_ci), + 224 => Ok(Collation::utf8mb4_unicode_ci), + 225 => Ok(Collation::utf8mb4_icelandic_ci), + 226 => Ok(Collation::utf8mb4_latvian_ci), + 227 => Ok(Collation::utf8mb4_romanian_ci), + 228 => Ok(Collation::utf8mb4_slovenian_ci), + 229 => Ok(Collation::utf8mb4_polish_ci), + 230 => Ok(Collation::utf8mb4_estonian_ci), + 231 => Ok(Collation::utf8mb4_spanish_ci), + 232 => Ok(Collation::utf8mb4_swedish_ci), + 233 => Ok(Collation::utf8mb4_turkish_ci), + 234 => Ok(Collation::utf8mb4_czech_ci), + 235 => Ok(Collation::utf8mb4_danish_ci), + 236 => Ok(Collation::utf8mb4_lithuanian_ci), + 237 => Ok(Collation::utf8mb4_slovak_ci), + 238 => Ok(Collation::utf8mb4_spanish2_ci), + 239 => Ok(Collation::utf8mb4_roman_ci), + 240 => Ok(Collation::utf8mb4_persian_ci), + 241 => Ok(Collation::utf8mb4_esperanto_ci), + 242 => Ok(Collation::utf8mb4_hungarian_ci), + 243 => Ok(Collation::utf8mb4_sinhala_ci), + 244 => Ok(Collation::utf8mb4_german2_ci), + 245 => Ok(Collation::utf8mb4_croatian_ci), + 246 => Ok(Collation::utf8mb4_unicode_520_ci), + 247 => Ok(Collation::utf8mb4_vietnamese_ci), + 248 => Ok(Collation::gb18030_chinese_ci), + 249 => Ok(Collation::gb18030_bin), + 250 => Ok(Collation::gb18030_unicode_520_ci), + 255 => Ok(Collation::utf8mb4_0900_ai_ci), + // 256 => Ok(Collation::utf8mb4_de_pb_0900_ai_ci), + // 257 => Ok(Collation::utf8mb4_is_0900_ai_ci), + // 258 => Ok(Collation::utf8mb4_lv_0900_ai_ci), + // 259 => Ok(Collation::utf8mb4_ro_0900_ai_ci), + // 260 => Ok(Collation::utf8mb4_sl_0900_ai_ci), + // 261 => Ok(Collation::utf8mb4_pl_0900_ai_ci), + // 262 => Ok(Collation::utf8mb4_et_0900_ai_ci), + // 263 => Ok(Collation::utf8mb4_es_0900_ai_ci), + // 264 => Ok(Collation::utf8mb4_sv_0900_ai_ci), + // 265 => Ok(Collation::utf8mb4_tr_0900_ai_ci), + // 266 => Ok(Collation::utf8mb4_cs_0900_ai_ci), + // 267 => Ok(Collation::utf8mb4_da_0900_ai_ci), + // 268 => Ok(Collation::utf8mb4_lt_0900_ai_ci), + // 269 => Ok(Collation::utf8mb4_sk_0900_ai_ci), + // 270 => Ok(Collation::utf8mb4_es_trad_0900_ai_ci), + // 271 => Ok(Collation::utf8mb4_la_0900_ai_ci), + // 273 => Ok(Collation::utf8mb4_eo_0900_ai_ci), + // 274 => Ok(Collation::utf8mb4_hu_0900_ai_ci), + // 275 => Ok(Collation::utf8mb4_hr_0900_ai_ci), + // 277 => Ok(Collation::utf8mb4_vi_0900_ai_ci), + // 278 => Ok(Collation::utf8mb4_0900_as_cs), + // 279 => Ok(Collation::utf8mb4_de_pb_0900_as_cs), + // 280 => Ok(Collation::utf8mb4_is_0900_as_cs), + // 281 => Ok(Collation::utf8mb4_lv_0900_as_cs), + // 282 => Ok(Collation::utf8mb4_ro_0900_as_cs), + // 283 => Ok(Collation::utf8mb4_sl_0900_as_cs), + // 284 => Ok(Collation::utf8mb4_pl_0900_as_cs), + // 285 => Ok(Collation::utf8mb4_et_0900_as_cs), + // 286 => Ok(Collation::utf8mb4_es_0900_as_cs), + // 287 => Ok(Collation::utf8mb4_sv_0900_as_cs), + // 288 => Ok(Collation::utf8mb4_tr_0900_as_cs), + // 289 => Ok(Collation::utf8mb4_cs_0900_as_cs), + // 290 => Ok(Collation::utf8mb4_da_0900_as_cs), + // 291 => Ok(Collation::utf8mb4_lt_0900_as_cs), + // 292 => Ok(Collation::utf8mb4_sk_0900_as_cs), + // 293 => Ok(Collation::utf8mb4_es_trad_0900_as_cs), + // 294 => Ok(Collation::utf8mb4_la_0900_as_cs), + // 296 => Ok(Collation::utf8mb4_eo_0900_as_cs), + // 297 => Ok(Collation::utf8mb4_hu_0900_as_cs), + // 298 => Ok(Collation::utf8mb4_hr_0900_as_cs), + // 300 => Ok(Collation::utf8mb4_vi_0900_as_cs), + // 303 => Ok(Collation::utf8mb4_ja_0900_as_cs), + // 304 => Ok(Collation::utf8mb4_ja_0900_as_cs_ks), + // 305 => Ok(Collation::utf8mb4_0900_as_ci), + // 306 => Ok(Collation::utf8mb4_ru_0900_ai_ci), + // 307 => Ok(Collation::utf8mb4_ru_0900_as_cs), + // 308 => Ok(Collation::utf8mb4_zh_0900_as_cs), + // 309 => Ok(Collation::utf8mb4_0900_bin), + // 310 => Ok(Collation::utf8mb4_nb_0900_ai_ci), + // 311 => Ok(Collation::utf8mb4_nb_0900_as_cs), + // 312 => Ok(Collation::utf8mb4_nn_0900_ai_ci), + // 313 => Ok(Collation::utf8mb4_nn_0900_as_cs), + // 314 => Ok(Collation::utf8mb4_sr_latn_0900_ai_ci), + // 315 => Ok(Collation::utf8mb4_sr_latn_0900_as_cs), + // 316 => Ok(Collation::utf8mb4_bs_0900_ai_ci), + // 317 => Ok(Collation::utf8mb4_bs_0900_as_cs), + // 318 => Ok(Collation::utf8mb4_bg_0900_ai_ci), + // 319 => Ok(Collation::utf8mb4_bg_0900_as_cs), + // 320 => Ok(Collation::utf8mb4_gl_0900_ai_ci), + // 321 => Ok(Collation::utf8mb4_gl_0900_as_cs), + // 322 => Ok(Collation::utf8mb4_mn_cyrl_0900_ai_ci), + // 323 => Ok(Collation::utf8mb4_mn_cyrl_0900_as_cs), + _ => Err(Self::Error::Protocol(format!( + "unknown collation {}", + collation + ))), + } + } +} diff --git a/sqlx-mysql/src/protocol/text/column.rs b/sqlx-mysql/src/protocol/text/column.rs index 36778fec2a..be4ce69238 100644 --- a/sqlx-mysql/src/protocol/text/column.rs +++ b/sqlx-mysql/src/protocol/text/column.rs @@ -3,6 +3,7 @@ use std::str::from_utf8; use bitflags::bitflags; use bytes::{Buf, Bytes}; +use crate::collation::Collation; use crate::error::Error; use crate::io::Decode; use crate::io::MySqlBufExt; @@ -62,6 +63,10 @@ bitflags! { } // https://dev.mysql.com/doc/internals/en/com-query-response.html#column-type +// dead link ^ +// https://dev.mysql.com/doc/dev/mysql-server/9.0.0/page_protocol_com_query_response_text_resultset_column_definition.html +// the "type of the column as defined in enum_field_types" +// https://dev.mysql.com/doc/dev/mysql-server/9.0.0/field__types_8h.html #[derive(Debug, Copy, Clone, PartialEq)] #[cfg_attr(feature = "offline", derive(serde::Serialize, serde::Deserialize))] @@ -112,8 +117,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, @@ -156,7 +160,7 @@ impl Decode<'_, Capabilities> for ColumnDefinition { table, alias, name, - collation, + collation: Collation::try_from(collation)?, max_size, r#type: ColumnType::try_from_u16(type_id)?, flags: ColumnFlags::from_bits_truncate(flags), @@ -166,8 +170,13 @@ impl Decode<'_, Capabilities> for ColumnDefinition { } impl ColumnType { - pub(crate) fn name(self, flags: ColumnFlags, max_size: Option) -> &'static str { - let is_binary = flags.contains(ColumnFlags::BINARY); + pub(crate) fn name( + self, + collation: Collation, + flags: ColumnFlags, + max_size: Option, + ) -> &'static str { + let is_binary = collation == Collation::binary; let is_unsigned = flags.contains(ColumnFlags::UNSIGNED); let is_enum = flags.contains(ColumnFlags::ENUM); diff --git a/sqlx-mysql/src/type_info.rs b/sqlx-mysql/src/type_info.rs index a80b233fc9..eb43c5a2e2 100644 --- a/sqlx-mysql/src/type_info.rs +++ b/sqlx-mysql/src/type_info.rs @@ -2,7 +2,10 @@ use std::fmt::{self, Display, Formatter}; pub(crate) use sqlx_core::type_info::*; -use crate::protocol::text::{ColumnDefinition, ColumnFlags, ColumnType}; +use crate::{ + collation::Collation, + protocol::text::{ColumnDefinition, ColumnFlags, ColumnType}, +}; /// Type information for a MySql type. #[derive(Debug, Clone)] @@ -10,6 +13,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))] @@ -20,6 +24,7 @@ impl MySqlTypeInfo { pub(crate) const fn binary(ty: ColumnType) -> Self { Self { r#type: ty, + collation: Collation::binary, flags: ColumnFlags::BINARY, max_size: None, } @@ -38,6 +43,7 @@ impl MySqlTypeInfo { Self { r#type: ColumnType::String, flags: ColumnFlags::ENUM, + collation: Collation::binary, max_size: None, } } @@ -60,6 +66,7 @@ impl MySqlTypeInfo { Self { r#type: column.r#type, flags: column.flags, + collation: column.collation, max_size: Some(column.max_size), } } @@ -77,7 +84,7 @@ impl TypeInfo for MySqlTypeInfo { } fn name(&self) -> &str { - self.r#type.name(self.flags, self.max_size) + self.r#type.name(self.collation, self.flags, self.max_size) } } diff --git a/sqlx-mysql/src/types/bool.rs b/sqlx-mysql/src/types/bool.rs index 7d8c243d36..32ecaf60d4 100644 --- a/sqlx-mysql/src/types/bool.rs +++ b/sqlx-mysql/src/types/bool.rs @@ -1,3 +1,4 @@ +use crate::collation::Collation; use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; @@ -12,6 +13,7 @@ impl Type for bool { // MySQL has no actual `BOOLEAN` type, the type is an alias of `TINYINT(1)` MySqlTypeInfo { flags: ColumnFlags::BINARY | ColumnFlags::UNSIGNED, + collation: Collation::binary, max_size: Some(1), r#type: ColumnType::Tiny, } diff --git a/sqlx-mysql/src/types/str.rs b/sqlx-mysql/src/types/str.rs index 8233e90893..ea05a3b95b 100644 --- a/sqlx-mysql/src/types/str.rs +++ b/sqlx-mysql/src/types/str.rs @@ -1,3 +1,4 @@ +use crate::collation::Collation; use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; @@ -12,6 +13,7 @@ impl Type for str { MySqlTypeInfo { r#type: ColumnType::VarString, // VARCHAR flags: ColumnFlags::empty(), + collation: Collation::utf8mb3_bin, max_size: None, } } @@ -28,7 +30,7 @@ impl Type for str { | ColumnType::String | ColumnType::VarString | ColumnType::Enum - ) && !ty.flags.contains(ColumnFlags::BINARY) + ) && ty.collation != Collation::binary } } diff --git a/sqlx-mysql/src/types/uint.rs b/sqlx-mysql/src/types/uint.rs index ca8eb75347..02a5a0904a 100644 --- a/sqlx-mysql/src/types/uint.rs +++ b/sqlx-mysql/src/types/uint.rs @@ -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, } } diff --git a/tests/mysql/types.rs b/tests/mysql/types.rs index e837a53f75..d540e4cff6 100644 --- a/tests/mysql/types.rs +++ b/tests/mysql/types.rs @@ -384,3 +384,75 @@ CREATE TEMPORARY TABLE user_login ( Ok(()) } + +mod string_collation_tests { + use super::*; + + #[sqlx_macros::test] + async fn test_binary_string_collation() -> anyhow::Result<()> { + let mut conn = new::().await?; + + conn.execute( + r#" + CREATE TEMPORARY TABLE strings ( + id INT PRIMARY KEY AUTO_INCREMENT, + char_bin CHAR(50) COLLATE utf8mb4_bin, + varchar_bin VARCHAR(255) COLLATE utf8mb4_bin, + text_bin TEXT COLLATE utf8mb4_bin + ); + "#, + ) + .await?; + + // Insert sample data + conn.execute( + r#" + INSERT INTO strings (char_bin, varchar_bin, text_bin) VALUES + ('char_binary', 'varchar_binary', 'text_binary'); + "#, + ) + .await?; + + // Query the data back + let row: (String, String, String) = sqlx::query_as( + r#" + SELECT char_bin, varchar_bin, text_bin FROM strings + "#, + ) + .fetch_one(&mut conn) + .await?; + + // Assert the values + assert_eq!(row.0, "char_binary"); + assert_eq!(row.1, "varchar_binary"); + assert_eq!(row.2, "text_binary"); + + Ok(()) + } + + #[sqlx_macros::test] + async fn test_blob_to_string_err() -> anyhow::Result<()> { + let mut conn = new::().await?; + conn.execute( + r#" + CREATE TEMPORARY TABLE blobs ( + id INT PRIMARY KEY AUTO_INCREMENT, + myblob BLOB + ); + "#, + ) + .await?; + + // Insert sample data + conn.execute("INSERT INTO blobs (myblob) VALUES ('0x243524598');") + .await?; + + let res: Result<(i32, String), sqlx::Error> = + sqlx::query_as("SELECT id, myblob FROM blobs") + .fetch_one(&mut conn) + .await; + + assert!(res.is_err()); + Ok(()) + } +}