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 }