github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/sql/sem/tree/eval.go (about) 1 // Copyright 2015 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package tree 12 13 import ( 14 "fmt" 15 16 "github.com/cockroachdb/cockroachdb-parser/pkg/geo" 17 "github.com/cockroachdb/cockroachdb-parser/pkg/sql/pgwire/pgcode" 18 "github.com/cockroachdb/cockroachdb-parser/pkg/sql/pgwire/pgerror" 19 "github.com/cockroachdb/cockroachdb-parser/pkg/sql/sem/cast" 20 "github.com/cockroachdb/cockroachdb-parser/pkg/sql/sem/tree/treebin" 21 "github.com/cockroachdb/cockroachdb-parser/pkg/sql/sem/tree/treecmp" 22 "github.com/cockroachdb/cockroachdb-parser/pkg/sql/sem/volatility" 23 "github.com/cockroachdb/cockroachdb-parser/pkg/sql/types" 24 "github.com/cockroachdb/cockroachdb-parser/pkg/util/iterutil" 25 "github.com/cockroachdb/cockroachdb-parser/pkg/util/json" 26 "github.com/cockroachdb/errors" 27 "github.com/cockroachdb/redact" 28 "github.com/lib/pq/oid" 29 ) 30 31 //go:generate go run ./evalgen *.go 32 33 var ( 34 // ErrIntOutOfRange is reported when integer arithmetic overflows. 35 ErrIntOutOfRange = pgerror.New(pgcode.NumericValueOutOfRange, "integer out of range") 36 // ErrInt4OutOfRange is reported when casting to INT4 overflows. 37 ErrInt4OutOfRange = pgerror.New(pgcode.NumericValueOutOfRange, "integer out of range for type int4") 38 // ErrInt2OutOfRange is reported when casting to INT2 overflows. 39 ErrInt2OutOfRange = pgerror.New(pgcode.NumericValueOutOfRange, "integer out of range for type int2") 40 // ErrFloatOutOfRange is reported when float arithmetic overflows. 41 ErrFloatOutOfRange = pgerror.New(pgcode.NumericValueOutOfRange, "float out of range") 42 // ErrDecOutOfRange is reported when decimal arithmetic overflows. 43 ErrDecOutOfRange = pgerror.New(pgcode.NumericValueOutOfRange, "decimal out of range") 44 // ErrCharOutOfRange is reported when int cast to ASCII byte overflows. 45 ErrCharOutOfRange = pgerror.New(pgcode.NumericValueOutOfRange, "\"char\" out of range") 46 47 // ErrDivByZero is reported on a division by zero. 48 ErrDivByZero = pgerror.New(pgcode.DivisionByZero, "division by zero") 49 // ErrSqrtOfNegNumber is reported when taking the sqrt of a negative number. 50 ErrSqrtOfNegNumber = pgerror.New(pgcode.InvalidArgumentForPowerFunction, "cannot take square root of a negative number") 51 52 // ErrShiftArgOutOfRange is reported when a shift argument is out of range. 53 ErrShiftArgOutOfRange = pgerror.New(pgcode.InvalidParameterValue, "shift argument out of range") 54 ) 55 56 // NewCannotMixBitArraySizesError creates an error for the case when a bitwise 57 // aggregate function is called on bit arrays with different sizes. 58 func NewCannotMixBitArraySizesError(op string) error { 59 return pgerror.Newf(pgcode.StringDataLengthMismatch, 60 "cannot %s bit strings of different sizes", op) 61 } 62 63 // UnaryOp is a unary operator. 64 type UnaryOp struct { 65 Typ *types.T 66 ReturnType *types.T 67 EvalOp UnaryEvalOp 68 Volatility volatility.V 69 70 types TypeList 71 retType ReturnTyper 72 73 // OnTypeCheck is called when the op is type checked. 74 OnTypeCheck func() 75 } 76 77 func (op *UnaryOp) params() TypeList { 78 return op.types 79 } 80 81 func (op *UnaryOp) returnType() ReturnTyper { 82 return op.retType 83 } 84 85 func (*UnaryOp) preferred() bool { 86 return false 87 } 88 89 func unaryOpFixups( 90 ops map[UnaryOperatorSymbol]*UnaryOpOverloads, 91 ) map[UnaryOperatorSymbol]*UnaryOpOverloads { 92 for _, overload := range ops { 93 for _, impl := range overload.overloads { 94 impl.types = ParamTypes{{"arg", impl.Typ}} 95 impl.retType = FixedReturnType(impl.ReturnType) 96 } 97 } 98 return ops 99 } 100 101 // UnaryOpOverloads is an overloaded set of unary operator implementations. 102 // It implements overloadSet. 103 type UnaryOpOverloads struct { 104 overloads []*UnaryOp 105 } 106 107 func (u *UnaryOpOverloads) len() int { return len(u.overloads) } 108 func (u *UnaryOpOverloads) get(i int) overloadImpl { return u.overloads[i] } 109 110 // ForEachUnaryOp iterates the set of overloads. 111 func (u *UnaryOpOverloads) ForEachUnaryOp(f func(op *UnaryOp) error) error { 112 if u == nil { 113 return nil 114 } 115 for _, op := range u.overloads { 116 if err := f(op); err != nil { 117 return iterutil.Map(err) 118 } 119 } 120 return nil 121 } 122 123 // UnaryOps contains the unary operations indexed by operation type. 124 var UnaryOps = unaryOpFixups(map[UnaryOperatorSymbol]*UnaryOpOverloads{ 125 UnaryPlus: {overloads: []*UnaryOp{ 126 { 127 Typ: types.Int, 128 ReturnType: types.Int, 129 EvalOp: &UnaryNoop{}, 130 Volatility: volatility.Immutable, 131 }, 132 { 133 Typ: types.Float, 134 ReturnType: types.Float, 135 EvalOp: &UnaryNoop{}, 136 Volatility: volatility.Immutable, 137 }, 138 { 139 Typ: types.Decimal, 140 ReturnType: types.Decimal, 141 EvalOp: &UnaryNoop{}, 142 Volatility: volatility.Immutable, 143 }, 144 { 145 Typ: types.Interval, 146 ReturnType: types.Interval, 147 EvalOp: &UnaryNoop{}, 148 Volatility: volatility.Immutable, 149 }, 150 }}, 151 152 UnaryMinus: {overloads: []*UnaryOp{ 153 { 154 Typ: types.Int, 155 ReturnType: types.Int, 156 EvalOp: &UnaryMinusIntOp{}, 157 Volatility: volatility.Immutable, 158 }, 159 { 160 Typ: types.Float, 161 ReturnType: types.Float, 162 EvalOp: &UnaryMinusFloatOp{}, 163 Volatility: volatility.Immutable, 164 }, 165 { 166 Typ: types.Decimal, 167 ReturnType: types.Decimal, 168 EvalOp: &UnaryMinusDecimalOp{}, 169 Volatility: volatility.Immutable, 170 }, 171 { 172 Typ: types.Interval, 173 ReturnType: types.Interval, 174 EvalOp: &UnaryMinusIntervalOp{}, 175 Volatility: volatility.Immutable, 176 }, 177 }}, 178 179 UnaryComplement: {overloads: []*UnaryOp{ 180 { 181 Typ: types.Int, 182 ReturnType: types.Int, 183 EvalOp: &ComplementIntOp{}, 184 Volatility: volatility.Immutable, 185 }, 186 { 187 Typ: types.VarBit, 188 ReturnType: types.VarBit, 189 EvalOp: &ComplementVarBitOp{}, 190 Volatility: volatility.Immutable, 191 }, 192 { 193 Typ: types.INet, 194 ReturnType: types.INet, 195 EvalOp: &ComplementINetOp{}, 196 Volatility: volatility.Immutable, 197 }, 198 }}, 199 200 UnarySqrt: {overloads: []*UnaryOp{ 201 { 202 Typ: types.Float, 203 ReturnType: types.Float, 204 EvalOp: &SqrtFloatOp{}, 205 Volatility: volatility.Immutable, 206 }, 207 { 208 Typ: types.Decimal, 209 ReturnType: types.Decimal, 210 EvalOp: &SqrtDecimalOp{}, 211 Volatility: volatility.Immutable, 212 }, 213 }}, 214 215 UnaryCbrt: {overloads: []*UnaryOp{ 216 { 217 Typ: types.Float, 218 ReturnType: types.Float, 219 EvalOp: &CbrtFloatOp{}, 220 Volatility: volatility.Immutable, 221 }, 222 { 223 Typ: types.Decimal, 224 ReturnType: types.Decimal, 225 EvalOp: &CbrtDecimalOp{}, 226 Volatility: volatility.Immutable, 227 }, 228 }}, 229 }) 230 231 // BinOp is a binary operator. 232 type BinOp struct { 233 LeftType *types.T 234 RightType *types.T 235 ReturnType *types.T 236 CalledOnNullInput bool 237 EvalOp BinaryEvalOp 238 Volatility volatility.V 239 PreferredOverload bool 240 241 types TypeList 242 retType ReturnTyper 243 244 OnTypeCheck func() 245 } 246 247 func (op *BinOp) params() TypeList { 248 return op.types 249 } 250 251 func (op *BinOp) matchParams(l, r *types.T) bool { 252 return op.params().MatchAt(l, 0) && op.params().MatchAt(r, 1) 253 } 254 255 func (op *BinOp) returnType() ReturnTyper { 256 return op.retType 257 } 258 259 func (op *BinOp) preferred() bool { 260 return op.PreferredOverload 261 } 262 263 // AppendToMaybeNullArray appends an element to an array. If the first 264 // argument is NULL, an array of one element is created. 265 func AppendToMaybeNullArray(typ *types.T, left Datum, right Datum) (Datum, error) { 266 result := NewDArray(typ) 267 if left != DNull { 268 for _, e := range MustBeDArray(left).Array { 269 if err := result.Append(e); err != nil { 270 return nil, err 271 } 272 } 273 } 274 if err := result.Append(right); err != nil { 275 return nil, err 276 } 277 return result, nil 278 } 279 280 // PrependToMaybeNullArray prepends an element in the front of an arrray. 281 // If the argument is NULL, an array of one element is created. 282 func PrependToMaybeNullArray(typ *types.T, left Datum, right Datum) (Datum, error) { 283 result := NewDArray(typ) 284 if err := result.Append(left); err != nil { 285 return nil, err 286 } 287 if right != DNull { 288 for _, e := range MustBeDArray(right).Array { 289 if err := result.Append(e); err != nil { 290 return nil, err 291 } 292 } 293 } 294 return result, nil 295 } 296 297 // TODO(justin): these might be improved by making arrays into an interface and 298 // then introducing a ConcatenatedArray implementation which just references two 299 // existing arrays. This would optimize the common case of appending an element 300 // (or array) to an array from O(n) to O(1). 301 func initArrayElementConcatenation() { 302 for _, t := range types.Scalar { 303 typ := t 304 addBinOp(treebin.Concat, &BinOp{ 305 LeftType: types.MakeArray(typ), 306 RightType: typ, 307 ReturnType: types.MakeArray(typ), 308 CalledOnNullInput: true, 309 EvalOp: &AppendToMaybeNullArrayOp{Typ: typ}, 310 Volatility: volatility.Immutable, 311 }, &BinOp{ 312 LeftType: typ, 313 RightType: types.MakeArray(typ), 314 ReturnType: types.MakeArray(typ), 315 CalledOnNullInput: true, 316 EvalOp: &PrependToMaybeNullArrayOp{Typ: typ}, 317 Volatility: volatility.Immutable, 318 }) 319 } 320 } 321 322 // ConcatArrays concatenates two arrays. 323 func ConcatArrays(typ *types.T, left Datum, right Datum) (Datum, error) { 324 if left == DNull && right == DNull { 325 return DNull, nil 326 } 327 result := NewDArray(typ) 328 if left != DNull { 329 for _, e := range MustBeDArray(left).Array { 330 if err := result.Append(e); err != nil { 331 return nil, err 332 } 333 } 334 } 335 if right != DNull { 336 for _, e := range MustBeDArray(right).Array { 337 if err := result.Append(e); err != nil { 338 return nil, err 339 } 340 } 341 } 342 return result, nil 343 } 344 345 // ArrayContains return true if the haystack contains all needles. 346 func ArrayContains(ctx CompareContext, haystack *DArray, needles *DArray) (*DBool, error) { 347 if !haystack.ParamTyp.Equivalent(needles.ParamTyp) { 348 return DBoolFalse, pgerror.New(pgcode.DatatypeMismatch, "cannot compare arrays with different element types") 349 } 350 for _, needle := range needles.Array { 351 // Nulls don't compare to each other in @> syntax. 352 if needle == DNull { 353 return DBoolFalse, nil 354 } 355 var found bool 356 for _, hay := range haystack.Array { 357 if cmp, err := needle.CompareError(ctx, hay); err != nil { 358 return DBoolFalse, err 359 } else if cmp == 0 { 360 found = true 361 break 362 } 363 } 364 if !found { 365 return DBoolFalse, nil 366 } 367 } 368 return DBoolTrue, nil 369 } 370 371 // ArrayOverlaps return true if there is even one element 372 // common between the left and right arrays. 373 func ArrayOverlaps(ctx CompareContext, array, other *DArray) (*DBool, error) { 374 if !array.ParamTyp.Equivalent(other.ParamTyp) { 375 return nil, pgerror.New(pgcode.DatatypeMismatch, "cannot compare arrays with different element types") 376 } 377 for _, needle := range array.Array { 378 // Nulls don't compare to each other in && syntax. 379 if needle == DNull { 380 continue 381 } 382 for _, hay := range other.Array { 383 if cmp, err := needle.CompareError(ctx, hay); err != nil { 384 return DBoolFalse, err 385 } else if cmp == 0 { 386 return DBoolTrue, nil 387 } 388 } 389 } 390 return DBoolFalse, nil 391 } 392 393 // JSONExistsAny return true if any value in dArray is exist in the json 394 func JSONExistsAny(json DJSON, dArray *DArray) (*DBool, error) { 395 // TODO(justin): this can be optimized. 396 for _, k := range dArray.Array { 397 if k == DNull { 398 continue 399 } 400 e, err := json.JSON.Exists(string(MustBeDString(k))) 401 if err != nil { 402 return nil, err 403 } 404 if e { 405 return DBoolTrue, nil 406 } 407 } 408 return DBoolFalse, nil 409 } 410 411 func initArrayToArrayConcatenation() { 412 for _, t := range types.Scalar { 413 typ := t 414 at := types.MakeArray(typ) 415 addBinOp(treebin.Concat, &BinOp{ 416 LeftType: at, 417 RightType: at, 418 ReturnType: at, 419 CalledOnNullInput: true, 420 EvalOp: &ConcatArraysOp{Typ: typ}, 421 Volatility: volatility.Immutable, 422 }) 423 } 424 } 425 426 // initNonArrayToNonArrayConcatenation initializes string + nonarrayelement 427 // and nonarrayelement + string concatenation. 428 func initNonArrayToNonArrayConcatenation() { 429 addConcat := func(leftType, rightType *types.T, volatility volatility.V) { 430 addBinOp(treebin.Concat, &BinOp{ 431 LeftType: leftType, 432 RightType: rightType, 433 ReturnType: types.String, 434 CalledOnNullInput: false, 435 EvalOp: &ConcatOp{ 436 Left: leftType, 437 Right: rightType, 438 }, 439 Volatility: volatility, 440 }) 441 } 442 fromTypeToVolatility := make(map[oid.Oid]volatility.V) 443 cast.ForEachCast(func(src, tgt oid.Oid, _ cast.Context, _ cast.ContextOrigin, v volatility.V) { 444 if tgt == oid.T_text { 445 fromTypeToVolatility[src] = v 446 } 447 }) 448 // We allow tuple + string concatenation, as well as any scalar types. 449 for _, t := range append([]*types.T{types.AnyTuple}, types.Scalar...) { 450 // Do not re-add String+String or String+Bytes, as they already exist 451 // and have predefined correct behavior. 452 if t != types.String && t != types.Bytes { 453 addConcat(t, types.String, fromTypeToVolatility[t.Oid()]) 454 addConcat(types.String, t, fromTypeToVolatility[t.Oid()]) 455 } 456 } 457 } 458 459 func init() { 460 initArrayElementConcatenation() 461 initArrayToArrayConcatenation() 462 initNonArrayToNonArrayConcatenation() 463 } 464 465 func init() { 466 for _, overload := range BinOps { 467 _ = overload.ForEachBinOp(func(impl *BinOp) error { 468 impl.types = ParamTypes{{"left", impl.LeftType}, {"right", impl.RightType}} 469 impl.retType = FixedReturnType(impl.ReturnType) 470 return nil 471 }) 472 } 473 } 474 475 // BinOpOverloads is an overloaded set of binary operator implementations. 476 // It implements overloadSet. 477 type BinOpOverloads struct { 478 overloads []*BinOp 479 } 480 481 // ForEachBinOp iterates the BinOps in the set. 482 func (o *BinOpOverloads) ForEachBinOp(f func(op *BinOp) error) error { 483 if o == nil { 484 return nil 485 } 486 for _, ol := range o.overloads { 487 if err := f(ol); err != nil { 488 return iterutil.Map(err) 489 } 490 } 491 return nil 492 } 493 494 func (o *BinOpOverloads) len() int { return len(o.overloads) } 495 func (o *BinOpOverloads) get(i int) overloadImpl { return o.overloads[i] } 496 497 // LookupImpl can be used to look up the overload which match the requested types. 498 func (o *BinOpOverloads) LookupImpl(left, right *types.T) (*BinOp, bool) { 499 if o == nil { 500 return nil, false 501 } 502 for _, ol := range o.overloads { 503 if ol.matchParams(left, right) { 504 return ol, true 505 } 506 } 507 return nil, false 508 } 509 510 // GetJSONPath is used for the #> and #>> operators. 511 func GetJSONPath(j json.JSON, ary DArray) (json.JSON, error) { 512 // TODO(justin): this is slightly annoying because we have to allocate 513 // a new array since the JSON package isn't aware of DArray. 514 path := make([]string, len(ary.Array)) 515 for i, v := range ary.Array { 516 if v == DNull { 517 return nil, nil 518 } 519 path[i] = string(MustBeDString(v)) 520 } 521 return json.FetchPath(j, path) 522 } 523 524 func addBinOp(symbol treebin.BinaryOperatorSymbol, ops ...*BinOp) { 525 s, ok := BinOps[symbol] 526 if !ok { 527 s = new(BinOpOverloads) 528 BinOps[symbol] = s 529 } 530 s.overloads = append(s.overloads, ops...) 531 } 532 533 // BinOps contains the binary operations indexed by operation type. 534 var BinOps = map[treebin.BinaryOperatorSymbol]*BinOpOverloads{ 535 treebin.Bitand: {overloads: []*BinOp{ 536 { 537 LeftType: types.Int, 538 RightType: types.Int, 539 ReturnType: types.Int, 540 EvalOp: &BitAndIntOp{}, 541 Volatility: volatility.Immutable, 542 }, 543 { 544 LeftType: types.VarBit, 545 RightType: types.VarBit, 546 ReturnType: types.VarBit, 547 EvalOp: &BitAndVarBitOp{}, 548 Volatility: volatility.Immutable, 549 }, 550 { 551 LeftType: types.INet, 552 RightType: types.INet, 553 ReturnType: types.INet, 554 EvalOp: &BitAndINetOp{}, 555 Volatility: volatility.Immutable, 556 }, 557 }}, 558 559 treebin.Bitor: {overloads: []*BinOp{ 560 { 561 LeftType: types.Int, 562 RightType: types.Int, 563 ReturnType: types.Int, 564 EvalOp: &BitOrIntOp{}, 565 Volatility: volatility.Immutable, 566 }, 567 { 568 LeftType: types.VarBit, 569 RightType: types.VarBit, 570 ReturnType: types.VarBit, 571 EvalOp: &BitOrVarBitOp{}, 572 Volatility: volatility.Immutable, 573 }, 574 { 575 LeftType: types.INet, 576 RightType: types.INet, 577 ReturnType: types.INet, 578 EvalOp: &BitOrINetOp{}, 579 Volatility: volatility.Immutable, 580 }, 581 }}, 582 583 treebin.Bitxor: {overloads: []*BinOp{ 584 { 585 LeftType: types.Int, 586 RightType: types.Int, 587 ReturnType: types.Int, 588 EvalOp: &BitXorIntOp{}, 589 Volatility: volatility.Immutable, 590 }, 591 { 592 LeftType: types.VarBit, 593 RightType: types.VarBit, 594 ReturnType: types.VarBit, 595 EvalOp: &BitXorVarBitOp{}, 596 Volatility: volatility.Immutable, 597 }, 598 }}, 599 600 treebin.Plus: {overloads: []*BinOp{ 601 { 602 LeftType: types.Int, 603 RightType: types.Int, 604 ReturnType: types.Int, 605 EvalOp: &PlusIntOp{}, 606 Volatility: volatility.Immutable, 607 }, 608 { 609 LeftType: types.Float, 610 RightType: types.Float, 611 ReturnType: types.Float, 612 EvalOp: &PlusFloatOp{}, 613 Volatility: volatility.Immutable, 614 }, 615 { 616 LeftType: types.Decimal, 617 RightType: types.Decimal, 618 ReturnType: types.Decimal, 619 EvalOp: &PlusDecimalOp{}, 620 Volatility: volatility.Immutable, 621 }, 622 { 623 LeftType: types.Decimal, 624 RightType: types.Int, 625 ReturnType: types.Decimal, 626 EvalOp: &PlusDecimalIntOp{}, 627 Volatility: volatility.Immutable, 628 }, 629 { 630 LeftType: types.Int, 631 RightType: types.Decimal, 632 ReturnType: types.Decimal, 633 EvalOp: &PlusIntDecimalOp{}, 634 Volatility: volatility.Immutable, 635 }, 636 { 637 LeftType: types.Date, 638 RightType: types.Int, 639 ReturnType: types.Date, 640 EvalOp: &PlusDateIntOp{}, 641 Volatility: volatility.Immutable, 642 }, 643 { 644 LeftType: types.Int, 645 RightType: types.Date, 646 ReturnType: types.Date, 647 EvalOp: &PlusIntDateOp{}, 648 Volatility: volatility.Immutable, 649 }, 650 { 651 LeftType: types.Date, 652 RightType: types.Time, 653 ReturnType: types.Timestamp, 654 EvalOp: &PlusDateTimeOp{}, 655 Volatility: volatility.Immutable, 656 }, 657 { 658 LeftType: types.Time, 659 RightType: types.Date, 660 ReturnType: types.Timestamp, 661 EvalOp: &PlusTimeDateOp{}, 662 Volatility: volatility.Immutable, 663 }, 664 { 665 LeftType: types.Date, 666 RightType: types.TimeTZ, 667 ReturnType: types.TimestampTZ, 668 EvalOp: &PlusDateTimeTZOp{}, 669 Volatility: volatility.Immutable, 670 }, 671 { 672 LeftType: types.TimeTZ, 673 RightType: types.Date, 674 ReturnType: types.TimestampTZ, 675 EvalOp: &PlusTimeTZDateOp{}, 676 Volatility: volatility.Immutable, 677 }, 678 { 679 LeftType: types.Time, 680 RightType: types.Interval, 681 ReturnType: types.Time, 682 EvalOp: &PlusTimeIntervalOp{}, 683 Volatility: volatility.Immutable, 684 }, 685 { 686 LeftType: types.Interval, 687 RightType: types.Time, 688 ReturnType: types.Time, 689 EvalOp: &PlusIntervalTimeOp{}, 690 Volatility: volatility.Immutable, 691 }, 692 { 693 LeftType: types.TimeTZ, 694 RightType: types.Interval, 695 ReturnType: types.TimeTZ, 696 EvalOp: &PlusTimeTZIntervalOp{}, 697 Volatility: volatility.Immutable, 698 }, 699 { 700 LeftType: types.Interval, 701 RightType: types.TimeTZ, 702 ReturnType: types.TimeTZ, 703 EvalOp: &PlusIntervalTimeTZOp{}, 704 Volatility: volatility.Immutable, 705 }, 706 { 707 LeftType: types.Timestamp, 708 RightType: types.Interval, 709 ReturnType: types.Timestamp, 710 EvalOp: &PlusTimestampIntervalOp{}, 711 Volatility: volatility.Immutable, 712 }, 713 { 714 LeftType: types.Interval, 715 RightType: types.Timestamp, 716 ReturnType: types.Timestamp, 717 EvalOp: &PlusIntervalTimestampOp{}, 718 Volatility: volatility.Immutable, 719 }, 720 { 721 LeftType: types.TimestampTZ, 722 RightType: types.Interval, 723 ReturnType: types.TimestampTZ, 724 EvalOp: &PlusTimestampTZIntervalOp{}, 725 Volatility: volatility.Stable, 726 }, 727 { 728 LeftType: types.Interval, 729 RightType: types.TimestampTZ, 730 ReturnType: types.TimestampTZ, 731 EvalOp: &PlusIntervalTimestampTZOp{}, 732 Volatility: volatility.Stable, 733 }, 734 { 735 LeftType: types.Interval, 736 RightType: types.Interval, 737 ReturnType: types.Interval, 738 EvalOp: &PlusIntervalOp{}, 739 Volatility: volatility.Immutable, 740 }, 741 { 742 LeftType: types.Date, 743 RightType: types.Interval, 744 ReturnType: types.Timestamp, 745 EvalOp: &PlusDateIntervalOp{}, 746 Volatility: volatility.Immutable, 747 }, 748 { 749 LeftType: types.Interval, 750 RightType: types.Date, 751 ReturnType: types.Timestamp, 752 EvalOp: &PlusIntervalDateOp{}, 753 Volatility: volatility.Immutable, 754 }, 755 { 756 LeftType: types.INet, 757 RightType: types.Int, 758 ReturnType: types.INet, 759 EvalOp: &PlusINetIntOp{}, 760 Volatility: volatility.Immutable, 761 }, 762 { 763 LeftType: types.Int, 764 RightType: types.INet, 765 ReturnType: types.INet, 766 EvalOp: &PlusIntINetOp{}, 767 Volatility: volatility.Immutable, 768 }, 769 { 770 LeftType: types.Decimal, 771 RightType: types.PGLSN, 772 ReturnType: types.PGLSN, 773 EvalOp: &PlusDecimalPGLSNOp{}, 774 Volatility: volatility.Immutable, 775 }, 776 { 777 LeftType: types.PGLSN, 778 RightType: types.Decimal, 779 ReturnType: types.PGLSN, 780 EvalOp: &PlusPGLSNDecimalOp{}, 781 Volatility: volatility.Immutable, 782 }, 783 }}, 784 785 treebin.Minus: {overloads: []*BinOp{ 786 { 787 LeftType: types.Int, 788 RightType: types.Int, 789 ReturnType: types.Int, 790 EvalOp: &MinusIntOp{}, 791 Volatility: volatility.Immutable, 792 }, 793 { 794 LeftType: types.Float, 795 RightType: types.Float, 796 ReturnType: types.Float, 797 EvalOp: &MinusFloatOp{}, 798 Volatility: volatility.Immutable, 799 }, 800 { 801 LeftType: types.Decimal, 802 RightType: types.Decimal, 803 ReturnType: types.Decimal, 804 EvalOp: &MinusDecimalOp{}, 805 Volatility: volatility.Immutable, 806 }, 807 { 808 LeftType: types.Decimal, 809 RightType: types.Int, 810 ReturnType: types.Decimal, 811 EvalOp: &MinusDecimalIntOp{}, 812 Volatility: volatility.Immutable, 813 }, 814 { 815 LeftType: types.Int, 816 RightType: types.Decimal, 817 ReturnType: types.Decimal, 818 EvalOp: &MinusIntDecimalOp{}, 819 Volatility: volatility.Immutable, 820 }, 821 { 822 LeftType: types.Date, 823 RightType: types.Int, 824 ReturnType: types.Date, 825 EvalOp: &MinusDateIntOp{}, 826 Volatility: volatility.Immutable, 827 }, 828 { 829 LeftType: types.Date, 830 RightType: types.Date, 831 ReturnType: types.Int, 832 EvalOp: &MinusDateOp{}, 833 Volatility: volatility.Immutable, 834 }, 835 { 836 LeftType: types.Date, 837 RightType: types.Time, 838 ReturnType: types.Timestamp, 839 EvalOp: &MinusDateTimeOp{}, 840 Volatility: volatility.Immutable, 841 }, 842 { 843 LeftType: types.Time, 844 RightType: types.Time, 845 ReturnType: types.Interval, 846 EvalOp: &MinusTimeOp{}, 847 Volatility: volatility.Immutable, 848 }, 849 { 850 LeftType: types.Timestamp, 851 RightType: types.Timestamp, 852 ReturnType: types.Interval, 853 EvalOp: &MinusTimestampOp{}, 854 Volatility: volatility.Immutable, 855 }, 856 { 857 LeftType: types.TimestampTZ, 858 RightType: types.TimestampTZ, 859 ReturnType: types.Interval, 860 EvalOp: &MinusTimestampTZOp{}, 861 Volatility: volatility.Immutable, 862 }, 863 { 864 LeftType: types.Timestamp, 865 RightType: types.TimestampTZ, 866 ReturnType: types.Interval, 867 EvalOp: &MinusTimestampTimestampTZOp{}, 868 Volatility: volatility.Stable, 869 }, 870 { 871 LeftType: types.TimestampTZ, 872 RightType: types.Timestamp, 873 ReturnType: types.Interval, 874 EvalOp: &MinusTimestampTZTimestampOp{}, 875 Volatility: volatility.Stable, 876 }, 877 { 878 LeftType: types.Time, 879 RightType: types.Interval, 880 ReturnType: types.Time, 881 EvalOp: &MinusTimeIntervalOp{}, 882 Volatility: volatility.Immutable, 883 }, 884 { 885 LeftType: types.TimeTZ, 886 RightType: types.Interval, 887 ReturnType: types.TimeTZ, 888 EvalOp: &MinusTimeTZIntervalOp{}, 889 Volatility: volatility.Immutable, 890 }, 891 { 892 LeftType: types.Timestamp, 893 RightType: types.Interval, 894 ReturnType: types.Timestamp, 895 EvalOp: &MinusTimestampIntervalOp{}, 896 Volatility: volatility.Immutable, 897 }, 898 { 899 LeftType: types.TimestampTZ, 900 RightType: types.Interval, 901 ReturnType: types.TimestampTZ, 902 EvalOp: &MinusTimestampTZIntervalOp{}, 903 Volatility: volatility.Stable, 904 }, 905 { 906 LeftType: types.Date, 907 RightType: types.Interval, 908 ReturnType: types.Timestamp, 909 EvalOp: &MinusDateIntervalOp{}, 910 Volatility: volatility.Immutable, 911 }, 912 { 913 LeftType: types.Interval, 914 RightType: types.Interval, 915 ReturnType: types.Interval, 916 EvalOp: &MinusIntervalOp{}, 917 Volatility: volatility.Immutable, 918 }, 919 { 920 LeftType: types.Jsonb, 921 RightType: types.String, 922 ReturnType: types.Jsonb, 923 EvalOp: &MinusJsonbStringOp{}, 924 Volatility: volatility.Immutable, 925 }, 926 { 927 LeftType: types.Jsonb, 928 RightType: types.Int, 929 ReturnType: types.Jsonb, 930 EvalOp: &MinusJsonbIntOp{}, 931 Volatility: volatility.Immutable, 932 }, 933 { 934 LeftType: types.Jsonb, 935 RightType: types.MakeArray(types.String), 936 ReturnType: types.Jsonb, 937 EvalOp: &MinusJsonbStringArrayOp{}, 938 Volatility: volatility.Immutable, 939 }, 940 { 941 LeftType: types.INet, 942 RightType: types.INet, 943 ReturnType: types.Int, 944 EvalOp: &MinusINetOp{}, 945 Volatility: volatility.Immutable, 946 }, 947 { 948 // Note: postgres ver 10 does NOT have Int - INet. Throws ERROR: 42883. 949 LeftType: types.INet, 950 RightType: types.Int, 951 ReturnType: types.INet, 952 EvalOp: &MinusINetIntOp{}, 953 Volatility: volatility.Immutable, 954 }, 955 { 956 LeftType: types.PGLSN, 957 RightType: types.Decimal, 958 ReturnType: types.PGLSN, 959 EvalOp: &MinusPGLSNDecimalOp{}, 960 Volatility: volatility.Immutable, 961 }, 962 { 963 LeftType: types.PGLSN, 964 RightType: types.PGLSN, 965 ReturnType: types.Decimal, 966 EvalOp: &MinusPGLSNOp{}, 967 Volatility: volatility.Immutable, 968 }, 969 }}, 970 971 treebin.Mult: {overloads: []*BinOp{ 972 { 973 LeftType: types.Int, 974 RightType: types.Int, 975 ReturnType: types.Int, 976 EvalOp: &MultIntOp{}, 977 Volatility: volatility.Immutable, 978 }, 979 { 980 LeftType: types.Float, 981 RightType: types.Float, 982 ReturnType: types.Float, 983 EvalOp: &MultFloatOp{}, 984 Volatility: volatility.Immutable, 985 }, 986 { 987 LeftType: types.Decimal, 988 RightType: types.Decimal, 989 ReturnType: types.Decimal, 990 EvalOp: &MultDecimalOp{}, 991 Volatility: volatility.Immutable, 992 }, 993 // The following two overloads are needed because DInt/DInt = DDecimal. Due 994 // to this operation, normalization may sometimes create a DInt * DDecimal 995 // operation. 996 { 997 LeftType: types.Decimal, 998 RightType: types.Int, 999 ReturnType: types.Decimal, 1000 EvalOp: &MultDecimalIntOp{}, 1001 Volatility: volatility.Immutable, 1002 }, 1003 { 1004 LeftType: types.Int, 1005 RightType: types.Decimal, 1006 ReturnType: types.Decimal, 1007 EvalOp: &MultIntDecimalOp{}, 1008 Volatility: volatility.Immutable, 1009 }, 1010 { 1011 LeftType: types.Int, 1012 RightType: types.Interval, 1013 ReturnType: types.Interval, 1014 EvalOp: &MultIntIntervalOp{}, 1015 Volatility: volatility.Immutable, 1016 }, 1017 { 1018 LeftType: types.Interval, 1019 RightType: types.Int, 1020 ReturnType: types.Interval, 1021 EvalOp: &MultIntervalIntOp{}, 1022 Volatility: volatility.Immutable, 1023 }, 1024 { 1025 LeftType: types.Interval, 1026 RightType: types.Float, 1027 ReturnType: types.Interval, 1028 EvalOp: &MultIntervalFloatOp{}, 1029 Volatility: volatility.Immutable, 1030 }, 1031 { 1032 LeftType: types.Float, 1033 RightType: types.Interval, 1034 ReturnType: types.Interval, 1035 EvalOp: &MultFloatIntervalOp{}, 1036 Volatility: volatility.Immutable, 1037 }, 1038 { 1039 LeftType: types.Decimal, 1040 RightType: types.Interval, 1041 ReturnType: types.Interval, 1042 EvalOp: &MultDecimalIntervalOp{}, 1043 Volatility: volatility.Immutable, 1044 }, 1045 { 1046 LeftType: types.Interval, 1047 RightType: types.Decimal, 1048 ReturnType: types.Interval, 1049 EvalOp: &MultIntervalDecimalOp{}, 1050 Volatility: volatility.Immutable, 1051 }, 1052 }}, 1053 1054 treebin.Div: {overloads: []*BinOp{ 1055 { 1056 LeftType: types.Int, 1057 RightType: types.Int, 1058 ReturnType: types.Decimal, 1059 EvalOp: &DivIntOp{}, 1060 Volatility: volatility.Immutable, 1061 }, 1062 { 1063 LeftType: types.Float, 1064 RightType: types.Float, 1065 ReturnType: types.Float, 1066 EvalOp: &DivFloatOp{}, 1067 Volatility: volatility.Immutable, 1068 }, 1069 { 1070 LeftType: types.Decimal, 1071 RightType: types.Decimal, 1072 ReturnType: types.Decimal, 1073 EvalOp: &DivDecimalOp{}, 1074 Volatility: volatility.Immutable, 1075 }, 1076 { 1077 LeftType: types.Decimal, 1078 RightType: types.Int, 1079 ReturnType: types.Decimal, 1080 EvalOp: &DivDecimalIntOp{}, 1081 Volatility: volatility.Immutable, 1082 }, 1083 { 1084 LeftType: types.Int, 1085 RightType: types.Decimal, 1086 ReturnType: types.Decimal, 1087 EvalOp: &DivIntDecimalOp{}, 1088 Volatility: volatility.Immutable, 1089 }, 1090 { 1091 LeftType: types.Interval, 1092 RightType: types.Int, 1093 ReturnType: types.Interval, 1094 EvalOp: &DivIntervalIntOp{}, 1095 Volatility: volatility.Immutable, 1096 }, 1097 { 1098 LeftType: types.Interval, 1099 RightType: types.Float, 1100 ReturnType: types.Interval, 1101 EvalOp: &DivIntervalFloatOp{}, 1102 Volatility: volatility.Immutable, 1103 }, 1104 }}, 1105 1106 treebin.FloorDiv: {overloads: []*BinOp{ 1107 { 1108 LeftType: types.Int, 1109 RightType: types.Int, 1110 ReturnType: types.Int, 1111 EvalOp: &FloorDivIntOp{}, 1112 Volatility: volatility.Immutable, 1113 }, 1114 { 1115 LeftType: types.Float, 1116 RightType: types.Float, 1117 ReturnType: types.Float, 1118 EvalOp: &FloorDivFloatOp{}, 1119 Volatility: volatility.Immutable, 1120 }, 1121 { 1122 LeftType: types.Decimal, 1123 RightType: types.Decimal, 1124 ReturnType: types.Decimal, 1125 EvalOp: &FloorDivDecimalOp{}, 1126 Volatility: volatility.Immutable, 1127 }, 1128 { 1129 LeftType: types.Decimal, 1130 RightType: types.Int, 1131 ReturnType: types.Decimal, 1132 EvalOp: &FloorDivDecimalIntOp{}, 1133 Volatility: volatility.Immutable, 1134 }, 1135 { 1136 LeftType: types.Int, 1137 RightType: types.Decimal, 1138 ReturnType: types.Decimal, 1139 EvalOp: &FloorDivIntDecimalOp{}, 1140 Volatility: volatility.Immutable, 1141 }, 1142 }}, 1143 1144 treebin.Mod: {overloads: []*BinOp{ 1145 { 1146 LeftType: types.Int, 1147 RightType: types.Int, 1148 ReturnType: types.Int, 1149 EvalOp: &ModIntOp{}, 1150 Volatility: volatility.Immutable, 1151 }, 1152 { 1153 LeftType: types.Float, 1154 RightType: types.Float, 1155 ReturnType: types.Float, 1156 EvalOp: &ModFloatOp{}, 1157 Volatility: volatility.Immutable, 1158 }, 1159 { 1160 LeftType: types.Decimal, 1161 RightType: types.Decimal, 1162 ReturnType: types.Decimal, 1163 EvalOp: &ModDecimalOp{}, 1164 Volatility: volatility.Immutable, 1165 }, 1166 { 1167 LeftType: types.Decimal, 1168 RightType: types.Int, 1169 ReturnType: types.Decimal, 1170 EvalOp: &ModDecimalIntOp{}, 1171 Volatility: volatility.Immutable, 1172 }, 1173 { 1174 LeftType: types.Int, 1175 RightType: types.Decimal, 1176 ReturnType: types.Decimal, 1177 EvalOp: &ModIntDecimalOp{}, 1178 Volatility: volatility.Immutable, 1179 }, 1180 { 1181 LeftType: types.String, 1182 RightType: types.String, 1183 ReturnType: types.Bool, 1184 EvalOp: &ModStringOp{}, 1185 // This operator is only stable because its result depends on the value 1186 // of the pg_trgm.similarity_threshold session setting. 1187 Volatility: volatility.Stable, 1188 }, 1189 }}, 1190 1191 treebin.Concat: {overloads: []*BinOp{ 1192 { 1193 LeftType: types.String, 1194 RightType: types.String, 1195 ReturnType: types.String, 1196 EvalOp: &ConcatStringOp{}, 1197 Volatility: volatility.Immutable, 1198 }, 1199 { 1200 LeftType: types.Bytes, 1201 RightType: types.Bytes, 1202 ReturnType: types.Bytes, 1203 EvalOp: &ConcatBytesOp{}, 1204 Volatility: volatility.Immutable, 1205 }, 1206 { 1207 LeftType: types.VarBit, 1208 RightType: types.VarBit, 1209 ReturnType: types.VarBit, 1210 EvalOp: &ConcatVarBitOp{}, 1211 Volatility: volatility.Immutable, 1212 }, 1213 { 1214 LeftType: types.Jsonb, 1215 RightType: types.Jsonb, 1216 ReturnType: types.Jsonb, 1217 EvalOp: &ConcatJsonbOp{}, 1218 Volatility: volatility.Immutable, 1219 }, 1220 }}, 1221 1222 // TODO(pmattis): Check that the shift is valid. 1223 treebin.LShift: {overloads: []*BinOp{ 1224 { 1225 LeftType: types.Int, 1226 RightType: types.Int, 1227 ReturnType: types.Int, 1228 EvalOp: &LShiftIntOp{}, 1229 Volatility: volatility.Immutable, 1230 }, 1231 { 1232 LeftType: types.VarBit, 1233 RightType: types.Int, 1234 ReturnType: types.VarBit, 1235 EvalOp: &LShiftVarBitIntOp{}, 1236 Volatility: volatility.Immutable, 1237 }, 1238 { 1239 LeftType: types.INet, 1240 RightType: types.INet, 1241 ReturnType: types.Bool, 1242 EvalOp: &LShiftINetOp{}, 1243 Volatility: volatility.Immutable, 1244 }, 1245 }}, 1246 1247 treebin.RShift: {overloads: []*BinOp{ 1248 { 1249 LeftType: types.Int, 1250 RightType: types.Int, 1251 ReturnType: types.Int, 1252 EvalOp: &RShiftIntOp{}, 1253 Volatility: volatility.Immutable, 1254 }, 1255 { 1256 LeftType: types.VarBit, 1257 RightType: types.Int, 1258 ReturnType: types.VarBit, 1259 EvalOp: &RShiftVarBitIntOp{}, 1260 Volatility: volatility.Immutable, 1261 }, 1262 { 1263 LeftType: types.INet, 1264 RightType: types.INet, 1265 ReturnType: types.Bool, 1266 EvalOp: &RShiftINetOp{}, 1267 Volatility: volatility.Immutable, 1268 }, 1269 }}, 1270 1271 treebin.Pow: {overloads: []*BinOp{ 1272 { 1273 LeftType: types.Int, 1274 RightType: types.Int, 1275 ReturnType: types.Int, 1276 EvalOp: &PowIntOp{}, 1277 Volatility: volatility.Immutable, 1278 }, 1279 { 1280 LeftType: types.Float, 1281 RightType: types.Float, 1282 ReturnType: types.Float, 1283 EvalOp: &PowFloatOp{}, 1284 Volatility: volatility.Immutable, 1285 }, 1286 { 1287 LeftType: types.Decimal, 1288 RightType: types.Decimal, 1289 ReturnType: types.Decimal, 1290 EvalOp: &PowDecimalOp{}, 1291 Volatility: volatility.Immutable, 1292 }, 1293 { 1294 LeftType: types.Decimal, 1295 RightType: types.Int, 1296 ReturnType: types.Decimal, 1297 EvalOp: &PowDecimalIntOp{}, 1298 Volatility: volatility.Immutable, 1299 }, 1300 { 1301 LeftType: types.Int, 1302 RightType: types.Decimal, 1303 ReturnType: types.Decimal, 1304 EvalOp: &PowIntDecimalOp{}, 1305 Volatility: volatility.Immutable, 1306 }, 1307 }}, 1308 1309 treebin.JSONFetchVal: {overloads: []*BinOp{ 1310 { 1311 LeftType: types.Jsonb, 1312 RightType: types.String, 1313 ReturnType: types.Jsonb, 1314 EvalOp: &JSONFetchValStringOp{}, 1315 PreferredOverload: true, 1316 Volatility: volatility.Immutable, 1317 }, 1318 { 1319 LeftType: types.Jsonb, 1320 RightType: types.Int, 1321 ReturnType: types.Jsonb, 1322 EvalOp: &JSONFetchValIntOp{}, 1323 Volatility: volatility.Immutable, 1324 }, 1325 }}, 1326 1327 treebin.JSONFetchValPath: {overloads: []*BinOp{ 1328 { 1329 LeftType: types.Jsonb, 1330 RightType: types.MakeArray(types.String), 1331 ReturnType: types.Jsonb, 1332 EvalOp: &JSONFetchValPathOp{}, 1333 Volatility: volatility.Immutable, 1334 }, 1335 }}, 1336 1337 treebin.JSONFetchText: {overloads: []*BinOp{ 1338 { 1339 LeftType: types.Jsonb, 1340 RightType: types.String, 1341 ReturnType: types.String, 1342 PreferredOverload: true, 1343 EvalOp: &JSONFetchTextStringOp{}, 1344 Volatility: volatility.Immutable, 1345 }, 1346 { 1347 LeftType: types.Jsonb, 1348 RightType: types.Int, 1349 ReturnType: types.String, 1350 EvalOp: &JSONFetchTextIntOp{}, 1351 Volatility: volatility.Immutable, 1352 }, 1353 }}, 1354 1355 treebin.JSONFetchTextPath: {overloads: []*BinOp{ 1356 { 1357 LeftType: types.Jsonb, 1358 RightType: types.MakeArray(types.String), 1359 ReturnType: types.String, 1360 EvalOp: &JSONFetchTextPathOp{}, 1361 Volatility: volatility.Immutable, 1362 }, 1363 }}, 1364 } 1365 1366 // CmpOp is a comparison operator. 1367 type CmpOp struct { 1368 types TypeList 1369 1370 LeftType *types.T 1371 RightType *types.T 1372 1373 // Datum return type is a union between *DBool and dNull. 1374 EvalOp BinaryEvalOp 1375 1376 OnTypeCheck func() 1377 1378 // If CalledOnNullInput is false, the operator returns NULL 1379 // whenever either argument is NULL. 1380 CalledOnNullInput bool 1381 1382 Volatility volatility.V 1383 1384 PreferredOverload bool 1385 } 1386 1387 func (op *CmpOp) params() TypeList { 1388 return op.types 1389 } 1390 1391 func (op *CmpOp) matchParams(l, r *types.T) bool { 1392 return op.params().MatchAt(l, 0) && op.params().MatchAt(r, 1) 1393 } 1394 1395 var cmpOpReturnType = FixedReturnType(types.Bool) 1396 1397 func (op *CmpOp) returnType() ReturnTyper { 1398 return cmpOpReturnType 1399 } 1400 1401 func (op *CmpOp) preferred() bool { 1402 return op.PreferredOverload 1403 } 1404 1405 func cmpOpFixups( 1406 cmpOps map[treecmp.ComparisonOperatorSymbol]*CmpOpOverloads, 1407 ) map[treecmp.ComparisonOperatorSymbol]*CmpOpOverloads { 1408 findVolatility := func(op treecmp.ComparisonOperatorSymbol, t *types.T) volatility.V { 1409 for _, o := range cmpOps[treecmp.EQ].overloads { 1410 if o.LeftType.Equivalent(t) && o.RightType.Equivalent(t) { 1411 return o.Volatility 1412 } 1413 } 1414 panic(errors.AssertionFailedf( 1415 "could not find cmp op %s(%s,%s)", 1416 redact.Safe(op.String()), t.SQLStringForError(), t.SQLStringForError(), 1417 )) 1418 } 1419 1420 // Array equality comparisons. 1421 for _, t := range append(types.Scalar, types.AnyEnum) { 1422 appendCmpOp := func(sym treecmp.ComparisonOperatorSymbol, cmpOp *CmpOp) { 1423 s, ok := cmpOps[sym] 1424 if !ok { 1425 s = new(CmpOpOverloads) 1426 cmpOps[sym] = s 1427 } 1428 s.overloads = append(s.overloads, cmpOp) 1429 } 1430 appendCmpOp(treecmp.EQ, &CmpOp{ 1431 LeftType: types.MakeArray(t), 1432 RightType: types.MakeArray(t), 1433 EvalOp: &CompareScalarOp{treecmp.MakeComparisonOperator(treecmp.EQ)}, 1434 Volatility: findVolatility(treecmp.EQ, t), 1435 }) 1436 appendCmpOp(treecmp.LE, &CmpOp{ 1437 LeftType: types.MakeArray(t), 1438 RightType: types.MakeArray(t), 1439 EvalOp: &CompareScalarOp{treecmp.MakeComparisonOperator(treecmp.LE)}, 1440 Volatility: findVolatility(treecmp.LE, t), 1441 }) 1442 appendCmpOp(treecmp.LT, &CmpOp{ 1443 LeftType: types.MakeArray(t), 1444 RightType: types.MakeArray(t), 1445 EvalOp: &CompareScalarOp{treecmp.MakeComparisonOperator(treecmp.LT)}, 1446 Volatility: findVolatility(treecmp.LT, t), 1447 }) 1448 appendCmpOp(treecmp.IsNotDistinctFrom, &CmpOp{ 1449 LeftType: types.MakeArray(t), 1450 RightType: types.MakeArray(t), 1451 EvalOp: &CompareScalarOp{treecmp.MakeComparisonOperator(treecmp.IsNotDistinctFrom)}, 1452 CalledOnNullInput: true, 1453 Volatility: findVolatility(treecmp.IsNotDistinctFrom, t), 1454 }) 1455 } 1456 1457 for _, overloads := range cmpOps { 1458 _ = overloads.ForEachCmpOp(func(op *CmpOp) error { 1459 op.types = ParamTypes{{"left", op.LeftType}, {"right", op.RightType}} 1460 return nil 1461 }) 1462 } 1463 1464 return cmpOps 1465 } 1466 1467 // CmpOpOverloads is an overloaded set of comparison operator implementations. 1468 type CmpOpOverloads struct { 1469 overloads []*CmpOp 1470 } 1471 1472 func (o *CmpOpOverloads) len() int { return len(o.overloads) } 1473 func (o *CmpOpOverloads) get(i int) overloadImpl { return o.overloads[i] } 1474 1475 // LookupImpl is used to look up the overload for a pair of types. 1476 func (o *CmpOpOverloads) LookupImpl(left, right *types.T) (*CmpOp, bool) { 1477 if o == nil { 1478 return nil, false 1479 } 1480 for _, fn := range o.overloads { 1481 if fn.matchParams(left, right) { 1482 return fn, true 1483 } 1484 } 1485 return nil, false 1486 } 1487 1488 // ForEachCmpOp iterates the ops in the set. 1489 func (o *CmpOpOverloads) ForEachCmpOp(f func(op *CmpOp) error) error { 1490 if o == nil { 1491 return nil 1492 } 1493 for _, ol := range o.overloads { 1494 if err := f(ol); err != nil { 1495 return iterutil.Map(err) 1496 } 1497 } 1498 return nil 1499 } 1500 1501 func makeCmpOpOverload( 1502 op treecmp.ComparisonOperatorSymbol, a, b *types.T, calledOnNullInput bool, v volatility.V, 1503 ) *CmpOp { 1504 return &CmpOp{ 1505 LeftType: a, 1506 RightType: b, 1507 EvalOp: &CompareScalarOp{ComparisonOperator: treecmp.MakeComparisonOperator(op)}, 1508 CalledOnNullInput: calledOnNullInput, 1509 Volatility: v, 1510 } 1511 } 1512 1513 func makeEqFn(a, b *types.T, v volatility.V) *CmpOp { 1514 return makeCmpOpOverload(treecmp.EQ, a, b, false, v) 1515 } 1516 func makeLtFn(a, b *types.T, v volatility.V) *CmpOp { 1517 return makeCmpOpOverload(treecmp.LT, a, b, false, v) 1518 } 1519 func makeLeFn(a, b *types.T, v volatility.V) *CmpOp { 1520 return makeCmpOpOverload(treecmp.LE, a, b, false, v) 1521 } 1522 func makeIsFn(a, b *types.T, v volatility.V) *CmpOp { 1523 return makeCmpOpOverload(treecmp.IsNotDistinctFrom, a, b, true, v) 1524 } 1525 1526 // CmpOps contains the comparison operations indexed by operation type. 1527 var CmpOps = cmpOpFixups(map[treecmp.ComparisonOperatorSymbol]*CmpOpOverloads{ 1528 treecmp.EQ: {overloads: []*CmpOp{ 1529 // Single-type comparisons. 1530 makeEqFn(types.AnyEnum, types.AnyEnum, volatility.Immutable), 1531 makeEqFn(types.Bool, types.Bool, volatility.Leakproof), 1532 makeEqFn(types.Bytes, types.Bytes, volatility.Leakproof), 1533 makeEqFn(types.Date, types.Date, volatility.Leakproof), 1534 makeEqFn(types.Decimal, types.Decimal, volatility.Immutable), 1535 // Note: it is an error to compare two strings with different collations; 1536 // the operator is leakproof under the assumption that these cases will be 1537 // detected during type checking. 1538 makeEqFn(types.AnyCollatedString, types.AnyCollatedString, volatility.Leakproof), 1539 makeEqFn(types.Float, types.Float, volatility.Leakproof), 1540 makeEqFn(types.Box2D, types.Box2D, volatility.Leakproof), 1541 makeEqFn(types.Geography, types.Geography, volatility.Leakproof), 1542 makeEqFn(types.Geometry, types.Geometry, volatility.Leakproof), 1543 makeEqFn(types.INet, types.INet, volatility.Leakproof), 1544 makeEqFn(types.Int, types.Int, volatility.Leakproof), 1545 makeEqFn(types.Interval, types.Interval, volatility.Leakproof), 1546 makeEqFn(types.Jsonb, types.Jsonb, volatility.Immutable), 1547 makeEqFn(types.Oid, types.Oid, volatility.Leakproof), 1548 makeEqFn(types.PGLSN, types.PGLSN, volatility.Leakproof), 1549 makeEqFn(types.RefCursor, types.RefCursor, volatility.Leakproof), 1550 makeEqFn(types.String, types.String, volatility.Leakproof), 1551 makeEqFn(types.Time, types.Time, volatility.Leakproof), 1552 makeEqFn(types.TimeTZ, types.TimeTZ, volatility.Leakproof), 1553 makeEqFn(types.Timestamp, types.Timestamp, volatility.Leakproof), 1554 makeEqFn(types.TimestampTZ, types.TimestampTZ, volatility.Leakproof), 1555 makeEqFn(types.TSQuery, types.TSQuery, volatility.Immutable), 1556 makeEqFn(types.TSVector, types.TSVector, volatility.Immutable), 1557 makeEqFn(types.Uuid, types.Uuid, volatility.Leakproof), 1558 makeEqFn(types.VarBit, types.VarBit, volatility.Leakproof), 1559 1560 // Mixed-type comparisons. 1561 makeEqFn(types.Date, types.Timestamp, volatility.Immutable), 1562 makeEqFn(types.Date, types.TimestampTZ, volatility.Stable), 1563 makeEqFn(types.Decimal, types.Float, volatility.Leakproof), 1564 makeEqFn(types.Decimal, types.Int, volatility.Leakproof), 1565 makeEqFn(types.Float, types.Decimal, volatility.Leakproof), 1566 makeEqFn(types.Float, types.Int, volatility.Leakproof), 1567 makeEqFn(types.Int, types.Decimal, volatility.Leakproof), 1568 makeEqFn(types.Int, types.Float, volatility.Leakproof), 1569 makeEqFn(types.Int, types.Oid, volatility.Leakproof), 1570 makeEqFn(types.Oid, types.Int, volatility.Leakproof), 1571 makeEqFn(types.Timestamp, types.Date, volatility.Immutable), 1572 makeEqFn(types.Timestamp, types.TimestampTZ, volatility.Stable), 1573 makeEqFn(types.TimestampTZ, types.Date, volatility.Stable), 1574 makeEqFn(types.TimestampTZ, types.Timestamp, volatility.Stable), 1575 makeEqFn(types.Time, types.TimeTZ, volatility.Stable), 1576 makeEqFn(types.TimeTZ, types.Time, volatility.Stable), 1577 1578 // Tuple comparison. 1579 { 1580 LeftType: types.AnyTuple, 1581 RightType: types.AnyTuple, 1582 EvalOp: &CompareTupleOp{ 1583 ComparisonOperator: treecmp.MakeComparisonOperator(treecmp.EQ), 1584 }, 1585 Volatility: volatility.Immutable, 1586 }, 1587 }}, 1588 1589 treecmp.LT: {overloads: []*CmpOp{ 1590 // Single-type comparisons. 1591 makeLtFn(types.AnyEnum, types.AnyEnum, volatility.Immutable), 1592 makeLtFn(types.Bool, types.Bool, volatility.Leakproof), 1593 makeLtFn(types.Bytes, types.Bytes, volatility.Leakproof), 1594 makeLtFn(types.Date, types.Date, volatility.Leakproof), 1595 makeLtFn(types.Decimal, types.Decimal, volatility.Immutable), 1596 // Note: it is an error to compare two strings with different collations; 1597 // the operator is leakproof under the assumption that these cases will be 1598 // detected during type checking. 1599 makeLtFn(types.AnyCollatedString, types.AnyCollatedString, volatility.Leakproof), 1600 makeLtFn(types.Float, types.Float, volatility.Leakproof), 1601 makeLtFn(types.Box2D, types.Box2D, volatility.Leakproof), 1602 makeLtFn(types.Geography, types.Geography, volatility.Leakproof), 1603 makeLtFn(types.Geometry, types.Geometry, volatility.Leakproof), 1604 makeLtFn(types.INet, types.INet, volatility.Leakproof), 1605 makeLtFn(types.Int, types.Int, volatility.Leakproof), 1606 makeLtFn(types.Interval, types.Interval, volatility.Leakproof), 1607 makeLtFn(types.Oid, types.Oid, volatility.Leakproof), 1608 makeLtFn(types.PGLSN, types.PGLSN, volatility.Leakproof), 1609 makeLtFn(types.RefCursor, types.RefCursor, volatility.Leakproof), 1610 makeLtFn(types.String, types.String, volatility.Leakproof), 1611 makeLtFn(types.Time, types.Time, volatility.Leakproof), 1612 makeLtFn(types.TimeTZ, types.TimeTZ, volatility.Leakproof), 1613 makeLtFn(types.Timestamp, types.Timestamp, volatility.Leakproof), 1614 makeLtFn(types.TimestampTZ, types.TimestampTZ, volatility.Leakproof), 1615 makeLtFn(types.Uuid, types.Uuid, volatility.Leakproof), 1616 makeLtFn(types.VarBit, types.VarBit, volatility.Leakproof), 1617 makeLtFn(types.Jsonb, types.Jsonb, volatility.Immutable), 1618 1619 // Mixed-type comparisons. 1620 makeLtFn(types.Date, types.Timestamp, volatility.Immutable), 1621 makeLtFn(types.Date, types.TimestampTZ, volatility.Stable), 1622 makeLtFn(types.Decimal, types.Float, volatility.Leakproof), 1623 makeLtFn(types.Decimal, types.Int, volatility.Leakproof), 1624 makeLtFn(types.Float, types.Decimal, volatility.Leakproof), 1625 makeLtFn(types.Float, types.Int, volatility.Leakproof), 1626 makeLtFn(types.Int, types.Decimal, volatility.Leakproof), 1627 makeLtFn(types.Int, types.Float, volatility.Leakproof), 1628 makeLtFn(types.Int, types.Oid, volatility.Leakproof), 1629 makeLtFn(types.Oid, types.Int, volatility.Leakproof), 1630 makeLtFn(types.Timestamp, types.Date, volatility.Immutable), 1631 makeLtFn(types.Timestamp, types.TimestampTZ, volatility.Stable), 1632 makeLtFn(types.TimestampTZ, types.Date, volatility.Stable), 1633 makeLtFn(types.TimestampTZ, types.Timestamp, volatility.Stable), 1634 makeLtFn(types.Time, types.TimeTZ, volatility.Stable), 1635 makeLtFn(types.TimeTZ, types.Time, volatility.Stable), 1636 1637 // Tuple comparison. 1638 { 1639 LeftType: types.AnyTuple, 1640 RightType: types.AnyTuple, 1641 EvalOp: &CompareTupleOp{ 1642 ComparisonOperator: treecmp.MakeComparisonOperator(treecmp.LT), 1643 }, 1644 Volatility: volatility.Immutable, 1645 }, 1646 }}, 1647 1648 treecmp.LE: {overloads: []*CmpOp{ 1649 // Single-type comparisons. 1650 makeLeFn(types.AnyEnum, types.AnyEnum, volatility.Immutable), 1651 makeLeFn(types.Bool, types.Bool, volatility.Leakproof), 1652 makeLeFn(types.Bytes, types.Bytes, volatility.Leakproof), 1653 makeLeFn(types.Date, types.Date, volatility.Leakproof), 1654 makeLeFn(types.Decimal, types.Decimal, volatility.Immutable), 1655 // Note: it is an error to compare two strings with different collations; 1656 // the operator is leakproof under the assumption that these cases will be 1657 // detected during type checking. 1658 makeLeFn(types.AnyCollatedString, types.AnyCollatedString, volatility.Leakproof), 1659 makeLeFn(types.Float, types.Float, volatility.Leakproof), 1660 makeLeFn(types.Box2D, types.Box2D, volatility.Leakproof), 1661 makeLeFn(types.Geography, types.Geography, volatility.Leakproof), 1662 makeLeFn(types.Geometry, types.Geometry, volatility.Leakproof), 1663 makeLeFn(types.INet, types.INet, volatility.Leakproof), 1664 makeLeFn(types.Int, types.Int, volatility.Leakproof), 1665 makeLeFn(types.Interval, types.Interval, volatility.Leakproof), 1666 makeLeFn(types.Oid, types.Oid, volatility.Leakproof), 1667 makeLeFn(types.PGLSN, types.PGLSN, volatility.Leakproof), 1668 makeLeFn(types.RefCursor, types.RefCursor, volatility.Leakproof), 1669 makeLeFn(types.String, types.String, volatility.Leakproof), 1670 makeLeFn(types.Time, types.Time, volatility.Leakproof), 1671 makeLeFn(types.TimeTZ, types.TimeTZ, volatility.Leakproof), 1672 makeLeFn(types.Timestamp, types.Timestamp, volatility.Leakproof), 1673 makeLeFn(types.TimestampTZ, types.TimestampTZ, volatility.Leakproof), 1674 makeLeFn(types.Uuid, types.Uuid, volatility.Leakproof), 1675 makeLeFn(types.VarBit, types.VarBit, volatility.Leakproof), 1676 makeLeFn(types.Jsonb, types.Jsonb, volatility.Immutable), 1677 1678 // Mixed-type comparisons. 1679 makeLeFn(types.Date, types.Timestamp, volatility.Immutable), 1680 makeLeFn(types.Date, types.TimestampTZ, volatility.Stable), 1681 makeLeFn(types.Decimal, types.Float, volatility.Leakproof), 1682 makeLeFn(types.Decimal, types.Int, volatility.Leakproof), 1683 makeLeFn(types.Float, types.Decimal, volatility.Leakproof), 1684 makeLeFn(types.Float, types.Int, volatility.Leakproof), 1685 makeLeFn(types.Int, types.Decimal, volatility.Leakproof), 1686 makeLeFn(types.Int, types.Float, volatility.Leakproof), 1687 makeLeFn(types.Int, types.Oid, volatility.Leakproof), 1688 makeLeFn(types.Oid, types.Int, volatility.Leakproof), 1689 makeLeFn(types.Timestamp, types.Date, volatility.Immutable), 1690 makeLeFn(types.Timestamp, types.TimestampTZ, volatility.Stable), 1691 makeLeFn(types.TimestampTZ, types.Date, volatility.Stable), 1692 makeLeFn(types.TimestampTZ, types.Timestamp, volatility.Stable), 1693 makeLeFn(types.Time, types.TimeTZ, volatility.Stable), 1694 makeLeFn(types.TimeTZ, types.Time, volatility.Stable), 1695 1696 // Tuple comparison. 1697 { 1698 LeftType: types.AnyTuple, 1699 RightType: types.AnyTuple, 1700 EvalOp: &CompareTupleOp{ 1701 ComparisonOperator: treecmp.MakeComparisonOperator(treecmp.LE), 1702 }, 1703 Volatility: volatility.Immutable, 1704 }, 1705 }}, 1706 1707 treecmp.IsNotDistinctFrom: {overloads: []*CmpOp{ 1708 { 1709 LeftType: types.Unknown, 1710 RightType: types.Unknown, 1711 EvalOp: &CompareScalarOp{ 1712 ComparisonOperator: treecmp.MakeComparisonOperator(treecmp.IsNotDistinctFrom), 1713 }, 1714 CalledOnNullInput: true, 1715 // Avoids ambiguous comparison error for NULL IS NOT DISTINCT FROM NULL. 1716 PreferredOverload: true, 1717 Volatility: volatility.Leakproof, 1718 }, 1719 { 1720 LeftType: types.AnyArray, 1721 RightType: types.Unknown, 1722 EvalOp: &CompareScalarOp{ 1723 ComparisonOperator: treecmp.MakeComparisonOperator(treecmp.IsNotDistinctFrom), 1724 }, 1725 CalledOnNullInput: true, 1726 Volatility: volatility.Leakproof, 1727 }, 1728 // Single-type comparisons. 1729 makeIsFn(types.AnyEnum, types.AnyEnum, volatility.Immutable), 1730 makeIsFn(types.Bool, types.Bool, volatility.Leakproof), 1731 makeIsFn(types.Bytes, types.Bytes, volatility.Leakproof), 1732 makeIsFn(types.Date, types.Date, volatility.Leakproof), 1733 makeIsFn(types.Decimal, types.Decimal, volatility.Immutable), 1734 // Note: it is an error to compare two strings with different collations; 1735 // the operator is leakproof under the assumption that these cases will be 1736 // detected during type checking. 1737 makeIsFn(types.AnyCollatedString, types.AnyCollatedString, volatility.Leakproof), 1738 makeIsFn(types.Float, types.Float, volatility.Leakproof), 1739 makeIsFn(types.Box2D, types.Box2D, volatility.Leakproof), 1740 makeIsFn(types.Geography, types.Geography, volatility.Leakproof), 1741 makeIsFn(types.Geometry, types.Geometry, volatility.Leakproof), 1742 makeIsFn(types.INet, types.INet, volatility.Leakproof), 1743 makeIsFn(types.Int, types.Int, volatility.Leakproof), 1744 makeIsFn(types.Interval, types.Interval, volatility.Leakproof), 1745 makeIsFn(types.Jsonb, types.Jsonb, volatility.Immutable), 1746 makeIsFn(types.Oid, types.Oid, volatility.Leakproof), 1747 makeIsFn(types.PGLSN, types.PGLSN, volatility.Leakproof), 1748 makeIsFn(types.RefCursor, types.RefCursor, volatility.Leakproof), 1749 makeIsFn(types.String, types.String, volatility.Leakproof), 1750 makeIsFn(types.Time, types.Time, volatility.Leakproof), 1751 makeIsFn(types.TimeTZ, types.TimeTZ, volatility.Leakproof), 1752 makeIsFn(types.Timestamp, types.Timestamp, volatility.Leakproof), 1753 makeIsFn(types.TimestampTZ, types.TimestampTZ, volatility.Leakproof), 1754 makeIsFn(types.TSQuery, types.TSQuery, volatility.Immutable), 1755 makeIsFn(types.TSVector, types.TSVector, volatility.Immutable), 1756 makeIsFn(types.Uuid, types.Uuid, volatility.Leakproof), 1757 makeIsFn(types.VarBit, types.VarBit, volatility.Leakproof), 1758 1759 // Mixed-type comparisons. 1760 makeIsFn(types.Date, types.Timestamp, volatility.Immutable), 1761 makeIsFn(types.Date, types.TimestampTZ, volatility.Stable), 1762 makeIsFn(types.Decimal, types.Float, volatility.Leakproof), 1763 makeIsFn(types.Decimal, types.Int, volatility.Leakproof), 1764 makeIsFn(types.Float, types.Decimal, volatility.Leakproof), 1765 makeIsFn(types.Float, types.Int, volatility.Leakproof), 1766 makeIsFn(types.Int, types.Decimal, volatility.Leakproof), 1767 makeIsFn(types.Int, types.Float, volatility.Leakproof), 1768 makeIsFn(types.Int, types.Oid, volatility.Leakproof), 1769 makeIsFn(types.Oid, types.Int, volatility.Leakproof), 1770 makeIsFn(types.Timestamp, types.Date, volatility.Immutable), 1771 makeIsFn(types.Timestamp, types.TimestampTZ, volatility.Stable), 1772 makeIsFn(types.TimestampTZ, types.Date, volatility.Stable), 1773 makeIsFn(types.TimestampTZ, types.Timestamp, volatility.Stable), 1774 makeIsFn(types.Time, types.TimeTZ, volatility.Stable), 1775 makeIsFn(types.TimeTZ, types.Time, volatility.Stable), 1776 1777 // Void is unique in that it is not equivalent with itself, so implicit 1778 // equivalence with Unknown in function ArgTypes.MatchAt due to the check 1779 // `(typ.Family() == types.UnknownFamily || a[i].Typ.Equivalent(typ))` does 1780 // not occur. Therefore, to allow the comparison 1781 // `''::VOID IS DISTINCT FROM NULL`, an explicit equivalence with Unknown is 1782 // added: 1783 makeIsFn(types.Void, types.Unknown, volatility.Leakproof), 1784 makeIsFn(types.Unknown, types.Void, volatility.Leakproof), 1785 1786 // Tuple comparison. 1787 { 1788 LeftType: types.AnyTuple, 1789 RightType: types.AnyTuple, 1790 CalledOnNullInput: true, 1791 EvalOp: &CompareAnyTupleOp{ 1792 ComparisonOperator: treecmp.MakeComparisonOperator(treecmp.IsNotDistinctFrom), 1793 }, 1794 Volatility: volatility.Immutable, 1795 }, 1796 }}, 1797 1798 treecmp.In: {overloads: []*CmpOp{ 1799 makeEvalTupleIn(types.AnyEnum, volatility.Leakproof), 1800 makeEvalTupleIn(types.Bool, volatility.Leakproof), 1801 makeEvalTupleIn(types.Bytes, volatility.Leakproof), 1802 makeEvalTupleIn(types.Date, volatility.Leakproof), 1803 makeEvalTupleIn(types.Decimal, volatility.Leakproof), 1804 makeEvalTupleIn(types.AnyCollatedString, volatility.Leakproof), 1805 makeEvalTupleIn(types.AnyTuple, volatility.Leakproof), 1806 makeEvalTupleIn(types.Float, volatility.Leakproof), 1807 makeEvalTupleIn(types.Box2D, volatility.Leakproof), 1808 makeEvalTupleIn(types.Geography, volatility.Leakproof), 1809 makeEvalTupleIn(types.Geometry, volatility.Leakproof), 1810 makeEvalTupleIn(types.INet, volatility.Leakproof), 1811 makeEvalTupleIn(types.Int, volatility.Leakproof), 1812 makeEvalTupleIn(types.Interval, volatility.Leakproof), 1813 makeEvalTupleIn(types.Jsonb, volatility.Leakproof), 1814 makeEvalTupleIn(types.Oid, volatility.Leakproof), 1815 makeEvalTupleIn(types.PGLSN, volatility.Leakproof), 1816 makeEvalTupleIn(types.RefCursor, volatility.Leakproof), 1817 makeEvalTupleIn(types.String, volatility.Leakproof), 1818 makeEvalTupleIn(types.Time, volatility.Leakproof), 1819 makeEvalTupleIn(types.TimeTZ, volatility.Leakproof), 1820 makeEvalTupleIn(types.Timestamp, volatility.Leakproof), 1821 makeEvalTupleIn(types.TimestampTZ, volatility.Leakproof), 1822 makeEvalTupleIn(types.Uuid, volatility.Leakproof), 1823 makeEvalTupleIn(types.VarBit, volatility.Leakproof), 1824 }}, 1825 1826 treecmp.Like: {overloads: []*CmpOp{ 1827 { 1828 LeftType: types.String, 1829 RightType: types.String, 1830 EvalOp: &MatchLikeOp{CaseInsensitive: false}, 1831 Volatility: volatility.Leakproof, 1832 }, 1833 }}, 1834 1835 treecmp.ILike: {overloads: []*CmpOp{ 1836 { 1837 LeftType: types.String, 1838 RightType: types.String, 1839 EvalOp: &MatchLikeOp{CaseInsensitive: true}, 1840 Volatility: volatility.Leakproof, 1841 }, 1842 }}, 1843 1844 treecmp.SimilarTo: {overloads: []*CmpOp{ 1845 { 1846 LeftType: types.String, 1847 RightType: types.String, 1848 EvalOp: &SimilarToOp{Escape: '\\'}, 1849 Volatility: volatility.Leakproof, 1850 }, 1851 }}, 1852 1853 treecmp.RegMatch: {overloads: append([]*CmpOp{ 1854 { 1855 LeftType: types.String, 1856 RightType: types.String, 1857 EvalOp: &MatchRegexpOp{}, 1858 Volatility: volatility.Immutable, 1859 }, 1860 }, 1861 makeBox2DComparisonOperators( 1862 func(lhs, rhs *geo.CartesianBoundingBox) bool { 1863 return lhs.Covers(rhs) 1864 }, 1865 )..., 1866 )}, 1867 1868 treecmp.RegIMatch: {overloads: []*CmpOp{ 1869 { 1870 LeftType: types.String, 1871 RightType: types.String, 1872 EvalOp: &MatchRegexpOp{CaseInsensitive: true}, 1873 Volatility: volatility.Immutable, 1874 }, 1875 }}, 1876 1877 treecmp.JSONExists: {overloads: []*CmpOp{ 1878 { 1879 LeftType: types.Jsonb, 1880 RightType: types.String, 1881 EvalOp: &JSONExistsOp{}, 1882 Volatility: volatility.Immutable, 1883 }, 1884 }}, 1885 1886 treecmp.JSONSomeExists: {overloads: []*CmpOp{ 1887 { 1888 LeftType: types.Jsonb, 1889 RightType: types.StringArray, 1890 EvalOp: &JSONSomeExistsOp{}, 1891 Volatility: volatility.Immutable, 1892 }, 1893 }}, 1894 1895 treecmp.JSONAllExists: {overloads: []*CmpOp{ 1896 { 1897 LeftType: types.Jsonb, 1898 RightType: types.StringArray, 1899 EvalOp: &JSONAllExistsOp{}, 1900 Volatility: volatility.Immutable, 1901 }, 1902 }}, 1903 1904 treecmp.Contains: {overloads: []*CmpOp{ 1905 { 1906 LeftType: types.AnyArray, 1907 RightType: types.AnyArray, 1908 EvalOp: &ContainsArrayOp{}, 1909 Volatility: volatility.Immutable, 1910 }, 1911 { 1912 LeftType: types.Jsonb, 1913 RightType: types.Jsonb, 1914 EvalOp: &ContainsJsonbOp{}, 1915 Volatility: volatility.Immutable, 1916 }, 1917 }}, 1918 1919 treecmp.ContainedBy: {overloads: []*CmpOp{ 1920 { 1921 LeftType: types.AnyArray, 1922 RightType: types.AnyArray, 1923 EvalOp: &ContainedByArrayOp{}, 1924 Volatility: volatility.Immutable, 1925 }, 1926 { 1927 LeftType: types.Jsonb, 1928 RightType: types.Jsonb, 1929 EvalOp: &ContainedByJsonbOp{}, 1930 Volatility: volatility.Immutable, 1931 }, 1932 }}, 1933 treecmp.Overlaps: {overloads: append([]*CmpOp{ 1934 { 1935 LeftType: types.AnyArray, 1936 RightType: types.AnyArray, 1937 EvalOp: &OverlapsArrayOp{}, 1938 Volatility: volatility.Immutable, 1939 }, 1940 { 1941 LeftType: types.INet, 1942 RightType: types.INet, 1943 EvalOp: &OverlapsINetOp{}, 1944 Volatility: volatility.Immutable, 1945 }, 1946 }, makeBox2DComparisonOperators( 1947 func(lhs, rhs *geo.CartesianBoundingBox) bool { 1948 return lhs.Intersects(rhs) 1949 }, 1950 )...), 1951 }, 1952 treecmp.TSMatches: {overloads: []*CmpOp{ 1953 { 1954 LeftType: types.TSQuery, 1955 RightType: types.TSVector, 1956 EvalOp: &TSMatchesQueryVectorOp{}, 1957 Volatility: volatility.Immutable, 1958 }, 1959 { 1960 LeftType: types.TSVector, 1961 RightType: types.TSQuery, 1962 EvalOp: &TSMatchesVectorQueryOp{}, 1963 Volatility: volatility.Immutable, 1964 }, 1965 }}, 1966 }) 1967 1968 func makeBox2DComparisonOperators(op func(lhs, rhs *geo.CartesianBoundingBox) bool) []*CmpOp { 1969 return []*CmpOp{ 1970 { 1971 LeftType: types.Box2D, 1972 RightType: types.Box2D, 1973 EvalOp: &CompareBox2DOp{Op: func(left, right Datum) bool { 1974 return op( 1975 &MustBeDBox2D(left).CartesianBoundingBox, 1976 &MustBeDBox2D(right).CartesianBoundingBox, 1977 ) 1978 }}, 1979 Volatility: volatility.Immutable, 1980 }, 1981 { 1982 LeftType: types.Box2D, 1983 RightType: types.Geometry, 1984 EvalOp: &CompareBox2DOp{Op: func(left, right Datum) bool { 1985 return op( 1986 &MustBeDBox2D(left).CartesianBoundingBox, 1987 MustBeDGeometry(right).CartesianBoundingBox(), 1988 ) 1989 }}, 1990 Volatility: volatility.Immutable, 1991 }, 1992 { 1993 LeftType: types.Geometry, 1994 RightType: types.Box2D, 1995 EvalOp: &CompareBox2DOp{Op: func(left, right Datum) bool { 1996 return op( 1997 MustBeDGeometry(left).CartesianBoundingBox(), 1998 &MustBeDBox2D(right).CartesianBoundingBox, 1999 ) 2000 }}, 2001 Volatility: volatility.Immutable, 2002 }, 2003 { 2004 LeftType: types.Geometry, 2005 RightType: types.Geometry, 2006 EvalOp: &CompareBox2DOp{Op: func(left, right Datum) bool { 2007 return op( 2008 MustBeDGeometry(left).CartesianBoundingBox(), 2009 MustBeDGeometry(right).CartesianBoundingBox(), 2010 ) 2011 }}, 2012 Volatility: volatility.Immutable, 2013 }, 2014 } 2015 } 2016 2017 // This map contains the inverses for operators in the CmpOps map that have 2018 // inverses. 2019 var cmpOpsInverse map[treecmp.ComparisonOperatorSymbol]treecmp.ComparisonOperatorSymbol 2020 2021 func init() { 2022 cmpOpsInverse = make(map[treecmp.ComparisonOperatorSymbol]treecmp.ComparisonOperatorSymbol) 2023 for cmpOp := treecmp.ComparisonOperatorSymbol(0); cmpOp < treecmp.NumComparisonOperatorSymbols; cmpOp++ { 2024 newOp, _, _, _, _ := FoldComparisonExpr(treecmp.MakeComparisonOperator(cmpOp), DNull, DNull) 2025 if newOp.Symbol != cmpOp { 2026 cmpOpsInverse[newOp.Symbol] = cmpOp 2027 cmpOpsInverse[cmpOp] = newOp.Symbol 2028 } 2029 } 2030 } 2031 2032 // CmpOpInverse returns the inverse of the comparison operator if it exists. The 2033 // second return value is true if it exists, and false otherwise. 2034 func CmpOpInverse(i treecmp.ComparisonOperatorSymbol) (treecmp.ComparisonOperatorSymbol, bool) { 2035 inverse, ok := cmpOpsInverse[i] 2036 return inverse, ok 2037 } 2038 2039 func makeEvalTupleIn(typ *types.T, v volatility.V) *CmpOp { 2040 return &CmpOp{ 2041 LeftType: typ, 2042 RightType: types.AnyTuple, 2043 EvalOp: &InTupleOp{}, 2044 CalledOnNullInput: true, 2045 Volatility: v, 2046 } 2047 } 2048 2049 // MultipleResultsError is returned by QueryRow when more than one result is 2050 // encountered. 2051 type MultipleResultsError struct { 2052 SQL string // the query that produced this error 2053 } 2054 2055 func (e *MultipleResultsError) Error() string { 2056 return fmt.Sprintf("%s: unexpected multiple results", e.SQL) 2057 } 2058 2059 // MaybeWrapError updates non-nil error depending on the FuncExpr to provide 2060 // more context. 2061 func (expr *FuncExpr) MaybeWrapError(err error) error { 2062 // If we are facing an explicit error, propagate it unchanged. 2063 fName := expr.Func.String() 2064 if fName == `crdb_internal.force_error` || fName == `crdb_internal.plpgsql_raise` || 2065 fName == `crdb_internal.plpgsql_close` || fName == `crdb_internal.plpgsql_fetch` { 2066 return err 2067 } 2068 // Otherwise, wrap it with context. 2069 newErr := errors.Wrapf(err, "%s()", errors.Safe(fName)) 2070 // Count function errors as it flows out of the system. We need to handle 2071 // them this way because if we are facing a retry error, in particular those 2072 // generated by crdb_internal.force_retry(), Wrap() will propagate it as a 2073 // non-pgerror error (so that the executor can see it with the right type). 2074 newErr = errors.WithTelemetry(newErr, fName+"()") 2075 return newErr 2076 } 2077 2078 // EqualComparisonFunctionExists looks up an overload of the "=" operator 2079 // for a given pair of input operand types. 2080 func EqualComparisonFunctionExists(leftType, rightType *types.T) bool { 2081 _, found := CmpOps[treecmp.EQ].LookupImpl(leftType, rightType) 2082 return found 2083 }