@@ -141,46 +141,51 @@ func (c *comparison) Compare(ctx *sql.Context, row sql.Row) (int, error) {
141
141
return c .Left ().Type ().Compare (ctx , left , right )
142
142
}
143
143
144
- // ENUM, SET, and TIME must be excluded when doing comparisons, as they're too restrictive to use as a comparison
145
- // base.
146
- //
147
- // The best overall method would be to assign type priority. For example, INT would have a higher priority than
148
- // TINYINT. This could then be combined with the origin of the value (table column, procedure param, etc.) to
149
- // determine the best type for any comparison (tie-breakers can be simple rules such as the current left preference).
150
- var compareType sql.Type
151
- collationPreference := sql .Collation_Default
152
- switch c .Left ().(type ) {
153
- case * GetField , * UserVar , * SystemVar , * ProcedureParam :
154
- compareType = c .Left ().Type ()
155
- if twc , ok := compareType .(sql.TypeWithCollation ); ok {
156
- collationPreference = twc .Collation ()
157
- }
158
- default :
159
- switch c .Right ().(type ) {
160
- case * GetField , * UserVar , * SystemVar , * ProcedureParam :
161
- compareType = c .Right ().Type ()
162
- if twc , ok := compareType .(sql.TypeWithCollation ); ok {
163
- collationPreference = twc .Collation ()
164
- }
165
- }
166
- }
167
- if compareType != nil {
168
- _ , isEnum := compareType .(sql.EnumType )
169
- _ , isSet := compareType .(sql.SetType )
170
- _ , isTime := compareType .(types.TimeType )
171
- if ! isEnum && ! isSet && ! isTime {
172
- compareType = nil
173
- }
174
- }
175
- if compareType == nil {
176
- left , right , compareType , err = c .castLeftAndRight (ctx , left , right )
177
- if err != nil {
178
- return 0 , err
179
- }
144
+ left , right , compareType , err := c .castLeftAndRight (ctx , left , right )
145
+ if err != nil {
146
+ return 0 , err
180
147
}
181
- if _ , isSet := compareType .(sql.SetType ); ! isSet && types .IsTextOnly (compareType ) {
182
- collationPreference , _ = c .CollationCoercibility (ctx )
183
- stringCompareType := compareType .(sql.StringType )
148
+
149
+ //var compareType sql.Type
150
+ //// ENUM, SET, and TIME must be excluded when doing comparisons, as they're too restrictive to use as a comparison
151
+ //// base.
152
+ ////
153
+ //// The best overall method would be to assign type priority. For example, INT would have a higher priority than
154
+ //// TINYINT. This could then be combined with the origin of the value (table column, procedure param, etc.) to
155
+ //// determine the best type for any comparison (tie-breakers can be simple rules such as the current left preference).
156
+ //
157
+ //collationPreference := sql.Collation_Default
158
+ //switch c.Left().(type) {
159
+ //case *GetField, *UserVar, *SystemVar, *ProcedureParam:
160
+ // compareType = c.Left().Type()
161
+ // if twc, ok := compareType.(sql.TypeWithCollation); ok {
162
+ // collationPreference = twc.Collation()
163
+ // }
164
+ //default:
165
+ // switch c.Right().(type) {
166
+ // case *GetField, *UserVar, *SystemVar, *ProcedureParam:
167
+ // compareType = c.Right().Type()
168
+ // if twc, ok := compareType.(sql.TypeWithCollation); ok {
169
+ // collationPreference = twc.Collation()
170
+ // }
171
+ // }
172
+ //}
173
+ //if compareType != nil {
174
+ // _, isEnum := compareType.(sql.EnumType)
175
+ // _, isSet := compareType.(sql.SetType)
176
+ // _, isTime := compareType.(types.TimeType)
177
+ // if !isEnum && !isSet && !isTime {
178
+ // compareType = nil
179
+ // }
180
+ //}
181
+ //if compareType == nil {
182
+ // left, right, compareType, err = c.castLeftAndRight(ctx, left, right)
183
+ // if err != nil {
184
+ // return 0, err
185
+ // }
186
+ //}
187
+ collationPreference , _ := c .CollationCoercibility (ctx )
188
+ if stringCompareType , ok := compareType .(sql.StringType ); ok {
184
189
compareType = types .MustCreateString (stringCompareType .Type (), stringCompareType .Length (), collationPreference )
185
190
}
186
191
@@ -204,6 +209,26 @@ func (c *comparison) evalLeftAndRight(ctx *sql.Context, row sql.Row) (interface{
204
209
func (c * comparison ) castLeftAndRight (ctx * sql.Context , left , right interface {}) (interface {}, interface {}, sql.Type , error ) {
205
210
leftType := c .Left ().Type ()
206
211
rightType := c .Right ().Type ()
212
+
213
+ leftIsEnumOrSet := types .IsEnum (leftType ) || types .IsSet (leftType )
214
+ rightIsEnumOrSet := types .IsEnum (rightType ) || types .IsSet (rightType )
215
+ leftIsText := types .IsTextOnly (leftType )
216
+ rightIsText := types .IsTextOnly (rightType )
217
+ if (leftIsEnumOrSet && rightIsText ) || (rightIsEnumOrSet && ! leftIsText ) {
218
+ l , err := types .TypeAwareConversion (ctx , left , leftType , rightType )
219
+ if err != nil {
220
+ return nil , nil , nil , err
221
+ }
222
+ return l , right , rightType , nil
223
+ }
224
+ if (rightIsEnumOrSet && leftIsText ) || (leftIsEnumOrSet && ! rightIsText ) {
225
+ r , err := types .TypeAwareConversion (ctx , right , rightType , leftType )
226
+ if err != nil {
227
+ return nil , nil , nil , err
228
+ }
229
+ return left , r , leftType , nil
230
+ }
231
+
207
232
if types .IsTuple (leftType ) && types .IsTuple (rightType ) {
208
233
return left , right , c .Left ().Type (), nil
209
234
}
0 commit comments