github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/drop_sequence.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 16 "github.com/cockroachdb/cockroach/pkg/server/telemetry" 17 "github.com/cockroachdb/cockroach/pkg/sql/catalog/resolver" 18 "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode" 19 "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror" 20 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 21 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 22 "github.com/cockroachdb/cockroach/pkg/sql/sqltelemetry" 23 "github.com/cockroachdb/cockroach/pkg/util/errorutil/unimplemented" 24 ) 25 26 type dropSequenceNode struct { 27 n *tree.DropSequence 28 td []toDelete 29 } 30 31 func (p *planner) DropSequence(ctx context.Context, n *tree.DropSequence) (planNode, error) { 32 td := make([]toDelete, 0, len(n.Names)) 33 for i := range n.Names { 34 tn := &n.Names[i] 35 droppedDesc, err := p.prepareDrop(ctx, tn, !n.IfExists, resolver.ResolveRequireSequenceDesc) 36 if err != nil { 37 return nil, err 38 } 39 if droppedDesc == nil { 40 // IfExists specified and descriptor does not exist. 41 continue 42 } 43 44 if depErr := p.sequenceDependencyError(ctx, droppedDesc); depErr != nil { 45 return nil, depErr 46 } 47 48 td = append(td, toDelete{tn, droppedDesc}) 49 } 50 51 if len(td) == 0 { 52 return newZeroNode(nil /* columns */), nil 53 } 54 55 return &dropSequenceNode{ 56 n: n, 57 td: td, 58 }, nil 59 } 60 61 // ReadingOwnWrites implements the planNodeReadingOwnWrites interface. 62 // This is because DROP SEQUENCE performs multiple KV operations on descriptors 63 // and expects to see its own writes. 64 func (n *dropSequenceNode) ReadingOwnWrites() {} 65 66 func (n *dropSequenceNode) startExec(params runParams) error { 67 telemetry.Inc(sqltelemetry.SchemaChangeDropCounter("sequence")) 68 69 ctx := params.ctx 70 for _, toDel := range n.td { 71 droppedDesc := toDel.desc 72 err := params.p.dropSequenceImpl( 73 ctx, droppedDesc, true /* queueJob */, tree.AsStringWithFQNames(n.n, params.Ann()), n.n.DropBehavior, 74 ) 75 if err != nil { 76 return err 77 } 78 // Log a Drop Sequence event for this table. This is an auditable log event 79 // and is recorded in the same transaction as the table descriptor 80 // update. 81 if err := MakeEventLogger(params.extendedEvalCtx.ExecCfg).InsertEventRecord( 82 ctx, 83 params.p.txn, 84 EventLogDropSequence, 85 int32(droppedDesc.ID), 86 int32(params.extendedEvalCtx.NodeID.SQLInstanceID()), 87 struct { 88 SequenceName string 89 Statement string 90 User string 91 }{toDel.tn.FQString(), n.n.String(), params.SessionData().User}, 92 ); err != nil { 93 return err 94 } 95 } 96 return nil 97 } 98 99 func (*dropSequenceNode) Next(runParams) (bool, error) { return false, nil } 100 func (*dropSequenceNode) Values() tree.Datums { return tree.Datums{} } 101 func (*dropSequenceNode) Close(context.Context) {} 102 103 func (p *planner) dropSequenceImpl( 104 ctx context.Context, 105 seqDesc *sqlbase.MutableTableDescriptor, 106 queueJob bool, 107 jobDesc string, 108 behavior tree.DropBehavior, 109 ) error { 110 return p.initiateDropTable(ctx, seqDesc, queueJob, jobDesc, true /* drainName */) 111 } 112 113 // sequenceDependency error returns an error if the given sequence cannot be dropped because 114 // a table uses it in a DEFAULT expression on one of its columns, or nil if there is no 115 // such dependency. 116 func (p *planner) sequenceDependencyError( 117 ctx context.Context, droppedDesc *sqlbase.MutableTableDescriptor, 118 ) error { 119 if len(droppedDesc.DependedOnBy) > 0 { 120 return pgerror.Newf( 121 pgcode.DependentObjectsStillExist, 122 "cannot drop sequence %s because other objects depend on it", 123 droppedDesc.Name, 124 ) 125 } 126 return nil 127 } 128 129 func (p *planner) canRemoveAllTableOwnedSequences( 130 ctx context.Context, desc *sqlbase.MutableTableDescriptor, behavior tree.DropBehavior, 131 ) error { 132 for _, col := range desc.Columns { 133 err := p.canRemoveOwnedSequencesImpl(ctx, desc, &col, behavior, false /* isColumnDrop */) 134 if err != nil { 135 return err 136 } 137 } 138 return nil 139 } 140 141 func (p *planner) canRemoveAllColumnOwnedSequences( 142 ctx context.Context, 143 desc *sqlbase.MutableTableDescriptor, 144 col *sqlbase.ColumnDescriptor, 145 behavior tree.DropBehavior, 146 ) error { 147 return p.canRemoveOwnedSequencesImpl(ctx, desc, col, behavior, true /* isColumnDrop */) 148 } 149 150 func (p *planner) canRemoveOwnedSequencesImpl( 151 ctx context.Context, 152 desc *sqlbase.MutableTableDescriptor, 153 col *sqlbase.ColumnDescriptor, 154 behavior tree.DropBehavior, 155 isColumnDrop bool, 156 ) error { 157 for _, sequenceID := range col.OwnsSequenceIds { 158 seqLookup, err := p.LookupTableByID(ctx, sequenceID) 159 if err != nil { 160 return err 161 } 162 seqDesc := seqLookup.Desc 163 affectsNoColumns := len(seqDesc.DependedOnBy) == 0 164 // It is okay if the sequence is depended on by columns that are being 165 // dropped in the same transaction 166 canBeSafelyRemoved := len(seqDesc.DependedOnBy) == 1 && seqDesc.DependedOnBy[0].ID == desc.ID 167 // If only the column is being dropped, no other columns of the table can 168 // depend on that sequence either 169 if isColumnDrop { 170 canBeSafelyRemoved = canBeSafelyRemoved && len(seqDesc.DependedOnBy[0].ColumnIDs) == 1 && 171 seqDesc.DependedOnBy[0].ColumnIDs[0] == col.ID 172 } 173 174 canRemove := affectsNoColumns || canBeSafelyRemoved 175 176 // Once Drop Sequence Cascade actually respects the drop behavior, this 177 // check should go away. 178 if behavior == tree.DropCascade && !canRemove { 179 return unimplemented.NewWithIssue(20965, "DROP SEQUENCE CASCADE is currently unimplemented") 180 } 181 // If Cascade is not enabled, and more than 1 columns depend on it, and the 182 if behavior != tree.DropCascade && !canRemove { 183 return pgerror.Newf( 184 pgcode.DependentObjectsStillExist, 185 "cannot drop table %s because other objects depend on it", 186 desc.Name, 187 ) 188 } 189 } 190 return nil 191 }