Skip to content

Commit

Permalink
sql: turn some catalog.TableDescriptor methods into functions
Browse files Browse the repository at this point in the history
The catalog.TableDescriptor has methods which can just as well be
expressed as functions, thereby lightening that interface definition
somewhat.

This patch also adds comments to many catalog.Index methods.

Release note: None
  • Loading branch information
Marius Posta committed Jan 7, 2021
1 parent 46e4d2e commit b519b11
Show file tree
Hide file tree
Showing 19 changed files with 335 additions and 220 deletions.
2 changes: 1 addition & 1 deletion pkg/ccl/backupccl/backup_planning.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ func getLogicallyMergedTableSpans(
checkForKVInBounds func(start, end roachpb.Key, endTime hlc.Timestamp) (bool, error),
) ([]roachpb.Span, error) {
var nonDropIndexIDs []descpb.IndexID
if err := table.ForEachNonDropIndex(func(idx catalog.Index) error {
if err := catalog.ForEachNonDropIndex(table, func(idx catalog.Index) error {
key := tableAndIndex{tableID: table.GetID(), indexID: idx.GetID()}
if added[key] {
return nil
Expand Down
2 changes: 1 addition & 1 deletion pkg/ccl/backupccl/restore_planning.go
Original file line number Diff line number Diff line change
Expand Up @@ -1021,7 +1021,7 @@ func RewriteTableDescs(
return err
}

if err := table.ForEachNonDropIndex(func(indexI catalog.Index) error {
if err := catalog.ForEachNonDropIndex(table, func(indexI catalog.Index) error {
index := indexI.IndexDesc()
// Verify that for any interleaved index being restored, the interleave
// parent is also being restored. Otherwise, the interleave entries in the
Expand Down
2 changes: 1 addition & 1 deletion pkg/ccl/backupccl/targets.go
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,7 @@ func ensureInterleavesIncluded(tables []catalog.TableDescriptor) error {
}

for _, table := range tables {
if err := table.ForEachIndex(catalog.IndexOpts{
if err := catalog.ForEachIndex(table, catalog.IndexOpts{
AddMutations: true,
}, func(index catalog.Index) error {
for i := 0; i < index.NumInterleaveAncestors(); i++ {
Expand Down
2 changes: 1 addition & 1 deletion pkg/ccl/importccl/import_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ func makeInputConverter(
}

if singleTable != nil {
if idx := singleTable.FindDeletableNonPrimaryIndex(func(idx catalog.Index) bool {
if idx := catalog.FindDeletableNonPrimaryIndex(singleTable, func(idx catalog.Index) bool {
return idx.IsPartial()
}); idx != nil {
return nil, unimplemented.NewWithIssue(50225, "cannot import into table with partial indexes")
Expand Down
2 changes: 1 addition & 1 deletion pkg/ccl/partitionccl/partition.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ func selectPartitionExprs(

a := &rowenc.DatumAlloc{}
var prefixDatums []tree.Datum
if err := tableDesc.ForEachIndex(catalog.IndexOpts{
if err := catalog.ForEachIndex(tableDesc, catalog.IndexOpts{
AddMutations: true,
}, func(idx catalog.Index) error {
return selectPartitionExprsByName(
Expand Down
2 changes: 1 addition & 1 deletion pkg/sql/alter_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -816,7 +816,7 @@ func (n *alterTableNode) startExec(params runParams) error {
// new name exists. This is what postgres does.
switch details.Kind {
case descpb.ConstraintTypeUnique, descpb.ConstraintTypePK:
if n.tableDesc.FindNonDropIndex(func(idx catalog.Index) bool {
if catalog.FindNonDropIndex(n.tableDesc, func(idx catalog.Index) bool {
return idx.GetName() == string(t.NewName)
}) != nil {
return pgerror.Newf(pgcode.DuplicateRelation,
Expand Down
272 changes: 248 additions & 24 deletions pkg/sql/catalog/descriptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,40 +112,78 @@ type TableDescriptor interface {
GetFormatVersion() descpb.FormatVersion

GetPrimaryIndexID() descpb.IndexID
GetPrimaryIndex() Index
PrimaryIndexSpan(codec keys.SQLCodec) roachpb.Span
IndexSpan(codec keys.SQLCodec, id descpb.IndexID) roachpb.Span
GetIndexMutationCapabilities(id descpb.IndexID) (isMutation, isWriteOnly bool)
KeysPerRow(id descpb.IndexID) (int, error)

GetPrimaryIndex() Index
// AllIndexes returns a slice with all indexes, public and non-public,
// in the underlying proto, in their canonical order:
// - the primary index,
// - the public non-primary indexes in the Indexes array, in order,
// - the non-public indexes present in the Mutations array, in order.
//
// See also Index.Ordinal().
AllIndexes() []Index

// ActiveIndexes returns a slice with all public indexes in the underlying
// proto, in their canonical order:
// - the primary index,
// - the public non-primary indexes in the Indexes array, in order.
//
// See also Index.Ordinal().
ActiveIndexes() []Index

// NonDropIndexes returns a slice of all non-drop indexes in the underlying
// proto, in their canonical order. This means:
// - the primary index, if the table is a physical table,
// - the public non-primary indexes in the Indexes array, in order,
// - the non-public indexes present in the Mutations array, in order,
// if the mutation is not a drop.
//
// See also Index.Ordinal().
NonDropIndexes() []Index

// NonDropIndexes returns a slice of all partial indexes in the underlying
// proto, in their canonical order. This is equivalent to taking the slice
// produced by AllIndexes and removing indexes with empty expressions.
PartialIndexes() []Index

// PublicNonPrimaryIndexes returns a slice of all active secondary indexes,
// in their canonical order. This is equivalent to the Indexes array in the
// proto.
PublicNonPrimaryIndexes() []Index

// WritableNonPrimaryIndexes returns a slice of all non-primary indexes which
// allow being written to: public + delete-and-write-only, in their canonical
// order. This is equivalent to taking the slice produced by
// DeletableNonPrimaryIndexes and removing the indexes which are in mutations
// in the delete-only state.
WritableNonPrimaryIndexes() []Index

// DeletableNonPrimaryIndexes returns a slice of all non-primary indexes
// which allow being deleted from: public + delete-and-write-only +
// delete-only, in their canonical order. This is equivalent to taking
// the slice produced by AllIndexes and removing the primary index.
DeletableNonPrimaryIndexes() []Index
DeleteOnlyNonPrimaryIndexes() []Index

ForEachIndex(opts IndexOpts, f func(idx Index) error) error
ForEachActiveIndex(f func(idx Index) error) error
ForEachNonDropIndex(f func(idx Index) error) error
ForEachPartialIndex(f func(idx Index) error) error
ForEachPublicNonPrimaryIndex(f func(idx Index) error) error
ForEachWritableNonPrimaryIndex(f func(idx Index) error) error
ForEachDeletableNonPrimaryIndex(f func(idx Index) error) error
ForEachDeleteOnlyNonPrimaryIndex(f func(idx Index) error) error

FindIndex(opts IndexOpts, test func(idx Index) bool) Index
FindActiveIndex(test func(idx Index) bool) Index
FindNonDropIndex(test func(idx Index) bool) Index
FindPartialIndex(test func(idx Index) bool) Index
FindPublicNonPrimaryIndex(test func(idx Index) bool) Index
FindWritableNonPrimaryIndex(test func(idx Index) bool) Index
FindDeletableNonPrimaryIndex(test func(idx Index) bool) Index
FindDeleteOnlyNonPrimaryIndex(test func(idx Index) bool) Index
// DeleteOnlyNonPrimaryIndexes returns a slice of all non-primary indexes
// which allow only being deleted from, in their canonical order. This is
// equivalent to taking the slice produced by DeletableNonPrimaryIndexes and
// removing the indexes which are not in mutations or not in the delete-only
// state.
DeleteOnlyNonPrimaryIndexes() []Index

// FindIndexWithID returns the first catalog.Index that matches the id
// in the set of all indexes, or an error if none was found. The order of
// traversal is the canonical order, see Index.Ordinal().
FindIndexWithID(id descpb.IndexID) (Index, error)

// FindIndexWithName returns the first catalog.Index that matches the name in
// the set of all indexes, excluding the primary index of non-physical
// tables, or an error if none was found. The order of traversal is the
// canonical order, see Index.Ordinal().
FindIndexWithName(name string) (Index, error)

HasPrimaryKey() bool
Expand Down Expand Up @@ -208,17 +246,52 @@ type TableDescriptor interface {

// Index is an interface around the index descriptor types.
type Index interface {

// IndexDesc returns the underlying protobuf descriptor.
// Ideally, this method should be called as rarely as possible.
IndexDesc() *descpb.IndexDescriptor

// IndexDescDeepCopy returns a deep copy of the underlying proto.
IndexDescDeepCopy() descpb.IndexDescriptor

// Ordinal returns the ordinal of the index in its parent table descriptor.
//
// The ordinal of an index in a `tableDesc descpb.TableDescriptor` is
// defined as follows:
// - 0 is the ordinal of the primary index,
// - [1:1+len(tableDesc.Indexes)] is the range of public non-primary indexes,
// - [1+len(tableDesc.Indexes):] is the range of non-public indexes.
//
// In terms of a `table catalog.TableDescriptor` interface, it is defined
// as the catalog.Index object's position in the table.AllIndexes() slice.
Ordinal() int

// Primary returns true iff the index is the primary index for the table
// descriptor.
Primary() bool

// Public returns true iff the index is active, i.e. readable, in the table
// descriptor.
Public() bool

// WriteAndDeleteOnly returns true iff the index is a mutation in the
// delete-and-write-only state in the table descriptor.
WriteAndDeleteOnly() bool

// DeleteOnly returns true iff the index is a mutation in the delete-only
// state in the table descriptor.
DeleteOnly() bool

// Adding returns true iff the index is an add mutation in the table
// descriptor.
Adding() bool

// Dropped returns true iff the index is a drop mutation in the table
// descriptor.
Dropped() bool

// The remaining methods operate on the underlying descpb.IndexDescriptor object.

GetID() descpb.IndexID
GetName() string
IsInterleaved() bool
Expand All @@ -229,34 +302,44 @@ type Index interface {
IsCreatedExplicitly() bool
GetPredicate() string
GetType() descpb.IndexDescriptor_Type
IsValidOriginIndex(originColIDs descpb.ColumnIDs) bool
IsValidReferencedIndex(referencedColIDs descpb.ColumnIDs) bool
GetGeoConfig() geoindex.Config
GetSharded() descpb.ShardedDescriptor
GetShardColumnName() string
GetVersion() descpb.IndexDescriptorVersion
GetEncodingType() descpb.IndexDescriptorEncodingType

GetSharded() descpb.ShardedDescriptor
GetShardColumnName() string

IsValidOriginIndex(originColIDs descpb.ColumnIDs) bool
IsValidReferencedIndex(referencedColIDs descpb.ColumnIDs) bool

GetPartitioning() descpb.PartitioningDescriptor
FindPartitionByName(name string) descpb.PartitioningDescriptor
PartitionNames() []string

NumInterleaveAncestors() int
GetInterleaveAncestor(ancestorOrdinal int) descpb.InterleaveDescriptor_Ancestor

NumInterleavedBy() int
GetInterleavedBy(interleavedByOrdinal int) descpb.ForeignKeyReference

NumColumns() int
GetColumnID(columnOrdinal int) descpb.ColumnID
GetColumnName(columnOrdinal int) string
GetColumnDirection(columnOrdinal int) descpb.IndexDescriptor_Direction

ForEachColumnID(func(id descpb.ColumnID) error) error
ContainsColumnID(colID descpb.ColumnID) bool
InvertedColumnID() descpb.ColumnID
InvertedColumnName() string
ForEachColumnID(func(id descpb.ColumnID) error) error

NumStoredColumns() int
GetStoredColumnID(storedColumnOrdinal int) descpb.ColumnID
GetStoredColumnName(storedColumnOrdinal int) string
HasOldStoredColumns() bool

NumExtraColumns() int
GetExtraColumnID(extraColumnOrdinal int) descpb.ColumnID

NumCompositeColumns() int
GetCompositeColumnID(compositeColumnOrdinal int) descpb.ColumnID
}
Expand Down Expand Up @@ -356,3 +439,144 @@ func FormatSafeDescriptorProperties(w *redact.StringBuilder, desc Descriptor) {
w.Printf(", NumDrainingNames: %d", len(drainingNames))
}
}

// ForEachIndex runs f over each index in the table descriptor according to
// filter parameters in opts. Indexes are visited in their canonical order,
// see Index.Ordinal().
func ForEachIndex(desc TableDescriptor, opts IndexOpts, f func(idx Index) error) error {
for _, idx := range desc.AllIndexes() {
if !opts.NonPhysicalPrimaryIndex && idx.Primary() && !desc.IsPhysicalTable() {
continue
}
if !opts.AddMutations && idx.Adding() {
continue
}
if !opts.DropMutations && idx.Dropped() {
continue
}
if err := f(idx); err != nil {
return err
}
}
return nil
}

func forEachIndex(slice []Index, f func(idx Index) error) error {
for _, idx := range slice {
if err := f(idx); err != nil {
return err
}
}
return nil
}

// ForEachActiveIndex is like ForEachIndex over ActiveIndexes().
func ForEachActiveIndex(desc TableDescriptor, f func(idx Index) error) error {
return forEachIndex(desc.ActiveIndexes(), f)
}

// ForEachNonDropIndex is like ForEachIndex over NonDropIndexes().
func ForEachNonDropIndex(desc TableDescriptor, f func(idx Index) error) error {
return forEachIndex(desc.NonDropIndexes(), f)
}

// ForEachPartialIndex is like ForEachIndex over PartialIndexes().
func ForEachPartialIndex(desc TableDescriptor, f func(idx Index) error) error {
return forEachIndex(desc.PartialIndexes(), f)
}

// ForEachPublicNonPrimaryIndex is like ForEachIndex over
// PublicNonPrimaryIndexes().
func ForEachPublicNonPrimaryIndex(desc TableDescriptor, f func(idx Index) error) error {
return forEachIndex(desc.PublicNonPrimaryIndexes(), f)
}

// ForEachWritableNonPrimaryIndex is like ForEachIndex over
// WritableNonPrimaryIndexes().
func ForEachWritableNonPrimaryIndex(desc TableDescriptor, f func(idx Index) error) error {
return forEachIndex(desc.WritableNonPrimaryIndexes(), f)
}

// ForEachDeletableNonPrimaryIndex is like ForEachIndex over
// DeletableNonPrimaryIndexes().
func ForEachDeletableNonPrimaryIndex(desc TableDescriptor, f func(idx Index) error) error {
return forEachIndex(desc.DeletableNonPrimaryIndexes(), f)
}

// ForEachDeleteOnlyNonPrimaryIndex is like ForEachIndex over
// DeleteOnlyNonPrimaryIndexes().
func ForEachDeleteOnlyNonPrimaryIndex(desc TableDescriptor, f func(idx Index) error) error {
return forEachIndex(desc.DeleteOnlyNonPrimaryIndexes(), f)
}

// FindIndex returns the first index for which test returns true, nil otherwise,
// according to the parameters in opts just like ForEachIndex.
// Indexes are visited in their canonical order, see Index.Ordinal().
func FindIndex(desc TableDescriptor, opts IndexOpts, test func(idx Index) bool) Index {
for _, idx := range desc.AllIndexes() {
if !opts.NonPhysicalPrimaryIndex && idx.Primary() && !desc.IsPhysicalTable() {
continue
}
if !opts.AddMutations && idx.Adding() {
continue
}
if !opts.DropMutations && idx.Dropped() {
continue
}
if test(idx) {
return idx
}
}
return nil
}

func findIndex(slice []Index, test func(idx Index) bool) Index {
for _, idx := range slice {
if test(idx) {
return idx
}
}
return nil
}

// FindActiveIndex returns the first index in ActiveIndex() for which test
// returns true.
func FindActiveIndex(desc TableDescriptor, test func(idx Index) bool) Index {
return findIndex(desc.ActiveIndexes(), test)
}

// FindNonDropIndex returns the first index in NonDropIndex() for which test
// returns true.
func FindNonDropIndex(desc TableDescriptor, test func(idx Index) bool) Index {
return findIndex(desc.NonDropIndexes(), test)
}

// FindPartialIndex returns the first index in PartialIndex() for which test
// returns true.
func FindPartialIndex(desc TableDescriptor, test func(idx Index) bool) Index {
return findIndex(desc.PartialIndexes(), test)
}

// FindPublicNonPrimaryIndex returns the first index in PublicNonPrimaryIndex()
// for which test returns true.
func FindPublicNonPrimaryIndex(desc TableDescriptor, test func(idx Index) bool) Index {
return findIndex(desc.PublicNonPrimaryIndexes(), test)
}

// FindWritableNonPrimaryIndex returns the first index in
// WritableNonPrimaryIndex() for which test returns true.
func FindWritableNonPrimaryIndex(desc TableDescriptor, test func(idx Index) bool) Index {
return findIndex(desc.WritableNonPrimaryIndexes(), test)
}

// FindDeletableNonPrimaryIndex returns the first index in
// DeletableNonPrimaryIndex() for which test returns true.
func FindDeletableNonPrimaryIndex(desc TableDescriptor, test func(idx Index) bool) Index {
return findIndex(desc.DeletableNonPrimaryIndexes(), test)
}

// FindDeleteOnlyNonPrimaryIndex returns the first index in
// DeleteOnlyNonPrimaryIndex() for which test returns true.
func FindDeleteOnlyNonPrimaryIndex(desc TableDescriptor, test func(idx Index) bool) Index {
return findIndex(desc.DeleteOnlyNonPrimaryIndexes(), test)
}
Loading

0 comments on commit b519b11

Please sign in to comment.