github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/cat/index.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 cat
    12  
    13  import (
    14  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    15  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    16  )
    17  
    18  // IndexOrdinal identifies an index (in the context of a Table).
    19  type IndexOrdinal = int
    20  
    21  // PrimaryIndex selects the primary index of a table when calling the
    22  // Table.Index method. Every table is guaranteed to have a unique primary
    23  // index, even if it meant adding a hidden unique rowid column.
    24  const PrimaryIndex IndexOrdinal = 0
    25  
    26  // Index is an interface to a database index, exposing only the information
    27  // needed by the query optimizer. Every index is treated as unique by the
    28  // optimizer. If an index was declared as non-unique, then the system will add
    29  // implicit columns from the primary key in order to make it unique (and even
    30  // add an implicit primary key based on a hidden rowid column if a primary key
    31  // was not explicitly declared).
    32  type Index interface {
    33  	// ID is the stable identifier for this index that is guaranteed to be
    34  	// unique within the owning table. See the comment for StableID for more
    35  	// detail.
    36  	ID() StableID
    37  
    38  	// Name is the name of the index.
    39  	Name() tree.Name
    40  
    41  	// Table returns a reference to the table this index is based on.
    42  	Table() Table
    43  
    44  	// Ordinal returns the ordinal of this index within the context of its Table.
    45  	// Specifically idx = Table().Index(idx.Ordinal).
    46  	Ordinal() int
    47  
    48  	// IsUnique returns true if this index is declared as UNIQUE in the schema.
    49  	IsUnique() bool
    50  
    51  	// IsInverted returns true if this is an inverted index.
    52  	IsInverted() bool
    53  
    54  	// ColumnCount returns the number of columns in the index. This includes
    55  	// columns that were part of the index definition (including the STORING
    56  	// clause), as well as implicitly added primary key columns.
    57  	ColumnCount() int
    58  
    59  	// Predicate returns the partial index predicate expression and true if the
    60  	// index is a partial index. If it is not a partial index, the empty string
    61  	// and false are returned.
    62  	Predicate() (string, bool)
    63  
    64  	// KeyColumnCount returns the number of columns in the index that are part
    65  	// of its unique key. No two rows in the index will have the same values for
    66  	// those columns (where NULL values are treated as equal). Every index has a
    67  	// set of key columns, regardless of how it was defined, because Cockroach
    68  	// will implicitly add primary key columns to any index which would not
    69  	// otherwise have a key, like when:
    70  	//
    71  	//   1. Index was not declared as UNIQUE.
    72  	//   2. Index was UNIQUE, but one or more columns have NULL values.
    73  	//
    74  	// The second case is subtle, because UNIQUE indexes treat NULL values as if
    75  	// they are *not* equal to one another. For example, this is allowed with a
    76  	// unique (b, c) index, even though it appears there are duplicate rows:
    77  	//
    78  	//   b     c
    79  	//   -------
    80  	//   NULL  1
    81  	//   NULL  1
    82  	//
    83  	// Since keys treat NULL values as if they *are* equal to each other,
    84  	// Cockroach must append the primary key columns in order to ensure this
    85  	// index has a key. If the primary key of this table was column (a), then
    86  	// the key of this secondary index would be (b,c,a).
    87  	//
    88  	// The key columns are always a prefix of the full column list, where
    89  	// KeyColumnCount <= ColumnCount.
    90  	KeyColumnCount() int
    91  
    92  	// LaxKeyColumnCount returns the number of columns in the index that are
    93  	// part of its "lax" key. Lax keys follow the same rules as keys (sometimes
    94  	// referred to as "strict" keys), except that NULL values are treated as
    95  	// *not* equal to one another, as in the case for UNIQUE indexes. This means
    96  	// that two rows can appear to have duplicate values when one of those values
    97  	// is NULL. See the KeyColumnCount comment for more details and an example.
    98  	//
    99  	// The lax key columns are always a prefix of the key columns, where
   100  	// LaxKeyColumnCount <= KeyColumnCount. However, it is not required that an
   101  	// index have a separate lax key, in which case LaxKeyColumnCount equals
   102  	// KeyColumnCount. Here are the cases:
   103  	//
   104  	//   PRIMARY KEY                : lax key cols = key cols
   105  	//   INDEX (not unique)         : lax key cols = key cols
   106  	//   UNIQUE INDEX, not-null cols: lax key cols = key cols
   107  	//   UNIQUE INDEX, nullable cols: lax key cols < key cols
   108  	//
   109  	// In the first three cases, all strict key columns (and thus all lax key
   110  	// columns as well) are guaranteed to be encoded in the row's key (as opposed
   111  	// to in its value). Note that the third case, the UNIQUE INDEX columns are
   112  	// sufficient to form a strict key without needing to append the primary key
   113  	// columns (which are stored in the value).
   114  	//
   115  	// For the last case of a UNIQUE INDEX with at least one NULL-able column,
   116  	// only the lax key columns are guaranteed to be encoded in the row's key.
   117  	// The strict key columns (the primary key columns in this case) are only
   118  	// encoded in the row's key when at least one of the lax key columns has a
   119  	// NULL value. Therefore, whether the row's key contains all the strict key
   120  	// columns is data-dependent, not schema-dependent.
   121  	LaxKeyColumnCount() int
   122  
   123  	// Column returns the ith IndexColumn within the index definition, where
   124  	// i < ColumnCount.
   125  	Column(i int) IndexColumn
   126  
   127  	// Zone returns the zone which constrains placement of the index's range
   128  	// replicas. If the index was not explicitly assigned to a zone, then it
   129  	// inherits the zone of its owning table (which in turn inherits from its
   130  	// owning database or the default zone). In addition, any unspecified zone
   131  	// information will also be inherited.
   132  	//
   133  	// NOTE: This zone always applies to the entire index and never to any
   134  	// particular partition of the index.
   135  	Zone() Zone
   136  
   137  	// Span returns the KV span associated with the index.
   138  	Span() roachpb.Span
   139  
   140  	// PartitionByListPrefixes returns values that correspond to PARTITION BY LIST
   141  	// values. Specifically, it returns a list of tuples where each tuple contains
   142  	// values for a prefix of index columns (indicating a region of the index).
   143  	// Each tuple corresponds to a configured partition or subpartition.
   144  	//
   145  	// Note: this function decodes and allocates datums; use sparingly.
   146  	//
   147  	// Example:
   148  	//
   149  	// CREATE INDEX idx ON t(region,subregion,val) PARTITION BY LIST (region,subregion) (
   150  	//     PARTITION westcoast VALUES IN (('us', 'seattle'), ('us', 'cali')),
   151  	//     PARTITION us VALUES IN (('us', DEFAULT)),
   152  	//     PARTITION eu VALUES IN (('eu', DEFAULT)),
   153  	//     PARTITION default VALUES IN (DEFAULT)
   154  	// );
   155  	//
   156  	// PartitionByListPrefixes() returns
   157  	//  ('us', 'seattle'),
   158  	//  ('us', 'cali'),
   159  	//  ('us'),
   160  	//  ('eu').
   161  	//
   162  	// The intended use of this function is for index skip scans. Each tuple
   163  	// corresponds to a region of the index that we can constrain further. In the
   164  	// example above: if we have a val=1 filter, instead of a full index scan we
   165  	// can skip most of the data under /us/cali and /us/seattle by scanning spans:
   166  	//   [                 - /us/cali      )
   167  	//   [ /us/cali/1      - /us/cali/1    ]
   168  	//   [ /us/cali\x00    - /us/seattle   )
   169  	//   [ /us/seattle/1   - /us/seattle/1 ]
   170  	//   [ /us/seattle\x00 -               ]
   171  	//
   172  	PartitionByListPrefixes() []tree.Datums
   173  
   174  	// InterleaveAncestorCount returns the number of interleave ancestors for this
   175  	// index (or zero if this is not an interleaved index). Each ancestor is an
   176  	// index (usually from another table) with a key that shares a prefix with
   177  	// the key of this index.
   178  	//
   179  	// Each ancestor contributes one or more key columns; together these pieces
   180  	// form a prefix of an index key.
   181  	//
   182  	// The ancestors appear in the order they appear in an encoded key. This means
   183  	// they are always in the far-to-near ancestor order (e.g.
   184  	// grand-grand-parent, grand-parent, parent).
   185  	//
   186  	//
   187  	// Example:
   188  	//   Index 1 -> /a/b
   189  	//   Index 2 -> /a/b/c
   190  	//   Index 3 -> /a/b/c/d
   191  	//
   192  	// Index 3 has two ancestors; the first is index 1 (contributing 2 key
   193  	// columns) and the second is index 2 (contributing 1 key column).
   194  	InterleaveAncestorCount() int
   195  
   196  	// InterleaveAncestor returns information about an ancestor index.
   197  	//
   198  	// numKeyCols is the number of key columns that this ancestor contributes to
   199  	// an encoded key. In other words: each ancestor has a shared key prefix
   200  	// with this index; numKeyCols is the difference the shared prefix length for
   201  	// this ancestor and the shared prefix length for the previous ancestor.
   202  	// See InterleaveAncestorCount for an example.
   203  	InterleaveAncestor(i int) (table, index StableID, numKeyCols int)
   204  
   205  	// InterleavedByCount returns the number of indexes (usually from other
   206  	// tables) that are interleaved into this index.
   207  	//
   208  	// Note that these indexes can themselves be interleaved by other indexes, but
   209  	// this list contains only those for which this index is a direct interleave
   210  	// parent.
   211  	InterleavedByCount() int
   212  
   213  	// InterleavedBy returns information about an index that is interleaved into
   214  	// this index; see InterleavedByCount.
   215  	InterleavedBy(i int) (table, index StableID)
   216  }
   217  
   218  // IndexColumn describes a single column that is part of an index definition.
   219  type IndexColumn struct {
   220  	// Column is a reference to the column returned by Table.Column, given the
   221  	// column ordinal.
   222  	Column
   223  
   224  	// Ordinal is the ordinal position of the indexed column in the table being
   225  	// indexed. It is always >= 0 and < Table.ColumnCount.
   226  	Ordinal int
   227  
   228  	// Descending is true if the index is ordered from greatest to least on
   229  	// this column, rather than least to greatest.
   230  	Descending bool
   231  }
   232  
   233  // IsMutationIndex is a convenience function that returns true if the index at
   234  // the given ordinal position is a mutation index.
   235  func IsMutationIndex(table Table, ord IndexOrdinal) bool {
   236  	return ord >= table.IndexCount()
   237  }