github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/create_sequence.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 sql
    12  
    13  import (
    14  	"context"
    15  
    16  	"github.com/cockroachdb/cockroach/pkg/keys"
    17  	"github.com/cockroachdb/cockroach/pkg/kv"
    18  	"github.com/cockroachdb/cockroach/pkg/server/telemetry"
    19  	"github.com/cockroachdb/cockroach/pkg/sql/catalog/catalogkv"
    20  	"github.com/cockroachdb/cockroach/pkg/sql/privilege"
    21  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    22  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    23  	"github.com/cockroachdb/cockroach/pkg/sql/sqltelemetry"
    24  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    25  	"github.com/cockroachdb/cockroach/pkg/util/hlc"
    26  )
    27  
    28  type createSequenceNode struct {
    29  	n      *tree.CreateSequence
    30  	dbDesc *sqlbase.DatabaseDescriptor
    31  }
    32  
    33  func (p *planner) CreateSequence(ctx context.Context, n *tree.CreateSequence) (planNode, error) {
    34  	un := n.Name.ToUnresolvedObjectName()
    35  	dbDesc, prefix, err := p.ResolveUncachedDatabase(ctx, un)
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  	n.Name.ObjectNamePrefix = prefix
    40  
    41  	if err := p.CheckPrivilege(ctx, dbDesc, privilege.CREATE); err != nil {
    42  		return nil, err
    43  	}
    44  
    45  	return &createSequenceNode{
    46  		n:      n,
    47  		dbDesc: dbDesc,
    48  	}, nil
    49  }
    50  
    51  // ReadingOwnWrites implements the planNodeReadingOwnWrites interface.
    52  // This is because CREATE SEQUENCE performs multiple KV operations on descriptors
    53  // and expects to see its own writes.
    54  func (n *createSequenceNode) ReadingOwnWrites() {}
    55  
    56  func (n *createSequenceNode) startExec(params runParams) error {
    57  	telemetry.Inc(sqltelemetry.SchemaChangeCreateCounter("sequence"))
    58  	isTemporary := n.n.Temporary
    59  
    60  	_, schemaID, err := getTableCreateParams(params, n.dbDesc.ID, isTemporary, n.n.Name.Table())
    61  	if err != nil {
    62  		if sqlbase.IsRelationAlreadyExistsError(err) && n.n.IfNotExists {
    63  			return nil
    64  		}
    65  		return err
    66  	}
    67  
    68  	return doCreateSequence(
    69  		params, n.n.String(), n.dbDesc, schemaID, &n.n.Name, isTemporary, n.n.Options,
    70  		tree.AsStringWithFQNames(n.n, params.Ann()),
    71  	)
    72  }
    73  
    74  // doCreateSequence performs the creation of a sequence in KV. The
    75  // context argument is a string to use in the event log.
    76  func doCreateSequence(
    77  	params runParams,
    78  	context string,
    79  	dbDesc *DatabaseDescriptor,
    80  	schemaID sqlbase.ID,
    81  	name *TableName,
    82  	isTemporary bool,
    83  	opts tree.SequenceOptions,
    84  	jobDesc string,
    85  ) error {
    86  	id, err := catalogkv.GenerateUniqueDescID(params.ctx, params.p.ExecCfg().DB, params.p.ExecCfg().Codec)
    87  	if err != nil {
    88  		return err
    89  	}
    90  
    91  	// Inherit permissions from the database descriptor.
    92  	privs := dbDesc.GetPrivileges()
    93  
    94  	if isTemporary {
    95  		telemetry.Inc(sqltelemetry.CreateTempSequenceCounter)
    96  	}
    97  
    98  	desc, err := MakeSequenceTableDesc(
    99  		name.Table(),
   100  		opts,
   101  		dbDesc.ID,
   102  		schemaID,
   103  		id,
   104  		params.creationTimeForNewTableDescriptor(),
   105  		privs,
   106  		isTemporary,
   107  		&params,
   108  	)
   109  	if err != nil {
   110  		return err
   111  	}
   112  
   113  	// makeSequenceTableDesc already validates the table. No call to
   114  	// desc.ValidateTable() needed here.
   115  
   116  	key := sqlbase.MakeObjectNameKey(
   117  		params.ctx,
   118  		params.ExecCfg().Settings,
   119  		dbDesc.ID,
   120  		schemaID,
   121  		name.Table(),
   122  	).Key(params.ExecCfg().Codec)
   123  	if err = params.p.createDescriptorWithID(
   124  		params.ctx, key, id, &desc, params.EvalContext().Settings, jobDesc,
   125  	); err != nil {
   126  		return err
   127  	}
   128  
   129  	// Initialize the sequence value.
   130  	seqValueKey := params.ExecCfg().Codec.SequenceKey(uint32(id))
   131  	b := &kv.Batch{}
   132  	b.Inc(seqValueKey, desc.SequenceOpts.Start-desc.SequenceOpts.Increment)
   133  	if err := params.p.txn.Run(params.ctx, b); err != nil {
   134  		return err
   135  	}
   136  
   137  	if err := desc.Validate(params.ctx, params.p.txn, params.ExecCfg().Codec); err != nil {
   138  		return err
   139  	}
   140  
   141  	// Log Create Sequence event. This is an auditable log event and is
   142  	// recorded in the same transaction as the table descriptor update.
   143  	return MakeEventLogger(params.extendedEvalCtx.ExecCfg).InsertEventRecord(
   144  		params.ctx,
   145  		params.p.txn,
   146  		EventLogCreateSequence,
   147  		int32(desc.ID),
   148  		int32(params.extendedEvalCtx.NodeID.SQLInstanceID()),
   149  		struct {
   150  			SequenceName string
   151  			Statement    string
   152  			User         string
   153  		}{name.FQString(), context, params.SessionData().User},
   154  	)
   155  }
   156  
   157  func (*createSequenceNode) Next(runParams) (bool, error) { return false, nil }
   158  func (*createSequenceNode) Values() tree.Datums          { return tree.Datums{} }
   159  func (*createSequenceNode) Close(context.Context)        {}
   160  
   161  // MakeSequenceTableDesc creates a sequence descriptor.
   162  func MakeSequenceTableDesc(
   163  	sequenceName string,
   164  	sequenceOptions tree.SequenceOptions,
   165  	parentID sqlbase.ID,
   166  	schemaID sqlbase.ID,
   167  	id sqlbase.ID,
   168  	creationTime hlc.Timestamp,
   169  	privileges *sqlbase.PrivilegeDescriptor,
   170  	isTemporary bool,
   171  	params *runParams,
   172  ) (sqlbase.MutableTableDescriptor, error) {
   173  	desc := InitTableDescriptor(
   174  		id,
   175  		parentID,
   176  		schemaID,
   177  		sequenceName,
   178  		creationTime,
   179  		privileges,
   180  		isTemporary,
   181  	)
   182  
   183  	// Mimic a table with one column, "value".
   184  	desc.Columns = []sqlbase.ColumnDescriptor{
   185  		{
   186  			ID:   sqlbase.SequenceColumnID,
   187  			Name: sqlbase.SequenceColumnName,
   188  			Type: types.Int,
   189  		},
   190  	}
   191  	desc.PrimaryIndex = sqlbase.IndexDescriptor{
   192  		ID:               keys.SequenceIndexID,
   193  		Name:             sqlbase.PrimaryKeyIndexName,
   194  		ColumnIDs:        []sqlbase.ColumnID{sqlbase.SequenceColumnID},
   195  		ColumnNames:      []string{sqlbase.SequenceColumnName},
   196  		ColumnDirections: []sqlbase.IndexDescriptor_Direction{sqlbase.IndexDescriptor_ASC},
   197  	}
   198  	desc.Families = []sqlbase.ColumnFamilyDescriptor{
   199  		{
   200  			ID:              keys.SequenceColumnFamilyID,
   201  			ColumnIDs:       []sqlbase.ColumnID{sqlbase.SequenceColumnID},
   202  			ColumnNames:     []string{sqlbase.SequenceColumnName},
   203  			Name:            "primary",
   204  			DefaultColumnID: sqlbase.SequenceColumnID,
   205  		},
   206  	}
   207  
   208  	// Fill in options, starting with defaults then overriding.
   209  	opts := &sqlbase.TableDescriptor_SequenceOpts{
   210  		Increment: 1,
   211  	}
   212  	err := assignSequenceOptions(opts, sequenceOptions, true /* setDefaults */, params, id)
   213  	if err != nil {
   214  		return desc, err
   215  	}
   216  	desc.SequenceOpts = opts
   217  
   218  	// A sequence doesn't have dependencies and thus can be made public
   219  	// immediately.
   220  	desc.State = sqlbase.TableDescriptor_PUBLIC
   221  
   222  	return desc, desc.ValidateTable()
   223  }