@@ -177,6 +177,85 @@ func TestInferCollation(t *testing.T) {
177177 false ,
178178 & ExprCollation {CoercibilityImplicit , UNICODE , charset .CharsetBin , charset .CollationBin },
179179 },
180+ // latin1_bin mixed with latin1_swedish_ci. At equal coercibility the _bin
181+ // collation wins regardless of argument order, so latin1_swedish_ci must be
182+ // recognized as the non-bin side (see isBinCollation).
183+ {
184+ []Expression {
185+ newExpression (CoercibilityImplicit , UNICODE , charset .CharsetLatin1 , charset .CollationLatin1 ),
186+ newExpression (CoercibilityImplicit , UNICODE , charset .CharsetLatin1 , "latin1_swedish_ci" ),
187+ },
188+ false ,
189+ & ExprCollation {CoercibilityImplicit , UNICODE , charset .CharsetLatin1 , charset .CollationLatin1 },
190+ },
191+ {
192+ []Expression {
193+ newExpression (CoercibilityImplicit , UNICODE , charset .CharsetLatin1 , "latin1_swedish_ci" ),
194+ newExpression (CoercibilityImplicit , UNICODE , charset .CharsetLatin1 , charset .CollationLatin1 ),
195+ },
196+ false ,
197+ & ExprCollation {CoercibilityImplicit , UNICODE , charset .CharsetLatin1 , charset .CollationLatin1 },
198+ },
199+ {
200+ []Expression {
201+ newExpression (CoercibilityImplicit , UNICODE , charset .CharsetLatin1 , "latin1_swedish_ci" ),
202+ newExpression (CoercibilityImplicit , UNICODE , charset .CharsetLatin1 , "latin1_swedish_ci" ),
203+ },
204+ false ,
205+ & ExprCollation {CoercibilityImplicit , UNICODE , charset .CharsetLatin1 , "latin1_swedish_ci" },
206+ },
207+ // An explicit COLLATE still beats the _bin collation, either way round.
208+ {
209+ []Expression {
210+ newExpression (CoercibilityExplicit , UNICODE , charset .CharsetLatin1 , "latin1_swedish_ci" ),
211+ newExpression (CoercibilityImplicit , UNICODE , charset .CharsetLatin1 , charset .CollationLatin1 ),
212+ },
213+ false ,
214+ & ExprCollation {CoercibilityExplicit , UNICODE , charset .CharsetLatin1 , "latin1_swedish_ci" },
215+ },
216+ {
217+ []Expression {
218+ newExpression (CoercibilityImplicit , UNICODE , charset .CharsetLatin1 , charset .CollationLatin1 ),
219+ newExpression (CoercibilityExplicit , UNICODE , charset .CharsetLatin1 , "latin1_swedish_ci" ),
220+ },
221+ false ,
222+ & ExprCollation {CoercibilityExplicit , UNICODE , charset .CharsetLatin1 , "latin1_swedish_ci" },
223+ },
224+ // Two conflicting explicit collations cannot be aggregated.
225+ {
226+ []Expression {
227+ newExpression (CoercibilityExplicit , UNICODE , charset .CharsetLatin1 , charset .CollationLatin1 ),
228+ newExpression (CoercibilityExplicit , UNICODE , charset .CharsetLatin1 , "latin1_swedish_ci" ),
229+ },
230+ true ,
231+ nil ,
232+ },
233+ // latin1 is not a Unicode charset, so utf8mb4 wins at equal coercibility.
234+ {
235+ []Expression {
236+ newExpression (CoercibilityImplicit , UNICODE , charset .CharsetLatin1 , "latin1_swedish_ci" ),
237+ newExpression (CoercibilityImplicit , UNICODE , charset .CharsetUTF8MB4 , charset .CollationUTF8MB4 ),
238+ },
239+ false ,
240+ & ExprCollation {CoercibilityImplicit , UNICODE , charset .CharsetUTF8MB4 , charset .CollationUTF8MB4 },
241+ },
242+ {
243+ []Expression {
244+ newExpression (CoercibilityImplicit , UNICODE , charset .CharsetUTF8MB4 , charset .CollationUTF8MB4 ),
245+ newExpression (CoercibilityImplicit , UNICODE , charset .CharsetLatin1 , "latin1_swedish_ci" ),
246+ },
247+ false ,
248+ & ExprCollation {CoercibilityImplicit , UNICODE , charset .CharsetUTF8MB4 , charset .CollationUTF8MB4 },
249+ },
250+ // binary takes precedence over latin1_swedish_ci at equal coercibility.
251+ {
252+ []Expression {
253+ newExpression (CoercibilityImplicit , UNICODE , charset .CharsetLatin1 , "latin1_swedish_ci" ),
254+ newExpression (CoercibilityImplicit , UNICODE , charset .CharsetBin , charset .CollationBin ),
255+ },
256+ false ,
257+ & ExprCollation {CoercibilityImplicit , UNICODE , charset .CharsetBin , charset .CollationBin },
258+ },
180259 // binary charset with non-binary charset.
181260 {
182261 []Expression {
@@ -830,6 +909,23 @@ func TestCompareString(t *testing.T) {
830909 require .NotEqual (t , 0 , types .CompareString ("\U000FFFFE " , "\U000FFFFF " , "utf8mb4_0900_ai_ci" ))
831910 require .Equal (t , 0 , types .CompareString ("æ" , "ae" , "utf8mb4_0900_ai_ci" ))
832911
912+ // latin1 collations are byte-oriented, so the arguments are spelled as cp1252
913+ // bytes rather than as Go literals, which the compiler would encode as UTF-8.
914+ require .Equal (t , 0 , types .CompareString ("a" , "A" , "latin1_swedish_ci" ))
915+ require .Equal (t , 0 , types .CompareString ("\xE9 " , "E" , "latin1_swedish_ci" ))
916+ require .Equal (t , 0 , types .CompareString ("a " , "a " , "latin1_swedish_ci" ))
917+ require .Equal (t , 0 , types .CompareString ("\xDC " , "Y" , "latin1_swedish_ci" ))
918+ // Å, Ä and Ö sort after Z rather than folding onto A and O.
919+ require .NotEqual (t , 0 , types .CompareString ("\xC5 " , "A" , "latin1_swedish_ci" ))
920+ require .NotEqual (t , 0 , types .CompareString ("\xD6 " , "O" , "latin1_swedish_ci" ))
921+ require .Equal (t , 1 , types .CompareString ("\xC5 " , "Z" , "latin1_swedish_ci" ))
922+ // ß folds to nothing here, unlike in the utf8 collations above.
923+ require .NotEqual (t , 0 , types .CompareString ("\xDF " , "s" , "latin1_swedish_ci" ))
924+ require .NotEqual (t , 0 , types .CompareString ("\xDF " , "ss" , "latin1_swedish_ci" ))
925+
926+ require .NotEqual (t , 0 , types .CompareString ("a" , "A" , "latin1_bin" ))
927+ require .Equal (t , 0 , types .CompareString ("a " , "a " , "latin1_bin" ))
928+
833929 require .NotEqual (t , 0 , types .CompareString ("a" , "A" , "binary" ))
834930 require .NotEqual (t , 0 , types .CompareString ("À" , "A" , "binary" ))
835931 require .NotEqual (t , 0 , types .CompareString ("😜" , "😃" , "binary" ))
0 commit comments