github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/props/cardinality.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 props
    12  
    13  import (
    14  	"fmt"
    15  	"math"
    16  )
    17  
    18  // ZeroCardinality indicates that no rows will be returned by expression.
    19  var ZeroCardinality = Cardinality{}
    20  
    21  // OneCardinality indicates that exactly one row will be returned by expression.
    22  var OneCardinality = Cardinality{Min: 1, Max: 1}
    23  
    24  // AnyCardinality indicates that any number of rows can be returned by an
    25  // expression.
    26  var AnyCardinality = Cardinality{Min: 0, Max: math.MaxUint32}
    27  
    28  // Cardinality is the number of rows that can be returned by a relational
    29  // expression. Both Min and Max are inclusive bounds. If Max = math.MaxUint32,
    30  // that indicates there is no limit to the number of returned rows. Max should
    31  // always be >= Min, or method results are undefined. Cardinality is determined
    32  // from the relational properties, and are "hard" bounds that are never
    33  // incorrect. This constrasts with row cardinality derived by the statistics
    34  // code, which are only estimates and may be incorrect.
    35  type Cardinality struct {
    36  	Min uint32
    37  	Max uint32
    38  }
    39  
    40  // IsZero returns true if the expression never returns any rows.
    41  func (c Cardinality) IsZero() bool {
    42  	return c.Min == 0 && c.Max == 0
    43  }
    44  
    45  // IsOne returns true if the expression always returns one row.
    46  func (c Cardinality) IsOne() bool {
    47  	return c.Min == 1 && c.Max == 1
    48  }
    49  
    50  // IsZeroOrOne is true if the expression never returns more than one row.
    51  func (c Cardinality) IsZeroOrOne() bool {
    52  	return c.Max <= 1
    53  }
    54  
    55  // CanBeZero is true if the expression can return zero rows.
    56  func (c Cardinality) CanBeZero() bool {
    57  	return c.Min == 0
    58  }
    59  
    60  // AsLowAs ratchets the min bound downwards in order to ensure that it allows
    61  // values that are >= the min value.
    62  func (c Cardinality) AsLowAs(min uint32) Cardinality {
    63  	return Cardinality{
    64  		Min: minVal(c.Min, min),
    65  		Max: c.Max,
    66  	}
    67  }
    68  
    69  // Limit ratchets the bounds downwards so that they're no bigger than the given
    70  // max value.
    71  func (c Cardinality) Limit(max uint32) Cardinality {
    72  	return Cardinality{
    73  		Min: minVal(c.Min, max),
    74  		Max: minVal(c.Max, max),
    75  	}
    76  }
    77  
    78  // AtLeast ratchets the bounds upwards so that they're at least as large as the
    79  // bounds in the given cardinality.
    80  func (c Cardinality) AtLeast(other Cardinality) Cardinality {
    81  	return Cardinality{
    82  		Min: maxVal(c.Min, other.Min),
    83  		Max: maxVal(c.Max, other.Max),
    84  	}
    85  }
    86  
    87  // Add sums the min and max bounds to get a combined count of rows.
    88  func (c Cardinality) Add(other Cardinality) Cardinality {
    89  	// Make sure to detect overflow.
    90  	min := c.Min + other.Min
    91  	if min < c.Min {
    92  		min = math.MaxUint32
    93  	}
    94  	max := c.Max + other.Max
    95  	if max < c.Max {
    96  		max = math.MaxUint32
    97  	}
    98  	return Cardinality{Min: min, Max: max}
    99  }
   100  
   101  // Product multiples the min and max bounds to get the combined product of rows.
   102  func (c Cardinality) Product(other Cardinality) Cardinality {
   103  	// Prevent overflow by using 64-bit multiplication.
   104  	min := uint64(c.Min) * uint64(other.Min)
   105  	if min > math.MaxUint32 {
   106  		min = math.MaxUint32
   107  	}
   108  	max := uint64(c.Max) * uint64(other.Max)
   109  	if max > math.MaxUint32 {
   110  		max = math.MaxUint32
   111  	}
   112  	return Cardinality{Min: uint32(min), Max: uint32(max)}
   113  }
   114  
   115  // Skip subtracts the given number of rows from the min and max bounds to
   116  // account for skipped rows.
   117  func (c Cardinality) Skip(rows uint32) Cardinality {
   118  	min := c.Min - rows
   119  	if min > c.Min {
   120  		min = 0
   121  	}
   122  	if c.Max == math.MaxUint32 {
   123  		// No upper bound, so treat it as if it's infinity.
   124  		return Cardinality{Min: min, Max: c.Max}
   125  	}
   126  	max := c.Max - rows
   127  	if max > c.Max {
   128  		max = 0
   129  	}
   130  	return Cardinality{Min: min, Max: max}
   131  }
   132  
   133  func (c Cardinality) String() string {
   134  	if c.Max == math.MaxUint32 {
   135  		return fmt.Sprintf("[%d - ]", c.Min)
   136  	}
   137  	return fmt.Sprintf("[%d - %d]", c.Min, c.Max)
   138  }
   139  
   140  func minVal(a, b uint32) uint32 {
   141  	if a <= b {
   142  		return a
   143  	}
   144  	return b
   145  }
   146  
   147  func maxVal(a, b uint32) uint32 {
   148  	if a >= b {
   149  		return a
   150  	}
   151  	return b
   152  }