github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/norm/general_funcs.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 norm
    12  
    13  import (
    14  	"github.com/cockroachdb/apd"
    15  	"github.com/cockroachdb/cockroach/pkg/sql/opt"
    16  	"github.com/cockroachdb/cockroach/pkg/sql/opt/cat"
    17  	"github.com/cockroachdb/cockroach/pkg/sql/opt/constraint"
    18  	"github.com/cockroachdb/cockroach/pkg/sql/opt/memo"
    19  	"github.com/cockroachdb/cockroach/pkg/sql/opt/props"
    20  	"github.com/cockroachdb/cockroach/pkg/sql/opt/props/physical"
    21  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    22  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    23  	"github.com/cockroachdb/cockroach/pkg/util/arith"
    24  	"github.com/cockroachdb/errors"
    25  )
    26  
    27  // CustomFuncs contains all the custom match and replace functions used by
    28  // the normalization rules. These are also imported and used by the explorer.
    29  type CustomFuncs struct {
    30  	f   *Factory
    31  	mem *memo.Memo
    32  }
    33  
    34  // Init initializes a new CustomFuncs with the given factory.
    35  func (c *CustomFuncs) Init(f *Factory) {
    36  	c.f = f
    37  	c.mem = f.Memo()
    38  }
    39  
    40  // Succeeded returns true if a result expression is not nil.
    41  func (c *CustomFuncs) Succeeded(result opt.Expr) bool {
    42  	return result != nil
    43  }
    44  
    45  // ----------------------------------------------------------------------
    46  //
    47  // Typing functions
    48  //   General functions used to test and construct expression data types.
    49  //
    50  // ----------------------------------------------------------------------
    51  
    52  // HasColType returns true if the given scalar expression has a static type
    53  // that's identical to the requested coltype.
    54  func (c *CustomFuncs) HasColType(scalar opt.ScalarExpr, dstTyp *types.T) bool {
    55  	return scalar.DataType().Identical(dstTyp)
    56  }
    57  
    58  // IsString returns true if the given scalar expression is of type String.
    59  func (c *CustomFuncs) IsString(scalar opt.ScalarExpr) bool {
    60  	return scalar.DataType().Family() == types.StringFamily
    61  }
    62  
    63  // IsTimestamp returns true if the given scalar expression is of type Timestamp.
    64  func (c *CustomFuncs) IsTimestamp(scalar opt.ScalarExpr) bool {
    65  	return scalar.DataType().Family() == types.TimestampFamily
    66  }
    67  
    68  // IsTimestampTZ returns true if the given scalar expression is of type
    69  // TimestampTZ.
    70  func (c *CustomFuncs) IsTimestampTZ(scalar opt.ScalarExpr) bool {
    71  	return scalar.DataType().Family() == types.TimestampTZFamily
    72  }
    73  
    74  // BoolType returns the boolean SQL type.
    75  func (c *CustomFuncs) BoolType() *types.T {
    76  	return types.Bool
    77  }
    78  
    79  // AnyType returns the wildcard Any type.
    80  func (c *CustomFuncs) AnyType() *types.T {
    81  	return types.Any
    82  }
    83  
    84  // CanConstructBinary returns true if (op left right) has a valid binary op
    85  // overload and is therefore legal to construct. For example, while
    86  // (Minus <date> <int>) is valid, (Minus <int> <date>) is not.
    87  func (c *CustomFuncs) CanConstructBinary(op opt.Operator, left, right opt.ScalarExpr) bool {
    88  	return memo.BinaryOverloadExists(op, left.DataType(), right.DataType())
    89  }
    90  
    91  // ArrayType returns the type of the given column wrapped
    92  // in an array.
    93  func (c *CustomFuncs) ArrayType(inCol opt.ColumnID) *types.T {
    94  	inTyp := c.mem.Metadata().ColumnMeta(inCol).Type
    95  	return types.MakeArray(inTyp)
    96  }
    97  
    98  // BinaryType returns the type of the binary overload for the given operator and
    99  // operands.
   100  func (c *CustomFuncs) BinaryType(op opt.Operator, left, right opt.ScalarExpr) *types.T {
   101  	o, _ := memo.FindBinaryOverload(op, left.DataType(), right.DataType())
   102  	return o.ReturnType
   103  }
   104  
   105  // TypeOf returns the type of the expression.
   106  func (c *CustomFuncs) TypeOf(e opt.ScalarExpr) *types.T {
   107  	return e.DataType()
   108  }
   109  
   110  // IsConstArray returns true if the expression is a constant array.
   111  func (c *CustomFuncs) IsConstArray(scalar opt.ScalarExpr) bool {
   112  	if cnst, ok := scalar.(*memo.ConstExpr); ok {
   113  		if _, ok := cnst.Value.(*tree.DArray); ok {
   114  			return true
   115  		}
   116  	}
   117  	return false
   118  }
   119  
   120  // IsAdditiveType returns true if the given type supports addition and
   121  // subtraction in the natural way. This differs from "has a +/- Numeric
   122  // implementation" because JSON has an implementation for "- INT" which doesn't
   123  // obey x - 0 = x. Additive types include all numeric types as well as
   124  // timestamps and dates.
   125  func (c *CustomFuncs) IsAdditiveType(typ *types.T) bool {
   126  	return types.IsAdditiveType(typ)
   127  }
   128  
   129  // ----------------------------------------------------------------------
   130  //
   131  // Column functions
   132  //   General custom match and replace functions related to columns.
   133  //
   134  // ----------------------------------------------------------------------
   135  
   136  // OutputCols returns the set of columns returned by the input expression.
   137  func (c *CustomFuncs) OutputCols(input memo.RelExpr) opt.ColSet {
   138  	return input.Relational().OutputCols
   139  }
   140  
   141  // OutputCols2 returns the union of columns returned by the left and right
   142  // expressions.
   143  func (c *CustomFuncs) OutputCols2(left, right memo.RelExpr) opt.ColSet {
   144  	return left.Relational().OutputCols.Union(right.Relational().OutputCols)
   145  }
   146  
   147  // NotNullCols returns the set of columns returned by the input expression that
   148  // are guaranteed to never be NULL.
   149  func (c *CustomFuncs) NotNullCols(input memo.RelExpr) opt.ColSet {
   150  	return input.Relational().NotNullCols
   151  }
   152  
   153  // IsColNotNull returns true if the given input column is never null.
   154  func (c *CustomFuncs) IsColNotNull(col opt.ColumnID, input memo.RelExpr) bool {
   155  	return input.Relational().NotNullCols.Contains(col)
   156  }
   157  
   158  // IsColNotNull2 returns true if the given column is part of the left or right
   159  // expressions' set of not-null columns.
   160  func (c *CustomFuncs) IsColNotNull2(col opt.ColumnID, left, right memo.RelExpr) bool {
   161  	return left.Relational().NotNullCols.Contains(col) ||
   162  		right.Relational().NotNullCols.Contains(col)
   163  }
   164  
   165  // HasNoCols returns true if the input expression has zero output columns.
   166  func (c *CustomFuncs) HasNoCols(input memo.RelExpr) bool {
   167  	return input.Relational().OutputCols.Empty()
   168  }
   169  
   170  // HasOneCol returns true if the input expression has exactly one output column.
   171  func (c *CustomFuncs) HasOneCol(input memo.RelExpr) bool {
   172  	return input.Relational().OutputCols.Len() == 1
   173  }
   174  
   175  // ColsAreConst returns true if the given columns have the same values for all
   176  // rows in the given input expression.
   177  func (c *CustomFuncs) ColsAreConst(cols opt.ColSet, input memo.RelExpr) bool {
   178  	return cols.SubsetOf(input.Relational().FuncDeps.ConstantCols())
   179  }
   180  
   181  // ColsAreEmpty returns true if the column set is empty.
   182  func (c *CustomFuncs) ColsAreEmpty(cols opt.ColSet) bool {
   183  	return cols.Empty()
   184  }
   185  
   186  // MakeEmptyColSet returns a column set with no columns in it.
   187  func (c *CustomFuncs) MakeEmptyColSet() opt.ColSet {
   188  	return opt.ColSet{}
   189  }
   190  
   191  // ColsAreSubset returns true if the left columns are a subset of the right
   192  // columns.
   193  func (c *CustomFuncs) ColsAreSubset(left, right opt.ColSet) bool {
   194  	return left.SubsetOf(right)
   195  }
   196  
   197  // ColsAreEqual returns true if left and right contain the same set of columns.
   198  func (c *CustomFuncs) ColsAreEqual(left, right opt.ColSet) bool {
   199  	return left.Equals(right)
   200  }
   201  
   202  // ColsIntersect returns true if at least one column appears in both the left
   203  // and right sets.
   204  func (c *CustomFuncs) ColsIntersect(left, right opt.ColSet) bool {
   205  	return left.Intersects(right)
   206  }
   207  
   208  // IntersectionCols returns the intersection of the left and right column sets.
   209  func (c *CustomFuncs) IntersectionCols(left, right opt.ColSet) opt.ColSet {
   210  	return left.Intersection(right)
   211  }
   212  
   213  // UnionCols returns the union of the left and right column sets.
   214  func (c *CustomFuncs) UnionCols(left, right opt.ColSet) opt.ColSet {
   215  	return left.Union(right)
   216  }
   217  
   218  // UnionCols3 returns the union of the three column sets.
   219  func (c *CustomFuncs) UnionCols3(cols1, cols2, cols3 opt.ColSet) opt.ColSet {
   220  	cols := cols1.Union(cols2)
   221  	cols.UnionWith(cols3)
   222  	return cols
   223  }
   224  
   225  // UnionCols4 returns the union of the four column sets.
   226  func (c *CustomFuncs) UnionCols4(cols1, cols2, cols3, cols4 opt.ColSet) opt.ColSet {
   227  	cols := cols1.Union(cols2)
   228  	cols.UnionWith(cols3)
   229  	cols.UnionWith(cols4)
   230  	return cols
   231  }
   232  
   233  // DifferenceCols returns the difference of the left and right column sets.
   234  func (c *CustomFuncs) DifferenceCols(left, right opt.ColSet) opt.ColSet {
   235  	return left.Difference(right)
   236  }
   237  
   238  // AddColToSet returns a set containing both the given set and the given column.
   239  func (c *CustomFuncs) AddColToSet(set opt.ColSet, col opt.ColumnID) opt.ColSet {
   240  	if set.Contains(col) {
   241  		return set
   242  	}
   243  	newSet := set.Copy()
   244  	newSet.Add(col)
   245  	return newSet
   246  }
   247  
   248  // SingleColFromSet returns the single column in s. Panics if s does not contain
   249  // exactly one column.
   250  func (c *CustomFuncs) SingleColFromSet(s opt.ColSet) opt.ColumnID {
   251  	return s.SingleColumn()
   252  }
   253  
   254  // RedundantCols returns the subset of the given columns that are functionally
   255  // determined by the remaining columns. In many contexts (such as if they are
   256  // grouping columns), these columns can be dropped. The input expression's
   257  // functional dependencies are used to make the decision.
   258  func (c *CustomFuncs) RedundantCols(input memo.RelExpr, cols opt.ColSet) opt.ColSet {
   259  	reducedCols := input.Relational().FuncDeps.ReduceCols(cols)
   260  	if reducedCols.Equals(cols) {
   261  		return opt.ColSet{}
   262  	}
   263  	return cols.Difference(reducedCols)
   264  }
   265  
   266  // ----------------------------------------------------------------------
   267  //
   268  // Outer column functions
   269  //   General custom functions related to outer column references.
   270  //
   271  // ----------------------------------------------------------------------
   272  
   273  // OuterCols returns the set of outer columns associated with the given
   274  // expression, whether it be a relational or scalar operator.
   275  func (c *CustomFuncs) OuterCols(e opt.Expr) opt.ColSet {
   276  	return c.sharedProps(e).OuterCols
   277  }
   278  
   279  // HasOuterCols returns true if the input expression has at least one outer
   280  // column, or in other words, a reference to a variable that is not bound within
   281  // its own scope. For example:
   282  //
   283  //   SELECT * FROM a WHERE EXISTS(SELECT * FROM b WHERE b.x = a.x)
   284  //
   285  // The a.x variable in the EXISTS subquery references a column outside the scope
   286  // of the subquery. It is an "outer column" for the subquery (see the comment on
   287  // RelationalProps.OuterCols for more details).
   288  func (c *CustomFuncs) HasOuterCols(input opt.Expr) bool {
   289  	return !c.OuterCols(input).Empty()
   290  }
   291  
   292  // IsCorrelated returns true if any variable in the source expression references
   293  // a column from the destination expression. For example:
   294  //   (InnerJoin
   295  //     (Scan a)
   296  //     (Scan b)
   297  //     [ ... (FiltersItem $item:(Eq (Variable a.x) (Const 1))) ... ]
   298  //   )
   299  //
   300  // The $item expression is correlated with the (Scan a) expression because it
   301  // references one of its columns. But the $item expression is not correlated
   302  // with the (Scan b) expression.
   303  func (c *CustomFuncs) IsCorrelated(src, dst memo.RelExpr) bool {
   304  	return src.Relational().OuterCols.Intersects(dst.Relational().OutputCols)
   305  }
   306  
   307  // IsBoundBy returns true if all outer references in the source expression are
   308  // bound by the given columns. For example:
   309  //
   310  //   (InnerJoin
   311  //     (Scan a)
   312  //     (Scan b)
   313  //     [ ... $item:(FiltersItem (Eq (Variable a.x) (Const 1))) ... ]
   314  //   )
   315  //
   316  // The $item expression is fully bound by the output columns of the (Scan a)
   317  // expression because all of its outer references are satisfied by the columns
   318  // produced by the Scan.
   319  func (c *CustomFuncs) IsBoundBy(src opt.Expr, cols opt.ColSet) bool {
   320  	return c.OuterCols(src).SubsetOf(cols)
   321  }
   322  
   323  // ColsAreDeterminedBy returns true if the given columns are functionally
   324  // determined by the "in" ColSet according to the functional dependencies of the
   325  // input expression.
   326  func (c *CustomFuncs) ColsAreDeterminedBy(cols, in opt.ColSet, input memo.RelExpr) bool {
   327  	return input.Relational().FuncDeps.InClosureOf(cols, in)
   328  }
   329  
   330  // AreProjectionsCorrelated returns true if any element in the projections
   331  // references any of the given columns.
   332  func (c *CustomFuncs) AreProjectionsCorrelated(
   333  	projections memo.ProjectionsExpr, cols opt.ColSet,
   334  ) bool {
   335  	for i := range projections {
   336  		if projections[i].ScalarProps().OuterCols.Intersects(cols) {
   337  			return true
   338  		}
   339  	}
   340  	return false
   341  }
   342  
   343  // IsZipCorrelated returns true if any element in the zip references
   344  // any of the given columns.
   345  func (c *CustomFuncs) IsZipCorrelated(zip memo.ZipExpr, cols opt.ColSet) bool {
   346  	for i := range zip {
   347  		if zip[i].ScalarProps().OuterCols.Intersects(cols) {
   348  			return true
   349  		}
   350  	}
   351  	return false
   352  }
   353  
   354  // FilterOuterCols returns the union of all outer columns from the given filter
   355  // conditions.
   356  func (c *CustomFuncs) FilterOuterCols(filters memo.FiltersExpr) opt.ColSet {
   357  	var colSet opt.ColSet
   358  	for i := range filters {
   359  		colSet.UnionWith(filters[i].ScalarProps().OuterCols)
   360  	}
   361  	return colSet
   362  }
   363  
   364  // FiltersBoundBy returns true if all outer references in any of the filter
   365  // conditions are bound by the given columns. For example:
   366  //
   367  //   (InnerJoin
   368  //     (Scan a)
   369  //     (Scan b)
   370  //     $filters:[ (FiltersItem (Eq (Variable a.x) (Const 1))) ]
   371  //   )
   372  //
   373  // The $filters expression is fully bound by the output columns of the (Scan a)
   374  // expression because all of its outer references are satisfied by the columns
   375  // produced by the Scan.
   376  func (c *CustomFuncs) FiltersBoundBy(filters memo.FiltersExpr, cols opt.ColSet) bool {
   377  	for i := range filters {
   378  		if !filters[i].ScalarProps().OuterCols.SubsetOf(cols) {
   379  			return false
   380  		}
   381  	}
   382  	return true
   383  }
   384  
   385  // ProjectionOuterCols returns the union of all outer columns from the given
   386  // projection expressions.
   387  func (c *CustomFuncs) ProjectionOuterCols(projections memo.ProjectionsExpr) opt.ColSet {
   388  	var colSet opt.ColSet
   389  	for i := range projections {
   390  		colSet.UnionWith(projections[i].ScalarProps().OuterCols)
   391  	}
   392  	return colSet
   393  }
   394  
   395  // AggregationOuterCols returns the union of all outer columns from the given
   396  // aggregation expressions.
   397  func (c *CustomFuncs) AggregationOuterCols(aggregations memo.AggregationsExpr) opt.ColSet {
   398  	var colSet opt.ColSet
   399  	for i := range aggregations {
   400  		colSet.UnionWith(aggregations[i].ScalarProps().OuterCols)
   401  	}
   402  	return colSet
   403  }
   404  
   405  // ZipOuterCols returns the union of all outer columns from the given
   406  // zip expressions.
   407  func (c *CustomFuncs) ZipOuterCols(zip memo.ZipExpr) opt.ColSet {
   408  	var colSet opt.ColSet
   409  	for i := range zip {
   410  		colSet.UnionWith(zip[i].ScalarProps().OuterCols)
   411  	}
   412  	return colSet
   413  }
   414  
   415  // ----------------------------------------------------------------------
   416  //
   417  // Row functions
   418  //   General custom match and replace functions related to rows.
   419  //
   420  // ----------------------------------------------------------------------
   421  
   422  // HasZeroRows returns true if the input expression never returns any rows.
   423  func (c *CustomFuncs) HasZeroRows(input memo.RelExpr) bool {
   424  	return input.Relational().Cardinality.IsZero()
   425  }
   426  
   427  // HasOneRow returns true if the input expression always returns exactly one
   428  // row.
   429  func (c *CustomFuncs) HasOneRow(input memo.RelExpr) bool {
   430  	return input.Relational().Cardinality.IsOne()
   431  }
   432  
   433  // HasZeroOrOneRow returns true if the input expression returns at most one row.
   434  func (c *CustomFuncs) HasZeroOrOneRow(input memo.RelExpr) bool {
   435  	return input.Relational().Cardinality.IsZeroOrOne()
   436  }
   437  
   438  // CanHaveZeroRows returns true if the input expression might return zero rows.
   439  func (c *CustomFuncs) CanHaveZeroRows(input memo.RelExpr) bool {
   440  	return input.Relational().Cardinality.CanBeZero()
   441  }
   442  
   443  // ----------------------------------------------------------------------
   444  //
   445  // Key functions
   446  //   General custom match and replace functions related to keys.
   447  //
   448  // ----------------------------------------------------------------------
   449  
   450  // CandidateKey returns the candidate key columns from the given input
   451  // expression. If there is no candidate key, CandidateKey returns ok=false.
   452  func (c *CustomFuncs) CandidateKey(input memo.RelExpr) (key opt.ColSet, ok bool) {
   453  	return input.Relational().FuncDeps.StrictKey()
   454  }
   455  
   456  // HasStrictKey returns true if the input expression has one or more columns
   457  // that form a strict key (see comment for ColsAreStrictKey for definition).
   458  func (c *CustomFuncs) HasStrictKey(input memo.RelExpr) bool {
   459  	inputFDs := &input.Relational().FuncDeps
   460  	_, hasKey := inputFDs.StrictKey()
   461  	return hasKey
   462  }
   463  
   464  // ColsAreStrictKey returns true if the given columns form a strict key for the
   465  // given input expression. A strict key means that any two rows will have unique
   466  // key column values. Nulls are treated as equal to one another (i.e. no
   467  // duplicate nulls allowed). Having a strict key means that the set of key
   468  // column values uniquely determine the values of all other columns in the
   469  // relation.
   470  func (c *CustomFuncs) ColsAreStrictKey(cols opt.ColSet, input memo.RelExpr) bool {
   471  	return input.Relational().FuncDeps.ColsAreStrictKey(cols)
   472  }
   473  
   474  // PrimaryKeyCols returns the key columns of the primary key of the table.
   475  func (c *CustomFuncs) PrimaryKeyCols(table opt.TableID) opt.ColSet {
   476  	tabMeta := c.mem.Metadata().TableMeta(table)
   477  	return tabMeta.IndexKeyColumns(cat.PrimaryIndex)
   478  }
   479  
   480  // ----------------------------------------------------------------------
   481  //
   482  // Property functions
   483  //   General custom functions related to expression properties.
   484  //
   485  // ----------------------------------------------------------------------
   486  
   487  // ExprIsNeverNull returns true if we can prove that the given scalar expression
   488  // is always non-NULL. Any variables that refer to columns in the notNullCols
   489  // set are assumed to be non-NULL. See memo.ExprIsNeverNull.
   490  func (c *CustomFuncs) ExprIsNeverNull(e opt.ScalarExpr, notNullCols opt.ColSet) bool {
   491  	return memo.ExprIsNeverNull(e, notNullCols)
   492  }
   493  
   494  // sharedProps returns the shared logical properties for the given expression.
   495  // Only relational expressions and certain scalar list items (e.g. FiltersItem,
   496  // ProjectionsItem, AggregationsItem) have shared properties.
   497  func (c *CustomFuncs) sharedProps(e opt.Expr) *props.Shared {
   498  	switch t := e.(type) {
   499  	case memo.RelExpr:
   500  		return &t.Relational().Shared
   501  	case memo.ScalarPropsExpr:
   502  		return &t.ScalarProps().Shared
   503  	default:
   504  		var p props.Shared
   505  		memo.BuildSharedProps(e, &p)
   506  		return &p
   507  	}
   508  }
   509  
   510  // ----------------------------------------------------------------------
   511  //
   512  // Ordering functions
   513  //   General functions related to orderings.
   514  //
   515  // ----------------------------------------------------------------------
   516  
   517  // OrderingCanProjectCols returns true if the given OrderingChoice can be
   518  // expressed using only the given columns. Or in other words, at least one
   519  // column from every ordering group is a member of the given ColSet.
   520  func (c *CustomFuncs) OrderingCanProjectCols(
   521  	ordering physical.OrderingChoice, cols opt.ColSet,
   522  ) bool {
   523  	return ordering.CanProjectCols(cols)
   524  }
   525  
   526  // OrderingCols returns all non-optional columns that are part of the given
   527  // OrderingChoice.
   528  func (c *CustomFuncs) OrderingCols(ordering physical.OrderingChoice) opt.ColSet {
   529  	return ordering.ColSet()
   530  }
   531  
   532  // PruneOrdering removes any columns referenced by an OrderingChoice that are
   533  // not part of the needed column set. Should only be called if
   534  // OrderingCanProjectCols is true.
   535  func (c *CustomFuncs) PruneOrdering(
   536  	ordering physical.OrderingChoice, needed opt.ColSet,
   537  ) physical.OrderingChoice {
   538  	if ordering.SubsetOfCols(needed) {
   539  		return ordering
   540  	}
   541  	ordCopy := ordering.Copy()
   542  	ordCopy.ProjectCols(needed)
   543  	return ordCopy
   544  }
   545  
   546  // EmptyOrdering returns a pseudo-choice that does not require any
   547  // ordering.
   548  func (c *CustomFuncs) EmptyOrdering() physical.OrderingChoice {
   549  	return physical.OrderingChoice{}
   550  }
   551  
   552  // OrderingIntersects returns true if <ordering1> and <ordering2> have an
   553  // intersection. See OrderingChoice.Intersection for more information.
   554  func (c *CustomFuncs) OrderingIntersects(ordering1, ordering2 physical.OrderingChoice) bool {
   555  	return ordering1.Intersects(&ordering2)
   556  }
   557  
   558  // OrderingIntersection returns the intersection of two orderings. Should only be
   559  // called if it is known that an intersection exists.
   560  // See OrderingChoice.Intersection for more information.
   561  func (c *CustomFuncs) OrderingIntersection(
   562  	ordering1, ordering2 physical.OrderingChoice,
   563  ) physical.OrderingChoice {
   564  	return ordering1.Intersection(&ordering2)
   565  }
   566  
   567  // OrdinalityOrdering returns an ordinality operator's ordering choice.
   568  func (c *CustomFuncs) OrdinalityOrdering(private *memo.OrdinalityPrivate) physical.OrderingChoice {
   569  	return private.Ordering
   570  }
   571  
   572  // IsSameOrdering evaluates whether the two orderings are equal.
   573  func (c *CustomFuncs) IsSameOrdering(
   574  	first physical.OrderingChoice, other physical.OrderingChoice,
   575  ) bool {
   576  	return first.Equals(&other)
   577  }
   578  
   579  // -----------------------------------------------------------------------
   580  //
   581  // Filter functions
   582  //   General functions used to test and construct filters.
   583  //
   584  // -----------------------------------------------------------------------
   585  
   586  // FilterHasCorrelatedSubquery returns true if any of the filter conditions
   587  // contain a correlated subquery.
   588  func (c *CustomFuncs) FilterHasCorrelatedSubquery(filters memo.FiltersExpr) bool {
   589  	for i := range filters {
   590  		if filters[i].ScalarProps().HasCorrelatedSubquery {
   591  			return true
   592  		}
   593  	}
   594  	return false
   595  }
   596  
   597  // IsFilterFalse returns true if the filters always evaluate to false. The only
   598  // case that's checked is the fully normalized case, when the list contains a
   599  // single False condition.
   600  func (c *CustomFuncs) IsFilterFalse(filters memo.FiltersExpr) bool {
   601  	return filters.IsFalse()
   602  }
   603  
   604  // IsContradiction returns true if the given filter item contains a
   605  // contradiction constraint.
   606  func (c *CustomFuncs) IsContradiction(item *memo.FiltersItem) bool {
   607  	return item.ScalarProps().Constraints == constraint.Contradiction
   608  }
   609  
   610  // ConcatFilters creates a new Filters operator that contains conditions from
   611  // both the left and right boolean filter expressions.
   612  func (c *CustomFuncs) ConcatFilters(left, right memo.FiltersExpr) memo.FiltersExpr {
   613  	// No need to recompute properties on the new filters, since they should
   614  	// still be valid.
   615  	newFilters := make(memo.FiltersExpr, len(left)+len(right))
   616  	copy(newFilters, left)
   617  	copy(newFilters[len(left):], right)
   618  	return newFilters
   619  }
   620  
   621  // RemoveFiltersItem returns a new list that is a copy of the given list, except
   622  // that it does not contain the given search item. If the list contains the item
   623  // multiple times, then only the first instance is removed. If the list does not
   624  // contain the item, then the method panics.
   625  func (c *CustomFuncs) RemoveFiltersItem(
   626  	filters memo.FiltersExpr, search *memo.FiltersItem,
   627  ) memo.FiltersExpr {
   628  	newFilters := make(memo.FiltersExpr, len(filters)-1)
   629  	for i := range filters {
   630  		if search == &filters[i] {
   631  			copy(newFilters, filters[:i])
   632  			copy(newFilters[i:], filters[i+1:])
   633  			return newFilters
   634  		}
   635  	}
   636  	panic(errors.AssertionFailedf("item to remove is not in the list: %v", search))
   637  }
   638  
   639  // ReplaceFiltersItem returns a new list that is a copy of the given list,
   640  // except that the given search item has been replaced by the given replace
   641  // item. If the list contains the search item multiple times, then only the
   642  // first instance is replaced. If the list does not contain the item, then the
   643  // method panics.
   644  func (c *CustomFuncs) ReplaceFiltersItem(
   645  	filters memo.FiltersExpr, search *memo.FiltersItem, replace opt.ScalarExpr,
   646  ) memo.FiltersExpr {
   647  	newFilters := make([]memo.FiltersItem, len(filters))
   648  	for i := range filters {
   649  		if search == &filters[i] {
   650  			copy(newFilters, filters[:i])
   651  			newFilters[i] = c.f.ConstructFiltersItem(replace)
   652  			copy(newFilters[i+1:], filters[i+1:])
   653  			return newFilters
   654  		}
   655  	}
   656  	panic(errors.AssertionFailedf("item to replace is not in the list: %v", search))
   657  }
   658  
   659  // ExtractBoundConditions returns a new list containing only those expressions
   660  // from the given list that are fully bound by the given columns (i.e. all
   661  // outer references are to one of these columns). For example:
   662  //
   663  //   (InnerJoin
   664  //     (Scan a)
   665  //     (Scan b)
   666  //     (Filters [
   667  //       (Eq (Variable a.x) (Variable b.x))
   668  //       (Gt (Variable a.x) (Const 1))
   669  //     ])
   670  //   )
   671  //
   672  // Calling ExtractBoundConditions with the filter conditions list and the output
   673  // columns of (Scan a) would extract the (Gt) expression, since its outer
   674  // references only reference columns from a.
   675  func (c *CustomFuncs) ExtractBoundConditions(
   676  	filters memo.FiltersExpr, cols opt.ColSet,
   677  ) memo.FiltersExpr {
   678  	newFilters := make(memo.FiltersExpr, 0, len(filters))
   679  	for i := range filters {
   680  		if c.IsBoundBy(&filters[i], cols) {
   681  			newFilters = append(newFilters, filters[i])
   682  		}
   683  	}
   684  	return newFilters
   685  }
   686  
   687  // ExtractUnboundConditions is the opposite of ExtractBoundConditions. Instead of
   688  // extracting expressions that are bound by the given columns, it extracts
   689  // list expressions that have at least one outer reference that is *not* bound
   690  // by the given columns (i.e. it has a "free" variable).
   691  func (c *CustomFuncs) ExtractUnboundConditions(
   692  	filters memo.FiltersExpr, cols opt.ColSet,
   693  ) memo.FiltersExpr {
   694  	newFilters := make(memo.FiltersExpr, 0, len(filters))
   695  	for i := range filters {
   696  		if !c.IsBoundBy(&filters[i], cols) {
   697  			newFilters = append(newFilters, filters[i])
   698  		}
   699  	}
   700  	return newFilters
   701  }
   702  
   703  // ----------------------------------------------------------------------
   704  //
   705  // Project functions
   706  //   General functions related to Project operators.
   707  //
   708  // ----------------------------------------------------------------------
   709  
   710  // ProjectionCols returns the ids of the columns synthesized by the given
   711  // Projections operator.
   712  func (c *CustomFuncs) ProjectionCols(projections memo.ProjectionsExpr) opt.ColSet {
   713  	var colSet opt.ColSet
   714  	for i := range projections {
   715  		colSet.Add(projections[i].Col)
   716  	}
   717  	return colSet
   718  }
   719  
   720  // ProjectExtraCol constructs a new Project operator that passes through all
   721  // columns in the given "in" expression, and then adds the given "extra"
   722  // expression as an additional column.
   723  func (c *CustomFuncs) ProjectExtraCol(
   724  	in memo.RelExpr, extra opt.ScalarExpr, extraID opt.ColumnID,
   725  ) memo.RelExpr {
   726  	projections := memo.ProjectionsExpr{c.f.ConstructProjectionsItem(extra, extraID)}
   727  	return c.f.ConstructProject(in, projections, in.Relational().OutputCols)
   728  }
   729  
   730  // ----------------------------------------------------------------------
   731  //
   732  // Values functions
   733  //   General functions related to Values operators.
   734  //
   735  // ----------------------------------------------------------------------
   736  
   737  // ValuesCols returns the Cols field of the ValuesPrivate struct.
   738  func (c *CustomFuncs) ValuesCols(valuesPrivate *memo.ValuesPrivate) opt.ColList {
   739  	return valuesPrivate.Cols
   740  }
   741  
   742  // ConstructEmptyValues constructs a Values expression with no rows.
   743  func (c *CustomFuncs) ConstructEmptyValues(cols opt.ColSet) memo.RelExpr {
   744  	colList := make(opt.ColList, 0, cols.Len())
   745  	for i, ok := cols.Next(0); ok; i, ok = cols.Next(i + 1) {
   746  		colList = append(colList, i)
   747  	}
   748  	return c.f.ConstructValues(memo.EmptyScalarListExpr, &memo.ValuesPrivate{
   749  		Cols: colList,
   750  		ID:   c.mem.Metadata().NextUniqueID(),
   751  	})
   752  }
   753  
   754  // ----------------------------------------------------------------------
   755  //
   756  // Grouping functions
   757  //   General functions related to grouping expressions such as GroupBy,
   758  //   DistinctOn, etc.
   759  //
   760  // ----------------------------------------------------------------------
   761  
   762  // GroupingOutputCols returns the output columns of a GroupBy, ScalarGroupBy, or
   763  // DistinctOn expression.
   764  func (c *CustomFuncs) GroupingOutputCols(
   765  	grouping *memo.GroupingPrivate, aggs memo.AggregationsExpr,
   766  ) opt.ColSet {
   767  	result := grouping.GroupingCols.Copy()
   768  	for i := range aggs {
   769  		result.Add(aggs[i].Col)
   770  	}
   771  	return result
   772  }
   773  
   774  // GroupingCols returns the grouping columns from the given grouping private.
   775  func (c *CustomFuncs) GroupingCols(grouping *memo.GroupingPrivate) opt.ColSet {
   776  	return grouping.GroupingCols
   777  }
   778  
   779  // AddColsToGrouping returns a new GroupByDef that is a copy of the given
   780  // GroupingPrivate, except with the given set of grouping columns union'ed with
   781  // the existing grouping columns.
   782  func (c *CustomFuncs) AddColsToGrouping(
   783  	private *memo.GroupingPrivate, groupingCols opt.ColSet,
   784  ) *memo.GroupingPrivate {
   785  	p := *private
   786  	p.GroupingCols = private.GroupingCols.Union(groupingCols)
   787  	return &p
   788  }
   789  
   790  // ExtractAggInputColumns returns the set of columns the aggregate depends on.
   791  func (c *CustomFuncs) ExtractAggInputColumns(e opt.ScalarExpr) opt.ColSet {
   792  	return memo.ExtractAggInputColumns(e)
   793  }
   794  
   795  // IsUnorderedGrouping returns true if the given grouping ordering is not
   796  // specified.
   797  func (c *CustomFuncs) IsUnorderedGrouping(grouping *memo.GroupingPrivate) bool {
   798  	return grouping.Ordering.Any()
   799  }
   800  
   801  // MakeGrouping constructs a new GroupingPrivate using the given grouping
   802  // columns and OrderingChoice. ErrorOnDup will be empty and NullsAreDistinct
   803  // will be false.
   804  func (c *CustomFuncs) MakeGrouping(
   805  	groupingCols opt.ColSet, ordering physical.OrderingChoice,
   806  ) *memo.GroupingPrivate {
   807  	return &memo.GroupingPrivate{GroupingCols: groupingCols, Ordering: ordering}
   808  }
   809  
   810  // MakeErrorOnDupGrouping constructs a new GroupingPrivate using the given
   811  // grouping columns, OrderingChoice, and ErrorOnDup text. NullsAreDistinct will
   812  // be false.
   813  func (c *CustomFuncs) MakeErrorOnDupGrouping(
   814  	groupingCols opt.ColSet, ordering physical.OrderingChoice, errorText string,
   815  ) *memo.GroupingPrivate {
   816  	return &memo.GroupingPrivate{
   817  		GroupingCols: groupingCols, Ordering: ordering, ErrorOnDup: errorText,
   818  	}
   819  }
   820  
   821  // NullsAreDistinct returns true if a distinct operator with the given
   822  // GroupingPrivate treats NULL values as not equal to one another
   823  // (i.e. distinct). UpsertDistinctOp and EnsureUpsertDistinctOp treat NULL
   824  // values as distinct, whereas DistinctOp does not.
   825  func (c *CustomFuncs) NullsAreDistinct(private *memo.GroupingPrivate) bool {
   826  	return private.NullsAreDistinct
   827  }
   828  
   829  // ErrorOnDup returns the error text contained by the given GroupingPrivate.
   830  func (c *CustomFuncs) ErrorOnDup(private *memo.GroupingPrivate) string {
   831  	return private.ErrorOnDup
   832  }
   833  
   834  // ExtractGroupingOrdering returns the ordering associated with the input
   835  // GroupingPrivate.
   836  func (c *CustomFuncs) ExtractGroupingOrdering(
   837  	private *memo.GroupingPrivate,
   838  ) physical.OrderingChoice {
   839  	return private.Ordering
   840  }
   841  
   842  // ----------------------------------------------------------------------
   843  //
   844  // Join functions
   845  //   General functions related to join operators.
   846  //
   847  // ----------------------------------------------------------------------
   848  
   849  // JoinDoesNotDuplicateLeftRows returns true if the given InnerJoin, LeftJoin or
   850  // FullJoin is guaranteed not to output any given row from its left input more
   851  // than once.
   852  func (c *CustomFuncs) JoinDoesNotDuplicateLeftRows(join memo.RelExpr) bool {
   853  	mult := memo.DeriveJoinMultiplicity(join)
   854  	return mult.JoinDoesNotDuplicateLeftRows()
   855  }
   856  
   857  // JoinDoesNotDuplicateRightRows returns true if the given InnerJoin, LeftJoin
   858  // or FullJoin is guaranteed not to output any given row from its right input
   859  // more than once.
   860  func (c *CustomFuncs) JoinDoesNotDuplicateRightRows(join memo.RelExpr) bool {
   861  	mult := memo.DeriveJoinMultiplicity(join)
   862  	return mult.JoinDoesNotDuplicateRightRows()
   863  }
   864  
   865  // JoinPreservesLeftRows returns true if the given InnerJoin, LeftJoin or
   866  // FullJoin is guaranteed to output every row from its left input at least once.
   867  func (c *CustomFuncs) JoinPreservesLeftRows(join memo.RelExpr) bool {
   868  	mult := memo.DeriveJoinMultiplicity(join)
   869  	return mult.JoinPreservesLeftRows()
   870  }
   871  
   872  // JoinPreservesRightRows returns true if the given InnerJoin, LeftJoin or
   873  // FullJoin is guaranteed to output every row from its right input at least
   874  // once.
   875  func (c *CustomFuncs) JoinPreservesRightRows(join memo.RelExpr) bool {
   876  	mult := memo.DeriveJoinMultiplicity(join)
   877  	return mult.JoinPreservesRightRows()
   878  }
   879  
   880  // ----------------------------------------------------------------------
   881  //
   882  // Constant value functions
   883  //   General functions related to constant values and datums.
   884  //
   885  // ----------------------------------------------------------------------
   886  
   887  // IsPositiveInt is true if the given Datum value is greater than zero.
   888  func (c *CustomFuncs) IsPositiveInt(datum tree.Datum) bool {
   889  	val := int64(*datum.(*tree.DInt))
   890  	return val > 0
   891  }
   892  
   893  // EqualsString returns true if the given strings are equal. This function is
   894  // useful in matching expressions that have string fields.
   895  //
   896  // For example, NormalizeCmpTimeZoneFunction uses this function implicitly to
   897  // match a specific function, like so:
   898  //
   899  //   (Function $args:* (FunctionPrivate "timezone"))
   900  //
   901  func (c *CustomFuncs) EqualsString(left string, right string) bool {
   902  	return left == right
   903  }
   904  
   905  // EqualsNumber returns true if the given numeric value (decimal, float, or
   906  // integer) is equal to the given integer value.
   907  func (c *CustomFuncs) EqualsNumber(datum tree.Datum, value int64) bool {
   908  	switch t := datum.(type) {
   909  	case *tree.DDecimal:
   910  		if value == 0 {
   911  			return t.Decimal.IsZero()
   912  		} else if value == 1 {
   913  			return t.Decimal.Cmp(&tree.DecimalOne.Decimal) == 0
   914  		}
   915  		var dec apd.Decimal
   916  		dec.SetInt64(value)
   917  		return t.Decimal.Cmp(&dec) == 0
   918  
   919  	case *tree.DFloat:
   920  		return *t == tree.DFloat(value)
   921  
   922  	case *tree.DInt:
   923  		return *t == tree.DInt(value)
   924  	}
   925  	return false
   926  }
   927  
   928  // AddConstInts adds the numeric constants together and constructs a Const.
   929  // AddConstInts assumes the sum will not overflow. Call CanAddConstInts on the
   930  // constants to guarantee this.
   931  func (c *CustomFuncs) AddConstInts(first tree.Datum, second tree.Datum) opt.ScalarExpr {
   932  	firstVal := int64(*first.(*tree.DInt))
   933  	secondVal := int64(*second.(*tree.DInt))
   934  	sum, ok := arith.AddWithOverflow(firstVal, secondVal)
   935  	if !ok {
   936  		panic(errors.AssertionFailedf("addition of %d and %d overflowed", firstVal, secondVal))
   937  	}
   938  	return c.f.ConstructConst(tree.NewDInt(tree.DInt(sum)), types.Int)
   939  }
   940  
   941  // CanAddConstInts returns true if the addition of the two integers overflows.
   942  func (c *CustomFuncs) CanAddConstInts(first tree.Datum, second tree.Datum) bool {
   943  	firstVal := int64(*first.(*tree.DInt))
   944  	secondVal := int64(*second.(*tree.DInt))
   945  	_, ok := arith.AddWithOverflow(firstVal, secondVal)
   946  	return ok
   947  }
   948  
   949  // IntConst constructs a Const holding a DInt.
   950  func (c *CustomFuncs) IntConst(d *tree.DInt) opt.ScalarExpr {
   951  	return c.f.ConstructConst(d, types.Int)
   952  }