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

     1  // Copyright 2015 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 sqlbase
    12  
    13  import (
    14  	"strings"
    15  
    16  	"github.com/cockroachdb/cockroach/pkg/keys"
    17  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    18  	"github.com/cockroachdb/cockroach/pkg/util/encoding"
    19  	"github.com/cockroachdb/errors"
    20  )
    21  
    22  const (
    23  	// DefaultDatabaseName is the name ofthe default CockroachDB database used
    24  	// for connections without a current db set.
    25  	DefaultDatabaseName = "defaultdb"
    26  
    27  	// PgDatabaseName is the name of the default postgres system database.
    28  	PgDatabaseName = "postgres"
    29  )
    30  
    31  // DefaultUserDBs is a set of the databases which are present in a new cluster.
    32  var DefaultUserDBs = map[string]struct{}{
    33  	DefaultDatabaseName: {},
    34  	PgDatabaseName:      {},
    35  }
    36  
    37  // MaxDefaultDescriptorID is the maximum ID of a descriptor that exists in a
    38  // new cluster.
    39  var MaxDefaultDescriptorID = keys.MaxReservedDescID + ID(len(DefaultUserDBs))
    40  
    41  // IsDefaultCreatedDescriptor returns whether or not a given descriptor ID is
    42  // present at the time of starting a cluster.
    43  func IsDefaultCreatedDescriptor(descID ID) bool {
    44  	return descID <= MaxDefaultDescriptorID
    45  }
    46  
    47  // MakeNameMetadataKey returns the key for the name, as expected by
    48  // versions >= 20.1.
    49  // Pass name == "" in order to generate the prefix key to use to scan over all
    50  // of the names for the specified parentID.
    51  func MakeNameMetadataKey(
    52  	codec keys.SQLCodec, parentID ID, parentSchemaID ID, name string,
    53  ) roachpb.Key {
    54  	k := codec.IndexPrefix(uint32(NamespaceTable.ID), uint32(NamespaceTable.PrimaryIndex.ID))
    55  	k = encoding.EncodeUvarintAscending(k, uint64(parentID))
    56  	k = encoding.EncodeUvarintAscending(k, uint64(parentSchemaID))
    57  	if name != "" {
    58  		k = encoding.EncodeBytesAscending(k, []byte(name))
    59  		k = keys.MakeFamilyKey(k, uint32(NamespaceTable.Columns[3].ID))
    60  	}
    61  	return k
    62  }
    63  
    64  // DecodeNameMetadataKey returns the components that make up the
    65  // NameMetadataKey for version >= 20.1.
    66  func DecodeNameMetadataKey(
    67  	codec keys.SQLCodec, k roachpb.Key,
    68  ) (parentID ID, parentSchemaID ID, name string, err error) {
    69  	k, _, err = codec.DecodeTablePrefix(k)
    70  	if err != nil {
    71  		return 0, 0, "", err
    72  	}
    73  
    74  	var buf uint64
    75  	k, buf, err = encoding.DecodeUvarintAscending(k)
    76  	if err != nil {
    77  		return 0, 0, "", err
    78  	}
    79  	if buf != uint64(NamespaceTable.PrimaryIndex.ID) {
    80  		return 0, 0, "", errors.Newf("tried get table %d, but got %d", NamespaceTable.PrimaryIndex.ID, buf)
    81  	}
    82  
    83  	k, buf, err = encoding.DecodeUvarintAscending(k)
    84  	if err != nil {
    85  		return 0, 0, "", err
    86  	}
    87  	parentID = ID(buf)
    88  
    89  	k, buf, err = encoding.DecodeUvarintAscending(k)
    90  	if err != nil {
    91  		return 0, 0, "", err
    92  	}
    93  	parentSchemaID = ID(buf)
    94  
    95  	var bytesBuf []byte
    96  	_, bytesBuf, err = encoding.DecodeBytesAscending(k, nil)
    97  	if err != nil {
    98  		return 0, 0, "", err
    99  	}
   100  	name = string(bytesBuf)
   101  
   102  	return parentID, parentSchemaID, name, nil
   103  }
   104  
   105  // MakeDeprecatedNameMetadataKey returns the key for a name, as expected by
   106  // versions < 20.1. Pass name == "" in order to generate the prefix key to use
   107  // to scan over all of the names for the specified parentID.
   108  func MakeDeprecatedNameMetadataKey(codec keys.SQLCodec, parentID ID, name string) roachpb.Key {
   109  	k := codec.IndexPrefix(
   110  		uint32(DeprecatedNamespaceTable.ID), uint32(DeprecatedNamespaceTable.PrimaryIndex.ID))
   111  	k = encoding.EncodeUvarintAscending(k, uint64(parentID))
   112  	if name != "" {
   113  		k = encoding.EncodeBytesAscending(k, []byte(name))
   114  		k = keys.MakeFamilyKey(k, uint32(DeprecatedNamespaceTable.Columns[2].ID))
   115  	}
   116  	return k
   117  }
   118  
   119  // MakeAllDescsMetadataKey returns the key for all descriptors.
   120  func MakeAllDescsMetadataKey(codec keys.SQLCodec) roachpb.Key {
   121  	return codec.DescMetadataPrefix()
   122  }
   123  
   124  // MakeDescMetadataKey returns the key for the descriptor.
   125  func MakeDescMetadataKey(codec keys.SQLCodec, descID ID) roachpb.Key {
   126  	return codec.DescMetadataKey(uint32(descID))
   127  }
   128  
   129  // IndexKeyValDirs returns the corresponding encoding.Directions for all the
   130  // encoded values in index's "fullest" possible index key, including directions
   131  // for table/index IDs, the interleaved sentinel and the index column values.
   132  // For example, given
   133  //    CREATE INDEX foo ON bar (a, b DESC) INTERLEAVED IN PARENT bar (a)
   134  // a typical index key with all values specified could be
   135  //    /51/1/42/#/51/2/1337
   136  // which would return the slice
   137  //    {ASC, ASC, ASC, 0, ASC, ASC, DESC}
   138  func IndexKeyValDirs(index *IndexDescriptor) []encoding.Direction {
   139  	if index == nil {
   140  		return nil
   141  	}
   142  
   143  	dirs := make([]encoding.Direction, 0, (len(index.Interleave.Ancestors)+1)*2+len(index.ColumnDirections))
   144  
   145  	colIdx := 0
   146  	for _, ancs := range index.Interleave.Ancestors {
   147  		// Table/Index IDs are always encoded ascending.
   148  		dirs = append(dirs, encoding.Ascending, encoding.Ascending)
   149  		for i := 0; i < int(ancs.SharedPrefixLen); i++ {
   150  			d, err := index.ColumnDirections[colIdx].ToEncodingDirection()
   151  			if err != nil {
   152  				panic(err)
   153  			}
   154  			dirs = append(dirs, d)
   155  			colIdx++
   156  		}
   157  
   158  		// The interleaved sentinel uses the 0 value for
   159  		// encoding.Direction when pretty-printing (see
   160  		// encoding.go:prettyPrintFirstValue).
   161  		dirs = append(dirs, 0)
   162  	}
   163  
   164  	// The index's table/index ID.
   165  	dirs = append(dirs, encoding.Ascending, encoding.Ascending)
   166  
   167  	for colIdx < len(index.ColumnDirections) {
   168  		d, err := index.ColumnDirections[colIdx].ToEncodingDirection()
   169  		if err != nil {
   170  			panic(err)
   171  		}
   172  		dirs = append(dirs, d)
   173  		colIdx++
   174  	}
   175  
   176  	return dirs
   177  }
   178  
   179  // PrettyKey pretty-prints the specified key, skipping over the first `skip`
   180  // fields. The pretty printed key looks like:
   181  //
   182  //   /Table/<tableID>/<indexID>/...
   183  //
   184  // We always strip off the /Table prefix and then `skip` more fields. Note that
   185  // this assumes that the fields themselves do not contain '/', but that is
   186  // currently true for the fields we care about stripping (the table and index
   187  // ID).
   188  func PrettyKey(valDirs []encoding.Direction, key roachpb.Key, skip int) string {
   189  	p := key.StringWithDirs(valDirs, 0 /* maxLen */)
   190  	for i := 0; i <= skip; i++ {
   191  		n := strings.IndexByte(p[1:], '/')
   192  		if n == -1 {
   193  			return ""
   194  		}
   195  		p = p[n+1:]
   196  	}
   197  	return p
   198  }
   199  
   200  // PrettySpan returns a human-readable representation of a span.
   201  func PrettySpan(valDirs []encoding.Direction, span roachpb.Span, skip int) string {
   202  	var b strings.Builder
   203  	b.WriteString(PrettyKey(valDirs, span.Key, skip))
   204  	b.WriteByte('-')
   205  	b.WriteString(PrettyKey(valDirs, span.EndKey, skip))
   206  	return b.String()
   207  }
   208  
   209  // PrettySpans returns a human-readable description of the spans.
   210  // If index is nil, then pretty print subroutines will use their default
   211  // settings.
   212  func PrettySpans(index *IndexDescriptor, spans []roachpb.Span, skip int) string {
   213  	if len(spans) == 0 {
   214  		return ""
   215  	}
   216  
   217  	valDirs := IndexKeyValDirs(index)
   218  
   219  	var b strings.Builder
   220  	for i, span := range spans {
   221  		if i > 0 {
   222  			b.WriteString(" ")
   223  		}
   224  		b.WriteString(PrettySpan(valDirs, span, skip))
   225  	}
   226  	return b.String()
   227  }