github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/norm/comp_funcs.go (about)

     1  // Copyright 2020 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 norm
    12  
    13  import (
    14  	"github.com/cockroachdb/cockroach/pkg/sql/opt"
    15  	"github.com/cockroachdb/cockroach/pkg/sql/opt/memo"
    16  	"github.com/cockroachdb/cockroach/pkg/sql/sem/builtins"
    17  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    18  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    19  	"github.com/cockroachdb/cockroach/pkg/util/log"
    20  	"github.com/cockroachdb/errors"
    21  )
    22  
    23  // CommuteInequality swaps the operands of an inequality comparison expression,
    24  // changing the operator to compensate:
    25  //   5 < x
    26  // to:
    27  //   x > 5
    28  func (c *CustomFuncs) CommuteInequality(
    29  	op opt.Operator, left, right opt.ScalarExpr,
    30  ) opt.ScalarExpr {
    31  	switch op {
    32  	case opt.GeOp:
    33  		return c.f.ConstructLe(right, left)
    34  	case opt.GtOp:
    35  		return c.f.ConstructLt(right, left)
    36  	case opt.LeOp:
    37  		return c.f.ConstructGe(right, left)
    38  	case opt.LtOp:
    39  		return c.f.ConstructGt(right, left)
    40  	}
    41  	panic(errors.AssertionFailedf("called commuteInequality with operator %s", log.Safe(op)))
    42  }
    43  
    44  // NormalizeTupleEquality remaps the elements of two tuples compared for
    45  // equality, like this:
    46  //   (a, b, c) = (x, y, z)
    47  // into this:
    48  //   (a = x) AND (b = y) AND (c = z)
    49  func (c *CustomFuncs) NormalizeTupleEquality(left, right memo.ScalarListExpr) opt.ScalarExpr {
    50  	if len(left) != len(right) {
    51  		panic(errors.AssertionFailedf("tuple length mismatch"))
    52  	}
    53  	if len(left) == 0 {
    54  		// () = (), which is always true.
    55  		return memo.TrueSingleton
    56  	}
    57  
    58  	var result opt.ScalarExpr
    59  	for i := range left {
    60  		eq := c.f.ConstructEq(left[i], right[i])
    61  		if result == nil {
    62  			result = eq
    63  		} else {
    64  			result = c.f.ConstructAnd(result, eq)
    65  		}
    66  	}
    67  	return result
    68  }
    69  
    70  // FirstScalarListExpr returns the first ScalarExpr in the given list.
    71  func (c *CustomFuncs) FirstScalarListExpr(list memo.ScalarListExpr) opt.ScalarExpr {
    72  	return list[0]
    73  }
    74  
    75  // SecondScalarListExpr returns the second ScalarExpr in the given list.
    76  func (c *CustomFuncs) SecondScalarListExpr(list memo.ScalarListExpr) opt.ScalarExpr {
    77  	return list[1]
    78  }
    79  
    80  // MakeTimeZoneFunction constructs a new timezone() function with the given zone
    81  // and timestamp as arguments. The type of the function result is TIMESTAMPTZ if
    82  // ts is of type TIMESTAMP, or TIMESTAMP if is of type TIMESTAMPTZ.
    83  func (c *CustomFuncs) MakeTimeZoneFunction(zone opt.ScalarExpr, ts opt.ScalarExpr) opt.ScalarExpr {
    84  	argType := types.TimestampTZ
    85  	resultType := types.Timestamp
    86  	if ts.DataType().Family() == types.TimestampFamily {
    87  		argType, resultType = resultType, argType
    88  	}
    89  
    90  	args := make(memo.ScalarListExpr, 2)
    91  	args[0] = zone
    92  	args[1] = ts
    93  
    94  	props, overload := findTimeZoneFunction(argType)
    95  	return c.f.ConstructFunction(args, &memo.FunctionPrivate{
    96  		Name:       "timezone",
    97  		Typ:        resultType,
    98  		Properties: props,
    99  		Overload:   overload,
   100  	})
   101  }
   102  
   103  // findTimeZoneFunction returns the function properties and overload of the
   104  // timezone() function with a second argument that matches the given input type.
   105  // If no overload is found, findTimeZoneFunction panics.
   106  func findTimeZoneFunction(typ *types.T) (*tree.FunctionProperties, *tree.Overload) {
   107  	props, overloads := builtins.GetBuiltinProperties("timezone")
   108  	for o := range overloads {
   109  		overload := &overloads[o]
   110  		if overload.Types.MatchAt(typ, 1) {
   111  			return props, overload
   112  		}
   113  	}
   114  	panic(errors.AssertionFailedf("could not find overload for timezone"))
   115  }