github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/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 "context" 15 "fmt" 16 "math" 17 "math/big" 18 "regexp" 19 "strings" 20 "time" 21 "unicode/utf8" 22 23 "github.com/cockroachdb/apd" 24 "github.com/cockroachdb/cockroach/pkg/base" 25 "github.com/cockroachdb/cockroach/pkg/keys" 26 "github.com/cockroachdb/cockroach/pkg/kv" 27 "github.com/cockroachdb/cockroach/pkg/roachpb" 28 "github.com/cockroachdb/cockroach/pkg/server/telemetry" 29 "github.com/cockroachdb/cockroach/pkg/settings/cluster" 30 "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode" 31 "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror" 32 "github.com/cockroachdb/cockroach/pkg/sql/sessiondata" 33 "github.com/cockroachdb/cockroach/pkg/sql/sqltelemetry" 34 "github.com/cockroachdb/cockroach/pkg/sql/types" 35 "github.com/cockroachdb/cockroach/pkg/util/arith" 36 "github.com/cockroachdb/cockroach/pkg/util/bitarray" 37 "github.com/cockroachdb/cockroach/pkg/util/duration" 38 "github.com/cockroachdb/cockroach/pkg/util/hlc" 39 "github.com/cockroachdb/cockroach/pkg/util/json" 40 "github.com/cockroachdb/cockroach/pkg/util/mon" 41 "github.com/cockroachdb/cockroach/pkg/util/timeofday" 42 "github.com/cockroachdb/cockroach/pkg/util/timeutil" 43 "github.com/cockroachdb/cockroach/pkg/util/uuid" 44 "github.com/cockroachdb/errors" 45 "github.com/lib/pq/oid" 46 ) 47 48 var ( 49 // ErrIntOutOfRange is reported when integer arithmetic overflows. 50 ErrIntOutOfRange = pgerror.New(pgcode.NumericValueOutOfRange, "integer out of range") 51 // ErrFloatOutOfRange is reported when float arithmetic overflows. 52 ErrFloatOutOfRange = pgerror.New(pgcode.NumericValueOutOfRange, "float out of range") 53 errDecOutOfRange = pgerror.New(pgcode.NumericValueOutOfRange, "decimal out of range") 54 55 // ErrDivByZero is reported on a division by zero. 56 ErrDivByZero = pgerror.New(pgcode.DivisionByZero, "division by zero") 57 errSqrtOfNegNumber = pgerror.New(pgcode.InvalidArgumentForPowerFunction, "cannot take square root of a negative number") 58 // ErrZeroModulus is reported when computing the rest of a division by zero. 59 ErrZeroModulus = pgerror.New(pgcode.DivisionByZero, "zero modulus") 60 61 big10E6 = big.NewInt(1e6) 62 big10E10 = big.NewInt(1e10) 63 ) 64 65 // NewCannotMixBitArraySizesError creates an error for the case when a bitwise 66 // aggregate function is called on bit arrays with different sizes. 67 func NewCannotMixBitArraySizesError(op string) error { 68 return pgerror.Newf(pgcode.StringDataLengthMismatch, 69 "cannot %s bit strings of different sizes", op) 70 } 71 72 // UnaryOp is a unary operator. 73 type UnaryOp struct { 74 Typ *types.T 75 ReturnType *types.T 76 Fn func(*EvalContext, Datum) (Datum, error) 77 Volatility Volatility 78 79 types TypeList 80 retType ReturnTyper 81 82 // counter, if non-nil, should be incremented every time the 83 // operator is type checked. 84 counter telemetry.Counter 85 } 86 87 func (op *UnaryOp) params() TypeList { 88 return op.types 89 } 90 91 func (op *UnaryOp) returnType() ReturnTyper { 92 return op.retType 93 } 94 95 func (*UnaryOp) preferred() bool { 96 return false 97 } 98 99 func unaryOpFixups(ops map[UnaryOperator]unaryOpOverload) map[UnaryOperator]unaryOpOverload { 100 for op, overload := range ops { 101 for i, impl := range overload { 102 casted := impl.(*UnaryOp) 103 casted.types = ArgTypes{{"arg", casted.Typ}} 104 casted.retType = FixedReturnType(casted.ReturnType) 105 ops[op][i] = casted 106 } 107 } 108 return ops 109 } 110 111 // unaryOpOverload is an overloaded set of unary operator implementations. 112 type unaryOpOverload []overloadImpl 113 114 // UnaryOps contains the unary operations indexed by operation type. 115 var UnaryOps = unaryOpFixups(map[UnaryOperator]unaryOpOverload{ 116 UnaryMinus: { 117 &UnaryOp{ 118 Typ: types.Int, 119 ReturnType: types.Int, 120 Fn: func(_ *EvalContext, d Datum) (Datum, error) { 121 i := MustBeDInt(d) 122 if i == math.MinInt64 { 123 return nil, ErrIntOutOfRange 124 } 125 return NewDInt(-i), nil 126 }, 127 Volatility: VolatilityImmutable, 128 }, 129 &UnaryOp{ 130 Typ: types.Float, 131 ReturnType: types.Float, 132 Fn: func(_ *EvalContext, d Datum) (Datum, error) { 133 return NewDFloat(-*d.(*DFloat)), nil 134 }, 135 Volatility: VolatilityImmutable, 136 }, 137 &UnaryOp{ 138 Typ: types.Decimal, 139 ReturnType: types.Decimal, 140 Fn: func(_ *EvalContext, d Datum) (Datum, error) { 141 dec := &d.(*DDecimal).Decimal 142 dd := &DDecimal{} 143 dd.Decimal.Neg(dec) 144 return dd, nil 145 }, 146 Volatility: VolatilityImmutable, 147 }, 148 &UnaryOp{ 149 Typ: types.Interval, 150 ReturnType: types.Interval, 151 Fn: func(_ *EvalContext, d Datum) (Datum, error) { 152 i := d.(*DInterval).Duration 153 i.SetNanos(-i.Nanos()) 154 i.Days = -i.Days 155 i.Months = -i.Months 156 return &DInterval{Duration: i}, nil 157 }, 158 Volatility: VolatilityImmutable, 159 }, 160 }, 161 162 UnaryComplement: { 163 &UnaryOp{ 164 Typ: types.Int, 165 ReturnType: types.Int, 166 Fn: func(_ *EvalContext, d Datum) (Datum, error) { 167 return NewDInt(^MustBeDInt(d)), nil 168 }, 169 Volatility: VolatilityImmutable, 170 }, 171 &UnaryOp{ 172 Typ: types.VarBit, 173 ReturnType: types.VarBit, 174 Fn: func(_ *EvalContext, d Datum) (Datum, error) { 175 p := MustBeDBitArray(d) 176 return &DBitArray{BitArray: bitarray.Not(p.BitArray)}, nil 177 }, 178 Volatility: VolatilityImmutable, 179 }, 180 &UnaryOp{ 181 Typ: types.INet, 182 ReturnType: types.INet, 183 Fn: func(_ *EvalContext, d Datum) (Datum, error) { 184 ipAddr := MustBeDIPAddr(d).IPAddr 185 return NewDIPAddr(DIPAddr{ipAddr.Complement()}), nil 186 }, 187 Volatility: VolatilityImmutable, 188 }, 189 }, 190 191 UnarySqrt: { 192 &UnaryOp{ 193 Typ: types.Float, 194 ReturnType: types.Float, 195 Fn: func(_ *EvalContext, d Datum) (Datum, error) { 196 return Sqrt(float64(*d.(*DFloat))) 197 }, 198 Volatility: VolatilityImmutable, 199 }, 200 &UnaryOp{ 201 Typ: types.Decimal, 202 ReturnType: types.Decimal, 203 Fn: func(_ *EvalContext, d Datum) (Datum, error) { 204 dec := &d.(*DDecimal).Decimal 205 return DecimalSqrt(dec) 206 }, 207 Volatility: VolatilityImmutable, 208 }, 209 }, 210 211 UnaryCbrt: { 212 &UnaryOp{ 213 Typ: types.Float, 214 ReturnType: types.Float, 215 Fn: func(_ *EvalContext, d Datum) (Datum, error) { 216 return Cbrt(float64(*d.(*DFloat))) 217 }, 218 Volatility: VolatilityImmutable, 219 }, 220 &UnaryOp{ 221 Typ: types.Decimal, 222 ReturnType: types.Decimal, 223 Fn: func(_ *EvalContext, d Datum) (Datum, error) { 224 dec := &d.(*DDecimal).Decimal 225 return DecimalCbrt(dec) 226 }, 227 Volatility: VolatilityImmutable, 228 }, 229 }, 230 }) 231 232 // BinOp is a binary operator. 233 type BinOp struct { 234 LeftType *types.T 235 RightType *types.T 236 ReturnType *types.T 237 NullableArgs bool 238 Fn func(*EvalContext, Datum, Datum) (Datum, error) 239 Volatility Volatility 240 241 types TypeList 242 retType ReturnTyper 243 244 // counter, if non-nil, should be incremented every time the 245 // operator is type checked. 246 counter telemetry.Counter 247 } 248 249 func (op *BinOp) params() TypeList { 250 return op.types 251 } 252 253 func (op *BinOp) matchParams(l, r *types.T) bool { 254 return op.params().MatchAt(l, 0) && op.params().MatchAt(r, 1) 255 } 256 257 func (op *BinOp) returnType() ReturnTyper { 258 return op.retType 259 } 260 261 func (*BinOp) preferred() bool { 262 return false 263 } 264 265 // AppendToMaybeNullArray appends an element to an array. If the first 266 // argument is NULL, an array of one element is created. 267 func AppendToMaybeNullArray(typ *types.T, left Datum, right Datum) (Datum, error) { 268 result := NewDArray(typ) 269 if left != DNull { 270 for _, e := range MustBeDArray(left).Array { 271 if err := result.Append(e); err != nil { 272 return nil, err 273 } 274 } 275 } 276 if err := result.Append(right); err != nil { 277 return nil, err 278 } 279 return result, nil 280 } 281 282 // PrependToMaybeNullArray prepends an element in the front of an arrray. 283 // If the argument is NULL, an array of one element is created. 284 func PrependToMaybeNullArray(typ *types.T, left Datum, right Datum) (Datum, error) { 285 result := NewDArray(typ) 286 if err := result.Append(left); err != nil { 287 return nil, err 288 } 289 if right != DNull { 290 for _, e := range MustBeDArray(right).Array { 291 if err := result.Append(e); err != nil { 292 return nil, err 293 } 294 } 295 } 296 return result, nil 297 } 298 299 // TODO(justin): these might be improved by making arrays into an interface and 300 // then introducing a ConcatenatedArray implementation which just references two 301 // existing arrays. This would optimize the common case of appending an element 302 // (or array) to an array from O(n) to O(1). 303 func initArrayElementConcatenation() { 304 for _, t := range types.Scalar { 305 typ := t 306 BinOps[Concat] = append(BinOps[Concat], &BinOp{ 307 LeftType: types.MakeArray(typ), 308 RightType: typ, 309 ReturnType: types.MakeArray(typ), 310 NullableArgs: true, 311 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 312 return AppendToMaybeNullArray(typ, left, right) 313 }, 314 Volatility: VolatilityImmutable, 315 }) 316 317 BinOps[Concat] = append(BinOps[Concat], &BinOp{ 318 LeftType: typ, 319 RightType: types.MakeArray(typ), 320 ReturnType: types.MakeArray(typ), 321 NullableArgs: true, 322 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 323 return PrependToMaybeNullArray(typ, left, right) 324 }, 325 Volatility: VolatilityImmutable, 326 }) 327 } 328 } 329 330 // ConcatArrays concatenates two arrays. 331 func ConcatArrays(typ *types.T, left Datum, right Datum) (Datum, error) { 332 if left == DNull && right == DNull { 333 return DNull, nil 334 } 335 result := NewDArray(typ) 336 if left != DNull { 337 for _, e := range MustBeDArray(left).Array { 338 if err := result.Append(e); err != nil { 339 return nil, err 340 } 341 } 342 } 343 if right != DNull { 344 for _, e := range MustBeDArray(right).Array { 345 if err := result.Append(e); err != nil { 346 return nil, err 347 } 348 } 349 } 350 return result, nil 351 } 352 353 // ArrayContains return true if the haystack contains all needles. 354 func ArrayContains(ctx *EvalContext, haystack *DArray, needles *DArray) (*DBool, error) { 355 if !haystack.ParamTyp.Equivalent(needles.ParamTyp) { 356 return DBoolFalse, pgerror.New(pgcode.DatatypeMismatch, "cannot compare arrays with different element types") 357 } 358 for _, needle := range needles.Array { 359 // Nulls don't compare to each other in @> syntax. 360 if needle == DNull { 361 return DBoolFalse, nil 362 } 363 var found bool 364 for _, hay := range haystack.Array { 365 if needle.Compare(ctx, hay) == 0 { 366 found = true 367 break 368 } 369 } 370 if !found { 371 return DBoolFalse, nil 372 } 373 } 374 return DBoolTrue, nil 375 } 376 377 func initArrayToArrayConcatenation() { 378 for _, t := range types.Scalar { 379 typ := t 380 BinOps[Concat] = append(BinOps[Concat], &BinOp{ 381 LeftType: types.MakeArray(typ), 382 RightType: types.MakeArray(typ), 383 ReturnType: types.MakeArray(typ), 384 NullableArgs: true, 385 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 386 return ConcatArrays(typ, left, right) 387 }, 388 Volatility: VolatilityImmutable, 389 }) 390 } 391 } 392 393 func init() { 394 initArrayElementConcatenation() 395 initArrayToArrayConcatenation() 396 } 397 398 func init() { 399 for op, overload := range BinOps { 400 for i, impl := range overload { 401 casted := impl.(*BinOp) 402 casted.types = ArgTypes{{"left", casted.LeftType}, {"right", casted.RightType}} 403 casted.retType = FixedReturnType(casted.ReturnType) 404 BinOps[op][i] = casted 405 } 406 } 407 } 408 409 // binOpOverload is an overloaded set of binary operator implementations. 410 type binOpOverload []overloadImpl 411 412 func (o binOpOverload) lookupImpl(left, right *types.T) (*BinOp, bool) { 413 for _, fn := range o { 414 casted := fn.(*BinOp) 415 if casted.matchParams(left, right) { 416 return casted, true 417 } 418 } 419 return nil, false 420 } 421 422 // getJSONPath is used for the #> and #>> operators. 423 func getJSONPath(j DJSON, ary DArray) (Datum, error) { 424 // TODO(justin): this is slightly annoying because we have to allocate 425 // a new array since the JSON package isn't aware of DArray. 426 path := make([]string, len(ary.Array)) 427 for i, v := range ary.Array { 428 if v == DNull { 429 return DNull, nil 430 } 431 path[i] = string(MustBeDString(v)) 432 } 433 result, err := json.FetchPath(j.JSON, path) 434 if err != nil { 435 return nil, err 436 } 437 if result == nil { 438 return DNull, nil 439 } 440 return &DJSON{result}, nil 441 } 442 443 // BinOps contains the binary operations indexed by operation type. 444 var BinOps = map[BinaryOperator]binOpOverload{ 445 Bitand: { 446 &BinOp{ 447 LeftType: types.Int, 448 RightType: types.Int, 449 ReturnType: types.Int, 450 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 451 return NewDInt(MustBeDInt(left) & MustBeDInt(right)), nil 452 }, 453 Volatility: VolatilityImmutable, 454 }, 455 &BinOp{ 456 LeftType: types.VarBit, 457 RightType: types.VarBit, 458 ReturnType: types.VarBit, 459 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 460 lhs := MustBeDBitArray(left) 461 rhs := MustBeDBitArray(right) 462 if lhs.BitLen() != rhs.BitLen() { 463 return nil, NewCannotMixBitArraySizesError("AND") 464 } 465 return &DBitArray{ 466 BitArray: bitarray.And(lhs.BitArray, rhs.BitArray), 467 }, nil 468 }, 469 Volatility: VolatilityImmutable, 470 }, 471 &BinOp{ 472 LeftType: types.INet, 473 RightType: types.INet, 474 ReturnType: types.INet, 475 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 476 ipAddr := MustBeDIPAddr(left).IPAddr 477 other := MustBeDIPAddr(right).IPAddr 478 newIPAddr, err := ipAddr.And(&other) 479 return NewDIPAddr(DIPAddr{newIPAddr}), err 480 }, 481 Volatility: VolatilityImmutable, 482 }, 483 }, 484 485 Bitor: { 486 &BinOp{ 487 LeftType: types.Int, 488 RightType: types.Int, 489 ReturnType: types.Int, 490 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 491 return NewDInt(MustBeDInt(left) | MustBeDInt(right)), nil 492 }, 493 Volatility: VolatilityImmutable, 494 }, 495 &BinOp{ 496 LeftType: types.VarBit, 497 RightType: types.VarBit, 498 ReturnType: types.VarBit, 499 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 500 lhs := MustBeDBitArray(left) 501 rhs := MustBeDBitArray(right) 502 if lhs.BitLen() != rhs.BitLen() { 503 return nil, NewCannotMixBitArraySizesError("OR") 504 } 505 return &DBitArray{ 506 BitArray: bitarray.Or(lhs.BitArray, rhs.BitArray), 507 }, nil 508 }, 509 Volatility: VolatilityImmutable, 510 }, 511 &BinOp{ 512 LeftType: types.INet, 513 RightType: types.INet, 514 ReturnType: types.INet, 515 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 516 ipAddr := MustBeDIPAddr(left).IPAddr 517 other := MustBeDIPAddr(right).IPAddr 518 newIPAddr, err := ipAddr.Or(&other) 519 return NewDIPAddr(DIPAddr{newIPAddr}), err 520 }, 521 Volatility: VolatilityImmutable, 522 }, 523 }, 524 525 Bitxor: { 526 &BinOp{ 527 LeftType: types.Int, 528 RightType: types.Int, 529 ReturnType: types.Int, 530 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 531 return NewDInt(MustBeDInt(left) ^ MustBeDInt(right)), nil 532 }, 533 Volatility: VolatilityImmutable, 534 }, 535 &BinOp{ 536 LeftType: types.VarBit, 537 RightType: types.VarBit, 538 ReturnType: types.VarBit, 539 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 540 lhs := MustBeDBitArray(left) 541 rhs := MustBeDBitArray(right) 542 if lhs.BitLen() != rhs.BitLen() { 543 return nil, NewCannotMixBitArraySizesError("XOR") 544 } 545 return &DBitArray{ 546 BitArray: bitarray.Xor(lhs.BitArray, rhs.BitArray), 547 }, nil 548 }, 549 Volatility: VolatilityImmutable, 550 }, 551 }, 552 553 Plus: { 554 &BinOp{ 555 LeftType: types.Int, 556 RightType: types.Int, 557 ReturnType: types.Int, 558 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 559 a, b := MustBeDInt(left), MustBeDInt(right) 560 r, ok := arith.AddWithOverflow(int64(a), int64(b)) 561 if !ok { 562 return nil, ErrIntOutOfRange 563 } 564 return NewDInt(DInt(r)), nil 565 }, 566 Volatility: VolatilityImmutable, 567 }, 568 &BinOp{ 569 LeftType: types.Float, 570 RightType: types.Float, 571 ReturnType: types.Float, 572 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 573 return NewDFloat(*left.(*DFloat) + *right.(*DFloat)), nil 574 }, 575 Volatility: VolatilityImmutable, 576 }, 577 &BinOp{ 578 LeftType: types.Decimal, 579 RightType: types.Decimal, 580 ReturnType: types.Decimal, 581 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 582 l := &left.(*DDecimal).Decimal 583 r := &right.(*DDecimal).Decimal 584 dd := &DDecimal{} 585 _, err := ExactCtx.Add(&dd.Decimal, l, r) 586 return dd, err 587 }, 588 Volatility: VolatilityImmutable, 589 }, 590 &BinOp{ 591 LeftType: types.Decimal, 592 RightType: types.Int, 593 ReturnType: types.Decimal, 594 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 595 l := &left.(*DDecimal).Decimal 596 r := MustBeDInt(right) 597 dd := &DDecimal{} 598 dd.SetFinite(int64(r), 0) 599 _, err := ExactCtx.Add(&dd.Decimal, l, &dd.Decimal) 600 return dd, err 601 }, 602 Volatility: VolatilityImmutable, 603 }, 604 &BinOp{ 605 LeftType: types.Int, 606 RightType: types.Decimal, 607 ReturnType: types.Decimal, 608 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 609 l := MustBeDInt(left) 610 r := &right.(*DDecimal).Decimal 611 dd := &DDecimal{} 612 dd.SetFinite(int64(l), 0) 613 _, err := ExactCtx.Add(&dd.Decimal, &dd.Decimal, r) 614 return dd, err 615 }, 616 Volatility: VolatilityImmutable, 617 }, 618 &BinOp{ 619 LeftType: types.Date, 620 RightType: types.Int, 621 ReturnType: types.Date, 622 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 623 d, err := left.(*DDate).AddDays(int64(MustBeDInt(right))) 624 if err != nil { 625 return nil, err 626 } 627 return NewDDate(d), nil 628 }, 629 Volatility: VolatilityImmutable, 630 }, 631 &BinOp{ 632 LeftType: types.Int, 633 RightType: types.Date, 634 ReturnType: types.Date, 635 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 636 d, err := right.(*DDate).AddDays(int64(MustBeDInt(left))) 637 if err != nil { 638 return nil, err 639 } 640 return NewDDate(d), nil 641 642 }, 643 Volatility: VolatilityImmutable, 644 }, 645 &BinOp{ 646 LeftType: types.Date, 647 RightType: types.Time, 648 ReturnType: types.Timestamp, 649 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 650 leftTime, err := left.(*DDate).ToTime() 651 if err != nil { 652 return nil, err 653 } 654 t := time.Duration(*right.(*DTime)) * time.Microsecond 655 return MakeDTimestamp(leftTime.Add(t), time.Microsecond) 656 }, 657 Volatility: VolatilityImmutable, 658 }, 659 &BinOp{ 660 LeftType: types.Time, 661 RightType: types.Date, 662 ReturnType: types.Timestamp, 663 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 664 rightTime, err := right.(*DDate).ToTime() 665 if err != nil { 666 return nil, err 667 } 668 t := time.Duration(*left.(*DTime)) * time.Microsecond 669 return MakeDTimestamp(rightTime.Add(t), time.Microsecond) 670 }, 671 Volatility: VolatilityImmutable, 672 }, 673 &BinOp{ 674 LeftType: types.Date, 675 RightType: types.TimeTZ, 676 ReturnType: types.TimestampTZ, 677 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 678 leftTime, err := left.(*DDate).ToTime() 679 if err != nil { 680 return nil, err 681 } 682 t := leftTime.Add(right.(*DTimeTZ).ToDuration()) 683 return MakeDTimestampTZ(t, time.Microsecond) 684 }, 685 Volatility: VolatilityImmutable, 686 }, 687 &BinOp{ 688 LeftType: types.TimeTZ, 689 RightType: types.Date, 690 ReturnType: types.TimestampTZ, 691 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 692 rightTime, err := right.(*DDate).ToTime() 693 if err != nil { 694 return nil, err 695 } 696 t := rightTime.Add(left.(*DTimeTZ).ToDuration()) 697 return MakeDTimestampTZ(t, time.Microsecond) 698 }, 699 Volatility: VolatilityImmutable, 700 }, 701 &BinOp{ 702 LeftType: types.Time, 703 RightType: types.Interval, 704 ReturnType: types.Time, 705 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 706 t := timeofday.TimeOfDay(*left.(*DTime)) 707 return MakeDTime(t.Add(right.(*DInterval).Duration)), nil 708 }, 709 Volatility: VolatilityImmutable, 710 }, 711 &BinOp{ 712 LeftType: types.Interval, 713 RightType: types.Time, 714 ReturnType: types.Time, 715 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 716 t := timeofday.TimeOfDay(*right.(*DTime)) 717 return MakeDTime(t.Add(left.(*DInterval).Duration)), nil 718 }, 719 Volatility: VolatilityImmutable, 720 }, 721 &BinOp{ 722 LeftType: types.TimeTZ, 723 RightType: types.Interval, 724 ReturnType: types.TimeTZ, 725 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 726 t := left.(*DTimeTZ) 727 duration := right.(*DInterval).Duration 728 return NewDTimeTZFromOffset(t.Add(duration), t.OffsetSecs), nil 729 }, 730 Volatility: VolatilityImmutable, 731 }, 732 &BinOp{ 733 LeftType: types.Interval, 734 RightType: types.TimeTZ, 735 ReturnType: types.TimeTZ, 736 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 737 t := right.(*DTimeTZ) 738 duration := left.(*DInterval).Duration 739 return NewDTimeTZFromOffset(t.Add(duration), t.OffsetSecs), nil 740 }, 741 Volatility: VolatilityImmutable, 742 }, 743 &BinOp{ 744 LeftType: types.Timestamp, 745 RightType: types.Interval, 746 ReturnType: types.Timestamp, 747 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 748 return MakeDTimestamp(duration.Add( 749 left.(*DTimestamp).Time, right.(*DInterval).Duration), time.Microsecond) 750 }, 751 Volatility: VolatilityImmutable, 752 }, 753 &BinOp{ 754 LeftType: types.Interval, 755 RightType: types.Timestamp, 756 ReturnType: types.Timestamp, 757 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 758 return MakeDTimestamp(duration.Add( 759 right.(*DTimestamp).Time, left.(*DInterval).Duration), time.Microsecond) 760 }, 761 Volatility: VolatilityImmutable, 762 }, 763 &BinOp{ 764 LeftType: types.TimestampTZ, 765 RightType: types.Interval, 766 ReturnType: types.TimestampTZ, 767 Fn: func(ctx *EvalContext, left Datum, right Datum) (Datum, error) { 768 // Convert time to be in the given timezone, as math relies on matching timezones.. 769 t := duration.Add(left.(*DTimestampTZ).Time.In(ctx.GetLocation()), right.(*DInterval).Duration) 770 return MakeDTimestampTZ(t, time.Microsecond) 771 }, 772 Volatility: VolatilityStable, 773 }, 774 &BinOp{ 775 LeftType: types.Interval, 776 RightType: types.TimestampTZ, 777 ReturnType: types.TimestampTZ, 778 Fn: func(ctx *EvalContext, left Datum, right Datum) (Datum, error) { 779 // Convert time to be in the given timezone, as math relies on matching timezones.. 780 t := duration.Add(right.(*DTimestampTZ).Time.In(ctx.GetLocation()), left.(*DInterval).Duration) 781 return MakeDTimestampTZ(t, time.Microsecond) 782 }, 783 Volatility: VolatilityStable, 784 }, 785 &BinOp{ 786 LeftType: types.Interval, 787 RightType: types.Interval, 788 ReturnType: types.Interval, 789 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 790 return &DInterval{Duration: left.(*DInterval).Duration.Add(right.(*DInterval).Duration)}, nil 791 }, 792 Volatility: VolatilityImmutable, 793 }, 794 &BinOp{ 795 LeftType: types.Date, 796 RightType: types.Interval, 797 ReturnType: types.Timestamp, 798 Fn: func(ctx *EvalContext, left Datum, right Datum) (Datum, error) { 799 leftTime, err := left.(*DDate).ToTime() 800 if err != nil { 801 return nil, err 802 } 803 t := duration.Add(leftTime, right.(*DInterval).Duration) 804 return MakeDTimestamp(t, time.Microsecond) 805 }, 806 Volatility: VolatilityImmutable, 807 }, 808 &BinOp{ 809 LeftType: types.Interval, 810 RightType: types.Date, 811 ReturnType: types.Timestamp, 812 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 813 rightTime, err := right.(*DDate).ToTime() 814 if err != nil { 815 return nil, err 816 } 817 t := duration.Add(rightTime, left.(*DInterval).Duration) 818 return MakeDTimestamp(t, time.Microsecond) 819 }, 820 Volatility: VolatilityImmutable, 821 }, 822 &BinOp{ 823 LeftType: types.INet, 824 RightType: types.Int, 825 ReturnType: types.INet, 826 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 827 ipAddr := MustBeDIPAddr(left).IPAddr 828 i := MustBeDInt(right) 829 newIPAddr, err := ipAddr.Add(int64(i)) 830 return NewDIPAddr(DIPAddr{newIPAddr}), err 831 }, 832 Volatility: VolatilityImmutable, 833 }, 834 &BinOp{ 835 LeftType: types.Int, 836 RightType: types.INet, 837 ReturnType: types.INet, 838 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 839 i := MustBeDInt(left) 840 ipAddr := MustBeDIPAddr(right).IPAddr 841 newIPAddr, err := ipAddr.Add(int64(i)) 842 return NewDIPAddr(DIPAddr{newIPAddr}), err 843 }, 844 Volatility: VolatilityImmutable, 845 }, 846 }, 847 848 Minus: { 849 &BinOp{ 850 LeftType: types.Int, 851 RightType: types.Int, 852 ReturnType: types.Int, 853 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 854 a, b := MustBeDInt(left), MustBeDInt(right) 855 r, ok := arith.SubWithOverflow(int64(a), int64(b)) 856 if !ok { 857 return nil, ErrIntOutOfRange 858 } 859 return NewDInt(DInt(r)), nil 860 }, 861 Volatility: VolatilityImmutable, 862 }, 863 &BinOp{ 864 LeftType: types.Float, 865 RightType: types.Float, 866 ReturnType: types.Float, 867 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 868 return NewDFloat(*left.(*DFloat) - *right.(*DFloat)), nil 869 }, 870 Volatility: VolatilityImmutable, 871 }, 872 &BinOp{ 873 LeftType: types.Decimal, 874 RightType: types.Decimal, 875 ReturnType: types.Decimal, 876 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 877 l := &left.(*DDecimal).Decimal 878 r := &right.(*DDecimal).Decimal 879 dd := &DDecimal{} 880 _, err := ExactCtx.Sub(&dd.Decimal, l, r) 881 return dd, err 882 }, 883 Volatility: VolatilityImmutable, 884 }, 885 &BinOp{ 886 LeftType: types.Decimal, 887 RightType: types.Int, 888 ReturnType: types.Decimal, 889 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 890 l := &left.(*DDecimal).Decimal 891 r := MustBeDInt(right) 892 dd := &DDecimal{} 893 dd.SetFinite(int64(r), 0) 894 _, err := ExactCtx.Sub(&dd.Decimal, l, &dd.Decimal) 895 return dd, err 896 }, 897 Volatility: VolatilityImmutable, 898 }, 899 &BinOp{ 900 LeftType: types.Int, 901 RightType: types.Decimal, 902 ReturnType: types.Decimal, 903 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 904 l := MustBeDInt(left) 905 r := &right.(*DDecimal).Decimal 906 dd := &DDecimal{} 907 dd.SetFinite(int64(l), 0) 908 _, err := ExactCtx.Sub(&dd.Decimal, &dd.Decimal, r) 909 return dd, err 910 }, 911 Volatility: VolatilityImmutable, 912 }, 913 &BinOp{ 914 LeftType: types.Date, 915 RightType: types.Int, 916 ReturnType: types.Date, 917 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 918 d, err := left.(*DDate).SubDays(int64(MustBeDInt(right))) 919 if err != nil { 920 return nil, err 921 } 922 return NewDDate(d), nil 923 }, 924 Volatility: VolatilityImmutable, 925 }, 926 &BinOp{ 927 LeftType: types.Date, 928 RightType: types.Date, 929 ReturnType: types.Int, 930 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 931 l, r := left.(*DDate).Date, right.(*DDate).Date 932 if !l.IsFinite() || !r.IsFinite() { 933 return nil, pgerror.New(pgcode.DatetimeFieldOverflow, "cannot subtract infinite dates") 934 } 935 a := l.PGEpochDays() 936 b := r.PGEpochDays() 937 // This can't overflow because they are upconverted from int32 to int64. 938 return NewDInt(DInt(int64(a) - int64(b))), nil 939 }, 940 Volatility: VolatilityImmutable, 941 }, 942 &BinOp{ 943 LeftType: types.Date, 944 RightType: types.Time, 945 ReturnType: types.Timestamp, 946 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 947 leftTime, err := left.(*DDate).ToTime() 948 if err != nil { 949 return nil, err 950 } 951 t := time.Duration(*right.(*DTime)) * time.Microsecond 952 return MakeDTimestamp(leftTime.Add(-1*t), time.Microsecond) 953 }, 954 Volatility: VolatilityImmutable, 955 }, 956 &BinOp{ 957 LeftType: types.Time, 958 RightType: types.Time, 959 ReturnType: types.Interval, 960 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 961 t1 := timeofday.TimeOfDay(*left.(*DTime)) 962 t2 := timeofday.TimeOfDay(*right.(*DTime)) 963 diff := timeofday.Difference(t1, t2) 964 return &DInterval{Duration: diff}, nil 965 }, 966 Volatility: VolatilityImmutable, 967 }, 968 &BinOp{ 969 LeftType: types.Timestamp, 970 RightType: types.Timestamp, 971 ReturnType: types.Interval, 972 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 973 nanos := left.(*DTimestamp).Sub(right.(*DTimestamp).Time).Nanoseconds() 974 return &DInterval{Duration: duration.MakeDuration(nanos, 0, 0)}, nil 975 }, 976 Volatility: VolatilityImmutable, 977 }, 978 &BinOp{ 979 LeftType: types.TimestampTZ, 980 RightType: types.TimestampTZ, 981 ReturnType: types.Interval, 982 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 983 nanos := left.(*DTimestampTZ).Sub(right.(*DTimestampTZ).Time).Nanoseconds() 984 return &DInterval{Duration: duration.MakeDuration(nanos, 0, 0)}, nil 985 }, 986 Volatility: VolatilityImmutable, 987 }, 988 &BinOp{ 989 LeftType: types.Timestamp, 990 RightType: types.TimestampTZ, 991 ReturnType: types.Interval, 992 Fn: func(ctx *EvalContext, left Datum, right Datum) (Datum, error) { 993 // These two quantities aren't directly comparable. Convert the 994 // TimestampTZ to a timestamp first. 995 stripped, err := right.(*DTimestampTZ).stripTimeZone(ctx) 996 if err != nil { 997 return nil, err 998 } 999 nanos := left.(*DTimestamp).Sub(stripped.Time).Nanoseconds() 1000 return &DInterval{Duration: duration.MakeDuration(nanos, 0, 0)}, nil 1001 }, 1002 Volatility: VolatilityStable, 1003 }, 1004 &BinOp{ 1005 LeftType: types.TimestampTZ, 1006 RightType: types.Timestamp, 1007 ReturnType: types.Interval, 1008 Fn: func(ctx *EvalContext, left Datum, right Datum) (Datum, error) { 1009 // These two quantities aren't directly comparable. Convert the 1010 // TimestampTZ to a timestamp first. 1011 stripped, err := left.(*DTimestampTZ).stripTimeZone(ctx) 1012 if err != nil { 1013 return nil, err 1014 } 1015 nanos := stripped.Sub(right.(*DTimestamp).Time).Nanoseconds() 1016 return &DInterval{Duration: duration.MakeDuration(nanos, 0, 0)}, nil 1017 }, 1018 Volatility: VolatilityStable, 1019 }, 1020 &BinOp{ 1021 LeftType: types.Time, 1022 RightType: types.Interval, 1023 ReturnType: types.Time, 1024 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1025 t := timeofday.TimeOfDay(*left.(*DTime)) 1026 return MakeDTime(t.Add(right.(*DInterval).Duration.Mul(-1))), nil 1027 }, 1028 Volatility: VolatilityImmutable, 1029 }, 1030 &BinOp{ 1031 LeftType: types.TimeTZ, 1032 RightType: types.Interval, 1033 ReturnType: types.TimeTZ, 1034 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1035 t := left.(*DTimeTZ) 1036 duration := right.(*DInterval).Duration 1037 return NewDTimeTZFromOffset(t.Add(duration.Mul(-1)), t.OffsetSecs), nil 1038 }, 1039 Volatility: VolatilityImmutable, 1040 }, 1041 &BinOp{ 1042 LeftType: types.Timestamp, 1043 RightType: types.Interval, 1044 ReturnType: types.Timestamp, 1045 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1046 return MakeDTimestamp(duration.Add( 1047 left.(*DTimestamp).Time, right.(*DInterval).Duration.Mul(-1)), time.Microsecond) 1048 }, 1049 Volatility: VolatilityImmutable, 1050 }, 1051 &BinOp{ 1052 LeftType: types.TimestampTZ, 1053 RightType: types.Interval, 1054 ReturnType: types.TimestampTZ, 1055 Fn: func(ctx *EvalContext, left Datum, right Datum) (Datum, error) { 1056 t := duration.Add( 1057 left.(*DTimestampTZ).Time.In(ctx.GetLocation()), 1058 right.(*DInterval).Duration.Mul(-1), 1059 ) 1060 return MakeDTimestampTZ(t, time.Microsecond) 1061 }, 1062 Volatility: VolatilityStable, 1063 }, 1064 &BinOp{ 1065 LeftType: types.Date, 1066 RightType: types.Interval, 1067 ReturnType: types.Timestamp, 1068 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1069 leftTime, err := left.(*DDate).ToTime() 1070 if err != nil { 1071 return nil, err 1072 } 1073 t := duration.Add(leftTime, right.(*DInterval).Duration.Mul(-1)) 1074 return MakeDTimestamp(t, time.Microsecond) 1075 }, 1076 Volatility: VolatilityImmutable, 1077 }, 1078 &BinOp{ 1079 LeftType: types.Interval, 1080 RightType: types.Interval, 1081 ReturnType: types.Interval, 1082 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1083 return &DInterval{Duration: left.(*DInterval).Duration.Sub(right.(*DInterval).Duration)}, nil 1084 }, 1085 Volatility: VolatilityImmutable, 1086 }, 1087 &BinOp{ 1088 LeftType: types.Jsonb, 1089 RightType: types.String, 1090 ReturnType: types.Jsonb, 1091 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1092 j, _, err := left.(*DJSON).JSON.RemoveString(string(MustBeDString(right))) 1093 if err != nil { 1094 return nil, err 1095 } 1096 return &DJSON{j}, nil 1097 }, 1098 Volatility: VolatilityImmutable, 1099 }, 1100 &BinOp{ 1101 LeftType: types.Jsonb, 1102 RightType: types.Int, 1103 ReturnType: types.Jsonb, 1104 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1105 j, _, err := left.(*DJSON).JSON.RemoveIndex(int(MustBeDInt(right))) 1106 if err != nil { 1107 return nil, err 1108 } 1109 return &DJSON{j}, nil 1110 }, 1111 Volatility: VolatilityImmutable, 1112 }, 1113 &BinOp{ 1114 LeftType: types.Jsonb, 1115 RightType: types.MakeArray(types.String), 1116 ReturnType: types.Jsonb, 1117 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1118 j := left.(*DJSON).JSON 1119 arr := *MustBeDArray(right) 1120 1121 for _, str := range arr.Array { 1122 if str == DNull { 1123 continue 1124 } 1125 var err error 1126 j, _, err = j.RemoveString(string(MustBeDString(str))) 1127 if err != nil { 1128 return nil, err 1129 } 1130 } 1131 return &DJSON{j}, nil 1132 }, 1133 Volatility: VolatilityImmutable, 1134 }, 1135 &BinOp{ 1136 LeftType: types.INet, 1137 RightType: types.INet, 1138 ReturnType: types.Int, 1139 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1140 ipAddr := MustBeDIPAddr(left).IPAddr 1141 other := MustBeDIPAddr(right).IPAddr 1142 diff, err := ipAddr.SubIPAddr(&other) 1143 return NewDInt(DInt(diff)), err 1144 }, 1145 Volatility: VolatilityImmutable, 1146 }, 1147 &BinOp{ 1148 // Note: postgres ver 10 does NOT have Int - INet. Throws ERROR: 42883. 1149 LeftType: types.INet, 1150 RightType: types.Int, 1151 ReturnType: types.INet, 1152 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1153 ipAddr := MustBeDIPAddr(left).IPAddr 1154 i := MustBeDInt(right) 1155 newIPAddr, err := ipAddr.Sub(int64(i)) 1156 return NewDIPAddr(DIPAddr{newIPAddr}), err 1157 }, 1158 Volatility: VolatilityImmutable, 1159 }, 1160 }, 1161 1162 Mult: { 1163 &BinOp{ 1164 LeftType: types.Int, 1165 RightType: types.Int, 1166 ReturnType: types.Int, 1167 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1168 // See Rob Pike's implementation from 1169 // https://groups.google.com/d/msg/golang-nuts/h5oSN5t3Au4/KaNQREhZh0QJ 1170 1171 a, b := MustBeDInt(left), MustBeDInt(right) 1172 c := a * b 1173 if a == 0 || b == 0 || a == 1 || b == 1 { 1174 // ignore 1175 } else if a == math.MinInt64 || b == math.MinInt64 { 1176 // This test is required to detect math.MinInt64 * -1. 1177 return nil, ErrIntOutOfRange 1178 } else if c/b != a { 1179 return nil, ErrIntOutOfRange 1180 } 1181 return NewDInt(c), nil 1182 }, 1183 Volatility: VolatilityImmutable, 1184 }, 1185 &BinOp{ 1186 LeftType: types.Float, 1187 RightType: types.Float, 1188 ReturnType: types.Float, 1189 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1190 return NewDFloat(*left.(*DFloat) * *right.(*DFloat)), nil 1191 }, 1192 Volatility: VolatilityImmutable, 1193 }, 1194 &BinOp{ 1195 LeftType: types.Decimal, 1196 RightType: types.Decimal, 1197 ReturnType: types.Decimal, 1198 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1199 l := &left.(*DDecimal).Decimal 1200 r := &right.(*DDecimal).Decimal 1201 dd := &DDecimal{} 1202 _, err := ExactCtx.Mul(&dd.Decimal, l, r) 1203 return dd, err 1204 }, 1205 Volatility: VolatilityImmutable, 1206 }, 1207 // The following two overloads are needed because DInt/DInt = DDecimal. Due 1208 // to this operation, normalization may sometimes create a DInt * DDecimal 1209 // operation. 1210 &BinOp{ 1211 LeftType: types.Decimal, 1212 RightType: types.Int, 1213 ReturnType: types.Decimal, 1214 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1215 l := &left.(*DDecimal).Decimal 1216 r := MustBeDInt(right) 1217 dd := &DDecimal{} 1218 dd.SetFinite(int64(r), 0) 1219 _, err := ExactCtx.Mul(&dd.Decimal, l, &dd.Decimal) 1220 return dd, err 1221 }, 1222 Volatility: VolatilityImmutable, 1223 }, 1224 &BinOp{ 1225 LeftType: types.Int, 1226 RightType: types.Decimal, 1227 ReturnType: types.Decimal, 1228 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1229 l := MustBeDInt(left) 1230 r := &right.(*DDecimal).Decimal 1231 dd := &DDecimal{} 1232 dd.SetFinite(int64(l), 0) 1233 _, err := ExactCtx.Mul(&dd.Decimal, &dd.Decimal, r) 1234 return dd, err 1235 }, 1236 Volatility: VolatilityImmutable, 1237 }, 1238 &BinOp{ 1239 LeftType: types.Int, 1240 RightType: types.Interval, 1241 ReturnType: types.Interval, 1242 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1243 return &DInterval{Duration: right.(*DInterval).Duration.Mul(int64(MustBeDInt(left)))}, nil 1244 }, 1245 Volatility: VolatilityImmutable, 1246 }, 1247 &BinOp{ 1248 LeftType: types.Interval, 1249 RightType: types.Int, 1250 ReturnType: types.Interval, 1251 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1252 return &DInterval{Duration: left.(*DInterval).Duration.Mul(int64(MustBeDInt(right)))}, nil 1253 }, 1254 Volatility: VolatilityImmutable, 1255 }, 1256 &BinOp{ 1257 LeftType: types.Interval, 1258 RightType: types.Float, 1259 ReturnType: types.Interval, 1260 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1261 r := float64(*right.(*DFloat)) 1262 return &DInterval{Duration: left.(*DInterval).Duration.MulFloat(r)}, nil 1263 }, 1264 Volatility: VolatilityImmutable, 1265 }, 1266 &BinOp{ 1267 LeftType: types.Float, 1268 RightType: types.Interval, 1269 ReturnType: types.Interval, 1270 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1271 l := float64(*left.(*DFloat)) 1272 return &DInterval{Duration: right.(*DInterval).Duration.MulFloat(l)}, nil 1273 }, 1274 Volatility: VolatilityImmutable, 1275 }, 1276 &BinOp{ 1277 LeftType: types.Decimal, 1278 RightType: types.Interval, 1279 ReturnType: types.Interval, 1280 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1281 l := &left.(*DDecimal).Decimal 1282 t, err := l.Float64() 1283 if err != nil { 1284 return nil, err 1285 } 1286 return &DInterval{Duration: right.(*DInterval).Duration.MulFloat(t)}, nil 1287 }, 1288 Volatility: VolatilityImmutable, 1289 }, 1290 &BinOp{ 1291 LeftType: types.Interval, 1292 RightType: types.Decimal, 1293 ReturnType: types.Interval, 1294 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1295 r := &right.(*DDecimal).Decimal 1296 t, err := r.Float64() 1297 if err != nil { 1298 return nil, err 1299 } 1300 return &DInterval{Duration: left.(*DInterval).Duration.MulFloat(t)}, nil 1301 }, 1302 Volatility: VolatilityImmutable, 1303 }, 1304 }, 1305 1306 Div: { 1307 &BinOp{ 1308 LeftType: types.Int, 1309 RightType: types.Int, 1310 ReturnType: types.Decimal, 1311 Fn: func(ctx *EvalContext, left Datum, right Datum) (Datum, error) { 1312 rInt := MustBeDInt(right) 1313 div := ctx.getTmpDec().SetFinite(int64(rInt), 0) 1314 dd := &DDecimal{} 1315 dd.SetFinite(int64(MustBeDInt(left)), 0) 1316 cond, err := DecimalCtx.Quo(&dd.Decimal, &dd.Decimal, div) 1317 if cond.DivisionByZero() { 1318 return dd, ErrDivByZero 1319 } 1320 return dd, err 1321 }, 1322 Volatility: VolatilityImmutable, 1323 }, 1324 &BinOp{ 1325 LeftType: types.Float, 1326 RightType: types.Float, 1327 ReturnType: types.Float, 1328 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1329 r := *right.(*DFloat) 1330 if r == 0.0 { 1331 return nil, ErrDivByZero 1332 } 1333 return NewDFloat(*left.(*DFloat) / r), nil 1334 }, 1335 Volatility: VolatilityImmutable, 1336 }, 1337 &BinOp{ 1338 LeftType: types.Decimal, 1339 RightType: types.Decimal, 1340 ReturnType: types.Decimal, 1341 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1342 l := &left.(*DDecimal).Decimal 1343 r := &right.(*DDecimal).Decimal 1344 dd := &DDecimal{} 1345 cond, err := DecimalCtx.Quo(&dd.Decimal, l, r) 1346 if cond.DivisionByZero() { 1347 return dd, ErrDivByZero 1348 } 1349 return dd, err 1350 }, 1351 Volatility: VolatilityImmutable, 1352 }, 1353 &BinOp{ 1354 LeftType: types.Decimal, 1355 RightType: types.Int, 1356 ReturnType: types.Decimal, 1357 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1358 l := &left.(*DDecimal).Decimal 1359 r := MustBeDInt(right) 1360 dd := &DDecimal{} 1361 dd.SetFinite(int64(r), 0) 1362 cond, err := DecimalCtx.Quo(&dd.Decimal, l, &dd.Decimal) 1363 if cond.DivisionByZero() { 1364 return dd, ErrDivByZero 1365 } 1366 return dd, err 1367 }, 1368 Volatility: VolatilityImmutable, 1369 }, 1370 &BinOp{ 1371 LeftType: types.Int, 1372 RightType: types.Decimal, 1373 ReturnType: types.Decimal, 1374 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1375 l := MustBeDInt(left) 1376 r := &right.(*DDecimal).Decimal 1377 dd := &DDecimal{} 1378 dd.SetFinite(int64(l), 0) 1379 cond, err := DecimalCtx.Quo(&dd.Decimal, &dd.Decimal, r) 1380 if cond.DivisionByZero() { 1381 return dd, ErrDivByZero 1382 } 1383 return dd, err 1384 }, 1385 Volatility: VolatilityImmutable, 1386 }, 1387 &BinOp{ 1388 LeftType: types.Interval, 1389 RightType: types.Int, 1390 ReturnType: types.Interval, 1391 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1392 rInt := MustBeDInt(right) 1393 if rInt == 0 { 1394 return nil, ErrDivByZero 1395 } 1396 return &DInterval{Duration: left.(*DInterval).Duration.Div(int64(rInt))}, nil 1397 }, 1398 Volatility: VolatilityImmutable, 1399 }, 1400 &BinOp{ 1401 LeftType: types.Interval, 1402 RightType: types.Float, 1403 ReturnType: types.Interval, 1404 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1405 r := float64(*right.(*DFloat)) 1406 if r == 0.0 { 1407 return nil, ErrDivByZero 1408 } 1409 return &DInterval{Duration: left.(*DInterval).Duration.DivFloat(r)}, nil 1410 }, 1411 Volatility: VolatilityImmutable, 1412 }, 1413 }, 1414 1415 FloorDiv: { 1416 &BinOp{ 1417 LeftType: types.Int, 1418 RightType: types.Int, 1419 ReturnType: types.Int, 1420 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1421 rInt := MustBeDInt(right) 1422 if rInt == 0 { 1423 return nil, ErrDivByZero 1424 } 1425 return NewDInt(MustBeDInt(left) / rInt), nil 1426 }, 1427 Volatility: VolatilityImmutable, 1428 }, 1429 &BinOp{ 1430 LeftType: types.Float, 1431 RightType: types.Float, 1432 ReturnType: types.Float, 1433 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1434 l := float64(*left.(*DFloat)) 1435 r := float64(*right.(*DFloat)) 1436 return NewDFloat(DFloat(math.Trunc(l / r))), nil 1437 }, 1438 Volatility: VolatilityImmutable, 1439 }, 1440 &BinOp{ 1441 LeftType: types.Decimal, 1442 RightType: types.Decimal, 1443 ReturnType: types.Decimal, 1444 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1445 l := &left.(*DDecimal).Decimal 1446 r := &right.(*DDecimal).Decimal 1447 dd := &DDecimal{} 1448 _, err := HighPrecisionCtx.QuoInteger(&dd.Decimal, l, r) 1449 return dd, err 1450 }, 1451 Volatility: VolatilityImmutable, 1452 }, 1453 &BinOp{ 1454 LeftType: types.Decimal, 1455 RightType: types.Int, 1456 ReturnType: types.Decimal, 1457 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1458 l := &left.(*DDecimal).Decimal 1459 r := MustBeDInt(right) 1460 if r == 0 { 1461 return nil, ErrDivByZero 1462 } 1463 dd := &DDecimal{} 1464 dd.SetFinite(int64(r), 0) 1465 _, err := HighPrecisionCtx.QuoInteger(&dd.Decimal, l, &dd.Decimal) 1466 return dd, err 1467 }, 1468 Volatility: VolatilityImmutable, 1469 }, 1470 &BinOp{ 1471 LeftType: types.Int, 1472 RightType: types.Decimal, 1473 ReturnType: types.Decimal, 1474 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1475 l := MustBeDInt(left) 1476 r := &right.(*DDecimal).Decimal 1477 if r.Sign() == 0 { 1478 return nil, ErrDivByZero 1479 } 1480 dd := &DDecimal{} 1481 dd.SetFinite(int64(l), 0) 1482 _, err := HighPrecisionCtx.QuoInteger(&dd.Decimal, &dd.Decimal, r) 1483 return dd, err 1484 }, 1485 Volatility: VolatilityImmutable, 1486 }, 1487 }, 1488 1489 Mod: { 1490 &BinOp{ 1491 LeftType: types.Int, 1492 RightType: types.Int, 1493 ReturnType: types.Int, 1494 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1495 r := MustBeDInt(right) 1496 if r == 0 { 1497 return nil, ErrZeroModulus 1498 } 1499 return NewDInt(MustBeDInt(left) % r), nil 1500 }, 1501 Volatility: VolatilityImmutable, 1502 }, 1503 &BinOp{ 1504 LeftType: types.Float, 1505 RightType: types.Float, 1506 ReturnType: types.Float, 1507 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1508 return NewDFloat(DFloat(math.Mod(float64(*left.(*DFloat)), float64(*right.(*DFloat))))), nil 1509 }, 1510 Volatility: VolatilityImmutable, 1511 }, 1512 &BinOp{ 1513 LeftType: types.Decimal, 1514 RightType: types.Decimal, 1515 ReturnType: types.Decimal, 1516 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1517 l := &left.(*DDecimal).Decimal 1518 r := &right.(*DDecimal).Decimal 1519 dd := &DDecimal{} 1520 _, err := HighPrecisionCtx.Rem(&dd.Decimal, l, r) 1521 return dd, err 1522 }, 1523 Volatility: VolatilityImmutable, 1524 }, 1525 &BinOp{ 1526 LeftType: types.Decimal, 1527 RightType: types.Int, 1528 ReturnType: types.Decimal, 1529 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1530 l := &left.(*DDecimal).Decimal 1531 r := MustBeDInt(right) 1532 dd := &DDecimal{} 1533 dd.SetFinite(int64(r), 0) 1534 _, err := HighPrecisionCtx.Rem(&dd.Decimal, l, &dd.Decimal) 1535 return dd, err 1536 }, 1537 Volatility: VolatilityImmutable, 1538 }, 1539 &BinOp{ 1540 LeftType: types.Int, 1541 RightType: types.Decimal, 1542 ReturnType: types.Decimal, 1543 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1544 l := MustBeDInt(left) 1545 r := &right.(*DDecimal).Decimal 1546 dd := &DDecimal{} 1547 dd.SetFinite(int64(l), 0) 1548 _, err := HighPrecisionCtx.Rem(&dd.Decimal, &dd.Decimal, r) 1549 return dd, err 1550 }, 1551 Volatility: VolatilityImmutable, 1552 }, 1553 }, 1554 1555 Concat: { 1556 &BinOp{ 1557 LeftType: types.String, 1558 RightType: types.String, 1559 ReturnType: types.String, 1560 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1561 return NewDString(string(MustBeDString(left) + MustBeDString(right))), nil 1562 }, 1563 Volatility: VolatilityImmutable, 1564 }, 1565 &BinOp{ 1566 LeftType: types.Bytes, 1567 RightType: types.Bytes, 1568 ReturnType: types.Bytes, 1569 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1570 return NewDBytes(*left.(*DBytes) + *right.(*DBytes)), nil 1571 }, 1572 Volatility: VolatilityImmutable, 1573 }, 1574 &BinOp{ 1575 LeftType: types.VarBit, 1576 RightType: types.VarBit, 1577 ReturnType: types.VarBit, 1578 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1579 lhs := MustBeDBitArray(left) 1580 rhs := MustBeDBitArray(right) 1581 return &DBitArray{ 1582 BitArray: bitarray.Concat(lhs.BitArray, rhs.BitArray), 1583 }, nil 1584 }, 1585 Volatility: VolatilityImmutable, 1586 }, 1587 &BinOp{ 1588 LeftType: types.Jsonb, 1589 RightType: types.Jsonb, 1590 ReturnType: types.Jsonb, 1591 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1592 j, err := MustBeDJSON(left).JSON.Concat(MustBeDJSON(right).JSON) 1593 if err != nil { 1594 return nil, err 1595 } 1596 return &DJSON{j}, nil 1597 }, 1598 Volatility: VolatilityImmutable, 1599 }, 1600 }, 1601 1602 // TODO(pmattis): Check that the shift is valid. 1603 LShift: { 1604 &BinOp{ 1605 LeftType: types.Int, 1606 RightType: types.Int, 1607 ReturnType: types.Int, 1608 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1609 rval := MustBeDInt(right) 1610 if rval < 0 || rval >= 64 { 1611 telemetry.Inc(sqltelemetry.LargeLShiftArgumentCounter) 1612 return nil, pgerror.Newf(pgcode.InvalidParameterValue, "shift argument out of range") 1613 } 1614 return NewDInt(MustBeDInt(left) << uint(rval)), nil 1615 }, 1616 Volatility: VolatilityImmutable, 1617 }, 1618 &BinOp{ 1619 LeftType: types.VarBit, 1620 RightType: types.Int, 1621 ReturnType: types.VarBit, 1622 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1623 lhs := MustBeDBitArray(left) 1624 rhs := MustBeDInt(right) 1625 return &DBitArray{ 1626 BitArray: lhs.BitArray.LeftShiftAny(int64(rhs)), 1627 }, nil 1628 }, 1629 Volatility: VolatilityImmutable, 1630 }, 1631 &BinOp{ 1632 LeftType: types.INet, 1633 RightType: types.INet, 1634 ReturnType: types.Bool, 1635 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1636 ipAddr := MustBeDIPAddr(left).IPAddr 1637 other := MustBeDIPAddr(right).IPAddr 1638 return MakeDBool(DBool(ipAddr.ContainedBy(&other))), nil 1639 }, 1640 Volatility: VolatilityImmutable, 1641 }, 1642 }, 1643 1644 RShift: { 1645 &BinOp{ 1646 LeftType: types.Int, 1647 RightType: types.Int, 1648 ReturnType: types.Int, 1649 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1650 rval := MustBeDInt(right) 1651 if rval < 0 || rval >= 64 { 1652 telemetry.Inc(sqltelemetry.LargeRShiftArgumentCounter) 1653 return nil, pgerror.Newf(pgcode.InvalidParameterValue, "shift argument out of range") 1654 } 1655 return NewDInt(MustBeDInt(left) >> uint(rval)), nil 1656 }, 1657 Volatility: VolatilityImmutable, 1658 }, 1659 &BinOp{ 1660 LeftType: types.VarBit, 1661 RightType: types.Int, 1662 ReturnType: types.VarBit, 1663 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1664 lhs := MustBeDBitArray(left) 1665 rhs := MustBeDInt(right) 1666 return &DBitArray{ 1667 BitArray: lhs.BitArray.LeftShiftAny(-int64(rhs)), 1668 }, nil 1669 }, 1670 Volatility: VolatilityImmutable, 1671 }, 1672 &BinOp{ 1673 LeftType: types.INet, 1674 RightType: types.INet, 1675 ReturnType: types.Bool, 1676 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1677 ipAddr := MustBeDIPAddr(left).IPAddr 1678 other := MustBeDIPAddr(right).IPAddr 1679 return MakeDBool(DBool(ipAddr.Contains(&other))), nil 1680 }, 1681 Volatility: VolatilityImmutable, 1682 }, 1683 }, 1684 1685 Pow: { 1686 &BinOp{ 1687 LeftType: types.Int, 1688 RightType: types.Int, 1689 ReturnType: types.Int, 1690 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1691 return IntPow(MustBeDInt(left), MustBeDInt(right)) 1692 }, 1693 Volatility: VolatilityImmutable, 1694 }, 1695 &BinOp{ 1696 LeftType: types.Float, 1697 RightType: types.Float, 1698 ReturnType: types.Float, 1699 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1700 f := math.Pow(float64(*left.(*DFloat)), float64(*right.(*DFloat))) 1701 return NewDFloat(DFloat(f)), nil 1702 }, 1703 Volatility: VolatilityImmutable, 1704 }, 1705 &BinOp{ 1706 LeftType: types.Decimal, 1707 RightType: types.Decimal, 1708 ReturnType: types.Decimal, 1709 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1710 l := &left.(*DDecimal).Decimal 1711 r := &right.(*DDecimal).Decimal 1712 dd := &DDecimal{} 1713 _, err := DecimalCtx.Pow(&dd.Decimal, l, r) 1714 return dd, err 1715 }, 1716 Volatility: VolatilityImmutable, 1717 }, 1718 &BinOp{ 1719 LeftType: types.Decimal, 1720 RightType: types.Int, 1721 ReturnType: types.Decimal, 1722 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1723 l := &left.(*DDecimal).Decimal 1724 r := MustBeDInt(right) 1725 dd := &DDecimal{} 1726 dd.SetFinite(int64(r), 0) 1727 _, err := DecimalCtx.Pow(&dd.Decimal, l, &dd.Decimal) 1728 return dd, err 1729 }, 1730 Volatility: VolatilityImmutable, 1731 }, 1732 &BinOp{ 1733 LeftType: types.Int, 1734 RightType: types.Decimal, 1735 ReturnType: types.Decimal, 1736 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1737 l := MustBeDInt(left) 1738 r := &right.(*DDecimal).Decimal 1739 dd := &DDecimal{} 1740 dd.SetFinite(int64(l), 0) 1741 _, err := DecimalCtx.Pow(&dd.Decimal, &dd.Decimal, r) 1742 return dd, err 1743 }, 1744 Volatility: VolatilityImmutable, 1745 }, 1746 }, 1747 1748 JSONFetchVal: { 1749 &BinOp{ 1750 LeftType: types.Jsonb, 1751 RightType: types.String, 1752 ReturnType: types.Jsonb, 1753 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1754 j, err := left.(*DJSON).JSON.FetchValKey(string(MustBeDString(right))) 1755 if err != nil { 1756 return nil, err 1757 } 1758 if j == nil { 1759 return DNull, nil 1760 } 1761 return &DJSON{j}, nil 1762 }, 1763 Volatility: VolatilityImmutable, 1764 }, 1765 &BinOp{ 1766 LeftType: types.Jsonb, 1767 RightType: types.Int, 1768 ReturnType: types.Jsonb, 1769 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1770 j, err := left.(*DJSON).JSON.FetchValIdx(int(MustBeDInt(right))) 1771 if err != nil { 1772 return nil, err 1773 } 1774 if j == nil { 1775 return DNull, nil 1776 } 1777 return &DJSON{j}, nil 1778 }, 1779 Volatility: VolatilityImmutable, 1780 }, 1781 }, 1782 1783 JSONFetchValPath: { 1784 &BinOp{ 1785 LeftType: types.Jsonb, 1786 RightType: types.MakeArray(types.String), 1787 ReturnType: types.Jsonb, 1788 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1789 return getJSONPath(*left.(*DJSON), *MustBeDArray(right)) 1790 }, 1791 Volatility: VolatilityImmutable, 1792 }, 1793 }, 1794 1795 JSONFetchText: { 1796 &BinOp{ 1797 LeftType: types.Jsonb, 1798 RightType: types.String, 1799 ReturnType: types.String, 1800 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1801 res, err := left.(*DJSON).JSON.FetchValKey(string(MustBeDString(right))) 1802 if err != nil { 1803 return nil, err 1804 } 1805 if res == nil { 1806 return DNull, nil 1807 } 1808 text, err := res.AsText() 1809 if err != nil { 1810 return nil, err 1811 } 1812 if text == nil { 1813 return DNull, nil 1814 } 1815 return NewDString(*text), nil 1816 }, 1817 Volatility: VolatilityImmutable, 1818 }, 1819 &BinOp{ 1820 LeftType: types.Jsonb, 1821 RightType: types.Int, 1822 ReturnType: types.String, 1823 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1824 res, err := left.(*DJSON).JSON.FetchValIdx(int(MustBeDInt(right))) 1825 if err != nil { 1826 return nil, err 1827 } 1828 if res == nil { 1829 return DNull, nil 1830 } 1831 text, err := res.AsText() 1832 if err != nil { 1833 return nil, err 1834 } 1835 if text == nil { 1836 return DNull, nil 1837 } 1838 return NewDString(*text), nil 1839 }, 1840 Volatility: VolatilityImmutable, 1841 }, 1842 }, 1843 1844 JSONFetchTextPath: { 1845 &BinOp{ 1846 LeftType: types.Jsonb, 1847 RightType: types.MakeArray(types.String), 1848 ReturnType: types.String, 1849 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 1850 res, err := getJSONPath(*left.(*DJSON), *MustBeDArray(right)) 1851 if err != nil { 1852 return nil, err 1853 } 1854 if res == DNull { 1855 return DNull, nil 1856 } 1857 text, err := res.(*DJSON).JSON.AsText() 1858 if err != nil { 1859 return nil, err 1860 } 1861 if text == nil { 1862 return DNull, nil 1863 } 1864 return NewDString(*text), nil 1865 }, 1866 Volatility: VolatilityImmutable, 1867 }, 1868 }, 1869 } 1870 1871 // timestampMinusBinOp is the implementation of the subtraction 1872 // between types.TimestampTZ operands. 1873 var timestampMinusBinOp *BinOp 1874 1875 // TimestampDifference computes the interval difference between two 1876 // TimestampTZ datums. The result is a DInterval. The caller must 1877 // ensure that the arguments are of the proper Datum type. 1878 func TimestampDifference(ctx *EvalContext, start, end Datum) (Datum, error) { 1879 return timestampMinusBinOp.Fn(ctx, start, end) 1880 } 1881 1882 func init() { 1883 timestampMinusBinOp, _ = BinOps[Minus].lookupImpl(types.TimestampTZ, types.TimestampTZ) 1884 } 1885 1886 // CmpOp is a comparison operator. 1887 type CmpOp struct { 1888 LeftType *types.T 1889 RightType *types.T 1890 1891 // If NullableArgs is false, the operator returns NULL 1892 // whenever either argument is NULL. 1893 NullableArgs bool 1894 1895 // Datum return type is a union between *DBool and dNull. 1896 Fn func(*EvalContext, Datum, Datum) (Datum, error) 1897 1898 Volatility Volatility 1899 1900 types TypeList 1901 isPreferred bool 1902 1903 // counter, if non-nil, should be incremented every time the 1904 // operator is type checked. 1905 counter telemetry.Counter 1906 } 1907 1908 func (op *CmpOp) params() TypeList { 1909 return op.types 1910 } 1911 1912 func (op *CmpOp) matchParams(l, r *types.T) bool { 1913 return op.params().MatchAt(l, 0) && op.params().MatchAt(r, 1) 1914 } 1915 1916 var cmpOpReturnType = FixedReturnType(types.Bool) 1917 1918 func (op *CmpOp) returnType() ReturnTyper { 1919 return cmpOpReturnType 1920 } 1921 1922 func (op *CmpOp) preferred() bool { 1923 return op.isPreferred 1924 } 1925 1926 func cmpOpFixups(cmpOps map[ComparisonOperator]cmpOpOverload) map[ComparisonOperator]cmpOpOverload { 1927 findVolatility := func(op ComparisonOperator, t *types.T) Volatility { 1928 for _, impl := range cmpOps[EQ] { 1929 o := impl.(*CmpOp) 1930 if o.LeftType.Equivalent(t) && o.RightType.Equivalent(t) { 1931 return o.Volatility 1932 } 1933 } 1934 panic(errors.AssertionFailedf("could not find cmp op %s(%s,%s)", op, t, t)) 1935 } 1936 1937 // Array equality comparisons. 1938 for _, t := range types.Scalar { 1939 cmpOps[EQ] = append(cmpOps[EQ], &CmpOp{ 1940 LeftType: types.MakeArray(t), 1941 RightType: types.MakeArray(t), 1942 Fn: cmpOpScalarEQFn, 1943 Volatility: findVolatility(EQ, t), 1944 }) 1945 cmpOps[LE] = append(cmpOps[LE], &CmpOp{ 1946 LeftType: types.MakeArray(t), 1947 RightType: types.MakeArray(t), 1948 Fn: cmpOpScalarLEFn, 1949 Volatility: findVolatility(LE, t), 1950 }) 1951 cmpOps[LT] = append(cmpOps[LT], &CmpOp{ 1952 LeftType: types.MakeArray(t), 1953 RightType: types.MakeArray(t), 1954 Fn: cmpOpScalarLTFn, 1955 Volatility: findVolatility(LT, t), 1956 }) 1957 1958 cmpOps[IsNotDistinctFrom] = append(cmpOps[IsNotDistinctFrom], &CmpOp{ 1959 LeftType: types.MakeArray(t), 1960 RightType: types.MakeArray(t), 1961 Fn: cmpOpScalarIsFn, 1962 NullableArgs: true, 1963 Volatility: findVolatility(IsNotDistinctFrom, t), 1964 }) 1965 } 1966 1967 for op, overload := range cmpOps { 1968 for i, impl := range overload { 1969 casted := impl.(*CmpOp) 1970 casted.types = ArgTypes{{"left", casted.LeftType}, {"right", casted.RightType}} 1971 cmpOps[op][i] = casted 1972 } 1973 } 1974 1975 return cmpOps 1976 } 1977 1978 // cmpOpOverload is an overloaded set of comparison operator implementations. 1979 type cmpOpOverload []overloadImpl 1980 1981 func (o cmpOpOverload) LookupImpl(left, right *types.T) (*CmpOp, bool) { 1982 for _, fn := range o { 1983 casted := fn.(*CmpOp) 1984 if casted.matchParams(left, right) { 1985 return casted, true 1986 } 1987 } 1988 return nil, false 1989 } 1990 1991 func makeCmpOpOverload( 1992 fn func(ctx *EvalContext, left, right Datum) (Datum, error), 1993 a, b *types.T, 1994 nullableArgs bool, 1995 v Volatility, 1996 ) *CmpOp { 1997 return &CmpOp{ 1998 LeftType: a, 1999 RightType: b, 2000 Fn: fn, 2001 NullableArgs: nullableArgs, 2002 Volatility: v, 2003 } 2004 } 2005 2006 func makeEqFn(a, b *types.T, v Volatility) *CmpOp { 2007 return makeCmpOpOverload(cmpOpScalarEQFn, a, b, false /* NullableArgs */, v) 2008 } 2009 func makeLtFn(a, b *types.T, v Volatility) *CmpOp { 2010 return makeCmpOpOverload(cmpOpScalarLTFn, a, b, false /* NullableArgs */, v) 2011 } 2012 func makeLeFn(a, b *types.T, v Volatility) *CmpOp { 2013 return makeCmpOpOverload(cmpOpScalarLEFn, a, b, false /* NullableArgs */, v) 2014 } 2015 func makeIsFn(a, b *types.T, v Volatility) *CmpOp { 2016 return makeCmpOpOverload(cmpOpScalarIsFn, a, b, true /* NullableArgs */, v) 2017 } 2018 2019 // CmpOps contains the comparison operations indexed by operation type. 2020 var CmpOps = cmpOpFixups(map[ComparisonOperator]cmpOpOverload{ 2021 EQ: { 2022 // Single-type comparisons. 2023 makeEqFn(types.AnyEnum, types.AnyEnum, VolatilityImmutable), 2024 makeEqFn(types.Bool, types.Bool, VolatilityLeakProof), 2025 makeEqFn(types.Bytes, types.Bytes, VolatilityLeakProof), 2026 makeEqFn(types.Date, types.Date, VolatilityLeakProof), 2027 makeEqFn(types.Decimal, types.Decimal, VolatilityImmutable), 2028 // Note: it is an error to compare two strings with different collations; 2029 // the operator is leak proof under the assumption that these cases will be 2030 // detected during type checking. 2031 makeEqFn(types.AnyCollatedString, types.AnyCollatedString, VolatilityLeakProof), 2032 makeEqFn(types.Float, types.Float, VolatilityLeakProof), 2033 makeEqFn(types.Geography, types.Geography, VolatilityLeakProof), 2034 makeEqFn(types.Geometry, types.Geometry, VolatilityLeakProof), 2035 makeEqFn(types.INet, types.INet, VolatilityLeakProof), 2036 makeEqFn(types.Int, types.Int, VolatilityLeakProof), 2037 makeEqFn(types.Interval, types.Interval, VolatilityLeakProof), 2038 makeEqFn(types.Jsonb, types.Jsonb, VolatilityImmutable), 2039 makeEqFn(types.Oid, types.Oid, VolatilityLeakProof), 2040 makeEqFn(types.String, types.String, VolatilityLeakProof), 2041 makeEqFn(types.Time, types.Time, VolatilityLeakProof), 2042 makeEqFn(types.TimeTZ, types.TimeTZ, VolatilityLeakProof), 2043 makeEqFn(types.Timestamp, types.Timestamp, VolatilityLeakProof), 2044 makeEqFn(types.TimestampTZ, types.TimestampTZ, VolatilityLeakProof), 2045 makeEqFn(types.Uuid, types.Uuid, VolatilityLeakProof), 2046 makeEqFn(types.VarBit, types.VarBit, VolatilityLeakProof), 2047 2048 // Mixed-type comparisons. 2049 makeEqFn(types.Date, types.Timestamp, VolatilityImmutable), 2050 makeEqFn(types.Date, types.TimestampTZ, VolatilityStable), 2051 makeEqFn(types.Decimal, types.Float, VolatilityLeakProof), 2052 makeEqFn(types.Decimal, types.Int, VolatilityLeakProof), 2053 makeEqFn(types.Float, types.Decimal, VolatilityLeakProof), 2054 makeEqFn(types.Float, types.Int, VolatilityLeakProof), 2055 makeEqFn(types.Int, types.Decimal, VolatilityLeakProof), 2056 makeEqFn(types.Int, types.Float, VolatilityLeakProof), 2057 makeEqFn(types.Timestamp, types.Date, VolatilityImmutable), 2058 makeEqFn(types.Timestamp, types.TimestampTZ, VolatilityStable), 2059 makeEqFn(types.TimestampTZ, types.Date, VolatilityStable), 2060 makeEqFn(types.TimestampTZ, types.Timestamp, VolatilityStable), 2061 makeEqFn(types.Time, types.TimeTZ, VolatilityStable), 2062 makeEqFn(types.TimeTZ, types.Time, VolatilityStable), 2063 2064 // Tuple comparison. 2065 &CmpOp{ 2066 LeftType: types.AnyTuple, 2067 RightType: types.AnyTuple, 2068 Fn: func(ctx *EvalContext, left Datum, right Datum) (Datum, error) { 2069 return cmpOpTupleFn(ctx, *left.(*DTuple), *right.(*DTuple), EQ), nil 2070 }, 2071 Volatility: VolatilityImmutable, 2072 }, 2073 }, 2074 2075 LT: { 2076 // Single-type comparisons. 2077 makeLtFn(types.AnyEnum, types.AnyEnum, VolatilityImmutable), 2078 makeLtFn(types.Bool, types.Bool, VolatilityLeakProof), 2079 makeLtFn(types.Bytes, types.Bytes, VolatilityLeakProof), 2080 makeLtFn(types.Date, types.Date, VolatilityLeakProof), 2081 makeLtFn(types.Decimal, types.Decimal, VolatilityImmutable), 2082 makeLtFn(types.AnyCollatedString, types.AnyCollatedString, VolatilityLeakProof), 2083 // Note: it is an error to compare two strings with different collations; 2084 // the operator is leak proof under the assumption that these cases will be 2085 // detected during type checking. 2086 makeLtFn(types.Float, types.Float, VolatilityLeakProof), 2087 makeLtFn(types.Geography, types.Geography, VolatilityLeakProof), 2088 makeLtFn(types.Geometry, types.Geometry, VolatilityLeakProof), 2089 makeLtFn(types.INet, types.INet, VolatilityLeakProof), 2090 makeLtFn(types.Int, types.Int, VolatilityLeakProof), 2091 makeLtFn(types.Interval, types.Interval, VolatilityLeakProof), 2092 makeLtFn(types.Oid, types.Oid, VolatilityLeakProof), 2093 makeLtFn(types.String, types.String, VolatilityLeakProof), 2094 makeLtFn(types.Time, types.Time, VolatilityLeakProof), 2095 makeLtFn(types.TimeTZ, types.TimeTZ, VolatilityLeakProof), 2096 makeLtFn(types.Timestamp, types.Timestamp, VolatilityLeakProof), 2097 makeLtFn(types.TimestampTZ, types.TimestampTZ, VolatilityLeakProof), 2098 makeLtFn(types.Uuid, types.Uuid, VolatilityLeakProof), 2099 makeLtFn(types.VarBit, types.VarBit, VolatilityLeakProof), 2100 2101 // Mixed-type comparisons. 2102 makeLtFn(types.Date, types.Timestamp, VolatilityImmutable), 2103 makeLtFn(types.Date, types.TimestampTZ, VolatilityStable), 2104 makeLtFn(types.Decimal, types.Float, VolatilityLeakProof), 2105 makeLtFn(types.Decimal, types.Int, VolatilityLeakProof), 2106 makeLtFn(types.Float, types.Decimal, VolatilityLeakProof), 2107 makeLtFn(types.Float, types.Int, VolatilityLeakProof), 2108 makeLtFn(types.Int, types.Decimal, VolatilityLeakProof), 2109 makeLtFn(types.Int, types.Float, VolatilityLeakProof), 2110 makeLtFn(types.Timestamp, types.Date, VolatilityImmutable), 2111 makeLtFn(types.Timestamp, types.TimestampTZ, VolatilityStable), 2112 makeLtFn(types.TimestampTZ, types.Date, VolatilityStable), 2113 makeLtFn(types.TimestampTZ, types.Timestamp, VolatilityStable), 2114 makeLtFn(types.Time, types.TimeTZ, VolatilityStable), 2115 makeLtFn(types.TimeTZ, types.Time, VolatilityStable), 2116 2117 // Tuple comparison. 2118 &CmpOp{ 2119 LeftType: types.AnyTuple, 2120 RightType: types.AnyTuple, 2121 Fn: func(ctx *EvalContext, left Datum, right Datum) (Datum, error) { 2122 return cmpOpTupleFn(ctx, *left.(*DTuple), *right.(*DTuple), LT), nil 2123 }, 2124 Volatility: VolatilityImmutable, 2125 }, 2126 }, 2127 2128 LE: { 2129 // Single-type comparisons. 2130 makeLeFn(types.AnyEnum, types.AnyEnum, VolatilityImmutable), 2131 makeLeFn(types.Bool, types.Bool, VolatilityLeakProof), 2132 makeLeFn(types.Bytes, types.Bytes, VolatilityLeakProof), 2133 makeLeFn(types.Date, types.Date, VolatilityLeakProof), 2134 makeLeFn(types.Decimal, types.Decimal, VolatilityImmutable), 2135 // Note: it is an error to compare two strings with different collations; 2136 // the operator is leak proof under the assumption that these cases will be 2137 // detected during type checking. 2138 makeLeFn(types.AnyCollatedString, types.AnyCollatedString, VolatilityLeakProof), 2139 makeLeFn(types.Float, types.Float, VolatilityLeakProof), 2140 makeLeFn(types.Geography, types.Geography, VolatilityLeakProof), 2141 makeLeFn(types.Geometry, types.Geometry, VolatilityLeakProof), 2142 makeLeFn(types.INet, types.INet, VolatilityLeakProof), 2143 makeLeFn(types.Int, types.Int, VolatilityLeakProof), 2144 makeLeFn(types.Interval, types.Interval, VolatilityLeakProof), 2145 makeLeFn(types.Oid, types.Oid, VolatilityLeakProof), 2146 makeLeFn(types.String, types.String, VolatilityLeakProof), 2147 makeLeFn(types.Time, types.Time, VolatilityLeakProof), 2148 makeLeFn(types.TimeTZ, types.TimeTZ, VolatilityLeakProof), 2149 makeLeFn(types.Timestamp, types.Timestamp, VolatilityLeakProof), 2150 makeLeFn(types.TimestampTZ, types.TimestampTZ, VolatilityLeakProof), 2151 makeLeFn(types.Uuid, types.Uuid, VolatilityLeakProof), 2152 makeLeFn(types.VarBit, types.VarBit, VolatilityLeakProof), 2153 2154 // Mixed-type comparisons. 2155 makeLeFn(types.Date, types.Timestamp, VolatilityImmutable), 2156 makeLeFn(types.Date, types.TimestampTZ, VolatilityStable), 2157 makeLeFn(types.Decimal, types.Float, VolatilityLeakProof), 2158 makeLeFn(types.Decimal, types.Int, VolatilityLeakProof), 2159 makeLeFn(types.Float, types.Decimal, VolatilityLeakProof), 2160 makeLeFn(types.Float, types.Int, VolatilityLeakProof), 2161 makeLeFn(types.Int, types.Decimal, VolatilityLeakProof), 2162 makeLeFn(types.Int, types.Float, VolatilityLeakProof), 2163 makeLeFn(types.Timestamp, types.Date, VolatilityImmutable), 2164 makeLeFn(types.Timestamp, types.TimestampTZ, VolatilityStable), 2165 makeLeFn(types.TimestampTZ, types.Date, VolatilityStable), 2166 makeLeFn(types.TimestampTZ, types.Timestamp, VolatilityStable), 2167 makeLeFn(types.Time, types.TimeTZ, VolatilityStable), 2168 makeLeFn(types.TimeTZ, types.Time, VolatilityStable), 2169 2170 // Tuple comparison. 2171 &CmpOp{ 2172 LeftType: types.AnyTuple, 2173 RightType: types.AnyTuple, 2174 Fn: func(ctx *EvalContext, left Datum, right Datum) (Datum, error) { 2175 return cmpOpTupleFn(ctx, *left.(*DTuple), *right.(*DTuple), LE), nil 2176 }, 2177 Volatility: VolatilityImmutable, 2178 }, 2179 }, 2180 2181 IsNotDistinctFrom: { 2182 &CmpOp{ 2183 LeftType: types.Unknown, 2184 RightType: types.Unknown, 2185 Fn: cmpOpScalarIsFn, 2186 NullableArgs: true, 2187 // Avoids ambiguous comparison error for NULL IS NOT DISTINCT FROM NULL> 2188 isPreferred: true, 2189 Volatility: VolatilityLeakProof, 2190 }, 2191 // Single-type comparisons. 2192 makeIsFn(types.AnyEnum, types.AnyEnum, VolatilityImmutable), 2193 makeIsFn(types.Bool, types.Bool, VolatilityLeakProof), 2194 makeIsFn(types.Bytes, types.Bytes, VolatilityLeakProof), 2195 makeIsFn(types.Date, types.Date, VolatilityLeakProof), 2196 makeIsFn(types.Decimal, types.Decimal, VolatilityImmutable), 2197 // Note: it is an error to compare two strings with different collations; 2198 // the operator is leak proof under the assumption that these cases will be 2199 // detected during type checking. 2200 makeIsFn(types.AnyCollatedString, types.AnyCollatedString, VolatilityLeakProof), 2201 makeIsFn(types.Float, types.Float, VolatilityLeakProof), 2202 makeIsFn(types.Geography, types.Geography, VolatilityLeakProof), 2203 makeIsFn(types.Geometry, types.Geometry, VolatilityLeakProof), 2204 makeIsFn(types.INet, types.INet, VolatilityLeakProof), 2205 makeIsFn(types.Int, types.Int, VolatilityLeakProof), 2206 makeIsFn(types.Interval, types.Interval, VolatilityLeakProof), 2207 makeIsFn(types.Jsonb, types.Jsonb, VolatilityImmutable), 2208 makeIsFn(types.Oid, types.Oid, VolatilityLeakProof), 2209 makeIsFn(types.String, types.String, VolatilityLeakProof), 2210 makeIsFn(types.Time, types.Time, VolatilityLeakProof), 2211 makeIsFn(types.TimeTZ, types.TimeTZ, VolatilityLeakProof), 2212 makeIsFn(types.Timestamp, types.Timestamp, VolatilityLeakProof), 2213 makeIsFn(types.TimestampTZ, types.TimestampTZ, VolatilityLeakProof), 2214 makeIsFn(types.Uuid, types.Uuid, VolatilityLeakProof), 2215 makeIsFn(types.VarBit, types.VarBit, VolatilityLeakProof), 2216 2217 // Mixed-type comparisons. 2218 makeIsFn(types.Date, types.Timestamp, VolatilityImmutable), 2219 makeIsFn(types.Date, types.TimestampTZ, VolatilityStable), 2220 makeIsFn(types.Decimal, types.Float, VolatilityLeakProof), 2221 makeIsFn(types.Decimal, types.Int, VolatilityLeakProof), 2222 makeIsFn(types.Float, types.Decimal, VolatilityLeakProof), 2223 makeIsFn(types.Float, types.Int, VolatilityLeakProof), 2224 makeIsFn(types.Int, types.Decimal, VolatilityLeakProof), 2225 makeIsFn(types.Int, types.Float, VolatilityLeakProof), 2226 makeIsFn(types.Timestamp, types.Date, VolatilityImmutable), 2227 makeIsFn(types.Timestamp, types.TimestampTZ, VolatilityStable), 2228 makeIsFn(types.TimestampTZ, types.Date, VolatilityStable), 2229 makeIsFn(types.TimestampTZ, types.Timestamp, VolatilityStable), 2230 makeIsFn(types.Time, types.TimeTZ, VolatilityStable), 2231 makeIsFn(types.TimeTZ, types.Time, VolatilityStable), 2232 2233 // Tuple comparison. 2234 &CmpOp{ 2235 LeftType: types.AnyTuple, 2236 RightType: types.AnyTuple, 2237 NullableArgs: true, 2238 Fn: func(ctx *EvalContext, left Datum, right Datum) (Datum, error) { 2239 if left == DNull || right == DNull { 2240 return MakeDBool(left == DNull && right == DNull), nil 2241 } 2242 return cmpOpTupleFn(ctx, *left.(*DTuple), *right.(*DTuple), IsNotDistinctFrom), nil 2243 }, 2244 Volatility: VolatilityImmutable, 2245 }, 2246 }, 2247 2248 In: { 2249 makeEvalTupleIn(types.AnyEnum, VolatilityLeakProof), 2250 makeEvalTupleIn(types.Bool, VolatilityLeakProof), 2251 makeEvalTupleIn(types.Bytes, VolatilityLeakProof), 2252 makeEvalTupleIn(types.Date, VolatilityLeakProof), 2253 makeEvalTupleIn(types.Decimal, VolatilityLeakProof), 2254 makeEvalTupleIn(types.AnyCollatedString, VolatilityLeakProof), 2255 makeEvalTupleIn(types.AnyTuple, VolatilityLeakProof), 2256 makeEvalTupleIn(types.Float, VolatilityLeakProof), 2257 makeEvalTupleIn(types.Geography, VolatilityLeakProof), 2258 makeEvalTupleIn(types.Geometry, VolatilityLeakProof), 2259 makeEvalTupleIn(types.INet, VolatilityLeakProof), 2260 makeEvalTupleIn(types.Int, VolatilityLeakProof), 2261 makeEvalTupleIn(types.Interval, VolatilityLeakProof), 2262 makeEvalTupleIn(types.Jsonb, VolatilityLeakProof), 2263 makeEvalTupleIn(types.Oid, VolatilityLeakProof), 2264 makeEvalTupleIn(types.String, VolatilityLeakProof), 2265 makeEvalTupleIn(types.Time, VolatilityLeakProof), 2266 makeEvalTupleIn(types.TimeTZ, VolatilityLeakProof), 2267 makeEvalTupleIn(types.Timestamp, VolatilityLeakProof), 2268 makeEvalTupleIn(types.TimestampTZ, VolatilityLeakProof), 2269 makeEvalTupleIn(types.Uuid, VolatilityLeakProof), 2270 makeEvalTupleIn(types.VarBit, VolatilityLeakProof), 2271 }, 2272 2273 Like: { 2274 &CmpOp{ 2275 LeftType: types.String, 2276 RightType: types.String, 2277 Fn: func(ctx *EvalContext, left Datum, right Datum) (Datum, error) { 2278 return matchLike(ctx, left, right, false) 2279 }, 2280 Volatility: VolatilityLeakProof, 2281 }, 2282 }, 2283 2284 ILike: { 2285 &CmpOp{ 2286 LeftType: types.String, 2287 RightType: types.String, 2288 Fn: func(ctx *EvalContext, left Datum, right Datum) (Datum, error) { 2289 return matchLike(ctx, left, right, true) 2290 }, 2291 Volatility: VolatilityLeakProof, 2292 }, 2293 }, 2294 2295 SimilarTo: { 2296 &CmpOp{ 2297 LeftType: types.String, 2298 RightType: types.String, 2299 Fn: func(ctx *EvalContext, left Datum, right Datum) (Datum, error) { 2300 key := similarToKey{s: string(MustBeDString(right)), escape: '\\'} 2301 return matchRegexpWithKey(ctx, left, key) 2302 }, 2303 Volatility: VolatilityLeakProof, 2304 }, 2305 }, 2306 2307 RegMatch: { 2308 &CmpOp{ 2309 LeftType: types.String, 2310 RightType: types.String, 2311 Fn: func(ctx *EvalContext, left Datum, right Datum) (Datum, error) { 2312 key := regexpKey{s: string(MustBeDString(right)), caseInsensitive: false} 2313 return matchRegexpWithKey(ctx, left, key) 2314 }, 2315 Volatility: VolatilityImmutable, 2316 }, 2317 }, 2318 2319 RegIMatch: { 2320 &CmpOp{ 2321 LeftType: types.String, 2322 RightType: types.String, 2323 Fn: func(ctx *EvalContext, left Datum, right Datum) (Datum, error) { 2324 key := regexpKey{s: string(MustBeDString(right)), caseInsensitive: true} 2325 return matchRegexpWithKey(ctx, left, key) 2326 }, 2327 Volatility: VolatilityImmutable, 2328 }, 2329 }, 2330 2331 JSONExists: { 2332 &CmpOp{ 2333 LeftType: types.Jsonb, 2334 RightType: types.String, 2335 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 2336 e, err := left.(*DJSON).JSON.Exists(string(MustBeDString(right))) 2337 if err != nil { 2338 return nil, err 2339 } 2340 if e { 2341 return DBoolTrue, nil 2342 } 2343 return DBoolFalse, nil 2344 }, 2345 Volatility: VolatilityImmutable, 2346 }, 2347 }, 2348 2349 JSONSomeExists: { 2350 &CmpOp{ 2351 LeftType: types.Jsonb, 2352 RightType: types.StringArray, 2353 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 2354 // TODO(justin): this can be optimized. 2355 for _, k := range MustBeDArray(right).Array { 2356 if k == DNull { 2357 continue 2358 } 2359 e, err := left.(*DJSON).JSON.Exists(string(MustBeDString(k))) 2360 if err != nil { 2361 return nil, err 2362 } 2363 if e { 2364 return DBoolTrue, nil 2365 } 2366 } 2367 return DBoolFalse, nil 2368 }, 2369 Volatility: VolatilityImmutable, 2370 }, 2371 }, 2372 2373 JSONAllExists: { 2374 &CmpOp{ 2375 LeftType: types.Jsonb, 2376 RightType: types.StringArray, 2377 Fn: func(_ *EvalContext, left Datum, right Datum) (Datum, error) { 2378 // TODO(justin): this can be optimized. 2379 for _, k := range MustBeDArray(right).Array { 2380 if k == DNull { 2381 continue 2382 } 2383 e, err := left.(*DJSON).JSON.Exists(string(MustBeDString(k))) 2384 if err != nil { 2385 return nil, err 2386 } 2387 if !e { 2388 return DBoolFalse, nil 2389 } 2390 } 2391 return DBoolTrue, nil 2392 }, 2393 Volatility: VolatilityImmutable, 2394 }, 2395 }, 2396 2397 Contains: { 2398 &CmpOp{ 2399 LeftType: types.AnyArray, 2400 RightType: types.AnyArray, 2401 Fn: func(ctx *EvalContext, left Datum, right Datum) (Datum, error) { 2402 haystack := MustBeDArray(left) 2403 needles := MustBeDArray(right) 2404 return ArrayContains(ctx, haystack, needles) 2405 }, 2406 Volatility: VolatilityImmutable, 2407 }, 2408 &CmpOp{ 2409 LeftType: types.Jsonb, 2410 RightType: types.Jsonb, 2411 Fn: func(ctx *EvalContext, left Datum, right Datum) (Datum, error) { 2412 c, err := json.Contains(left.(*DJSON).JSON, right.(*DJSON).JSON) 2413 if err != nil { 2414 return nil, err 2415 } 2416 return MakeDBool(DBool(c)), nil 2417 }, 2418 Volatility: VolatilityImmutable, 2419 }, 2420 }, 2421 2422 ContainedBy: { 2423 &CmpOp{ 2424 LeftType: types.AnyArray, 2425 RightType: types.AnyArray, 2426 Fn: func(ctx *EvalContext, left Datum, right Datum) (Datum, error) { 2427 needles := MustBeDArray(left) 2428 haystack := MustBeDArray(right) 2429 return ArrayContains(ctx, haystack, needles) 2430 }, 2431 Volatility: VolatilityImmutable, 2432 }, 2433 &CmpOp{ 2434 LeftType: types.Jsonb, 2435 RightType: types.Jsonb, 2436 Fn: func(ctx *EvalContext, left Datum, right Datum) (Datum, error) { 2437 c, err := json.Contains(right.(*DJSON).JSON, left.(*DJSON).JSON) 2438 if err != nil { 2439 return nil, err 2440 } 2441 return MakeDBool(DBool(c)), nil 2442 }, 2443 Volatility: VolatilityImmutable, 2444 }, 2445 }, 2446 Overlaps: { 2447 &CmpOp{ 2448 LeftType: types.AnyArray, 2449 RightType: types.AnyArray, 2450 Fn: func(ctx *EvalContext, left Datum, right Datum) (Datum, error) { 2451 array := MustBeDArray(left) 2452 other := MustBeDArray(right) 2453 if !array.ParamTyp.Equivalent(other.ParamTyp) { 2454 return nil, pgerror.New(pgcode.DatatypeMismatch, "cannot compare arrays with different element types") 2455 } 2456 for _, needle := range array.Array { 2457 // Nulls don't compare to each other in && syntax. 2458 if needle == DNull { 2459 continue 2460 } 2461 for _, hay := range other.Array { 2462 if needle.Compare(ctx, hay) == 0 { 2463 return DBoolTrue, nil 2464 } 2465 } 2466 } 2467 return DBoolFalse, nil 2468 }, 2469 Volatility: VolatilityImmutable, 2470 }, 2471 &CmpOp{ 2472 LeftType: types.INet, 2473 RightType: types.INet, 2474 Fn: func(_ *EvalContext, left, right Datum) (Datum, error) { 2475 ipAddr := MustBeDIPAddr(left).IPAddr 2476 other := MustBeDIPAddr(right).IPAddr 2477 return MakeDBool(DBool(ipAddr.ContainsOrContainedBy(&other))), nil 2478 }, 2479 Volatility: VolatilityImmutable, 2480 }, 2481 }, 2482 }) 2483 2484 // This map contains the inverses for operators in the CmpOps map that have 2485 // inverses. 2486 var cmpOpsInverse map[ComparisonOperator]ComparisonOperator 2487 2488 func init() { 2489 cmpOpsInverse = make(map[ComparisonOperator]ComparisonOperator) 2490 for cmpOpIdx := range comparisonOpName { 2491 cmpOp := ComparisonOperator(cmpOpIdx) 2492 newOp, _, _, _, _ := foldComparisonExpr(cmpOp, DNull, DNull) 2493 if newOp != cmpOp { 2494 cmpOpsInverse[newOp] = cmpOp 2495 cmpOpsInverse[cmpOp] = newOp 2496 } 2497 } 2498 } 2499 2500 func boolFromCmp(cmp int, op ComparisonOperator) *DBool { 2501 switch op { 2502 case EQ, IsNotDistinctFrom: 2503 return MakeDBool(cmp == 0) 2504 case LT: 2505 return MakeDBool(cmp < 0) 2506 case LE: 2507 return MakeDBool(cmp <= 0) 2508 default: 2509 panic(errors.AssertionFailedf("unexpected ComparisonOperator in boolFromCmp: %v", errors.Safe(op))) 2510 } 2511 } 2512 2513 func cmpOpScalarFn(ctx *EvalContext, left, right Datum, op ComparisonOperator) Datum { 2514 // Before deferring to the Datum.Compare method, check for values that should 2515 // be handled differently during SQL comparison evaluation than they should when 2516 // ordering Datum values. 2517 if left == DNull || right == DNull { 2518 switch op { 2519 case IsNotDistinctFrom: 2520 return MakeDBool((left == DNull) == (right == DNull)) 2521 2522 default: 2523 // If either Datum is NULL, the result of the comparison is NULL. 2524 return DNull 2525 } 2526 } 2527 cmp := left.Compare(ctx, right) 2528 return boolFromCmp(cmp, op) 2529 } 2530 2531 func cmpOpScalarEQFn(ctx *EvalContext, left, right Datum) (Datum, error) { 2532 return cmpOpScalarFn(ctx, left, right, EQ), nil 2533 } 2534 func cmpOpScalarLTFn(ctx *EvalContext, left, right Datum) (Datum, error) { 2535 return cmpOpScalarFn(ctx, left, right, LT), nil 2536 } 2537 func cmpOpScalarLEFn(ctx *EvalContext, left, right Datum) (Datum, error) { 2538 return cmpOpScalarFn(ctx, left, right, LE), nil 2539 } 2540 func cmpOpScalarIsFn(ctx *EvalContext, left, right Datum) (Datum, error) { 2541 return cmpOpScalarFn(ctx, left, right, IsNotDistinctFrom), nil 2542 } 2543 2544 func cmpOpTupleFn(ctx *EvalContext, left, right DTuple, op ComparisonOperator) Datum { 2545 cmp := 0 2546 sawNull := false 2547 for i, leftElem := range left.D { 2548 rightElem := right.D[i] 2549 // Like with cmpOpScalarFn, check for values that need to be handled 2550 // differently than when ordering Datums. 2551 if leftElem == DNull || rightElem == DNull { 2552 switch op { 2553 case EQ: 2554 // If either Datum is NULL and the op is EQ, we continue the 2555 // comparison and the result is only NULL if the other (non-NULL) 2556 // elements are equal. This is because NULL is thought of as "unknown", 2557 // so a NULL equality comparison does not prevent the equality from 2558 // being proven false, but does prevent it from being proven true. 2559 sawNull = true 2560 2561 case IsNotDistinctFrom: 2562 // For IS NOT DISTINCT FROM, NULLs are "equal". 2563 if leftElem != DNull || rightElem != DNull { 2564 return DBoolFalse 2565 } 2566 2567 default: 2568 // If either Datum is NULL and the op is not EQ or IS NOT DISTINCT FROM, 2569 // we short-circuit the evaluation and the result of the comparison is 2570 // NULL. This is because NULL is thought of as "unknown" and tuple 2571 // inequality is defined lexicographically, so once a NULL comparison is 2572 // seen, the result of the entire tuple comparison is unknown. 2573 return DNull 2574 } 2575 } else { 2576 cmp = leftElem.Compare(ctx, rightElem) 2577 if cmp != 0 { 2578 break 2579 } 2580 } 2581 } 2582 b := boolFromCmp(cmp, op) 2583 if b == DBoolTrue && sawNull { 2584 // The op is EQ and all non-NULL elements are equal, but we saw at least 2585 // one NULL element. Since NULL comparisons are treated as unknown, the 2586 // result of the comparison becomes unknown (NULL). 2587 return DNull 2588 } 2589 return b 2590 } 2591 2592 func makeEvalTupleIn(typ *types.T, v Volatility) *CmpOp { 2593 return &CmpOp{ 2594 LeftType: typ, 2595 RightType: types.AnyTuple, 2596 Fn: func(ctx *EvalContext, arg, values Datum) (Datum, error) { 2597 vtuple := values.(*DTuple) 2598 // If the tuple was sorted during normalization, we can perform an 2599 // efficient binary search to find if the arg is in the tuple (as 2600 // long as the arg doesn't contain any NULLs). 2601 if len(vtuple.D) == 0 { 2602 // If the rhs tuple is empty, the result is always false (even if arg is 2603 // or contains NULL). 2604 return DBoolFalse, nil 2605 } 2606 if arg == DNull { 2607 return DNull, nil 2608 } 2609 argTuple, argIsTuple := arg.(*DTuple) 2610 if vtuple.Sorted() && !(argIsTuple && argTuple.ContainsNull()) { 2611 // The right-hand tuple is already sorted and contains no NULLs, and the 2612 // left side is not NULL (e.g. `NULL IN (1, 2)`) or a tuple that 2613 // contains NULL (e.g. `(1, NULL) IN ((1, 2), (3, 4))`). 2614 // 2615 // We can use binary search to make a determination in this case. This 2616 // is the common case when tuples don't contain NULLs. 2617 _, result := vtuple.SearchSorted(ctx, arg) 2618 return MakeDBool(DBool(result)), nil 2619 } 2620 2621 sawNull := false 2622 if !argIsTuple { 2623 // The left-hand side is not a tuple, e.g. `1 IN (1, 2)`. 2624 for _, val := range vtuple.D { 2625 if val == DNull { 2626 sawNull = true 2627 } else if val.Compare(ctx, arg) == 0 { 2628 return DBoolTrue, nil 2629 } 2630 } 2631 } else { 2632 // The left-hand side is a tuple, e.g. `(1, 2) IN ((1, 2), (3, 4))`. 2633 for _, val := range vtuple.D { 2634 if val == DNull { 2635 // We allow for a null value to be in the list of tuples, so we 2636 // need to check that upfront. 2637 sawNull = true 2638 } else { 2639 // Use the EQ function which properly handles NULLs. 2640 if res := cmpOpTupleFn(ctx, *argTuple, *val.(*DTuple), EQ); res == DNull { 2641 sawNull = true 2642 } else if res == DBoolTrue { 2643 return DBoolTrue, nil 2644 } 2645 } 2646 } 2647 } 2648 if sawNull { 2649 return DNull, nil 2650 } 2651 return DBoolFalse, nil 2652 }, 2653 NullableArgs: true, 2654 Volatility: v, 2655 } 2656 } 2657 2658 // evalDatumsCmp evaluates Datums (slice of Datum) using the provided 2659 // sub-operator type (ANY/SOME, ALL) and its CmpOp with the left Datum. 2660 // It returns the result of the ANY/SOME/ALL predicate. 2661 // 2662 // A NULL result is returned if there exists a NULL element and: 2663 // ANY/SOME: no comparisons evaluate to true 2664 // ALL: no comparisons evaluate to false 2665 // 2666 // For example, given 1 < ANY (SELECT * FROM generate_series(1,3)) 2667 // (right is a DTuple), evalTupleCmp would be called with: 2668 // evalDatumsCmp(ctx, LT, Any, CmpOp(LT, leftType, rightParamType), leftDatum, rightTuple.D). 2669 // Similarly, given 1 < ANY (ARRAY[1, 2, 3]) (right is a DArray), 2670 // evalArrayCmp would be called with: 2671 // evalDatumsCmp(ctx, LT, Any, CmpOp(LT, leftType, rightParamType), leftDatum, rightArray.Array). 2672 func evalDatumsCmp( 2673 ctx *EvalContext, op, subOp ComparisonOperator, fn *CmpOp, left Datum, right Datums, 2674 ) (Datum, error) { 2675 all := op == All 2676 any := !all 2677 sawNull := false 2678 for _, elem := range right { 2679 if elem == DNull { 2680 sawNull = true 2681 continue 2682 } 2683 2684 _, newLeft, newRight, _, not := foldComparisonExpr(subOp, left, elem) 2685 d, err := fn.Fn(ctx, newLeft.(Datum), newRight.(Datum)) 2686 if err != nil { 2687 return nil, err 2688 } 2689 if d == DNull { 2690 sawNull = true 2691 continue 2692 } 2693 2694 b := d.(*DBool) 2695 res := *b != DBool(not) 2696 if any && res { 2697 return DBoolTrue, nil 2698 } else if all && !res { 2699 return DBoolFalse, nil 2700 } 2701 } 2702 2703 if sawNull { 2704 // If the right-hand array contains any null elements and no [false,true] 2705 // comparison result is obtained, the result of [ALL,ANY] will be null. 2706 return DNull, nil 2707 } 2708 2709 if all { 2710 // ALL are true && !sawNull 2711 return DBoolTrue, nil 2712 } 2713 // ANY is false && !sawNull 2714 return DBoolFalse, nil 2715 } 2716 2717 // MatchLikeEscape matches 'unescaped' with 'pattern' using custom escape character 'escape' which 2718 // must be either empty (which disables the escape mechanism) or a single unicode character. 2719 func MatchLikeEscape( 2720 ctx *EvalContext, unescaped, pattern, escape string, caseInsensitive bool, 2721 ) (Datum, error) { 2722 var escapeRune rune 2723 if len(escape) > 0 { 2724 var width int 2725 escapeRune, width = utf8.DecodeRuneInString(escape) 2726 if len(escape) > width { 2727 return DBoolFalse, pgerror.Newf(pgcode.InvalidEscapeSequence, "invalid escape string") 2728 } 2729 } 2730 2731 if len(unescaped) == 0 { 2732 // An empty string only matches with an empty pattern or a pattern 2733 // consisting only of '%' (if this wildcard is not used as a custom escape 2734 // character). To match PostgreSQL's behavior, we have a special handling 2735 // of this case. 2736 for _, c := range pattern { 2737 if c != '%' || (c == '%' && escape == `%`) { 2738 return DBoolFalse, nil 2739 } 2740 } 2741 return DBoolTrue, nil 2742 } 2743 2744 like, err := optimizedLikeFunc(pattern, caseInsensitive, escapeRune) 2745 if err != nil { 2746 return DBoolFalse, pgerror.Newf( 2747 pgcode.InvalidRegularExpression, "LIKE regexp compilation failed: %v", err) 2748 } 2749 2750 if like == nil { 2751 re, err := ConvertLikeToRegexp(ctx, pattern, caseInsensitive, escapeRune) 2752 if err != nil { 2753 return DBoolFalse, err 2754 } 2755 like = func(s string) (bool, error) { 2756 return re.MatchString(s), nil 2757 } 2758 } 2759 matches, err := like(unescaped) 2760 return MakeDBool(DBool(matches)), err 2761 } 2762 2763 // ConvertLikeToRegexp compiles the specified LIKE pattern as an equivalent 2764 // regular expression. 2765 func ConvertLikeToRegexp( 2766 ctx *EvalContext, pattern string, caseInsensitive bool, escape rune, 2767 ) (*regexp.Regexp, error) { 2768 key := likeKey{s: pattern, caseInsensitive: caseInsensitive, escape: escape} 2769 re, err := ctx.ReCache.GetRegexp(key) 2770 if err != nil { 2771 return nil, pgerror.Newf( 2772 pgcode.InvalidRegularExpression, "LIKE regexp compilation failed: %v", err) 2773 } 2774 return re, nil 2775 } 2776 2777 func matchLike(ctx *EvalContext, left, right Datum, caseInsensitive bool) (Datum, error) { 2778 if left == DNull || right == DNull { 2779 return DNull, nil 2780 } 2781 s, pattern := string(MustBeDString(left)), string(MustBeDString(right)) 2782 if len(s) == 0 { 2783 // An empty string only matches with an empty pattern or a pattern 2784 // consisting only of '%'. To match PostgreSQL's behavior, we have a 2785 // special handling of this case. 2786 for _, c := range pattern { 2787 if c != '%' { 2788 return DBoolFalse, nil 2789 } 2790 } 2791 return DBoolTrue, nil 2792 } 2793 2794 like, err := optimizedLikeFunc(pattern, caseInsensitive, '\\') 2795 if err != nil { 2796 return DBoolFalse, pgerror.Newf( 2797 pgcode.InvalidRegularExpression, "LIKE regexp compilation failed: %v", err) 2798 } 2799 2800 if like == nil { 2801 re, err := ConvertLikeToRegexp(ctx, pattern, caseInsensitive, '\\') 2802 if err != nil { 2803 return DBoolFalse, err 2804 } 2805 like = func(s string) (bool, error) { 2806 return re.MatchString(s), nil 2807 } 2808 } 2809 matches, err := like(s) 2810 return MakeDBool(DBool(matches)), err 2811 } 2812 2813 func matchRegexpWithKey(ctx *EvalContext, str Datum, key RegexpCacheKey) (Datum, error) { 2814 re, err := ctx.ReCache.GetRegexp(key) 2815 if err != nil { 2816 return DBoolFalse, err 2817 } 2818 return MakeDBool(DBool(re.MatchString(string(MustBeDString(str))))), nil 2819 } 2820 2821 // MultipleResultsError is returned by QueryRow when more than one result is 2822 // encountered. 2823 type MultipleResultsError struct { 2824 SQL string // the query that produced this error 2825 } 2826 2827 func (e *MultipleResultsError) Error() string { 2828 return fmt.Sprintf("%s: unexpected multiple results", e.SQL) 2829 } 2830 2831 // EvalDatabase consists of functions that reference the session database 2832 // and is to be used from EvalContext. 2833 type EvalDatabase interface { 2834 // ParseQualifiedTableName parses a SQL string of the form 2835 // `[ database_name . ] [ schema_name . ] table_name`. 2836 // NB: this is deprecated! Use parser.ParseQualifiedTableName when possible. 2837 ParseQualifiedTableName(sql string) (*TableName, error) 2838 2839 // ResolveTableName expands the given table name and 2840 // makes it point to a valid object. 2841 // If the database name is not given, it uses the search path to find it, and 2842 // sets it on the returned TableName. 2843 // It returns the ID of the resolved table, and an error if the table doesn't exist. 2844 ResolveTableName(ctx context.Context, tn *TableName) (ID, error) 2845 2846 // LookupSchema looks up the schema with the given name in the given 2847 // database. 2848 LookupSchema(ctx context.Context, dbName, scName string) (found bool, scMeta SchemaMeta, err error) 2849 } 2850 2851 // EvalPlanner is a limited planner that can be used from EvalContext. 2852 type EvalPlanner interface { 2853 EvalDatabase 2854 // ParseType parses a column type. 2855 ParseType(sql string) (*types.T, error) 2856 2857 // EvalSubquery returns the Datum for the given subquery node. 2858 EvalSubquery(expr *Subquery) (Datum, error) 2859 } 2860 2861 // EvalSessionAccessor is a limited interface to access session variables. 2862 type EvalSessionAccessor interface { 2863 // SetConfig sets a session variable to a new value. 2864 // 2865 // This interface only supports strings as this is sufficient for 2866 // pg_catalog.set_config(). 2867 SetSessionVar(ctx context.Context, settingName, newValue string) error 2868 2869 // GetSessionVar retrieves the current value of a session variable. 2870 GetSessionVar(ctx context.Context, settingName string, missingOk bool) (bool, string, error) 2871 2872 // HasAdminRole returns true iff the current session user has the admin role. 2873 HasAdminRole(ctx context.Context) (bool, error) 2874 } 2875 2876 // ClientNoticeSender is a limited interface to send notices to the 2877 // client. 2878 // 2879 // TODO(knz): as of this writing, the implementations of this 2880 // interface only work on the gateway node (i.e. not from 2881 // distributed processors). 2882 type ClientNoticeSender interface { 2883 // SendClientNotice sends a notice out-of-band to the client. 2884 SendClientNotice(ctx context.Context, notice error) 2885 } 2886 2887 // InternalExecutor is a subset of sqlutil.InternalExecutor (which, in turn, is 2888 // implemented by sql.InternalExecutor) used by this sem/tree package which 2889 // can't even import sqlutil. 2890 // 2891 // Note that the functions offered here should be avoided when possible. They 2892 // execute the query as root if an user hadn't been previously set on the 2893 // executor through SetSessionData(). These functions are deprecated in 2894 // sql.InternalExecutor in favor of a safer interface. Unfortunately, those 2895 // safer functions cannot be exposed through this interface because they depend 2896 // on sqlbase, and this package cannot import sqlbase. When possible, downcast 2897 // this to sqlutil.InternalExecutor or sql.InternalExecutor, and use the 2898 // alternatives. 2899 type InternalExecutor interface { 2900 // Query is part of the sqlutil.InternalExecutor interface. 2901 Query( 2902 ctx context.Context, opName string, txn *kv.Txn, 2903 stmt string, qargs ...interface{}, 2904 ) ([]Datums, error) 2905 2906 // QueryRow is part of the sqlutil.InternalExecutor interface. 2907 QueryRow( 2908 ctx context.Context, opName string, txn *kv.Txn, stmt string, qargs ...interface{}, 2909 ) (Datums, error) 2910 } 2911 2912 // PrivilegedAccessor gives access to certain queries that would otherwise 2913 // require someone with RootUser access to query a given data source. 2914 // It is defined independently to prevent a circular dependency on sql, tree and sqlbase. 2915 type PrivilegedAccessor interface { 2916 // LookupNamespaceID returns the id of the namespace given it's parent id and name. 2917 // It is meant as a replacement for looking up the system.namespace directly. 2918 // Returns the id, a bool representing whether the namespace exists, and an error 2919 // if there is one. 2920 LookupNamespaceID( 2921 ctx context.Context, parentID int64, name string, 2922 ) (DInt, bool, error) 2923 2924 // LookupZoneConfig returns the zone config given a namespace id. 2925 // It is meant as a replacement for looking up system.zones directly. 2926 // Returns the config byte array, a bool representing whether the namespace exists, 2927 // and an error if there is one. 2928 LookupZoneConfigByNamespaceID(ctx context.Context, id int64) (DBytes, bool, error) 2929 } 2930 2931 // SequenceOperators is used for various sql related functions that can 2932 // be used from EvalContext. 2933 type SequenceOperators interface { 2934 EvalDatabase 2935 // IncrementSequence increments the given sequence and returns the result. 2936 // It returns an error if the given name is not a sequence. 2937 // The caller must ensure that seqName is fully qualified already. 2938 IncrementSequence(ctx context.Context, seqName *TableName) (int64, error) 2939 2940 // GetLatestValueInSessionForSequence returns the value most recently obtained by 2941 // nextval() for the given sequence in this session. 2942 GetLatestValueInSessionForSequence(ctx context.Context, seqName *TableName) (int64, error) 2943 2944 // SetSequenceValue sets the sequence's value. 2945 // If isCalled is false, the sequence is set such that the next time nextval() is called, 2946 // `newVal` is returned. Otherwise, the next call to nextval will return 2947 // `newVal + seqOpts.Increment`. 2948 SetSequenceValue(ctx context.Context, seqName *TableName, newVal int64, isCalled bool) error 2949 } 2950 2951 // TenantOperator is capable of interacting with tenant state, allowing SQL 2952 // builtin functions to create and destroy tenants. The methods will return 2953 // errors when run by any tenant other than the system tenant. 2954 type TenantOperator interface { 2955 // CreateTenant attempts to install a new tenant in the system. It returns 2956 // an error if the tenant already exists. 2957 CreateTenant(ctx context.Context, tenantID uint64, tenantInfo []byte) error 2958 2959 // DestroyTenant attempts to uninstall an existing tenant from the system. 2960 // It returns an error if the tenant does not exist. 2961 DestroyTenant(ctx context.Context, tenantID uint64) error 2962 } 2963 2964 // EvalContextTestingKnobs contains test knobs. 2965 type EvalContextTestingKnobs struct { 2966 // AssertFuncExprReturnTypes indicates whether FuncExpr evaluations 2967 // should assert that the returned Datum matches the expected 2968 // ReturnType of the function. 2969 AssertFuncExprReturnTypes bool 2970 // AssertUnaryExprReturnTypes indicates whether UnaryExpr evaluations 2971 // should assert that the returned Datum matches the expected 2972 // ReturnType of the function. 2973 AssertUnaryExprReturnTypes bool 2974 // AssertBinaryExprReturnTypes indicates whether BinaryExpr 2975 // evaluations should assert that the returned Datum matches the 2976 // expected ReturnType of the function. 2977 AssertBinaryExprReturnTypes bool 2978 // DisableOptimizerRuleProbability is the probability that any given 2979 // transformation rule in the optimizer is disabled. 2980 DisableOptimizerRuleProbability float64 2981 // OptimizerCostPerturbation is used to randomly perturb the estimated 2982 // cost of each expression in the query tree for the purpose of creating 2983 // alternate query plans in the optimizer. 2984 OptimizerCostPerturbation float64 2985 2986 CallbackGenerators map[string]*CallbackValueGenerator 2987 } 2988 2989 var _ base.ModuleTestingKnobs = &EvalContextTestingKnobs{} 2990 2991 // ModuleTestingKnobs is part of the base.ModuleTestingKnobs interface. 2992 func (*EvalContextTestingKnobs) ModuleTestingKnobs() {} 2993 2994 // EvalContext defines the context in which to evaluate an expression, allowing 2995 // the retrieval of state such as the node ID or statement start time. 2996 // 2997 // ATTENTION: Some fields from this struct (particularly, but not exclusively, 2998 // from SessionData) are also represented in execinfrapb.EvalContext. Whenever 2999 // something that affects DistSQL execution is added, it needs to be marshaled 3000 // through that proto too. 3001 // TODO(andrei): remove or limit the duplication. 3002 // 3003 // NOTE(andrei): EvalContext is dusty; it started as a collection of fields 3004 // needed by expression evaluation, but it has grown quite large; some of the 3005 // things in it don't seem to belong in this low-level package (e.g. Planner). 3006 // In the sql package it is embedded by extendedEvalContext, which adds some 3007 // more fields from the sql package. Through that extendedEvalContext, this 3008 // struct now generally used by planNodes. 3009 type EvalContext struct { 3010 // Session variables. This is a read-only copy of the values owned by the 3011 // Session. 3012 SessionData *sessiondata.SessionData 3013 // TxnState is a string representation of the current transactional state. 3014 TxnState string 3015 // TxnReadOnly specifies if the current transaction is read-only. 3016 TxnReadOnly bool 3017 TxnImplicit bool 3018 3019 Settings *cluster.Settings 3020 ClusterID uuid.UUID 3021 ClusterName string 3022 NodeID *base.SQLIDContainer 3023 Codec keys.SQLCodec 3024 3025 // Locality contains the location of the current node as a set of user-defined 3026 // key/value pairs, ordered from most inclusive to least inclusive. If there 3027 // are no tiers, then the node's location is not known. Example: 3028 // 3029 // [region=us,dc=east] 3030 // 3031 Locality roachpb.Locality 3032 3033 // The statement timestamp. May be different for every statement. 3034 // Used for statement_timestamp(). 3035 StmtTimestamp time.Time 3036 // The transaction timestamp. Needs to stay stable for the lifetime 3037 // of a transaction. Used for now(), current_timestamp(), 3038 // transaction_timestamp() and the like. 3039 TxnTimestamp time.Time 3040 3041 // Placeholders relates placeholder names to their type and, later, value. 3042 // This pointer should always be set to the location of the PlaceholderInfo 3043 // in the corresponding SemaContext during normal execution. Placeholders are 3044 // available during Eval to permit lookup of a particular placeholder's 3045 // underlying datum, if available. 3046 Placeholders *PlaceholderInfo 3047 3048 // Annotations augments the AST with extra information. This pointer should 3049 // always be set to the location of the Annotations in the corresponding 3050 // SemaContext. 3051 Annotations *Annotations 3052 3053 // IVarContainer is used to evaluate IndexedVars. 3054 IVarContainer IndexedVarContainer 3055 // iVarContainerStack is used when we swap out IVarContainers in order to 3056 // evaluate an intermediate expression. This keeps track of those which we 3057 // need to restore once we finish evaluating it. 3058 iVarContainerStack []IndexedVarContainer 3059 3060 // Context holds the context in which the expression is evaluated. 3061 Context context.Context 3062 3063 // InternalExecutor gives access to an executor to be used for running 3064 // "internal" statements. It may seem bizarre that "expression evaluation" may 3065 // need to run a statement, and yet many builtin functions do it. 3066 // Note that the executor will be "session-bound" - it will inherit session 3067 // variables from a parent session. 3068 InternalExecutor InternalExecutor 3069 3070 Planner EvalPlanner 3071 3072 PrivilegedAccessor PrivilegedAccessor 3073 3074 SessionAccessor EvalSessionAccessor 3075 3076 ClientNoticeSender ClientNoticeSender 3077 3078 Sequence SequenceOperators 3079 3080 Tenant TenantOperator 3081 3082 // DistSQLTypeResolver is a type resolver used during execution of DistSQL 3083 // flows. It is limited to only provide access to types via ID, meaning that 3084 // it cannot perform resolution of qualified names into types. It will be nil 3085 // when not in the context of a DistSQL flow. 3086 DistSQLTypeResolver TypeReferenceResolver 3087 3088 // The transaction in which the statement is executing. 3089 Txn *kv.Txn 3090 // A handle to the database. 3091 DB *kv.DB 3092 3093 ReCache *RegexpCache 3094 tmpDec apd.Decimal 3095 3096 // TODO(mjibson): remove prepareOnly in favor of a 2-step prepare-exec solution 3097 // that is also able to save the plan to skip work during the exec step. 3098 PrepareOnly bool 3099 3100 // SkipNormalize indicates whether expressions should be normalized 3101 // (false) or not (true). It is set to true conditionally by 3102 // EXPLAIN(TYPES[, NORMALIZE]). 3103 SkipNormalize bool 3104 3105 CollationEnv CollationEnvironment 3106 3107 TestingKnobs EvalContextTestingKnobs 3108 3109 Mon *mon.BytesMonitor 3110 3111 // SingleDatumAggMemAccount is a memory account that all aggregate builtins 3112 // that store a single datum will share to account for the memory needed to 3113 // perform the aggregation (i.e. memory not reported by AggregateFunc.Size 3114 // method). This memory account exists so that such aggregate functions 3115 // could "batch" their reservations - otherwise, we end up a situation 3116 // where each aggregate function struct grows its own memory account by 3117 // tiny amount, yet the account reserves a lot more resulting in 3118 // significantly overestimating the memory usage. 3119 SingleDatumAggMemAccount *mon.BoundAccount 3120 } 3121 3122 // MakeTestingEvalContext returns an EvalContext that includes a MemoryMonitor. 3123 func MakeTestingEvalContext(st *cluster.Settings) EvalContext { 3124 monitor := mon.MakeMonitor( 3125 "test-monitor", 3126 mon.MemoryResource, 3127 nil, /* curCount */ 3128 nil, /* maxHist */ 3129 -1, /* increment */ 3130 math.MaxInt64, /* noteworthy */ 3131 st, 3132 ) 3133 return MakeTestingEvalContextWithMon(st, &monitor) 3134 } 3135 3136 // MakeTestingEvalContextWithMon returns an EvalContext with the given 3137 // MemoryMonitor. Ownership of the memory monitor is transferred to the 3138 // EvalContext so do not start or close the memory monitor. 3139 func MakeTestingEvalContextWithMon(st *cluster.Settings, monitor *mon.BytesMonitor) EvalContext { 3140 ctx := EvalContext{ 3141 Codec: keys.SystemSQLCodec, 3142 Txn: &kv.Txn{}, 3143 SessionData: &sessiondata.SessionData{}, 3144 Settings: st, 3145 NodeID: base.TestingIDContainer, 3146 } 3147 monitor.Start(context.Background(), nil /* pool */, mon.MakeStandaloneBudget(math.MaxInt64)) 3148 ctx.Mon = monitor 3149 ctx.Context = context.TODO() 3150 now := timeutil.Now() 3151 ctx.SetTxnTimestamp(now) 3152 ctx.SetStmtTimestamp(now) 3153 return ctx 3154 } 3155 3156 // Copy returns a deep copy of ctx. 3157 func (ctx *EvalContext) Copy() *EvalContext { 3158 ctxCopy := *ctx 3159 ctxCopy.iVarContainerStack = make([]IndexedVarContainer, len(ctx.iVarContainerStack), cap(ctx.iVarContainerStack)) 3160 copy(ctxCopy.iVarContainerStack, ctx.iVarContainerStack) 3161 return &ctxCopy 3162 } 3163 3164 // PushIVarContainer replaces the current IVarContainer with a different one - 3165 // pushing the current one onto a stack to be replaced later once 3166 // PopIVarContainer is called. 3167 func (ctx *EvalContext) PushIVarContainer(c IndexedVarContainer) { 3168 ctx.iVarContainerStack = append(ctx.iVarContainerStack, ctx.IVarContainer) 3169 ctx.IVarContainer = c 3170 } 3171 3172 // PopIVarContainer discards the current IVarContainer on the EvalContext, 3173 // replacing it with an older one. 3174 func (ctx *EvalContext) PopIVarContainer() { 3175 ctx.IVarContainer = ctx.iVarContainerStack[len(ctx.iVarContainerStack)-1] 3176 ctx.iVarContainerStack = ctx.iVarContainerStack[:len(ctx.iVarContainerStack)-1] 3177 } 3178 3179 // NewTestingEvalContext is a convenience version of MakeTestingEvalContext 3180 // that returns a pointer. 3181 func NewTestingEvalContext(st *cluster.Settings) *EvalContext { 3182 ctx := MakeTestingEvalContext(st) 3183 return &ctx 3184 } 3185 3186 // Stop closes out the EvalContext and must be called once it is no longer in use. 3187 func (ctx *EvalContext) Stop(c context.Context) { 3188 ctx.Mon.Stop(c) 3189 } 3190 3191 // GetStmtTimestamp retrieves the current statement timestamp as per 3192 // the evaluation context. The timestamp is guaranteed to be nonzero. 3193 func (ctx *EvalContext) GetStmtTimestamp() time.Time { 3194 // TODO(knz): a zero timestamp should never be read, even during 3195 // Prepare. This will need to be addressed. 3196 if !ctx.PrepareOnly && ctx.StmtTimestamp.IsZero() { 3197 panic(errors.AssertionFailedf("zero statement timestamp in EvalContext")) 3198 } 3199 return ctx.StmtTimestamp 3200 } 3201 3202 // GetClusterTimestamp retrieves the current cluster timestamp as per 3203 // the evaluation context. The timestamp is guaranteed to be nonzero. 3204 func (ctx *EvalContext) GetClusterTimestamp() *DDecimal { 3205 ts := ctx.Txn.CommitTimestamp() 3206 if ts == (hlc.Timestamp{}) { 3207 panic(errors.AssertionFailedf("zero cluster timestamp in txn")) 3208 } 3209 return TimestampToDecimal(ts) 3210 } 3211 3212 // HasPlaceholders returns true if this EvalContext's placeholders have been 3213 // assigned. Will be false during Prepare. 3214 func (ctx *EvalContext) HasPlaceholders() bool { 3215 return ctx.Placeholders != nil 3216 } 3217 3218 // TimestampToDecimal converts the logical timestamp into a decimal 3219 // value with the number of nanoseconds in the integer part and the 3220 // logical counter in the decimal part. 3221 func TimestampToDecimal(ts hlc.Timestamp) *DDecimal { 3222 // Compute Walltime * 10^10 + Logical. 3223 // We need 10 decimals for the Logical field because its maximum 3224 // value is 4294967295 (2^32-1), a value with 10 decimal digits. 3225 var res DDecimal 3226 val := &res.Coeff 3227 val.SetInt64(ts.WallTime) 3228 val.Mul(val, big10E10) 3229 val.Add(val, big.NewInt(int64(ts.Logical))) 3230 3231 // val must be positive. If it was set to a negative value above, 3232 // transfer the sign to res.Negative. 3233 res.Negative = val.Sign() < 0 3234 val.Abs(val) 3235 3236 // Shift 10 decimals to the right, so that the logical 3237 // field appears as fractional part. 3238 res.Decimal.Exponent = -10 3239 return &res 3240 } 3241 3242 // TimestampToInexactDTimestamp converts the logical timestamp into an 3243 // inexact DTimestamp by dropping the logical counter and using the wall 3244 // time at the microsecond precision. 3245 func TimestampToInexactDTimestamp(ts hlc.Timestamp) *DTimestamp { 3246 return MustMakeDTimestamp(timeutil.Unix(0, ts.WallTime), time.Microsecond) 3247 } 3248 3249 // GetRelativeParseTime implements ParseTimeContext. 3250 func (ctx *EvalContext) GetRelativeParseTime() time.Time { 3251 ret := ctx.TxnTimestamp 3252 if ret.IsZero() { 3253 ret = timeutil.Now() 3254 } 3255 return ret.In(ctx.GetLocation()) 3256 } 3257 3258 // GetTxnTimestamp retrieves the current transaction timestamp as per 3259 // the evaluation context. The timestamp is guaranteed to be nonzero. 3260 func (ctx *EvalContext) GetTxnTimestamp(precision time.Duration) *DTimestampTZ { 3261 // TODO(knz): a zero timestamp should never be read, even during 3262 // Prepare. This will need to be addressed. 3263 if !ctx.PrepareOnly && ctx.TxnTimestamp.IsZero() { 3264 panic(errors.AssertionFailedf("zero transaction timestamp in EvalContext")) 3265 } 3266 return MustMakeDTimestampTZ(ctx.GetRelativeParseTime(), precision) 3267 } 3268 3269 // GetTxnTimestampNoZone retrieves the current transaction timestamp as per 3270 // the evaluation context. The timestamp is guaranteed to be nonzero. 3271 func (ctx *EvalContext) GetTxnTimestampNoZone(precision time.Duration) *DTimestamp { 3272 // TODO(knz): a zero timestamp should never be read, even during 3273 // Prepare. This will need to be addressed. 3274 if !ctx.PrepareOnly && ctx.TxnTimestamp.IsZero() { 3275 panic(errors.AssertionFailedf("zero transaction timestamp in EvalContext")) 3276 } 3277 // Move the time to UTC, but keeping the location's time. 3278 t := ctx.GetRelativeParseTime() 3279 _, offsetSecs := t.Zone() 3280 return MustMakeDTimestamp(t.Add(time.Second*time.Duration(offsetSecs)).In(time.UTC), precision) 3281 } 3282 3283 // GetTxnTime retrieves the current transaction time as per 3284 // the evaluation context. 3285 func (ctx *EvalContext) GetTxnTime(precision time.Duration) *DTimeTZ { 3286 // TODO(knz): a zero timestamp should never be read, even during 3287 // Prepare. This will need to be addressed. 3288 if !ctx.PrepareOnly && ctx.TxnTimestamp.IsZero() { 3289 panic(errors.AssertionFailedf("zero transaction timestamp in EvalContext")) 3290 } 3291 return NewDTimeTZFromTime(ctx.GetRelativeParseTime().Round(precision)) 3292 } 3293 3294 // GetTxnTimeNoZone retrieves the current transaction time as per 3295 // the evaluation context. 3296 func (ctx *EvalContext) GetTxnTimeNoZone(precision time.Duration) *DTime { 3297 // TODO(knz): a zero timestamp should never be read, even during 3298 // Prepare. This will need to be addressed. 3299 if !ctx.PrepareOnly && ctx.TxnTimestamp.IsZero() { 3300 panic(errors.AssertionFailedf("zero transaction timestamp in EvalContext")) 3301 } 3302 return MakeDTime(timeofday.FromTime(ctx.GetRelativeParseTime().Round(precision))) 3303 } 3304 3305 // SetTxnTimestamp sets the corresponding timestamp in the EvalContext. 3306 func (ctx *EvalContext) SetTxnTimestamp(ts time.Time) { 3307 ctx.TxnTimestamp = ts 3308 } 3309 3310 // SetStmtTimestamp sets the corresponding timestamp in the EvalContext. 3311 func (ctx *EvalContext) SetStmtTimestamp(ts time.Time) { 3312 ctx.StmtTimestamp = ts 3313 } 3314 3315 // GetLocation returns the session timezone. 3316 func (ctx *EvalContext) GetLocation() *time.Location { 3317 if ctx.SessionData == nil || ctx.SessionData.DataConversion.Location == nil { 3318 return time.UTC 3319 } 3320 return ctx.SessionData.DataConversion.Location 3321 } 3322 3323 // Ctx returns the session's context. 3324 func (ctx *EvalContext) Ctx() context.Context { 3325 return ctx.Context 3326 } 3327 3328 func (ctx *EvalContext) getTmpDec() *apd.Decimal { 3329 return &ctx.tmpDec 3330 } 3331 3332 // Eval implements the TypedExpr interface. 3333 func (expr *AndExpr) Eval(ctx *EvalContext) (Datum, error) { 3334 left, err := expr.Left.(TypedExpr).Eval(ctx) 3335 if err != nil { 3336 return nil, err 3337 } 3338 if left != DNull { 3339 if v, err := GetBool(left); err != nil { 3340 return nil, err 3341 } else if !v { 3342 return left, nil 3343 } 3344 } 3345 right, err := expr.Right.(TypedExpr).Eval(ctx) 3346 if err != nil { 3347 return nil, err 3348 } 3349 if right == DNull { 3350 return DNull, nil 3351 } 3352 if v, err := GetBool(right); err != nil { 3353 return nil, err 3354 } else if !v { 3355 return right, nil 3356 } 3357 return left, nil 3358 } 3359 3360 // Eval implements the TypedExpr interface. 3361 func (expr *BinaryExpr) Eval(ctx *EvalContext) (Datum, error) { 3362 left, err := expr.Left.(TypedExpr).Eval(ctx) 3363 if err != nil { 3364 return nil, err 3365 } 3366 if left == DNull && !expr.Fn.NullableArgs { 3367 return DNull, nil 3368 } 3369 right, err := expr.Right.(TypedExpr).Eval(ctx) 3370 if err != nil { 3371 return nil, err 3372 } 3373 if right == DNull && !expr.Fn.NullableArgs { 3374 return DNull, nil 3375 } 3376 res, err := expr.Fn.Fn(ctx, left, right) 3377 if err != nil { 3378 return nil, err 3379 } 3380 if ctx.TestingKnobs.AssertBinaryExprReturnTypes { 3381 if err := ensureExpectedType(expr.Fn.ReturnType, res); err != nil { 3382 return nil, errors.NewAssertionErrorWithWrappedErrf(err, 3383 "binary op %q", expr) 3384 } 3385 } 3386 return res, err 3387 } 3388 3389 // Eval implements the TypedExpr interface. 3390 func (expr *CaseExpr) Eval(ctx *EvalContext) (Datum, error) { 3391 if expr.Expr != nil { 3392 // CASE <val> WHEN <expr> THEN ... 3393 // 3394 // For each "when" expression we compare for equality to <val>. 3395 val, err := expr.Expr.(TypedExpr).Eval(ctx) 3396 if err != nil { 3397 return nil, err 3398 } 3399 3400 for _, when := range expr.Whens { 3401 arg, err := when.Cond.(TypedExpr).Eval(ctx) 3402 if err != nil { 3403 return nil, err 3404 } 3405 d, err := evalComparison(ctx, EQ, val, arg) 3406 if err != nil { 3407 return nil, err 3408 } 3409 if v, err := GetBool(d); err != nil { 3410 return nil, err 3411 } else if v { 3412 return when.Val.(TypedExpr).Eval(ctx) 3413 } 3414 } 3415 } else { 3416 // CASE WHEN <bool-expr> THEN ... 3417 for _, when := range expr.Whens { 3418 d, err := when.Cond.(TypedExpr).Eval(ctx) 3419 if err != nil { 3420 return nil, err 3421 } 3422 if v, err := GetBool(d); err != nil { 3423 return nil, err 3424 } else if v { 3425 return when.Val.(TypedExpr).Eval(ctx) 3426 } 3427 } 3428 } 3429 3430 if expr.Else != nil { 3431 return expr.Else.(TypedExpr).Eval(ctx) 3432 } 3433 return DNull, nil 3434 } 3435 3436 // pgSignatureRegexp matches a Postgres function type signature, capturing the 3437 // name of the function into group 1. 3438 // e.g. function(a, b, c) or function( a ) 3439 var pgSignatureRegexp = regexp.MustCompile(`^\s*([\w\.]+)\s*\((?:(?:\s*\w+\s*,)*\s*\w+)?\s*\)\s*$`) 3440 3441 // regTypeInfo contains details on a pg_catalog table that has a reg* type. 3442 type regTypeInfo struct { 3443 tableName string 3444 // nameCol is the name of the column that contains the table's entity name. 3445 nameCol string 3446 // objName is a human-readable name describing the objects in the table. 3447 objName string 3448 // errType is the pg error code in case the object does not exist. 3449 errType string 3450 } 3451 3452 // regTypeInfos maps an oid.Oid to a regTypeInfo that describes the pg_catalog 3453 // table that contains the entities of the type of the key. 3454 var regTypeInfos = map[oid.Oid]regTypeInfo{ 3455 oid.T_regclass: {"pg_class", "relname", "relation", pgcode.UndefinedTable}, 3456 oid.T_regtype: {"pg_type", "typname", "type", pgcode.UndefinedObject}, 3457 oid.T_regproc: {"pg_proc", "proname", "function", pgcode.UndefinedFunction}, 3458 oid.T_regprocedure: {"pg_proc", "proname", "function", pgcode.UndefinedFunction}, 3459 oid.T_regnamespace: {"pg_namespace", "nspname", "namespace", pgcode.UndefinedObject}, 3460 } 3461 3462 // queryOidWithJoin looks up the name or OID of an input OID or string in the 3463 // pg_catalog table that the input oid.Oid belongs to. If the input Datum 3464 // is a DOid, the relevant table will be queried by OID; if the input is a 3465 // DString, the table will be queried by its name column. 3466 // 3467 // The return value is a fresh DOid of the input oid.Oid with name and OID 3468 // set to the result of the query. If there was not exactly one result to the 3469 // query, an error will be returned. 3470 func queryOidWithJoin( 3471 ctx *EvalContext, typ *types.T, d Datum, joinClause string, additionalWhere string, 3472 ) (*DOid, error) { 3473 ret := &DOid{semanticType: typ} 3474 info := regTypeInfos[typ.Oid()] 3475 var queryCol string 3476 switch d.(type) { 3477 case *DOid: 3478 queryCol = "oid" 3479 case *DString: 3480 queryCol = info.nameCol 3481 default: 3482 return nil, errors.AssertionFailedf("invalid argument to OID cast: %s", d) 3483 } 3484 results, err := ctx.InternalExecutor.QueryRow( 3485 ctx.Ctx(), "queryOidWithJoin", 3486 ctx.Txn, 3487 fmt.Sprintf( 3488 "SELECT %s.oid, %s FROM pg_catalog.%s %s WHERE %s = $1 %s", 3489 info.tableName, info.nameCol, info.tableName, joinClause, queryCol, additionalWhere), 3490 d) 3491 if err != nil { 3492 if errors.HasType(err, (*MultipleResultsError)(nil)) { 3493 return nil, pgerror.Newf(pgcode.AmbiguousAlias, 3494 "more than one %s named %s", info.objName, d) 3495 } 3496 return nil, err 3497 } 3498 if results.Len() == 0 { 3499 return nil, pgerror.Newf(info.errType, "%s %s does not exist", info.objName, d) 3500 } 3501 ret.DInt = results[0].(*DOid).DInt 3502 ret.name = AsStringWithFlags(results[1], FmtBareStrings) 3503 return ret, nil 3504 } 3505 3506 func queryOid(ctx *EvalContext, typ *types.T, d Datum) (*DOid, error) { 3507 return queryOidWithJoin(ctx, typ, d, "", "") 3508 } 3509 3510 // Eval implements the TypedExpr interface. 3511 func (expr *CastExpr) Eval(ctx *EvalContext) (Datum, error) { 3512 d, err := expr.Expr.(TypedExpr).Eval(ctx) 3513 if err != nil { 3514 return nil, err 3515 } 3516 3517 // NULL cast to anything is NULL. 3518 if d == DNull { 3519 return d, nil 3520 } 3521 d = UnwrapDatum(ctx, d) 3522 return PerformCast(ctx, d, expr.ResolvedType()) 3523 } 3524 3525 // Eval implements the TypedExpr interface. 3526 func (expr *IndirectionExpr) Eval(ctx *EvalContext) (Datum, error) { 3527 var subscriptIdx int 3528 for i, t := range expr.Indirection { 3529 if t.Slice || i > 0 { 3530 return nil, errors.AssertionFailedf("unsupported feature should have been rejected during planning") 3531 } 3532 3533 d, err := t.Begin.(TypedExpr).Eval(ctx) 3534 if err != nil { 3535 return nil, err 3536 } 3537 if d == DNull { 3538 return d, nil 3539 } 3540 subscriptIdx = int(MustBeDInt(d)) 3541 } 3542 3543 d, err := expr.Expr.(TypedExpr).Eval(ctx) 3544 if err != nil { 3545 return nil, err 3546 } 3547 if d == DNull { 3548 return d, nil 3549 } 3550 3551 // Index into the DArray, using 1-indexing. 3552 arr := MustBeDArray(d) 3553 3554 // VECTOR types use 0-indexing. 3555 switch arr.customOid { 3556 case oid.T_oidvector, oid.T_int2vector: 3557 subscriptIdx++ 3558 } 3559 if subscriptIdx < 1 || subscriptIdx > arr.Len() { 3560 return DNull, nil 3561 } 3562 return arr.Array[subscriptIdx-1], nil 3563 } 3564 3565 // Eval implements the TypedExpr interface. 3566 func (expr *CollateExpr) Eval(ctx *EvalContext) (Datum, error) { 3567 d, err := expr.Expr.(TypedExpr).Eval(ctx) 3568 if err != nil { 3569 return nil, err 3570 } 3571 unwrapped := UnwrapDatum(ctx, d) 3572 if unwrapped == DNull { 3573 return DNull, nil 3574 } 3575 switch d := unwrapped.(type) { 3576 case *DString: 3577 return NewDCollatedString(string(*d), expr.Locale, &ctx.CollationEnv) 3578 case *DCollatedString: 3579 return NewDCollatedString(d.Contents, expr.Locale, &ctx.CollationEnv) 3580 default: 3581 return nil, pgerror.Newf(pgcode.DatatypeMismatch, "incompatible type for COLLATE: %s", d) 3582 } 3583 } 3584 3585 // Eval implements the TypedExpr interface. 3586 func (expr *ColumnAccessExpr) Eval(ctx *EvalContext) (Datum, error) { 3587 d, err := expr.Expr.(TypedExpr).Eval(ctx) 3588 if err != nil { 3589 return nil, err 3590 } 3591 return d.(*DTuple).D[expr.ColIndex], nil 3592 } 3593 3594 // Eval implements the TypedExpr interface. 3595 func (expr *CoalesceExpr) Eval(ctx *EvalContext) (Datum, error) { 3596 for _, e := range expr.Exprs { 3597 d, err := e.(TypedExpr).Eval(ctx) 3598 if err != nil { 3599 return nil, err 3600 } 3601 if d != DNull { 3602 return d, nil 3603 } 3604 } 3605 return DNull, nil 3606 } 3607 3608 // Eval implements the TypedExpr interface. 3609 func (expr *ComparisonExpr) Eval(ctx *EvalContext) (Datum, error) { 3610 left, err := expr.Left.(TypedExpr).Eval(ctx) 3611 if err != nil { 3612 return nil, err 3613 } 3614 right, err := expr.Right.(TypedExpr).Eval(ctx) 3615 if err != nil { 3616 return nil, err 3617 } 3618 3619 op := expr.Operator 3620 if op.hasSubOperator() { 3621 var datums Datums 3622 // Right is either a tuple or an array of Datums. 3623 if !expr.fn.NullableArgs && right == DNull { 3624 return DNull, nil 3625 } else if tuple, ok := AsDTuple(right); ok { 3626 datums = tuple.D 3627 } else if array, ok := AsDArray(right); ok { 3628 datums = array.Array 3629 } else { 3630 return nil, errors.AssertionFailedf("unhandled right expression %s", right) 3631 } 3632 return evalDatumsCmp(ctx, op, expr.SubOperator, expr.fn, left, datums) 3633 } 3634 3635 _, newLeft, newRight, _, not := foldComparisonExpr(op, left, right) 3636 if !expr.fn.NullableArgs && (newLeft == DNull || newRight == DNull) { 3637 return DNull, nil 3638 } 3639 d, err := expr.fn.Fn(ctx, newLeft.(Datum), newRight.(Datum)) 3640 if err != nil { 3641 return nil, err 3642 } 3643 if b, ok := d.(*DBool); ok { 3644 return MakeDBool(*b != DBool(not)), nil 3645 } 3646 return d, nil 3647 } 3648 3649 // EvalArgsAndGetGenerator evaluates the arguments and instanciates a 3650 // ValueGenerator for use by set projections. 3651 func (expr *FuncExpr) EvalArgsAndGetGenerator(ctx *EvalContext) (ValueGenerator, error) { 3652 if expr.fn == nil || expr.fnProps.Class != GeneratorClass { 3653 return nil, errors.AssertionFailedf("cannot call EvalArgsAndGetGenerator() on non-aggregate function: %q", ErrString(expr)) 3654 } 3655 nullArg, args, err := expr.evalArgs(ctx) 3656 if err != nil || nullArg { 3657 return nil, err 3658 } 3659 return expr.fn.Generator(ctx, args) 3660 } 3661 3662 // evalArgs evaluates just the function application's arguments. 3663 // The returned bool indicates that the NULL should be propagated. 3664 func (expr *FuncExpr) evalArgs(ctx *EvalContext) (bool, Datums, error) { 3665 args := make(Datums, len(expr.Exprs)) 3666 for i, e := range expr.Exprs { 3667 arg, err := e.(TypedExpr).Eval(ctx) 3668 if err != nil { 3669 return false, nil, err 3670 } 3671 if arg == DNull && !expr.fnProps.NullableArgs { 3672 return true, nil, nil 3673 } 3674 args[i] = arg 3675 } 3676 return false, args, nil 3677 } 3678 3679 // Eval implements the TypedExpr interface. 3680 func (expr *FuncExpr) Eval(ctx *EvalContext) (Datum, error) { 3681 nullResult, args, err := expr.evalArgs(ctx) 3682 if err != nil { 3683 return nil, err 3684 } 3685 if nullResult { 3686 return DNull, err 3687 } 3688 3689 res, err := expr.fn.Fn(ctx, args) 3690 if err != nil { 3691 // If we are facing an explicit error, propagate it unchanged. 3692 fName := expr.Func.String() 3693 if fName == `crdb_internal.force_error` { 3694 return nil, err 3695 } 3696 // Otherwise, wrap it with context. 3697 newErr := errors.Wrapf(err, "%s()", errors.Safe(fName)) 3698 // Count function errors as it flows out of the system. We need 3699 // to have this inside a if because if we are facing a retry 3700 // error, in particular those generated by 3701 // crdb_internal.force_retry(), Wrap() will propagate it as a 3702 // non-pgerror error (so that the executor can see it with the 3703 // right type). 3704 newErr = errors.WithTelemetry(newErr, fName+"()") 3705 return nil, newErr 3706 } 3707 if ctx.TestingKnobs.AssertFuncExprReturnTypes { 3708 if err := ensureExpectedType(expr.fn.FixedReturnType(), res); err != nil { 3709 return nil, errors.NewAssertionErrorWithWrappedErrf(err, "function %q", expr) 3710 } 3711 } 3712 return res, nil 3713 } 3714 3715 // ensureExpectedType will return an error if a datum does not match the 3716 // provided type. If the expected type is Any or if the datum is a Null 3717 // type, then no error will be returned. 3718 func ensureExpectedType(exp *types.T, d Datum) error { 3719 if !(exp.Family() == types.AnyFamily || d.ResolvedType().Family() == types.UnknownFamily || 3720 d.ResolvedType().Equivalent(exp)) { 3721 return errors.AssertionFailedf( 3722 "expected return type %q, got: %q", errors.Safe(exp), errors.Safe(d.ResolvedType())) 3723 } 3724 return nil 3725 } 3726 3727 // Eval implements the TypedExpr interface. 3728 func (expr *IfErrExpr) Eval(ctx *EvalContext) (Datum, error) { 3729 cond, evalErr := expr.Cond.(TypedExpr).Eval(ctx) 3730 if evalErr == nil { 3731 if expr.Else == nil { 3732 return DBoolFalse, nil 3733 } 3734 return cond, nil 3735 } 3736 if expr.ErrCode != nil { 3737 errpat, err := expr.ErrCode.(TypedExpr).Eval(ctx) 3738 if err != nil { 3739 return nil, err 3740 } 3741 if errpat == DNull { 3742 return nil, evalErr 3743 } 3744 errpatStr := string(MustBeDString(errpat)) 3745 if code := pgerror.GetPGCode(evalErr); code != errpatStr { 3746 return nil, evalErr 3747 } 3748 } 3749 if expr.Else == nil { 3750 return DBoolTrue, nil 3751 } 3752 return expr.Else.(TypedExpr).Eval(ctx) 3753 } 3754 3755 // Eval implements the TypedExpr interface. 3756 func (expr *IfExpr) Eval(ctx *EvalContext) (Datum, error) { 3757 cond, err := expr.Cond.(TypedExpr).Eval(ctx) 3758 if err != nil { 3759 return nil, err 3760 } 3761 if cond == DBoolTrue { 3762 return expr.True.(TypedExpr).Eval(ctx) 3763 } 3764 return expr.Else.(TypedExpr).Eval(ctx) 3765 } 3766 3767 // Eval implements the TypedExpr interface. 3768 func (expr *IsOfTypeExpr) Eval(ctx *EvalContext) (Datum, error) { 3769 d, err := expr.Expr.(TypedExpr).Eval(ctx) 3770 if err != nil { 3771 return nil, err 3772 } 3773 datumTyp := d.ResolvedType() 3774 3775 for _, t := range expr.ResolvedTypes() { 3776 if datumTyp.Equivalent(t) { 3777 return MakeDBool(DBool(!expr.Not)), nil 3778 } 3779 } 3780 return MakeDBool(DBool(expr.Not)), nil 3781 } 3782 3783 // Eval implements the TypedExpr interface. 3784 func (expr *NotExpr) Eval(ctx *EvalContext) (Datum, error) { 3785 d, err := expr.Expr.(TypedExpr).Eval(ctx) 3786 if err != nil { 3787 return nil, err 3788 } 3789 if d == DNull { 3790 return DNull, nil 3791 } 3792 v, err := GetBool(d) 3793 if err != nil { 3794 return nil, err 3795 } 3796 return MakeDBool(!v), nil 3797 } 3798 3799 // Eval implements the TypedExpr interface. 3800 func (expr *IsNullExpr) Eval(ctx *EvalContext) (Datum, error) { 3801 d, err := expr.Expr.(TypedExpr).Eval(ctx) 3802 if err != nil { 3803 return nil, err 3804 } 3805 if d == DNull { 3806 return MakeDBool(true), nil 3807 } 3808 if t, ok := d.(*DTuple); ok { 3809 // A tuple IS NULL if all elements are NULL. 3810 for _, tupleDatum := range t.D { 3811 if tupleDatum != DNull { 3812 return MakeDBool(false), nil 3813 } 3814 } 3815 return MakeDBool(true), nil 3816 } 3817 return MakeDBool(false), nil 3818 } 3819 3820 // Eval implements the TypedExpr interface. 3821 func (expr *IsNotNullExpr) Eval(ctx *EvalContext) (Datum, error) { 3822 d, err := expr.Expr.(TypedExpr).Eval(ctx) 3823 if err != nil { 3824 return nil, err 3825 } 3826 if d == DNull { 3827 return MakeDBool(false), nil 3828 } 3829 if t, ok := d.(*DTuple); ok { 3830 // A tuple IS NOT NULL if all elements are not NULL. 3831 for _, tupleDatum := range t.D { 3832 if tupleDatum == DNull { 3833 return MakeDBool(false), nil 3834 } 3835 } 3836 return MakeDBool(true), nil 3837 } 3838 return MakeDBool(true), nil 3839 } 3840 3841 // Eval implements the TypedExpr interface. 3842 func (expr *NullIfExpr) Eval(ctx *EvalContext) (Datum, error) { 3843 expr1, err := expr.Expr1.(TypedExpr).Eval(ctx) 3844 if err != nil { 3845 return nil, err 3846 } 3847 expr2, err := expr.Expr2.(TypedExpr).Eval(ctx) 3848 if err != nil { 3849 return nil, err 3850 } 3851 cond, err := evalComparison(ctx, EQ, expr1, expr2) 3852 if err != nil { 3853 return nil, err 3854 } 3855 if cond == DBoolTrue { 3856 return DNull, nil 3857 } 3858 return expr1, nil 3859 } 3860 3861 // Eval implements the TypedExpr interface. 3862 func (expr *OrExpr) Eval(ctx *EvalContext) (Datum, error) { 3863 left, err := expr.Left.(TypedExpr).Eval(ctx) 3864 if err != nil { 3865 return nil, err 3866 } 3867 if left != DNull { 3868 if v, err := GetBool(left); err != nil { 3869 return nil, err 3870 } else if v { 3871 return left, nil 3872 } 3873 } 3874 right, err := expr.Right.(TypedExpr).Eval(ctx) 3875 if err != nil { 3876 return nil, err 3877 } 3878 if right == DNull { 3879 return DNull, nil 3880 } 3881 if v, err := GetBool(right); err != nil { 3882 return nil, err 3883 } else if v { 3884 return right, nil 3885 } 3886 if left == DNull { 3887 return DNull, nil 3888 } 3889 return DBoolFalse, nil 3890 } 3891 3892 // Eval implements the TypedExpr interface. 3893 func (expr *ParenExpr) Eval(ctx *EvalContext) (Datum, error) { 3894 return expr.Expr.(TypedExpr).Eval(ctx) 3895 } 3896 3897 // Eval implements the TypedExpr interface. 3898 func (expr *RangeCond) Eval(ctx *EvalContext) (Datum, error) { 3899 return nil, errors.AssertionFailedf("unhandled type %T", expr) 3900 } 3901 3902 // Eval implements the TypedExpr interface. 3903 func (expr *UnaryExpr) Eval(ctx *EvalContext) (Datum, error) { 3904 d, err := expr.Expr.(TypedExpr).Eval(ctx) 3905 if err != nil { 3906 return nil, err 3907 } 3908 if d == DNull { 3909 return DNull, nil 3910 } 3911 res, err := expr.fn.Fn(ctx, d) 3912 if err != nil { 3913 return nil, err 3914 } 3915 if ctx.TestingKnobs.AssertUnaryExprReturnTypes { 3916 if err := ensureExpectedType(expr.fn.ReturnType, res); err != nil { 3917 return nil, errors.NewAssertionErrorWithWrappedErrf(err, "unary op %q", expr) 3918 } 3919 } 3920 return res, err 3921 } 3922 3923 // Eval implements the TypedExpr interface. 3924 func (expr DefaultVal) Eval(ctx *EvalContext) (Datum, error) { 3925 return nil, errors.AssertionFailedf("unhandled type %T", expr) 3926 } 3927 3928 // Eval implements the TypedExpr interface. 3929 func (expr UnqualifiedStar) Eval(ctx *EvalContext) (Datum, error) { 3930 return nil, errors.AssertionFailedf("unhandled type %T", expr) 3931 } 3932 3933 // Eval implements the TypedExpr interface. 3934 func (expr *UnresolvedName) Eval(ctx *EvalContext) (Datum, error) { 3935 return nil, errors.AssertionFailedf("unhandled type %T", expr) 3936 } 3937 3938 // Eval implements the TypedExpr interface. 3939 func (expr *AllColumnsSelector) Eval(ctx *EvalContext) (Datum, error) { 3940 return nil, errors.AssertionFailedf("unhandled type %T", expr) 3941 } 3942 3943 // Eval implements the TypedExpr interface. 3944 func (expr *TupleStar) Eval(ctx *EvalContext) (Datum, error) { 3945 return nil, errors.AssertionFailedf("unhandled type %T", expr) 3946 } 3947 3948 // Eval implements the TypedExpr interface. 3949 func (expr *ColumnItem) Eval(ctx *EvalContext) (Datum, error) { 3950 return nil, errors.AssertionFailedf("unhandled type %T", expr) 3951 } 3952 3953 // Eval implements the TypedExpr interface. 3954 func (t *Tuple) Eval(ctx *EvalContext) (Datum, error) { 3955 tuple := NewDTupleWithLen(t.typ, len(t.Exprs)) 3956 for i, v := range t.Exprs { 3957 d, err := v.(TypedExpr).Eval(ctx) 3958 if err != nil { 3959 return nil, err 3960 } 3961 tuple.D[i] = d 3962 } 3963 return tuple, nil 3964 } 3965 3966 // arrayOfType returns a fresh DArray of the input type. 3967 func arrayOfType(typ *types.T) (*DArray, error) { 3968 if typ.Family() != types.ArrayFamily { 3969 return nil, errors.AssertionFailedf("array node type (%v) is not types.TArray", typ) 3970 } 3971 if err := types.CheckArrayElementType(typ.ArrayContents()); err != nil { 3972 return nil, err 3973 } 3974 return NewDArray(typ.ArrayContents()), nil 3975 } 3976 3977 // Eval implements the TypedExpr interface. 3978 func (t *Array) Eval(ctx *EvalContext) (Datum, error) { 3979 array, err := arrayOfType(t.ResolvedType()) 3980 if err != nil { 3981 return nil, err 3982 } 3983 3984 for _, v := range t.Exprs { 3985 d, err := v.(TypedExpr).Eval(ctx) 3986 if err != nil { 3987 return nil, err 3988 } 3989 if err := array.Append(d); err != nil { 3990 return nil, err 3991 } 3992 } 3993 return array, nil 3994 } 3995 3996 // Eval implements the TypedExpr interface. 3997 func (expr *Subquery) Eval(ctx *EvalContext) (Datum, error) { 3998 return ctx.Planner.EvalSubquery(expr) 3999 } 4000 4001 // Eval implements the TypedExpr interface. 4002 func (t *ArrayFlatten) Eval(ctx *EvalContext) (Datum, error) { 4003 array, err := arrayOfType(t.ResolvedType()) 4004 if err != nil { 4005 return nil, err 4006 } 4007 4008 d, err := t.Subquery.(TypedExpr).Eval(ctx) 4009 if err != nil { 4010 return nil, err 4011 } 4012 4013 tuple, ok := d.(*DTuple) 4014 if !ok { 4015 return nil, errors.AssertionFailedf("array subquery result (%v) is not DTuple", d) 4016 } 4017 array.Array = tuple.D 4018 return array, nil 4019 } 4020 4021 // Eval implements the TypedExpr interface. 4022 func (t *DBitArray) Eval(_ *EvalContext) (Datum, error) { 4023 return t, nil 4024 } 4025 4026 // Eval implements the TypedExpr interface. 4027 func (t *DBool) Eval(_ *EvalContext) (Datum, error) { 4028 return t, nil 4029 } 4030 4031 // Eval implements the TypedExpr interface. 4032 func (t *DBytes) Eval(_ *EvalContext) (Datum, error) { 4033 return t, nil 4034 } 4035 4036 // Eval implements the TypedExpr interface. 4037 func (t *DUuid) Eval(_ *EvalContext) (Datum, error) { 4038 return t, nil 4039 } 4040 4041 // Eval implements the TypedExpr interface. 4042 func (t *DIPAddr) Eval(_ *EvalContext) (Datum, error) { 4043 return t, nil 4044 } 4045 4046 // Eval implements the TypedExpr interface. 4047 func (t *DDate) Eval(_ *EvalContext) (Datum, error) { 4048 return t, nil 4049 } 4050 4051 // Eval implements the TypedExpr interface. 4052 func (t *DTime) Eval(_ *EvalContext) (Datum, error) { 4053 return t, nil 4054 } 4055 4056 // Eval implements the TypedExpr interface. 4057 func (t *DTimeTZ) Eval(_ *EvalContext) (Datum, error) { 4058 return t, nil 4059 } 4060 4061 // Eval implements the TypedExpr interface. 4062 func (t *DFloat) Eval(_ *EvalContext) (Datum, error) { 4063 return t, nil 4064 } 4065 4066 // Eval implements the TypedExpr interface. 4067 func (t *DDecimal) Eval(_ *EvalContext) (Datum, error) { 4068 return t, nil 4069 } 4070 4071 // Eval implements the TypedExpr interface. 4072 func (t *DInt) Eval(_ *EvalContext) (Datum, error) { 4073 return t, nil 4074 } 4075 4076 // Eval implements the TypedExpr interface. 4077 func (t *DInterval) Eval(_ *EvalContext) (Datum, error) { 4078 return t, nil 4079 } 4080 4081 // Eval implements the TypedExpr interface. 4082 func (t *DGeography) Eval(_ *EvalContext) (Datum, error) { 4083 return t, nil 4084 } 4085 4086 // Eval implements the TypedExpr interface. 4087 func (t *DGeometry) Eval(_ *EvalContext) (Datum, error) { 4088 return t, nil 4089 } 4090 4091 // Eval implements the TypedExpr interface. 4092 func (t *DEnum) Eval(_ *EvalContext) (Datum, error) { 4093 return t, nil 4094 } 4095 4096 // Eval implements the TypedExpr interface. 4097 func (t *DJSON) Eval(_ *EvalContext) (Datum, error) { 4098 return t, nil 4099 } 4100 4101 // Eval implements the TypedExpr interface. 4102 func (t dNull) Eval(_ *EvalContext) (Datum, error) { 4103 return t, nil 4104 } 4105 4106 // Eval implements the TypedExpr interface. 4107 func (t *DString) Eval(_ *EvalContext) (Datum, error) { 4108 return t, nil 4109 } 4110 4111 // Eval implements the TypedExpr interface. 4112 func (t *DCollatedString) Eval(_ *EvalContext) (Datum, error) { 4113 return t, nil 4114 } 4115 4116 // Eval implements the TypedExpr interface. 4117 func (t *DTimestamp) Eval(_ *EvalContext) (Datum, error) { 4118 return t, nil 4119 } 4120 4121 // Eval implements the TypedExpr interface. 4122 func (t *DTimestampTZ) Eval(_ *EvalContext) (Datum, error) { 4123 return t, nil 4124 } 4125 4126 // Eval implements the TypedExpr interface. 4127 func (t *DTuple) Eval(_ *EvalContext) (Datum, error) { 4128 return t, nil 4129 } 4130 4131 // Eval implements the TypedExpr interface. 4132 func (t *DArray) Eval(_ *EvalContext) (Datum, error) { 4133 return t, nil 4134 } 4135 4136 // Eval implements the TypedExpr interface. 4137 func (t *DOid) Eval(_ *EvalContext) (Datum, error) { 4138 return t, nil 4139 } 4140 4141 // Eval implements the TypedExpr interface. 4142 func (t *DOidWrapper) Eval(_ *EvalContext) (Datum, error) { 4143 return t, nil 4144 } 4145 4146 // Eval implements the TypedExpr interface. 4147 func (t *Placeholder) Eval(ctx *EvalContext) (Datum, error) { 4148 if !ctx.HasPlaceholders() { 4149 // While preparing a query, there will be no available placeholders. A 4150 // placeholder evaluates to itself at this point. 4151 return t, nil 4152 } 4153 e, ok := ctx.Placeholders.Value(t.Idx) 4154 if !ok { 4155 return nil, pgerror.Newf(pgcode.UndefinedParameter, 4156 "no value provided for placeholder: %s", t) 4157 } 4158 // Placeholder expressions cannot contain other placeholders, so we do 4159 // not need to recurse. 4160 typ := ctx.Placeholders.Types[t.Idx] 4161 if typ == nil { 4162 // All placeholders should be typed at this point. 4163 return nil, errors.AssertionFailedf("missing type for placeholder %s", t) 4164 } 4165 if !e.ResolvedType().Equivalent(typ) { 4166 // This happens when we overrode the placeholder's type during type 4167 // checking, since the placeholder's type hint didn't match the desired 4168 // type for the placeholder. In this case, we cast the expression to 4169 // the desired type. 4170 // TODO(jordan): introduce a restriction on what casts are allowed here. 4171 cast := NewTypedCastExpr(e, typ) 4172 return cast.Eval(ctx) 4173 } 4174 return e.Eval(ctx) 4175 } 4176 4177 func evalComparison(ctx *EvalContext, op ComparisonOperator, left, right Datum) (Datum, error) { 4178 if left == DNull || right == DNull { 4179 return DNull, nil 4180 } 4181 ltype := left.ResolvedType() 4182 rtype := right.ResolvedType() 4183 if fn, ok := CmpOps[op].LookupImpl(ltype, rtype); ok { 4184 return fn.Fn(ctx, left, right) 4185 } 4186 return nil, pgerror.Newf( 4187 pgcode.UndefinedFunction, "unsupported comparison operator: <%s> %s <%s>", ltype, op, rtype) 4188 } 4189 4190 // foldComparisonExpr folds a given comparison operation and its expressions 4191 // into an equivalent operation that will hit in the CmpOps map, returning 4192 // this new operation, along with potentially flipped operands and "flipped" 4193 // and "not" flags. 4194 func foldComparisonExpr( 4195 op ComparisonOperator, left, right Expr, 4196 ) (newOp ComparisonOperator, newLeft Expr, newRight Expr, flipped bool, not bool) { 4197 switch op { 4198 case NE: 4199 // NE(left, right) is implemented as !EQ(left, right). 4200 return EQ, left, right, false, true 4201 case GT: 4202 // GT(left, right) is implemented as LT(right, left) 4203 return LT, right, left, true, false 4204 case GE: 4205 // GE(left, right) is implemented as LE(right, left) 4206 return LE, right, left, true, false 4207 case NotIn: 4208 // NotIn(left, right) is implemented as !IN(left, right) 4209 return In, left, right, false, true 4210 case NotLike: 4211 // NotLike(left, right) is implemented as !Like(left, right) 4212 return Like, left, right, false, true 4213 case NotILike: 4214 // NotILike(left, right) is implemented as !ILike(left, right) 4215 return ILike, left, right, false, true 4216 case NotSimilarTo: 4217 // NotSimilarTo(left, right) is implemented as !SimilarTo(left, right) 4218 return SimilarTo, left, right, false, true 4219 case NotRegMatch: 4220 // NotRegMatch(left, right) is implemented as !RegMatch(left, right) 4221 return RegMatch, left, right, false, true 4222 case NotRegIMatch: 4223 // NotRegIMatch(left, right) is implemented as !RegIMatch(left, right) 4224 return RegIMatch, left, right, false, true 4225 case IsDistinctFrom: 4226 // IsDistinctFrom(left, right) is implemented as !IsNotDistinctFrom(left, right) 4227 // Note: this seems backwards, but IS NOT DISTINCT FROM is an extended 4228 // version of IS and IS DISTINCT FROM is an extended version of IS NOT. 4229 return IsNotDistinctFrom, left, right, false, true 4230 } 4231 return op, left, right, false, false 4232 } 4233 4234 // hasUnescapedSuffix returns true if the ending byte is suffix and s has an 4235 // even number of escapeTokens preceding suffix. Otherwise hasUnescapedSuffix 4236 // will return false. 4237 func hasUnescapedSuffix(s string, suffix byte, escapeToken string) bool { 4238 if s[len(s)-1] == suffix { 4239 var count int 4240 idx := len(s) - len(escapeToken) - 1 4241 for idx >= 0 && s[idx:idx+len(escapeToken)] == escapeToken { 4242 count++ 4243 idx -= len(escapeToken) 4244 } 4245 return count%2 == 0 4246 } 4247 return false 4248 } 4249 4250 // Simplifies LIKE/ILIKE expressions that do not need full regular expressions to 4251 // evaluate the condition. For example, when the expression is just checking to see 4252 // if a string starts with a given pattern. 4253 func optimizedLikeFunc( 4254 pattern string, caseInsensitive bool, escape rune, 4255 ) (func(string) (bool, error), error) { 4256 switch len(pattern) { 4257 case 0: 4258 return func(s string) (bool, error) { 4259 return s == "", nil 4260 }, nil 4261 case 1: 4262 switch pattern[0] { 4263 case '%': 4264 if escape == '%' { 4265 return nil, pgerror.Newf(pgcode.InvalidEscapeSequence, "LIKE pattern must not end with escape character") 4266 } 4267 return func(s string) (bool, error) { 4268 return true, nil 4269 }, nil 4270 case '_': 4271 if escape == '_' { 4272 return nil, pgerror.Newf(pgcode.InvalidEscapeSequence, "LIKE pattern must not end with escape character") 4273 } 4274 return func(s string) (bool, error) { 4275 if len(s) == 0 { 4276 return false, nil 4277 } 4278 firstChar, _ := utf8.DecodeRuneInString(s) 4279 if firstChar == utf8.RuneError { 4280 return false, errors.Errorf("invalid encoding of the first character in string %s", s) 4281 } 4282 return len(s) == len(string(firstChar)), nil 4283 }, nil 4284 } 4285 default: 4286 if !strings.ContainsAny(pattern[1:len(pattern)-1], "_%") { 4287 // Patterns with even number of escape characters preceding the ending 4288 // `%` will have anyEnd set to true (if `%` itself is not an escape 4289 // character). Otherwise anyEnd will be set to false. 4290 anyEnd := hasUnescapedSuffix(pattern, '%', string(escape)) && escape != '%' 4291 // If '%' is the escape character, then it's not a wildcard. 4292 anyStart := pattern[0] == '%' && escape != '%' 4293 4294 // Patterns with even number of escape characters preceding the ending 4295 // `_` will have singleAnyEnd set to true (if `_` itself is not an escape 4296 // character). Otherwise singleAnyEnd will be set to false. 4297 singleAnyEnd := hasUnescapedSuffix(pattern, '_', string(escape)) && escape != '_' 4298 // If '_' is the escape character, then it's not a wildcard. 4299 singleAnyStart := pattern[0] == '_' && escape != '_' 4300 4301 // Since we've already checked for escaped characters 4302 // at the end, we can un-escape every character. 4303 // This is required since we do direct string 4304 // comparison. 4305 var err error 4306 if pattern, err = unescapePattern(pattern, string(escape), true /* emitEscapeCharacterLastError */); err != nil { 4307 return nil, err 4308 } 4309 switch { 4310 case anyEnd && anyStart: 4311 return func(s string) (bool, error) { 4312 substr := pattern[1 : len(pattern)-1] 4313 if caseInsensitive { 4314 s, substr = strings.ToUpper(s), strings.ToUpper(substr) 4315 } 4316 return strings.Contains(s, substr), nil 4317 }, nil 4318 4319 case anyEnd: 4320 return func(s string) (bool, error) { 4321 prefix := pattern[:len(pattern)-1] 4322 if singleAnyStart { 4323 if len(s) == 0 { 4324 return false, nil 4325 } 4326 prefix = prefix[1:] 4327 firstChar, _ := utf8.DecodeRuneInString(s) 4328 if firstChar == utf8.RuneError { 4329 return false, errors.Errorf("invalid encoding of the first character in string %s", s) 4330 } 4331 s = s[len(string(firstChar)):] 4332 } 4333 if caseInsensitive { 4334 s, prefix = strings.ToUpper(s), strings.ToUpper(prefix) 4335 } 4336 return strings.HasPrefix(s, prefix), nil 4337 }, nil 4338 4339 case anyStart: 4340 return func(s string) (bool, error) { 4341 suffix := pattern[1:] 4342 if singleAnyEnd { 4343 if len(s) == 0 { 4344 return false, nil 4345 } 4346 4347 suffix = suffix[:len(suffix)-1] 4348 lastChar, _ := utf8.DecodeLastRuneInString(s) 4349 if lastChar == utf8.RuneError { 4350 return false, errors.Errorf("invalid encoding of the last character in string %s", s) 4351 } 4352 s = s[:len(s)-len(string(lastChar))] 4353 } 4354 if caseInsensitive { 4355 s, suffix = strings.ToUpper(s), strings.ToUpper(suffix) 4356 } 4357 return strings.HasSuffix(s, suffix), nil 4358 }, nil 4359 4360 case singleAnyStart || singleAnyEnd: 4361 return func(s string) (bool, error) { 4362 if len(s) < 1 { 4363 return false, nil 4364 } 4365 firstChar, _ := utf8.DecodeRuneInString(s) 4366 if firstChar == utf8.RuneError { 4367 return false, errors.Errorf("invalid encoding of the first character in string %s", s) 4368 } 4369 lastChar, _ := utf8.DecodeLastRuneInString(s) 4370 if lastChar == utf8.RuneError { 4371 return false, errors.Errorf("invalid encoding of the last character in string %s", s) 4372 } 4373 if singleAnyStart && singleAnyEnd && len(string(firstChar))+len(string(lastChar)) > len(s) { 4374 return false, nil 4375 } 4376 4377 if singleAnyStart { 4378 pattern = pattern[1:] 4379 s = s[len(string(firstChar)):] 4380 } 4381 4382 if singleAnyEnd { 4383 pattern = pattern[:len(pattern)-1] 4384 s = s[:len(s)-len(string(lastChar))] 4385 } 4386 4387 if caseInsensitive { 4388 s, pattern = strings.ToUpper(s), strings.ToUpper(pattern) 4389 } 4390 4391 // We don't have to check for 4392 // prefixes/suffixes since we do not 4393 // have '%': 4394 // - singleAnyEnd && anyStart handled 4395 // in case anyStart 4396 // - singleAnyStart && anyEnd handled 4397 // in case anyEnd 4398 return s == pattern, nil 4399 }, nil 4400 } 4401 } 4402 } 4403 return nil, nil 4404 } 4405 4406 type likeKey struct { 4407 s string 4408 caseInsensitive bool 4409 escape rune 4410 } 4411 4412 // unescapePattern unescapes a pattern for a given escape token. 4413 // It handles escaped escape tokens properly by maintaining them as the escape 4414 // token in the return string. 4415 // For example, suppose we have escape token `\` (e.g. `B` is escaped in 4416 // `A\BC` and `\` is escaped in `A\\C`). 4417 // We need to convert 4418 // `\` --> `` 4419 // `\\` --> `\` 4420 // We cannot simply use strings.Replace for each conversion since the first 4421 // conversion will incorrectly replace our escaped escape token `\\` with ``. 4422 // Another example is if our escape token is `\\` (e.g. after 4423 // regexp.QuoteMeta). 4424 // We need to convert 4425 // `\\` --> `` 4426 // `\\\\` --> `\\` 4427 func unescapePattern( 4428 pattern, escapeToken string, emitEscapeCharacterLastError bool, 4429 ) (string, error) { 4430 escapedEscapeToken := escapeToken + escapeToken 4431 4432 // We need to subtract the escaped escape tokens to avoid double 4433 // counting. 4434 nEscapes := strings.Count(pattern, escapeToken) - strings.Count(pattern, escapedEscapeToken) 4435 if nEscapes == 0 { 4436 return pattern, nil 4437 } 4438 4439 // Allocate buffer for final un-escaped pattern. 4440 ret := make([]byte, len(pattern)-nEscapes*len(escapeToken)) 4441 retWidth := 0 4442 for i := 0; i < nEscapes; i++ { 4443 nextIdx := strings.Index(pattern, escapeToken) 4444 if nextIdx == len(pattern)-len(escapeToken) && emitEscapeCharacterLastError { 4445 return "", pgerror.Newf(pgcode.InvalidEscapeSequence, `LIKE pattern must not end with escape character`) 4446 } 4447 4448 retWidth += copy(ret[retWidth:], pattern[:nextIdx]) 4449 4450 if nextIdx < len(pattern)-len(escapedEscapeToken) && pattern[nextIdx:nextIdx+len(escapedEscapeToken)] == escapedEscapeToken { 4451 // We have an escaped escape token. 4452 // We want to keep it as the original escape token in 4453 // the return string. 4454 retWidth += copy(ret[retWidth:], escapeToken) 4455 pattern = pattern[nextIdx+len(escapedEscapeToken):] 4456 continue 4457 } 4458 4459 // Skip over the escape character we removed. 4460 pattern = pattern[nextIdx+len(escapeToken):] 4461 } 4462 4463 retWidth += copy(ret[retWidth:], pattern) 4464 return string(ret[0:retWidth]), nil 4465 } 4466 4467 // replaceUnescaped replaces all instances of oldStr that are not escaped (read: 4468 // preceded) with the specified unescape token with newStr. 4469 // For example, with an escape token of `\\` 4470 // replaceUnescaped("TE\\__ST", "_", ".", `\\`) --> "TE\\_.ST" 4471 // replaceUnescaped("TE\\%%ST", "%", ".*", `\\`) --> "TE\\%.*ST" 4472 // If the preceding escape token is escaped, then oldStr will be replaced. 4473 // For example 4474 // replaceUnescaped("TE\\\\_ST", "_", ".", `\\`) --> "TE\\\\.ST" 4475 func replaceUnescaped(s, oldStr, newStr string, escapeToken string) string { 4476 // We count the number of occurrences of 'oldStr'. 4477 // This however can be an overestimate since the oldStr token could be 4478 // escaped. e.g. `\\_`. 4479 nOld := strings.Count(s, oldStr) 4480 if nOld == 0 { 4481 return s 4482 } 4483 4484 // Allocate buffer for final string. 4485 // This can be an overestimate since some of the oldStr tokens may 4486 // be escaped. 4487 // This is fine since we keep track of the running number of bytes 4488 // actually copied. 4489 // It's rather difficult to count the exact number of unescaped 4490 // tokens without manually iterating through the entire string and 4491 // keeping track of escaped escape tokens. 4492 retLen := len(s) 4493 // If len(newStr) - len(oldStr) < 0, then this can under-allocate which 4494 // will not behave correctly with copy. 4495 if addnBytes := nOld * (len(newStr) - len(oldStr)); addnBytes > 0 { 4496 retLen += addnBytes 4497 } 4498 ret := make([]byte, retLen) 4499 retWidth := 0 4500 start := 0 4501 OldLoop: 4502 for i := 0; i < nOld; i++ { 4503 nextIdx := start + strings.Index(s[start:], oldStr) 4504 4505 escaped := false 4506 for { 4507 // We need to look behind to check if the escape token 4508 // is really an escape token. 4509 // E.g. if our specified escape token is `\\` and oldStr 4510 // is `_`, then 4511 // `\\_` --> escaped 4512 // `\\\\_` --> not escaped 4513 // `\\\\\\_` --> escaped 4514 curIdx := nextIdx 4515 lookbehindIdx := curIdx - len(escapeToken) 4516 for lookbehindIdx >= 0 && s[lookbehindIdx:curIdx] == escapeToken { 4517 escaped = !escaped 4518 curIdx = lookbehindIdx 4519 lookbehindIdx = curIdx - len(escapeToken) 4520 } 4521 4522 // The token was not be escaped. Proceed. 4523 if !escaped { 4524 break 4525 } 4526 4527 // Token was escaped. Copy everything over and continue. 4528 retWidth += copy(ret[retWidth:], s[start:nextIdx+len(oldStr)]) 4529 start = nextIdx + len(oldStr) 4530 4531 // Continue with next oldStr token. 4532 continue OldLoop 4533 } 4534 4535 // Token was not escaped so we replace it with newStr. 4536 // Two copies is more efficient than concatenating the slices. 4537 retWidth += copy(ret[retWidth:], s[start:nextIdx]) 4538 retWidth += copy(ret[retWidth:], newStr) 4539 start = nextIdx + len(oldStr) 4540 } 4541 4542 retWidth += copy(ret[retWidth:], s[start:]) 4543 return string(ret[0:retWidth]) 4544 } 4545 4546 // Replaces all custom escape characters in s with `\\` only when they are unescaped. (1) 4547 // E.g. original pattern after QuoteMeta after replaceCustomEscape with '@' as escape 4548 // '@w@w' -> '@w@w' -> '\\w\\w' 4549 // '@\@\' -> '@\\@\\' -> '\\\\\\\\' 4550 // 4551 // When an escape character is escaped, we replace it with its single occurrence. (2) 4552 // E.g. original pattern after QuoteMeta after replaceCustomEscape with '@' as escape 4553 // '@@w@w' -> '@@w@w' -> '@w\\w' 4554 // '@@@\' -> '@@@\\' -> '@\\\\' 4555 // 4556 // At the same time, we do not want to confuse original backslashes (which 4557 // after QuoteMeta are '\\') with backslashes that replace our custom escape characters, 4558 // so we escape these original backslashes again by converting '\\' into '\\\\'. (3) 4559 // E.g. original pattern after QuoteMeta after replaceCustomEscape with '@' as escape 4560 // '@\' -> '@\\' -> '\\\\\\' 4561 // '@\@@@\' -> '@\\@@@\\' -> '\\\\\\@\\\\\\' 4562 // 4563 // Explanation of the last example: 4564 // 1. we replace '@' with '\\' since it's unescaped; 4565 // 2. we escape single original backslash ('\' is not our escape character, so we want 4566 // the pattern to understand it) by putting an extra backslash in front of it. However, 4567 // we later will call unescapePattern, so we need to double our double backslashes. 4568 // Therefore, '\\' is converted into '\\\\'. 4569 // 3. '@@' is replaced by '@' because it is escaped escape character. 4570 // 4. '@' is replaced with '\\' since it's unescaped. 4571 // 5. Similar logic to step 2: '\\' -> '\\\\'. 4572 // 4573 // We always need to keep in mind that later call of unescapePattern 4574 // to actually unescape '\\' and '\\\\' is necessary and that 4575 // escape must be a single unicode character and not `\`. 4576 func replaceCustomEscape(s string, escape rune) (string, error) { 4577 changed, retLen, err := calculateLengthAfterReplacingCustomEscape(s, escape) 4578 if err != nil { 4579 return "", err 4580 } 4581 if !changed { 4582 return s, nil 4583 } 4584 4585 sLen := len(s) 4586 ret := make([]byte, retLen) 4587 retIndex, sIndex := 0, 0 4588 for retIndex < retLen { 4589 sRune, w := utf8.DecodeRuneInString(s[sIndex:]) 4590 if sRune == escape { 4591 // We encountered an escape character. 4592 if sIndex+w < sLen { 4593 // Escape character is not the last character in s, so we need 4594 // to look ahead to figure out how to process it. 4595 tRune, _ := utf8.DecodeRuneInString(s[(sIndex + w):]) 4596 if tRune == escape { 4597 // Escape character is escaped, so we replace its two occurrences with just one. See (2). 4598 // We copied only one escape character to ret, so we advance retIndex only by w. 4599 // Since we've already processed two characters in s, we advance sIndex by 2*w. 4600 utf8.EncodeRune(ret[retIndex:], escape) 4601 retIndex += w 4602 sIndex += 2 * w 4603 } else { 4604 // Escape character is unescaped, so we replace it with `\\`. See (1). 4605 // Since we've added two bytes to ret, we advance retIndex by 2. 4606 // We processed only a single escape character in s, we advance sIndex by w. 4607 ret[retIndex] = '\\' 4608 ret[retIndex+1] = '\\' 4609 retIndex += 2 4610 sIndex += w 4611 } 4612 } else { 4613 // Escape character is the last character in s which is an error 4614 // that must have been caught in calculateLengthAfterReplacingCustomEscape. 4615 return "", errors.AssertionFailedf( 4616 "unexpected: escape character is the last one in replaceCustomEscape.") 4617 } 4618 } else if s[sIndex] == '\\' { 4619 // We encountered a backslash, so we need to look ahead to figure out how 4620 // to process it. 4621 if sIndex+1 == sLen { 4622 // This case should never be reached since it should 4623 // have been caught in calculateLengthAfterReplacingCustomEscape. 4624 return "", errors.AssertionFailedf( 4625 "unexpected: a single backslash encountered in replaceCustomEscape.") 4626 } else if s[sIndex+1] == '\\' { 4627 // We want to escape '\\' to `\\\\` for correct processing later by unescapePattern. See (3). 4628 // Since we've added four characters to ret, we advance retIndex by 4. 4629 // Since we've already processed two characters in s, we advance sIndex by 2. 4630 ret[retIndex] = '\\' 4631 ret[retIndex+1] = '\\' 4632 ret[retIndex+2] = '\\' 4633 ret[retIndex+3] = '\\' 4634 retIndex += 4 4635 sIndex += 2 4636 } else { 4637 // A metacharacter other than a backslash is escaped here. 4638 // Note: all metacharacters are encoded as a single byte, so it is 4639 // correct to just convert it to string and to compare against a char 4640 // in s. 4641 if string(s[sIndex+1]) == string(escape) { 4642 // The metacharacter is our custom escape character. We need to look 4643 // ahead to process it. 4644 if sIndex+2 == sLen { 4645 // Escape character is the last character in s which is an error 4646 // that must have been caught in calculateLengthAfterReplacingCustomEscape. 4647 return "", errors.AssertionFailedf( 4648 "unexpected: escape character is the last one in replaceCustomEscape.") 4649 } 4650 if sIndex+4 <= sLen { 4651 if s[sIndex+2] == '\\' && string(s[sIndex+3]) == string(escape) { 4652 // We have a sequence of `\`+escape+`\`+escape which is replaced 4653 // by `\`+escape. 4654 ret[retIndex] = '\\' 4655 // Note: all metacharacters are encoded as a single byte, so it 4656 // is safe to just convert it to string and take the first 4657 // character. 4658 ret[retIndex+1] = string(escape)[0] 4659 retIndex += 2 4660 sIndex += 4 4661 continue 4662 } 4663 } 4664 // The metacharacter is escaping something different than itself, so 4665 // `\`+escape will be replaced by `\`. 4666 ret[retIndex] = '\\' 4667 retIndex++ 4668 sIndex += 2 4669 } else { 4670 // The metacharacter is not our custom escape character, so we're 4671 // simply copying the backslash and the metacharacter. 4672 ret[retIndex] = '\\' 4673 ret[retIndex+1] = s[sIndex+1] 4674 retIndex += 2 4675 sIndex += 2 4676 } 4677 } 4678 } else { 4679 // Regular symbol, so we simply copy it. 4680 copy(ret[retIndex:], s[sIndex:sIndex+w]) 4681 retIndex += w 4682 sIndex += w 4683 } 4684 } 4685 return string(ret), nil 4686 } 4687 4688 // calculateLengthAfterReplacingCustomEscape returns whether the pattern changes, the length 4689 // of the resulting pattern after calling replaceCustomEscape, and any error if found. 4690 func calculateLengthAfterReplacingCustomEscape(s string, escape rune) (bool, int, error) { 4691 changed := false 4692 retLen, sLen := 0, len(s) 4693 for i := 0; i < sLen; { 4694 sRune, w := utf8.DecodeRuneInString(s[i:]) 4695 if sRune == escape { 4696 // We encountered an escape character. 4697 if i+w < sLen { 4698 // Escape character is not the last character in s, so we need 4699 // to look ahead to figure out how to process it. 4700 tRune, _ := utf8.DecodeRuneInString(s[(i + w):]) 4701 if tRune == escape { 4702 // Escape character is escaped, so we'll replace its two occurrences with just one. 4703 // See (2) in the comment above replaceCustomEscape. 4704 changed = true 4705 retLen += w 4706 i += 2 * w 4707 } else { 4708 // Escape character is unescaped, so we'll replace it with `\\`. 4709 // See (1) in the comment above replaceCustomEscape. 4710 changed = true 4711 retLen += 2 4712 i += w 4713 } 4714 } else { 4715 // Escape character is the last character in s, so we need to return an error. 4716 return false, 0, pgerror.Newf(pgcode.InvalidEscapeSequence, "LIKE pattern must not end with escape character") 4717 } 4718 } else if s[i] == '\\' { 4719 // We encountered a backslash, so we need to look ahead to figure out how 4720 // to process it. 4721 if i+1 == sLen { 4722 // This case should never be reached because the backslash should be 4723 // escaping one of regexp metacharacters. 4724 return false, 0, pgerror.Newf(pgcode.InvalidEscapeSequence, "Unexpected behavior during processing custom escape character.") 4725 } else if s[i+1] == '\\' { 4726 // We'll want to escape '\\' to `\\\\` for correct processing later by 4727 // unescapePattern. See (3) in the comment above replaceCustomEscape. 4728 changed = true 4729 retLen += 4 4730 i += 2 4731 } else { 4732 // A metacharacter other than a backslash is escaped here. 4733 if string(s[i+1]) == string(escape) { 4734 // The metacharacter is our custom escape character. We need to look 4735 // ahead to process it. 4736 if i+2 == sLen { 4737 // Escape character is the last character in s, so we need to return an error. 4738 return false, 0, pgerror.Newf(pgcode.InvalidEscapeSequence, "LIKE pattern must not end with escape character") 4739 } 4740 if i+4 <= sLen { 4741 if s[i+2] == '\\' && string(s[i+3]) == string(escape) { 4742 // We have a sequence of `\`+escape+`\`+escape which will be 4743 // replaced by `\`+escape. 4744 changed = true 4745 retLen += 2 4746 i += 4 4747 continue 4748 } 4749 } 4750 // The metacharacter is escaping something different than itself, so 4751 // `\`+escape will be replaced by `\`. 4752 changed = true 4753 retLen++ 4754 i += 2 4755 } else { 4756 // The metacharacter is not our custom escape character, so we're 4757 // simply copying the backslash and the metacharacter. 4758 retLen += 2 4759 i += 2 4760 } 4761 } 4762 } else { 4763 // Regular symbol, so we'll simply copy it. 4764 retLen += w 4765 i += w 4766 } 4767 } 4768 return changed, retLen, nil 4769 } 4770 4771 // Pattern implements the RegexpCacheKey interface. 4772 // The strategy for handling custom escape character 4773 // is to convert all unescaped escape character into '\'. 4774 // k.escape can either be empty or a single character. 4775 func (k likeKey) Pattern() (string, error) { 4776 // QuoteMeta escapes all regexp metacharacters (`\.+*?()|[]{}^$`) with a `\`. 4777 pattern := regexp.QuoteMeta(k.s) 4778 var err error 4779 if k.escape == 0 { 4780 // Replace all LIKE/ILIKE specific wildcards with standard wildcards 4781 // (escape character is empty - escape mechanism is turned off - so 4782 // all '%' and '_' are actual wildcards regardless of what precedes them. 4783 pattern = strings.Replace(pattern, `%`, `.*`, -1) 4784 pattern = strings.Replace(pattern, `_`, `.`, -1) 4785 } else if k.escape == '\\' { 4786 // Replace LIKE/ILIKE specific wildcards with standard wildcards only when 4787 // these wildcards are not escaped by '\\' (equivalent of '\' after QuoteMeta). 4788 pattern = replaceUnescaped(pattern, `%`, `.*`, `\\`) 4789 pattern = replaceUnescaped(pattern, `_`, `.`, `\\`) 4790 } else { 4791 // k.escape is non-empty and not `\`. 4792 // If `%` is escape character, then it's not a wildcard. 4793 if k.escape != '%' { 4794 // Replace LIKE/ILIKE specific wildcards '%' only if it's unescaped. 4795 if k.escape == '.' { 4796 // '.' is the escape character, so for correct processing later by 4797 // replaceCustomEscape we need to escape it by itself. 4798 pattern = replaceUnescaped(pattern, `%`, `..*`, regexp.QuoteMeta(string(k.escape))) 4799 } else if k.escape == '*' { 4800 // '*' is the escape character, so for correct processing later by 4801 // replaceCustomEscape we need to escape it by itself. 4802 pattern = replaceUnescaped(pattern, `%`, `.**`, regexp.QuoteMeta(string(k.escape))) 4803 } else { 4804 pattern = replaceUnescaped(pattern, `%`, `.*`, regexp.QuoteMeta(string(k.escape))) 4805 } 4806 } 4807 // If `_` is escape character, then it's not a wildcard. 4808 if k.escape != '_' { 4809 // Replace LIKE/ILIKE specific wildcards '_' only if it's unescaped. 4810 if k.escape == '.' { 4811 // '.' is the escape character, so for correct processing later by 4812 // replaceCustomEscape we need to escape it by itself. 4813 pattern = replaceUnescaped(pattern, `_`, `..`, regexp.QuoteMeta(string(k.escape))) 4814 } else { 4815 pattern = replaceUnescaped(pattern, `_`, `.`, regexp.QuoteMeta(string(k.escape))) 4816 } 4817 } 4818 4819 // If a sequence of symbols ` escape+`\\` ` is unescaped, then that escape 4820 // character escapes backslash in the original pattern (we need to use double 4821 // backslash because of QuoteMeta behavior), so we want to "consume" the escape character. 4822 pattern = replaceUnescaped(pattern, string(k.escape)+`\\`, `\\`, regexp.QuoteMeta(string(k.escape))) 4823 4824 // We want to replace all escape characters with `\\` only 4825 // when they are unescaped. When an escape character is escaped, 4826 // we replace it with its single occurrence. 4827 if pattern, err = replaceCustomEscape(pattern, k.escape); err != nil { 4828 return pattern, err 4829 } 4830 } 4831 4832 // After QuoteMeta, all '\' were converted to '\\'. 4833 // After replaceCustomEscape, our custom unescaped escape characters were converted to `\\`, 4834 // so now our pattern contains only '\\' as escape tokens. 4835 // We need to unescape escaped escape tokens `\\` (now `\\\\`) and 4836 // other escaped characters `\A` (now `\\A`). 4837 if k.escape != 0 { 4838 // We do not want to return an error when pattern ends with the supposed escape character `\` 4839 // whereas the actual escape character is not `\`. The case when the pattern ends with 4840 // an actual escape character is handled in replaceCustomEscape. For example, with '-' as 4841 // the escape character on pattern 'abc\\' we do not want to return an error 'pattern ends 4842 // with escape character' because '\\' is not an escape character in this case. 4843 if pattern, err = unescapePattern( 4844 pattern, 4845 `\\`, 4846 k.escape == '\\', /* emitEscapeCharacterLastError */ 4847 ); err != nil { 4848 return "", err 4849 } 4850 } 4851 4852 return anchorPattern(pattern, k.caseInsensitive), nil 4853 } 4854 4855 type similarToKey struct { 4856 s string 4857 escape rune 4858 } 4859 4860 // Pattern implements the RegexpCacheKey interface. 4861 func (k similarToKey) Pattern() (string, error) { 4862 pattern := similarEscapeCustomChar(k.s, k.escape, k.escape != 0) 4863 return anchorPattern(pattern, false), nil 4864 } 4865 4866 // SimilarToEscape checks if 'unescaped' is SIMILAR TO 'pattern' using custom escape token 'escape' 4867 // which must be either empty (which disables the escape mechanism) or a single unicode character. 4868 func SimilarToEscape(ctx *EvalContext, unescaped, pattern, escape string) (Datum, error) { 4869 var escapeRune rune 4870 if len(escape) > 0 { 4871 var width int 4872 escapeRune, width = utf8.DecodeRuneInString(escape) 4873 if len(escape) > width { 4874 return DBoolFalse, pgerror.Newf(pgcode.InvalidEscapeSequence, "invalid escape string") 4875 } 4876 } 4877 key := similarToKey{s: pattern, escape: escapeRune} 4878 return matchRegexpWithKey(ctx, NewDString(unescaped), key) 4879 } 4880 4881 type regexpKey struct { 4882 s string 4883 caseInsensitive bool 4884 } 4885 4886 // Pattern implements the RegexpCacheKey interface. 4887 func (k regexpKey) Pattern() (string, error) { 4888 if k.caseInsensitive { 4889 return caseInsensitive(k.s), nil 4890 } 4891 return k.s, nil 4892 } 4893 4894 // SimilarEscape converts a SQL:2008 regexp pattern to POSIX style, so it can 4895 // be used by our regexp engine. 4896 func SimilarEscape(pattern string) string { 4897 return similarEscapeCustomChar(pattern, '\\', true) 4898 } 4899 4900 // similarEscapeCustomChar converts a SQL:2008 regexp pattern to POSIX style, 4901 // so it can be used by our regexp engine. This version of the function allows 4902 // for a custom escape character. 4903 // 'isEscapeNonEmpty' signals whether 'escapeChar' should be treated as empty. 4904 func similarEscapeCustomChar(pattern string, escapeChar rune, isEscapeNonEmpty bool) string { 4905 patternBuilder := make([]rune, 0, utf8.RuneCountInString(pattern)) 4906 4907 inCharClass := false 4908 afterEscape := false 4909 numQuotes := 0 4910 for _, c := range pattern { 4911 switch { 4912 case afterEscape: 4913 // For SUBSTRING patterns 4914 if c == '"' && !inCharClass { 4915 if numQuotes%2 == 0 { 4916 patternBuilder = append(patternBuilder, '(') 4917 } else { 4918 patternBuilder = append(patternBuilder, ')') 4919 } 4920 numQuotes++ 4921 } else if c == escapeChar && len(string(escapeChar)) > 1 { 4922 // We encountered escaped escape unicode character represented by at least two bytes, 4923 // so we keep only its single occurrence and need not to prepend it by '\'. 4924 patternBuilder = append(patternBuilder, c) 4925 } else { 4926 patternBuilder = append(patternBuilder, '\\', c) 4927 } 4928 afterEscape = false 4929 case utf8.ValidRune(escapeChar) && c == escapeChar && isEscapeNonEmpty: 4930 // SQL99 escape character; do not immediately send to output 4931 afterEscape = true 4932 case inCharClass: 4933 if c == '\\' { 4934 patternBuilder = append(patternBuilder, '\\') 4935 } 4936 patternBuilder = append(patternBuilder, c) 4937 if c == ']' { 4938 inCharClass = false 4939 } 4940 case c == '[': 4941 patternBuilder = append(patternBuilder, c) 4942 inCharClass = true 4943 case c == '%': 4944 patternBuilder = append(patternBuilder, '.', '*') 4945 case c == '_': 4946 patternBuilder = append(patternBuilder, '.') 4947 case c == '(': 4948 // Convert to non-capturing parenthesis 4949 patternBuilder = append(patternBuilder, '(', '?', ':') 4950 case c == '\\', c == '.', c == '^', c == '$': 4951 // Escape these characters because they are NOT 4952 // metacharacters for SQL-style regexp 4953 patternBuilder = append(patternBuilder, '\\', c) 4954 default: 4955 patternBuilder = append(patternBuilder, c) 4956 } 4957 } 4958 4959 return string(patternBuilder) 4960 } 4961 4962 // caseInsensitive surrounds the transformed input string with 4963 // (?i: ... ) 4964 // which uses a non-capturing set of parens to turn a case sensitive 4965 // regular expression pattern into a case insensitive regular 4966 // expression pattern. 4967 func caseInsensitive(pattern string) string { 4968 return fmt.Sprintf("(?i:%s)", pattern) 4969 } 4970 4971 // anchorPattern surrounds the transformed input string with 4972 // ^(?s: ... )$ 4973 // which requires some explanation. We need "^" and "$" to force 4974 // the pattern to match the entire input string as per SQL99 spec. 4975 // The "(?:" and ")" are a non-capturing set of parens; we have to have 4976 // parens in case the string contains "|", else the "^" and "$" will 4977 // be bound into the first and last alternatives which is not what we 4978 // want, and the parens must be non capturing because we don't want them 4979 // to count when selecting output for SUBSTRING. 4980 // "?s" turns on "dot all" mode meaning a dot will match any single character 4981 // (without turning this mode on, the dot matches any single character except 4982 // for line breaks). 4983 func anchorPattern(pattern string, caseInsensitive bool) string { 4984 if caseInsensitive { 4985 return fmt.Sprintf("^(?si:%s)$", pattern) 4986 } 4987 return fmt.Sprintf("^(?s:%s)$", pattern) 4988 } 4989 4990 // FindEqualComparisonFunction looks up an overload of the "=" operator 4991 // for a given pair of input operand types. 4992 func FindEqualComparisonFunction( 4993 leftType, rightType *types.T, 4994 ) (func(*EvalContext, Datum, Datum) (Datum, error), bool) { 4995 fn, found := CmpOps[EQ].LookupImpl(leftType, rightType) 4996 if found { 4997 return fn.Fn, true 4998 } 4999 return nil, false 5000 } 5001 5002 // IntPow computes the value of x^y. 5003 func IntPow(x, y DInt) (*DInt, error) { 5004 xd := apd.New(int64(x), 0) 5005 yd := apd.New(int64(y), 0) 5006 _, err := DecimalCtx.Pow(xd, xd, yd) 5007 if err != nil { 5008 return nil, err 5009 } 5010 i, err := xd.Int64() 5011 if err != nil { 5012 return nil, ErrIntOutOfRange 5013 } 5014 return NewDInt(DInt(i)), nil 5015 } 5016 5017 // PickFromTuple picks the greatest (or least value) from a tuple. 5018 func PickFromTuple(ctx *EvalContext, greatest bool, args Datums) (Datum, error) { 5019 g := args[0] 5020 // Pick a greater (or smaller) value. 5021 for _, d := range args[1:] { 5022 var eval Datum 5023 var err error 5024 if greatest { 5025 eval, err = evalComparison(ctx, LT, g, d) 5026 } else { 5027 eval, err = evalComparison(ctx, LT, d, g) 5028 } 5029 if err != nil { 5030 return nil, err 5031 } 5032 if eval == DBoolTrue || 5033 (eval == DNull && g == DNull) { 5034 g = d 5035 } 5036 } 5037 return g, nil 5038 } 5039 5040 // CallbackValueGenerator is a ValueGenerator that calls a supplied callback for 5041 // producing the values. To be used with 5042 // EvalContextTestingKnobs.CallbackGenerators. 5043 type CallbackValueGenerator struct { 5044 // cb is the callback to be called for producing values. It gets passed in 0 5045 // as prev initially, and the value it previously returned for subsequent 5046 // invocations. Once it returns -1 or an error, it will not be invoked any 5047 // more. 5048 cb func(ctx context.Context, prev int, txn *kv.Txn) (int, error) 5049 val int 5050 txn *kv.Txn 5051 } 5052 5053 var _ ValueGenerator = &CallbackValueGenerator{} 5054 5055 // NewCallbackValueGenerator creates a new CallbackValueGenerator. 5056 func NewCallbackValueGenerator( 5057 cb func(ctx context.Context, prev int, txn *kv.Txn) (int, error), 5058 ) *CallbackValueGenerator { 5059 return &CallbackValueGenerator{ 5060 cb: cb, 5061 } 5062 } 5063 5064 // ResolvedType is part of the ValueGenerator interface. 5065 func (c *CallbackValueGenerator) ResolvedType() *types.T { 5066 return types.Int 5067 } 5068 5069 // Start is part of the ValueGenerator interface. 5070 func (c *CallbackValueGenerator) Start(_ context.Context, txn *kv.Txn) error { 5071 c.txn = txn 5072 return nil 5073 } 5074 5075 // Next is part of the ValueGenerator interface. 5076 func (c *CallbackValueGenerator) Next(ctx context.Context) (bool, error) { 5077 var err error 5078 c.val, err = c.cb(ctx, c.val, c.txn) 5079 if err != nil { 5080 return false, err 5081 } 5082 if c.val == -1 { 5083 return false, nil 5084 } 5085 return true, nil 5086 } 5087 5088 // Values is part of the ValueGenerator interface. 5089 func (c *CallbackValueGenerator) Values() (Datums, error) { 5090 return Datums{NewDInt(DInt(c.val))}, nil 5091 } 5092 5093 // Close is part of the ValueGenerator interface. 5094 func (c *CallbackValueGenerator) Close() {} 5095 5096 // Sqrt returns the square root of x. 5097 func Sqrt(x float64) (*DFloat, error) { 5098 if x < 0.0 { 5099 return nil, errSqrtOfNegNumber 5100 } 5101 return NewDFloat(DFloat(math.Sqrt(x))), nil 5102 } 5103 5104 // DecimalSqrt returns the square root of x. 5105 func DecimalSqrt(x *apd.Decimal) (*DDecimal, error) { 5106 if x.Sign() < 0 { 5107 return nil, errSqrtOfNegNumber 5108 } 5109 dd := &DDecimal{} 5110 _, err := DecimalCtx.Sqrt(&dd.Decimal, x) 5111 return dd, err 5112 } 5113 5114 // Cbrt returns the cube root of x. 5115 func Cbrt(x float64) (*DFloat, error) { 5116 return NewDFloat(DFloat(math.Cbrt(x))), nil 5117 } 5118 5119 // DecimalCbrt returns the cube root of x. 5120 func DecimalCbrt(x *apd.Decimal) (*DDecimal, error) { 5121 dd := &DDecimal{} 5122 _, err := DecimalCtx.Cbrt(&dd.Decimal, x) 5123 return dd, err 5124 }