github.com/dolthub/go-mysql-server@v0.18.0/sql/expression/comparison.go (about) 1 // Copyright 2020-2021 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package expression 16 17 import ( 18 "fmt" 19 "sync" 20 21 errors "gopkg.in/src-d/go-errors.v1" 22 23 "github.com/dolthub/go-mysql-server/internal/regex" 24 "github.com/dolthub/go-mysql-server/sql" 25 "github.com/dolthub/go-mysql-server/sql/types" 26 ) 27 28 var ErrInvalidRegexp = errors.NewKind("Invalid regular expression: %s") 29 30 // Comparer implements a comparison expression. 31 type Comparer interface { 32 sql.Expression 33 Compare(ctx *sql.Context, row sql.Row) (int, error) 34 Left() sql.Expression 35 Right() sql.Expression 36 } 37 38 // ErrNilOperand ir returned if some or both of the comparison's operands is nil. 39 var ErrNilOperand = errors.NewKind("nil operand found in comparison") 40 41 // PreciseComparison searches an expression tree for comparison 42 // expressions that require a conversion or type promotion. 43 // This utility helps determine if filter predicates can be pushed down. 44 func PreciseComparison(e sql.Expression) bool { 45 var imprecise bool 46 sql.Inspect(e, func(expr sql.Expression) bool { 47 if cmp, ok := expr.(Comparer); ok { 48 left, right := cmp.Left().Type(), cmp.Right().Type() 49 50 // integer comparisons are exact 51 if types.IsInteger(left) && types.IsInteger(right) { 52 return true 53 } 54 55 // comparisons with type conversions are sometimes imprecise 56 if !left.Equals(right) { 57 imprecise = true 58 return false 59 } 60 } 61 return true 62 }) 63 return !imprecise 64 } 65 66 type comparison struct { 67 BinaryExpressionStub 68 } 69 70 // disableRounding disables rounding for the given expression. 71 func disableRounding(expr sql.Expression) { 72 setArithmeticOps(expr, -1) 73 setDivOps(expr, -1) 74 } 75 76 func newComparison(left, right sql.Expression) comparison { 77 disableRounding(left) 78 disableRounding(right) 79 return comparison{BinaryExpressionStub{left, right}} 80 } 81 82 // CollationCoercibility implements the interface sql.CollationCoercible. 83 func (c *comparison) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 84 leftCollation, leftCoercibility := sql.GetCoercibility(ctx, c.Left()) 85 rightCollation, rightCoercibility := sql.GetCoercibility(ctx, c.Right()) 86 return sql.ResolveCoercibility(leftCollation, leftCoercibility, rightCollation, rightCoercibility) 87 } 88 89 // Compare the two given values using the types of the expressions in the comparison. 90 // Since both types should be equal, it does not matter which type is used, but for 91 // reference, the left type is always used. 92 func (c *comparison) Compare(ctx *sql.Context, row sql.Row) (int, error) { 93 left, right, err := c.evalLeftAndRight(ctx, row) 94 if err != nil { 95 return 0, err 96 } 97 98 if left == nil || right == nil { 99 return 0, ErrNilOperand.New() 100 } 101 102 if types.TypesEqual(c.Left().Type(), c.Right().Type()) { 103 return c.Left().Type().Compare(left, right) 104 } 105 106 // ENUM, SET, and TIME must be excluded when doing comparisons, as they're too restrictive to use as a comparison 107 // base. 108 // 109 // The best overall method would be to assign type priority. For example, INT would have a higher priority than 110 // TINYINT. This could then be combined with the origin of the value (table column, procedure param, etc.) to 111 // determine the best type for any comparison (tie-breakers can be simple rules such as the current left preference). 112 var compareType sql.Type 113 collationPreference := sql.Collation_Default 114 switch c.Left().(type) { 115 case *GetField, *UserVar, *SystemVar, *ProcedureParam: 116 compareType = c.Left().Type() 117 if twc, ok := compareType.(sql.TypeWithCollation); ok { 118 collationPreference = twc.Collation() 119 } 120 default: 121 switch c.Right().(type) { 122 case *GetField, *UserVar, *SystemVar, *ProcedureParam: 123 compareType = c.Right().Type() 124 if twc, ok := compareType.(sql.TypeWithCollation); ok { 125 collationPreference = twc.Collation() 126 } 127 } 128 } 129 if compareType != nil { 130 _, isEnum := compareType.(sql.EnumType) 131 _, isSet := compareType.(sql.SetType) 132 _, isTime := compareType.(types.TimeType) 133 if !isEnum && !isSet && !isTime { 134 compareType = nil 135 } 136 } 137 if compareType == nil { 138 left, right, compareType, err = c.castLeftAndRight(left, right) 139 if err != nil { 140 return 0, err 141 } 142 } 143 if types.IsTextOnly(compareType) { 144 collationPreference, _ = c.CollationCoercibility(ctx) 145 if err != nil { 146 return 0, err 147 } 148 stringCompareType := compareType.(sql.StringType) 149 compareType = types.MustCreateString(stringCompareType.Type(), stringCompareType.Length(), collationPreference) 150 } 151 152 return compareType.Compare(left, right) 153 } 154 155 func (c *comparison) evalLeftAndRight(ctx *sql.Context, row sql.Row) (interface{}, interface{}, error) { 156 left, err := c.Left().Eval(ctx, row) 157 if err != nil { 158 return nil, nil, err 159 } 160 161 right, err := c.Right().Eval(ctx, row) 162 if err != nil { 163 return nil, nil, err 164 } 165 166 return left, right, nil 167 } 168 169 func (c *comparison) castLeftAndRight(left, right interface{}) (interface{}, interface{}, sql.Type, error) { 170 leftType := c.Left().Type() 171 rightType := c.Right().Type() 172 if types.IsTuple(leftType) && types.IsTuple(rightType) { 173 return left, right, c.Left().Type(), nil 174 } 175 176 if types.IsTime(leftType) || types.IsTime(rightType) { 177 l, r, err := convertLeftAndRight(left, right, ConvertToDatetime) 178 if err != nil { 179 return nil, nil, nil, err 180 } 181 182 return l, r, types.DatetimeMaxPrecision, nil 183 } 184 185 // Rely on types.JSON.Compare to handle JSON comparisons 186 if types.IsJSON(leftType) || types.IsJSON(rightType) { 187 return left, right, types.JSON, nil 188 } 189 190 if types.IsBinaryType(leftType) || types.IsBinaryType(rightType) { 191 l, r, err := convertLeftAndRight(left, right, ConvertToBinary) 192 if err != nil { 193 return nil, nil, nil, err 194 } 195 return l, r, types.LongBlob, nil 196 } 197 198 if types.IsNumber(leftType) || types.IsNumber(rightType) { 199 if types.IsDecimal(leftType) || types.IsDecimal(rightType) { 200 //TODO: We need to set to the actual DECIMAL type 201 l, r, err := convertLeftAndRight(left, right, ConvertToDecimal) 202 if err != nil { 203 return nil, nil, nil, err 204 } 205 206 if types.IsDecimal(leftType) { 207 return l, r, leftType, nil 208 } else { 209 return l, r, rightType, nil 210 } 211 } 212 213 if types.IsFloat(leftType) || types.IsFloat(rightType) { 214 l, r, err := convertLeftAndRight(left, right, ConvertToDouble) 215 if err != nil { 216 return nil, nil, nil, err 217 } 218 219 return l, r, types.Float64, nil 220 } 221 222 if types.IsSigned(leftType) && types.IsSigned(rightType) { 223 l, r, err := convertLeftAndRight(left, right, ConvertToSigned) 224 if err != nil { 225 return nil, nil, nil, err 226 } 227 228 return l, r, types.Int64, nil 229 } 230 231 if types.IsUnsigned(leftType) && types.IsUnsigned(rightType) { 232 l, r, err := convertLeftAndRight(left, right, ConvertToUnsigned) 233 if err != nil { 234 return nil, nil, nil, err 235 } 236 237 return l, r, types.Uint64, nil 238 } 239 240 l, r, err := convertLeftAndRight(left, right, ConvertToDouble) 241 if err != nil { 242 return nil, nil, nil, err 243 } 244 245 return l, r, types.Float64, nil 246 } 247 248 left, right, err := convertLeftAndRight(left, right, ConvertToChar) 249 if err != nil { 250 return nil, nil, nil, err 251 } 252 253 return left, right, types.LongText, nil 254 } 255 256 func convertLeftAndRight(left, right interface{}, convertTo string) (interface{}, interface{}, error) { 257 l, err := convertValue(left, convertTo, nil, 0, 0) 258 if err != nil { 259 return nil, nil, err 260 } 261 262 r, err := convertValue(right, convertTo, nil, 0, 0) 263 if err != nil { 264 return nil, nil, err 265 } 266 267 return l, r, nil 268 } 269 270 // Type implements the Expression interface. 271 func (*comparison) Type() sql.Type { 272 return types.Boolean 273 } 274 275 // Left implements Comparer interface 276 func (c *comparison) Left() sql.Expression { return c.BinaryExpressionStub.LeftChild } 277 278 // Right implements Comparer interface 279 func (c *comparison) Right() sql.Expression { return c.BinaryExpressionStub.RightChild } 280 281 // Equals is a comparison that checks an expression is equal to another. 282 type Equals struct { 283 comparison 284 } 285 286 var _ sql.Expression = (*Equals)(nil) 287 var _ sql.CollationCoercible = (*Equals)(nil) 288 289 // NewEquals returns a new Equals expression. 290 func NewEquals(left sql.Expression, right sql.Expression) *Equals { 291 return &Equals{newComparison(left, right)} 292 } 293 294 // CollationCoercibility implements the interface sql.CollationCoercible. 295 func (e *Equals) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 296 return sql.Collation_binary, 5 297 } 298 299 // Eval implements the Expression interface. 300 func (e *Equals) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) { 301 result, err := e.Compare(ctx, row) 302 if err != nil { 303 if ErrNilOperand.Is(err) { 304 return nil, nil 305 } 306 307 return nil, err 308 } 309 310 return result == 0, nil 311 } 312 313 // WithChildren implements the Expression interface. 314 func (e *Equals) WithChildren(children ...sql.Expression) (sql.Expression, error) { 315 if len(children) != 2 { 316 return nil, sql.ErrInvalidChildrenNumber.New(e, len(children), 2) 317 } 318 return NewEquals(children[0], children[1]), nil 319 } 320 321 func (e *Equals) String() string { 322 if e == nil { 323 return "" 324 } 325 return fmt.Sprintf("(%s = %s)", e.Left(), e.Right()) 326 } 327 328 func (e *Equals) DebugString() string { 329 if e == nil { 330 return "" 331 } 332 pr := sql.NewTreePrinter() 333 _ = pr.WriteNode("Eq") 334 children := []string{sql.DebugString(e.Left()), sql.DebugString(e.Right())} 335 _ = pr.WriteChildren(children...) 336 return pr.String() 337 } 338 339 // NullSafeEquals is a comparison that checks an expression is equal to 340 // another, where NULLs do not coalesce to NULL and two NULLs compare equal to 341 // each other. 342 type NullSafeEquals struct { 343 comparison 344 } 345 346 var _ sql.Expression = (*NullSafeEquals)(nil) 347 var _ sql.CollationCoercible = (*NullSafeEquals)(nil) 348 349 // NewNullSafeEquals returns a new NullSafeEquals expression. 350 func NewNullSafeEquals(left sql.Expression, right sql.Expression) *NullSafeEquals { 351 return &NullSafeEquals{newComparison(left, right)} 352 } 353 354 // Type implements the Expression interface. 355 func (e *NullSafeEquals) Type() sql.Type { 356 return types.Boolean 357 } 358 359 // CollationCoercibility implements the interface sql.CollationCoercible. 360 func (e *NullSafeEquals) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 361 return sql.Collation_binary, 5 362 } 363 364 func (e *NullSafeEquals) Compare(ctx *sql.Context, row sql.Row) (int, error) { 365 left, right, err := e.evalLeftAndRight(ctx, row) 366 if err != nil { 367 return 0, err 368 } 369 370 if left == nil && right == nil { 371 return 0, nil 372 } else if left == nil { 373 return 1, nil 374 } else if right == nil { 375 return -1, nil 376 } 377 378 if types.TypesEqual(e.Left().Type(), e.Right().Type()) { 379 return e.Left().Type().Compare(left, right) 380 } 381 382 var compareType sql.Type 383 left, right, compareType, err = e.castLeftAndRight(left, right) 384 if err != nil { 385 return 0, err 386 } 387 388 return compareType.Compare(left, right) 389 } 390 391 // Eval implements the Expression interface. 392 func (e *NullSafeEquals) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) { 393 result, err := e.Compare(ctx, row) 394 if err != nil { 395 return nil, err 396 } 397 398 return result == 0, nil 399 } 400 401 // WithChildren implements the Expression interface. 402 func (e *NullSafeEquals) WithChildren(children ...sql.Expression) (sql.Expression, error) { 403 if len(children) != 2 { 404 return nil, sql.ErrInvalidChildrenNumber.New(e, len(children), 2) 405 } 406 return NewNullSafeEquals(children[0], children[1]), nil 407 } 408 409 func (e *NullSafeEquals) String() string { 410 return fmt.Sprintf("(%s <=> %s)", e.Left(), e.Right()) 411 } 412 413 func (e *NullSafeEquals) DebugString() string { 414 return fmt.Sprintf("(%s <=> %s)", sql.DebugString(e.Left()), sql.DebugString(e.Right())) 415 } 416 417 // Regexp is a comparison that checks an expression matches a regexp. 418 type Regexp struct { 419 comparison 420 pool *sync.Pool 421 cached bool 422 once sync.Once 423 } 424 425 var _ sql.Expression = (*Regexp)(nil) 426 var _ sql.CollationCoercible = (*Regexp)(nil) 427 428 // NewRegexp creates a new Regexp expression. 429 func NewRegexp(left sql.Expression, right sql.Expression) *Regexp { 430 var cached = true 431 sql.Inspect(right, func(e sql.Expression) bool { 432 if _, ok := e.(*GetField); ok { 433 cached = false 434 } 435 return true 436 }) 437 438 return &Regexp{ 439 comparison: newComparison(left, right), 440 pool: nil, 441 cached: cached, 442 once: sync.Once{}, 443 } 444 } 445 446 // Eval implements the Expression interface. 447 func (re *Regexp) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) { 448 if types.IsText(re.Right().Type()) { 449 return re.compareRegexp(ctx, row) 450 } 451 452 result, err := re.Compare(ctx, row) 453 if err != nil { 454 if ErrNilOperand.Is(err) { 455 return nil, nil 456 } 457 458 return nil, err 459 } 460 461 return result == 0, nil 462 } 463 464 type matcherErrTuple struct { 465 matcher regex.DisposableMatcher 466 err error 467 } 468 469 func (re *Regexp) compareRegexp(ctx *sql.Context, row sql.Row) (interface{}, error) { 470 left, err := re.Left().Eval(ctx, row) 471 if err != nil || left == nil { 472 return nil, err 473 } 474 left, _, err = types.LongText.Convert(left) 475 if err != nil { 476 return nil, err 477 } 478 479 var matcher regex.DisposableMatcher 480 481 if !re.cached { 482 right, rerr := re.evalRight(ctx, row) 483 if rerr != nil || right == nil { 484 return right, rerr 485 } 486 matcher, err = regex.NewDisposableMatcher(regex.Default(), *right) 487 } else { 488 re.once.Do(func() { 489 right, err := re.evalRight(ctx, row) 490 re.pool = &sync.Pool{ 491 New: func() interface{} { 492 if err != nil || right == nil { 493 return matcherErrTuple{nil, err} 494 } 495 m, e := regex.NewDisposableMatcher(regex.Default(), *right) 496 return matcherErrTuple{m, e} 497 }, 498 } 499 }) 500 met := re.pool.Get().(matcherErrTuple) 501 matcher, err = met.matcher, met.err 502 } 503 504 if err != nil { 505 return nil, ErrInvalidRegexp.New(err.Error()) 506 } else if matcher == nil { 507 return nil, nil 508 } 509 510 ok := matcher.Match(left.(string)) 511 512 if !re.cached { 513 matcher.Dispose() 514 } else { 515 re.pool.Put(matcherErrTuple{matcher, nil}) 516 } 517 return ok, nil 518 } 519 520 func (re *Regexp) evalRight(ctx *sql.Context, row sql.Row) (*string, error) { 521 right, err := re.Right().Eval(ctx, row) 522 if err != nil { 523 return nil, err 524 } 525 if right == nil { 526 return nil, nil 527 } 528 right, _, err = types.LongText.Convert(right) 529 if err != nil { 530 return nil, err 531 } 532 s := right.(string) 533 return &s, nil 534 } 535 536 // WithChildren implements the Expression interface. 537 func (re *Regexp) WithChildren(children ...sql.Expression) (sql.Expression, error) { 538 if len(children) != 2 { 539 return nil, sql.ErrInvalidChildrenNumber.New(re, len(children), 2) 540 } 541 return NewRegexp(children[0], children[1]), nil 542 } 543 544 func (re *Regexp) String() string { 545 return fmt.Sprintf("(%s REGEXP %s)", re.Left(), re.Right()) 546 } 547 548 func (re *Regexp) DebugString() string { 549 return fmt.Sprintf("(%s REGEXP %s)", sql.DebugString(re.Left()), sql.DebugString(re.Right())) 550 } 551 552 // GreaterThan is a comparison that checks an expression is greater than another. 553 type GreaterThan struct { 554 comparison 555 } 556 557 var _ sql.Expression = (*GreaterThan)(nil) 558 var _ sql.CollationCoercible = (*GreaterThan)(nil) 559 560 // NewGreaterThan creates a new GreaterThan expression. 561 func NewGreaterThan(left sql.Expression, right sql.Expression) *GreaterThan { 562 return &GreaterThan{newComparison(left, right)} 563 } 564 565 // CollationCoercibility implements the interface sql.CollationCoercible. 566 func (gt *GreaterThan) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 567 return sql.Collation_binary, 5 568 } 569 570 // Eval implements the Expression interface. 571 func (gt *GreaterThan) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) { 572 result, err := gt.Compare(ctx, row) 573 if err != nil { 574 if ErrNilOperand.Is(err) { 575 return nil, nil 576 } 577 578 return nil, err 579 } 580 581 return result == 1, nil 582 } 583 584 // WithChildren implements the Expression interface. 585 func (gt *GreaterThan) WithChildren(children ...sql.Expression) (sql.Expression, error) { 586 if len(children) != 2 { 587 return nil, sql.ErrInvalidChildrenNumber.New(gt, len(children), 2) 588 } 589 return NewGreaterThan(children[0], children[1]), nil 590 } 591 592 func (gt *GreaterThan) String() string { 593 return fmt.Sprintf("(%s > %s)", gt.Left(), gt.Right()) 594 } 595 596 func (gt *GreaterThan) DebugString() string { 597 pr := sql.NewTreePrinter() 598 _ = pr.WriteNode("GreaterThan") 599 children := []string{sql.DebugString(gt.Left()), sql.DebugString(gt.Right())} 600 _ = pr.WriteChildren(children...) 601 return pr.String() 602 } 603 604 // LessThan is a comparison that checks an expression is less than another. 605 type LessThan struct { 606 comparison 607 } 608 609 var _ sql.Expression = (*LessThan)(nil) 610 var _ sql.CollationCoercible = (*LessThan)(nil) 611 612 // NewLessThan creates a new LessThan expression. 613 func NewLessThan(left sql.Expression, right sql.Expression) *LessThan { 614 return &LessThan{newComparison(left, right)} 615 } 616 617 // CollationCoercibility implements the interface sql.CollationCoercible. 618 func (lt *LessThan) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 619 return sql.Collation_binary, 5 620 } 621 622 // Eval implements the expression interface. 623 func (lt *LessThan) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) { 624 result, err := lt.Compare(ctx, row) 625 if err != nil { 626 if ErrNilOperand.Is(err) { 627 return nil, nil 628 } 629 630 return nil, err 631 } 632 633 return result == -1, nil 634 } 635 636 // WithChildren implements the Expression interface. 637 func (lt *LessThan) WithChildren(children ...sql.Expression) (sql.Expression, error) { 638 if len(children) != 2 { 639 return nil, sql.ErrInvalidChildrenNumber.New(lt, len(children), 2) 640 } 641 return NewLessThan(children[0], children[1]), nil 642 } 643 644 func (lt *LessThan) String() string { 645 return fmt.Sprintf("(%s < %s)", lt.Left(), lt.Right()) 646 } 647 648 func (lt *LessThan) DebugString() string { 649 pr := sql.NewTreePrinter() 650 _ = pr.WriteNode("LessThan") 651 children := []string{sql.DebugString(lt.Left()), sql.DebugString(lt.Right())} 652 _ = pr.WriteChildren(children...) 653 return pr.String() 654 } 655 656 // GreaterThanOrEqual is a comparison that checks an expression is greater or equal to 657 // another. 658 type GreaterThanOrEqual struct { 659 comparison 660 } 661 662 var _ sql.Expression = (*GreaterThanOrEqual)(nil) 663 var _ sql.CollationCoercible = (*GreaterThanOrEqual)(nil) 664 665 // NewGreaterThanOrEqual creates a new GreaterThanOrEqual 666 func NewGreaterThanOrEqual(left sql.Expression, right sql.Expression) *GreaterThanOrEqual { 667 return &GreaterThanOrEqual{newComparison(left, right)} 668 } 669 670 // CollationCoercibility implements the interface sql.CollationCoercible. 671 func (gte *GreaterThanOrEqual) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 672 return sql.Collation_binary, 5 673 } 674 675 // Eval implements the Expression interface. 676 func (gte *GreaterThanOrEqual) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) { 677 result, err := gte.Compare(ctx, row) 678 if err != nil { 679 if ErrNilOperand.Is(err) { 680 return nil, nil 681 } 682 683 return nil, err 684 } 685 686 return result > -1, nil 687 } 688 689 // WithChildren implements the Expression interface. 690 func (gte *GreaterThanOrEqual) WithChildren(children ...sql.Expression) (sql.Expression, error) { 691 if len(children) != 2 { 692 return nil, sql.ErrInvalidChildrenNumber.New(gte, len(children), 2) 693 } 694 return NewGreaterThanOrEqual(children[0], children[1]), nil 695 } 696 697 func (gte *GreaterThanOrEqual) String() string { 698 return fmt.Sprintf("(%s >= %s)", gte.Left(), gte.Right()) 699 } 700 701 func (gte *GreaterThanOrEqual) DebugString() string { 702 pr := sql.NewTreePrinter() 703 _ = pr.WriteNode("GreaterThanOrEqual") 704 children := []string{sql.DebugString(gte.Left()), sql.DebugString(gte.Right())} 705 _ = pr.WriteChildren(children...) 706 return pr.String() 707 } 708 709 // LessThanOrEqual is a comparison that checks an expression is equal or lower than 710 // another. 711 type LessThanOrEqual struct { 712 comparison 713 } 714 715 var _ sql.Expression = (*LessThanOrEqual)(nil) 716 var _ sql.CollationCoercible = (*LessThanOrEqual)(nil) 717 718 // NewLessThanOrEqual creates a LessThanOrEqual expression. 719 func NewLessThanOrEqual(left sql.Expression, right sql.Expression) *LessThanOrEqual { 720 return &LessThanOrEqual{newComparison(left, right)} 721 } 722 723 // CollationCoercibility implements the interface sql.CollationCoercible. 724 func (lte *LessThanOrEqual) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 725 return sql.Collation_binary, 5 726 } 727 728 // Eval implements the Expression interface. 729 func (lte *LessThanOrEqual) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) { 730 result, err := lte.Compare(ctx, row) 731 if err != nil { 732 if ErrNilOperand.Is(err) { 733 return nil, nil 734 } 735 736 return nil, err 737 } 738 739 return result < 1, nil 740 } 741 742 // WithChildren implements the Expression interface. 743 func (lte *LessThanOrEqual) WithChildren(children ...sql.Expression) (sql.Expression, error) { 744 if len(children) != 2 { 745 return nil, sql.ErrInvalidChildrenNumber.New(lte, len(children), 2) 746 } 747 return NewLessThanOrEqual(children[0], children[1]), nil 748 } 749 750 func (lte *LessThanOrEqual) String() string { 751 return fmt.Sprintf("(%s <= %s)", lte.Left(), lte.Right()) 752 } 753 754 func (lte *LessThanOrEqual) DebugString() string { 755 pr := sql.NewTreePrinter() 756 _ = pr.WriteNode("LessThanOrEqual") 757 children := []string{sql.DebugString(lte.Left()), sql.DebugString(lte.Right())} 758 _ = pr.WriteChildren(children...) 759 return pr.String() 760 } 761 762 var ( 763 // ErrUnsupportedInOperand is returned when there is an invalid righthand 764 // operand in an IN operator. 765 ErrUnsupportedInOperand = errors.NewKind("right operand in IN operation must be tuple, but is %T") 766 )