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

     1  // Copyright 2017 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 sql
    12  
    13  import (
    14  	"context"
    15  	"fmt"
    16  
    17  	"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
    18  	"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
    19  	"github.com/cockroachdb/cockroach/pkg/sql/privilege"
    20  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    21  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    22  )
    23  
    24  var errEmptyIndexName = pgerror.New(pgcode.Syntax, "empty index name")
    25  
    26  type renameIndexNode struct {
    27  	n         *tree.RenameIndex
    28  	tableDesc *sqlbase.MutableTableDescriptor
    29  	idx       *sqlbase.IndexDescriptor
    30  }
    31  
    32  // RenameIndex renames the index.
    33  // Privileges: CREATE on table.
    34  //   notes: postgres requires CREATE on the table.
    35  //          mysql requires ALTER, CREATE, INSERT on the table.
    36  func (p *planner) RenameIndex(ctx context.Context, n *tree.RenameIndex) (planNode, error) {
    37  	_, tableDesc, err := expandMutableIndexName(ctx, p, n.Index, !n.IfExists /* requireTable */)
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  	if tableDesc == nil {
    42  		// IfExists specified and table did not exist -- noop.
    43  		return newZeroNode(nil /* columns */), nil
    44  	}
    45  
    46  	idx, _, err := tableDesc.FindIndexByName(string(n.Index.Index))
    47  	if err != nil {
    48  		if n.IfExists {
    49  			// Noop.
    50  			return newZeroNode(nil /* columns */), nil
    51  		}
    52  		// Index does not exist, but we want it to: error out.
    53  		return nil, err
    54  	}
    55  
    56  	if err := p.CheckPrivilege(ctx, tableDesc, privilege.CREATE); err != nil {
    57  		return nil, err
    58  	}
    59  
    60  	return &renameIndexNode{n: n, idx: idx, tableDesc: tableDesc}, nil
    61  }
    62  
    63  // ReadingOwnWrites implements the planNodeReadingOwnWrites interface.
    64  // This is because RENAME DATABASE performs multiple KV operations on descriptors
    65  // and expects to see its own writes.
    66  func (n *renameIndexNode) ReadingOwnWrites() {}
    67  
    68  func (n *renameIndexNode) startExec(params runParams) error {
    69  	p := params.p
    70  	ctx := params.ctx
    71  	tableDesc := n.tableDesc
    72  	idx := n.idx
    73  
    74  	for _, tableRef := range tableDesc.DependedOnBy {
    75  		if tableRef.IndexID != idx.ID {
    76  			continue
    77  		}
    78  		return p.dependentViewRenameError(
    79  			ctx, "index", n.n.Index.Index.String(), tableDesc.ParentID, tableRef.ID)
    80  	}
    81  
    82  	if n.n.NewName == "" {
    83  		return errEmptyIndexName
    84  	}
    85  
    86  	if n.n.Index.Index == n.n.NewName {
    87  		// Noop.
    88  		return nil
    89  	}
    90  
    91  	if _, _, err := tableDesc.FindIndexByName(string(n.n.NewName)); err == nil {
    92  		return fmt.Errorf("index name %q already exists", string(n.n.NewName))
    93  	}
    94  
    95  	if err := tableDesc.RenameIndexDescriptor(idx, string(n.n.NewName)); err != nil {
    96  		return err
    97  	}
    98  
    99  	if err := tableDesc.Validate(ctx, p.txn, p.ExecCfg().Codec); err != nil {
   100  		return err
   101  	}
   102  
   103  	return p.writeSchemaChange(
   104  		ctx, tableDesc, sqlbase.InvalidMutationID, tree.AsStringWithFQNames(n.n, params.Ann()))
   105  }
   106  
   107  func (n *renameIndexNode) Next(runParams) (bool, error) { return false, nil }
   108  func (n *renameIndexNode) Values() tree.Datums          { return tree.Datums{} }
   109  func (n *renameIndexNode) Close(context.Context)        {}