github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/sql/sem/tree/eval.go (about)

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