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

     1  // Copyright 2018 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 opt
    12  
    13  import (
    14  	"fmt"
    15  
    16  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    17  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    18  	"github.com/cockroachdb/cockroach/pkg/util/log"
    19  	"github.com/cockroachdb/errors"
    20  )
    21  
    22  // Operator describes the type of operation that a memo expression performs.
    23  // Some operators are relational (join, select, project) and others are scalar
    24  // (and, or, plus, variable).
    25  type Operator uint16
    26  
    27  // String returns the name of the operator as a string.
    28  func (op Operator) String() string {
    29  	if op >= Operator(len(opNames)-1) {
    30  		return fmt.Sprintf("Operator(%d)", op)
    31  	}
    32  	return opNames[opNameIndexes[op]:opNameIndexes[op+1]]
    33  }
    34  
    35  // SyntaxTag returns the name of the operator using the SQL syntax that most
    36  // closely matches it.
    37  func (op Operator) SyntaxTag() string {
    38  	// Handle any special cases where default codegen tag isn't best choice as
    39  	// switch cases.
    40  	switch op {
    41  	default:
    42  		// Use default codegen tag, which is mechanically derived from the
    43  		// operator name.
    44  		if op >= Operator(len(opNames)-1) {
    45  			// Use UNKNOWN.
    46  			op = 0
    47  		}
    48  		return opSyntaxTags[opSyntaxTagIndexes[op]:opSyntaxTagIndexes[op+1]]
    49  	}
    50  }
    51  
    52  // Expr is a node in an expression tree. It offers methods to traverse and
    53  // inspect the tree. Each node in the tree has an enumerated operator type, zero
    54  // or more children, and an optional private value. The entire tree can be
    55  // easily visited using a pattern like this:
    56  //
    57  //   var visit func(e Expr)
    58  //   visit := func(e Expr) {
    59  //     for i, n := 0, e.ChildCount(); i < n; i++ {
    60  //       visit(e.Child(i))
    61  //     }
    62  //   }
    63  //
    64  type Expr interface {
    65  	// Op returns the operator type of the expression.
    66  	Op() Operator
    67  
    68  	// ChildCount returns the number of children of the expression.
    69  	ChildCount() int
    70  
    71  	// Child returns the nth child of the expression.
    72  	Child(nth int) Expr
    73  
    74  	// Private returns operator-specific data. Callers are expected to know the
    75  	// type and format of the data, which will differ from operator to operator.
    76  	// For example, an operator may choose to return one of its fields, or perhaps
    77  	// a pointer to itself, or nil if there is nothing useful to return.
    78  	Private() interface{}
    79  
    80  	// String returns a human-readable string representation for the expression
    81  	// that can be used for debugging and testing.
    82  	String() string
    83  }
    84  
    85  // ScalarID is the type of the memo-unique identifier given to every scalar
    86  // expression.
    87  type ScalarID int
    88  
    89  // ScalarExpr is a scalar expression, which is an expression that returns a
    90  // primitive-typed value like boolean or string rather than rows and columns.
    91  type ScalarExpr interface {
    92  	Expr
    93  
    94  	// ID is a unique (within the context of a memo) ID that can be
    95  	// used to define a total order over ScalarExprs.
    96  	ID() ScalarID
    97  
    98  	// DataType is the SQL type of the expression.
    99  	DataType() *types.T
   100  }
   101  
   102  // MutableExpr is implemented by expressions that allow their children to be
   103  // updated.
   104  type MutableExpr interface {
   105  	// SetChild updates the nth child of the expression to instead be the given
   106  	// child expression.
   107  	SetChild(nth int, child Expr)
   108  }
   109  
   110  // ComparisonOpMap maps from a semantic tree comparison operator type to an
   111  // optimizer operator type.
   112  var ComparisonOpMap [tree.NumComparisonOperators]Operator
   113  
   114  // ComparisonOpReverseMap maps from an optimizer operator type to a semantic
   115  // tree comparison operator type.
   116  var ComparisonOpReverseMap = map[Operator]tree.ComparisonOperator{
   117  	EqOp:             tree.EQ,
   118  	LtOp:             tree.LT,
   119  	GtOp:             tree.GT,
   120  	LeOp:             tree.LE,
   121  	GeOp:             tree.GE,
   122  	NeOp:             tree.NE,
   123  	InOp:             tree.In,
   124  	NotInOp:          tree.NotIn,
   125  	LikeOp:           tree.Like,
   126  	NotLikeOp:        tree.NotLike,
   127  	ILikeOp:          tree.ILike,
   128  	NotILikeOp:       tree.NotILike,
   129  	SimilarToOp:      tree.SimilarTo,
   130  	NotSimilarToOp:   tree.NotSimilarTo,
   131  	RegMatchOp:       tree.RegMatch,
   132  	NotRegMatchOp:    tree.NotRegMatch,
   133  	RegIMatchOp:      tree.RegIMatch,
   134  	NotRegIMatchOp:   tree.NotRegIMatch,
   135  	IsOp:             tree.IsNotDistinctFrom,
   136  	IsNotOp:          tree.IsDistinctFrom,
   137  	ContainsOp:       tree.Contains,
   138  	JsonExistsOp:     tree.JSONExists,
   139  	JsonSomeExistsOp: tree.JSONSomeExists,
   140  	JsonAllExistsOp:  tree.JSONAllExists,
   141  	OverlapsOp:       tree.Overlaps,
   142  }
   143  
   144  // BinaryOpReverseMap maps from an optimizer operator type to a semantic tree
   145  // binary operator type.
   146  var BinaryOpReverseMap = map[Operator]tree.BinaryOperator{
   147  	BitandOp:        tree.Bitand,
   148  	BitorOp:         tree.Bitor,
   149  	BitxorOp:        tree.Bitxor,
   150  	PlusOp:          tree.Plus,
   151  	MinusOp:         tree.Minus,
   152  	MultOp:          tree.Mult,
   153  	DivOp:           tree.Div,
   154  	FloorDivOp:      tree.FloorDiv,
   155  	ModOp:           tree.Mod,
   156  	PowOp:           tree.Pow,
   157  	ConcatOp:        tree.Concat,
   158  	LShiftOp:        tree.LShift,
   159  	RShiftOp:        tree.RShift,
   160  	FetchValOp:      tree.JSONFetchVal,
   161  	FetchTextOp:     tree.JSONFetchText,
   162  	FetchValPathOp:  tree.JSONFetchValPath,
   163  	FetchTextPathOp: tree.JSONFetchTextPath,
   164  }
   165  
   166  // UnaryOpReverseMap maps from an optimizer operator type to a semantic tree
   167  // unary operator type.
   168  var UnaryOpReverseMap = map[Operator]tree.UnaryOperator{
   169  	UnaryMinusOp:      tree.UnaryMinus,
   170  	UnaryComplementOp: tree.UnaryComplement,
   171  	UnarySqrtOp:       tree.UnarySqrt,
   172  	UnaryCbrtOp:       tree.UnaryCbrt,
   173  }
   174  
   175  // AggregateOpReverseMap maps from an optimizer operator type to the name of an
   176  // aggregation function.
   177  var AggregateOpReverseMap = map[Operator]string{
   178  	ArrayAggOp:        "array_agg",
   179  	AvgOp:             "avg",
   180  	BitAndAggOp:       "bit_and",
   181  	BitOrAggOp:        "bit_or",
   182  	BoolAndOp:         "bool_and",
   183  	BoolOrOp:          "bool_or",
   184  	ConcatAggOp:       "concat_agg",
   185  	CountOp:           "count",
   186  	CorrOp:            "corr",
   187  	CountRowsOp:       "count_rows",
   188  	MaxOp:             "max",
   189  	MinOp:             "min",
   190  	SumIntOp:          "sum_int",
   191  	SumOp:             "sum",
   192  	SqrDiffOp:         "sqrdiff",
   193  	VarianceOp:        "variance",
   194  	StdDevOp:          "stddev",
   195  	XorAggOp:          "xor_agg",
   196  	JsonAggOp:         "json_agg",
   197  	JsonbAggOp:        "jsonb_agg",
   198  	StringAggOp:       "string_agg",
   199  	ConstAggOp:        "any_not_null",
   200  	ConstNotNullAggOp: "any_not_null",
   201  	AnyNotNullAggOp:   "any_not_null",
   202  	PercentileDiscOp:  "percentile_disc_impl",
   203  	PercentileContOp:  "percentile_cont_impl",
   204  }
   205  
   206  // WindowOpReverseMap maps from an optimizer operator type to the name of a
   207  // window function.
   208  var WindowOpReverseMap = map[Operator]string{
   209  	RankOp:        "rank",
   210  	RowNumberOp:   "row_number",
   211  	DenseRankOp:   "dense_rank",
   212  	PercentRankOp: "percent_rank",
   213  	CumeDistOp:    "cume_dist",
   214  	NtileOp:       "ntile",
   215  	LagOp:         "lag",
   216  	LeadOp:        "lead",
   217  	FirstValueOp:  "first_value",
   218  	LastValueOp:   "last_value",
   219  	NthValueOp:    "nth_value",
   220  }
   221  
   222  // NegateOpMap maps from a comparison operator type to its negated operator
   223  // type, as if the Not operator was applied to it. Some comparison operators,
   224  // like Contains and JsonExists, do not have negated versions.
   225  var NegateOpMap = map[Operator]Operator{
   226  	EqOp:           NeOp,
   227  	LtOp:           GeOp,
   228  	GtOp:           LeOp,
   229  	LeOp:           GtOp,
   230  	GeOp:           LtOp,
   231  	NeOp:           EqOp,
   232  	InOp:           NotInOp,
   233  	NotInOp:        InOp,
   234  	LikeOp:         NotLikeOp,
   235  	NotLikeOp:      LikeOp,
   236  	ILikeOp:        NotILikeOp,
   237  	NotILikeOp:     ILikeOp,
   238  	SimilarToOp:    NotSimilarToOp,
   239  	NotSimilarToOp: SimilarToOp,
   240  	RegMatchOp:     NotRegMatchOp,
   241  	NotRegMatchOp:  RegMatchOp,
   242  	RegIMatchOp:    NotRegIMatchOp,
   243  	NotRegIMatchOp: RegIMatchOp,
   244  	IsOp:           IsNotOp,
   245  	IsNotOp:        IsOp,
   246  }
   247  
   248  // BoolOperatorRequiresNotNullArgs returns true if the operator can never
   249  // evaluate to true if one of its children is NULL.
   250  func BoolOperatorRequiresNotNullArgs(op Operator) bool {
   251  	switch op {
   252  	case
   253  		EqOp, LtOp, LeOp, GtOp, GeOp, NeOp,
   254  		LikeOp, NotLikeOp, ILikeOp, NotILikeOp, SimilarToOp, NotSimilarToOp,
   255  		RegMatchOp, NotRegMatchOp, RegIMatchOp, NotRegIMatchOp:
   256  		return true
   257  	}
   258  	return false
   259  }
   260  
   261  // AggregateIgnoresNulls returns true if the given aggregate operator ignores
   262  // rows where its first argument evaluates to NULL. In other words, it always
   263  // evaluates to the same result even if those rows are filtered. For example:
   264  //
   265  //   SELECT string_agg(x, y)
   266  //   FROM (VALUES ('foo', ','), ('bar', ','), (NULL, ',')) t(x, y)
   267  //
   268  // In this example, the NULL row can be removed from the input, and the
   269  // string_agg function still returns the same result. Contrast this to the
   270  // array_agg function:
   271  //
   272  //   SELECT array_agg(x)
   273  //   FROM (VALUES ('foo'), (NULL), ('bar')) t(x)
   274  //
   275  // If the NULL row is removed here, array_agg returns {foo,bar} instead of
   276  // {foo,NULL,bar}.
   277  func AggregateIgnoresNulls(op Operator) bool {
   278  	switch op {
   279  
   280  	case AnyNotNullAggOp, AvgOp, BitAndAggOp, BitOrAggOp, BoolAndOp, BoolOrOp,
   281  		ConstNotNullAggOp, CorrOp, CountOp, MaxOp, MinOp, SqrDiffOp, StdDevOp,
   282  		StringAggOp, SumOp, SumIntOp, VarianceOp, XorAggOp, PercentileDiscOp, PercentileContOp:
   283  		return true
   284  
   285  	case ArrayAggOp, ConcatAggOp, ConstAggOp, CountRowsOp, FirstAggOp, JsonAggOp,
   286  		JsonbAggOp:
   287  		return false
   288  
   289  	default:
   290  		panic(errors.AssertionFailedf("unhandled op %s", log.Safe(op)))
   291  	}
   292  }
   293  
   294  // AggregateIsNullOnEmpty returns true if the given aggregate operator returns
   295  // NULL when the input set contains no values. This group of aggregates turns
   296  // out to be the inverse of AggregateIsNeverNull in practice.
   297  func AggregateIsNullOnEmpty(op Operator) bool {
   298  	switch op {
   299  
   300  	case AnyNotNullAggOp, ArrayAggOp, AvgOp, BitAndAggOp,
   301  		BitOrAggOp, BoolAndOp, BoolOrOp, ConcatAggOp, ConstAggOp,
   302  		ConstNotNullAggOp, CorrOp, FirstAggOp, JsonAggOp, JsonbAggOp,
   303  		MaxOp, MinOp, SqrDiffOp, StdDevOp, StringAggOp, SumOp, SumIntOp,
   304  		VarianceOp, XorAggOp, PercentileDiscOp, PercentileContOp:
   305  		return true
   306  
   307  	case CountOp, CountRowsOp:
   308  		return false
   309  
   310  	default:
   311  		panic(errors.AssertionFailedf("unhandled op %s", log.Safe(op)))
   312  	}
   313  }
   314  
   315  // AggregateIsNeverNullOnNonNullInput returns true if the given aggregate
   316  // operator never returns NULL when the input set contains at least one non-NULL
   317  // value. This is true of most aggregates.
   318  //
   319  // For multi-input aggregations, returns true if the aggregate is never NULL
   320  // when all inputs have at least a non-NULL value (though not necessarily on the
   321  // same input row).
   322  func AggregateIsNeverNullOnNonNullInput(op Operator) bool {
   323  	switch op {
   324  
   325  	case AnyNotNullAggOp, ArrayAggOp, AvgOp, BitAndAggOp,
   326  		BitOrAggOp, BoolAndOp, BoolOrOp, ConcatAggOp, ConstAggOp,
   327  		ConstNotNullAggOp, CountOp, CountRowsOp, FirstAggOp,
   328  		JsonAggOp, JsonbAggOp, MaxOp, MinOp, SqrDiffOp,
   329  		StringAggOp, SumOp, SumIntOp, XorAggOp, PercentileDiscOp, PercentileContOp:
   330  		return true
   331  
   332  	case VarianceOp, StdDevOp, CorrOp:
   333  		// These aggregations return NULL if they are given a single not-NULL input.
   334  		return false
   335  
   336  	default:
   337  		panic(errors.AssertionFailedf("unhandled op %s", log.Safe(op)))
   338  	}
   339  }
   340  
   341  // AggregateIsNeverNull returns true if the given aggregate operator never
   342  // returns NULL, even if the input is empty, or one more more inputs are NULL.
   343  func AggregateIsNeverNull(op Operator) bool {
   344  	switch op {
   345  	case CountOp, CountRowsOp:
   346  		return true
   347  	}
   348  	return false
   349  }
   350  
   351  // AggregatesCanMerge returns true if the given inner and outer operators can be
   352  // replaced with a single equivalent operator, assuming the outer operator is
   353  // aggregating on the inner. In other words, the inner-outer aggregate pair
   354  // forms a valid "decomposition" of a single aggregate. For example, the
   355  // following pairs of queries are equivalent:
   356  //
   357  //   SELECT sum(s) FROM (SELECT sum(y) FROM xy GROUP BY x) AS f(s);
   358  //   SELECT sum(y) FROM xy;
   359  //
   360  //   SELECT sum_int(c) FROM (SELECT count(y) FROM xy GROUP BY x) AS f(c);
   361  //   SELECT count(y) FROM xy;
   362  //
   363  // Note: some aggregates like StringAggOp are decomposable in theory, but in
   364  // practice can not be easily merged as in the examples above.
   365  func AggregatesCanMerge(inner, outer Operator) bool {
   366  	switch inner {
   367  
   368  	case AnyNotNullAggOp, BitAndAggOp, BitOrAggOp, BoolAndOp,
   369  		BoolOrOp, ConstAggOp, ConstNotNullAggOp, FirstAggOp,
   370  		MaxOp, MinOp, SumOp, SumIntOp, XorAggOp:
   371  		return inner == outer
   372  
   373  	case CountOp, CountRowsOp:
   374  		// Only SumIntOp can be used here because SumOp outputs a decimal value,
   375  		// while CountOp and CountRowsOp both output int values.
   376  		return outer == SumIntOp
   377  
   378  	case ArrayAggOp, AvgOp, ConcatAggOp, CorrOp, JsonAggOp,
   379  		JsonbAggOp, PercentileContOp, PercentileDiscOp, SqrDiffOp,
   380  		StdDevOp, StringAggOp, VarianceOp:
   381  		return false
   382  
   383  	default:
   384  		panic(errors.AssertionFailedf("unhandled ops: %s, %s", log.Safe(inner), log.Safe(outer)))
   385  	}
   386  }
   387  
   388  // AggregateIgnoresDuplicates returns true if the output of the given aggregate
   389  // operator does not change when duplicate rows are added to the input.
   390  func AggregateIgnoresDuplicates(op Operator) bool {
   391  	switch op {
   392  	case AnyNotNullAggOp, BitAndAggOp, BitOrAggOp, BoolAndOp, BoolOrOp,
   393  		ConstAggOp, ConstNotNullAggOp, FirstAggOp, MaxOp, MinOp:
   394  		return true
   395  
   396  	case ArrayAggOp, AvgOp, ConcatAggOp, CountOp, CorrOp, CountRowsOp, SumIntOp,
   397  		SumOp, SqrDiffOp, VarianceOp, StdDevOp, XorAggOp, JsonAggOp, JsonbAggOp,
   398  		StringAggOp, PercentileDiscOp, PercentileContOp:
   399  		return false
   400  
   401  	default:
   402  		panic(errors.AssertionFailedf("unhandled op %s", log.Safe(op)))
   403  	}
   404  }
   405  
   406  // OpaqueMetadata is an object stored in OpaqueRelExpr and passed
   407  // through to the exec factory.
   408  type OpaqueMetadata interface {
   409  	ImplementsOpaqueMetadata()
   410  
   411  	// String is a short description used when printing optimizer trees and when
   412  	// forming error messages; it should be the SQL statement tag.
   413  	String() string
   414  }
   415  
   416  func init() {
   417  	for optOp, treeOp := range ComparisonOpReverseMap {
   418  		ComparisonOpMap[treeOp] = optOp
   419  	}
   420  }