github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/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 "fmt" 16 "math" 17 18 "github.com/cockroachdb/cockroach/pkg/keys" 19 "github.com/cockroachdb/cockroach/pkg/kv" 20 "github.com/cockroachdb/cockroach/pkg/roachpb" 21 "github.com/cockroachdb/cockroach/pkg/sql/catalog/resolver" 22 "github.com/cockroachdb/cockroach/pkg/sql/parser" 23 "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode" 24 "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror" 25 "github.com/cockroachdb/cockroach/pkg/sql/privilege" 26 "github.com/cockroachdb/cockroach/pkg/sql/sem/builtins" 27 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 28 "github.com/cockroachdb/cockroach/pkg/sql/sessiondata" 29 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 30 "github.com/cockroachdb/cockroach/pkg/util/errorutil/unimplemented" 31 "github.com/cockroachdb/errors" 32 ) 33 34 // IncrementSequence implements the tree.SequenceOperators interface. 35 func (p *planner) IncrementSequence(ctx context.Context, seqName *tree.TableName) (int64, error) { 36 if p.EvalContext().TxnReadOnly { 37 return 0, readOnlyError("nextval()") 38 } 39 40 descriptor, err := resolver.ResolveExistingTableObject(ctx, p, seqName, tree.ObjectLookupFlagsWithRequired(), resolver.ResolveRequireSequenceDesc) 41 if err != nil { 42 return 0, err 43 } 44 if err := p.CheckPrivilege(ctx, descriptor, privilege.UPDATE); err != nil { 45 return 0, err 46 } 47 48 seqOpts := descriptor.SequenceOpts 49 var val int64 50 if seqOpts.Virtual { 51 rowid := builtins.GenerateUniqueInt(p.EvalContext().NodeID.SQLInstanceID()) 52 val = int64(rowid) 53 } else { 54 seqValueKey := p.ExecCfg().Codec.SequenceKey(uint32(descriptor.ID)) 55 val, err = kv.IncrementValRetryable( 56 ctx, p.txn.DB(), seqValueKey, seqOpts.Increment) 57 if err != nil { 58 if errors.HasType(err, (*roachpb.IntegerOverflowError)(nil)) { 59 return 0, boundsExceededError(descriptor) 60 } 61 return 0, err 62 } 63 if val > seqOpts.MaxValue || val < seqOpts.MinValue { 64 return 0, boundsExceededError(descriptor) 65 } 66 } 67 68 p.ExtendedEvalContext().SessionMutator.RecordLatestSequenceVal(uint32(descriptor.ID), val) 69 70 return val, nil 71 } 72 73 func boundsExceededError(descriptor *sqlbase.ImmutableTableDescriptor) error { 74 seqOpts := descriptor.SequenceOpts 75 isAscending := seqOpts.Increment > 0 76 77 var word string 78 var value int64 79 if isAscending { 80 word = "maximum" 81 value = seqOpts.MaxValue 82 } else { 83 word = "minimum" 84 value = seqOpts.MinValue 85 } 86 return pgerror.Newf( 87 pgcode.SequenceGeneratorLimitExceeded, 88 `reached %s value of sequence %q (%d)`, word, 89 tree.ErrString((*tree.Name)(&descriptor.Name)), value) 90 } 91 92 // GetLatestValueInSessionForSequence implements the tree.SequenceOperators interface. 93 func (p *planner) GetLatestValueInSessionForSequence( 94 ctx context.Context, seqName *tree.TableName, 95 ) (int64, error) { 96 descriptor, err := resolver.ResolveExistingTableObject(ctx, p, seqName, tree.ObjectLookupFlagsWithRequired(), resolver.ResolveRequireSequenceDesc) 97 if err != nil { 98 return 0, err 99 } 100 101 val, ok := p.SessionData().SequenceState.GetLastValueByID(uint32(descriptor.ID)) 102 if !ok { 103 return 0, pgerror.Newf( 104 pgcode.ObjectNotInPrerequisiteState, 105 `currval of sequence %q is not yet defined in this session`, tree.ErrString(seqName)) 106 } 107 108 return val, nil 109 } 110 111 // SetSequenceValue implements the tree.SequenceOperators interface. 112 func (p *planner) SetSequenceValue( 113 ctx context.Context, seqName *tree.TableName, newVal int64, isCalled bool, 114 ) error { 115 if p.EvalContext().TxnReadOnly { 116 return readOnlyError("setval()") 117 } 118 119 descriptor, err := resolver.ResolveExistingTableObject(ctx, p, seqName, tree.ObjectLookupFlagsWithRequired(), resolver.ResolveRequireSequenceDesc) 120 if err != nil { 121 return err 122 } 123 if err := p.CheckPrivilege(ctx, descriptor, privilege.UPDATE); err != nil { 124 return err 125 } 126 127 if descriptor.SequenceOpts.Virtual { 128 // TODO(knz): we currently return an error here, but if/when 129 // CockroachDB grows to automatically make sequences virtual when 130 // clients don't expect it, we may need to make this a no-op 131 // instead. 132 return pgerror.Newf( 133 pgcode.ObjectNotInPrerequisiteState, 134 `cannot set the value of virtual sequence %q`, tree.ErrString(seqName)) 135 } 136 137 seqValueKey, newVal, err := MakeSequenceKeyVal(p.ExecCfg().Codec, descriptor.TableDesc(), newVal, isCalled) 138 if err != nil { 139 return err 140 } 141 142 // TODO(vilterp): not supposed to mix usage of Inc and Put on a key, 143 // according to comments on Inc operation. Switch to Inc if `desired-current` 144 // overflows correctly. 145 return p.txn.Put(ctx, seqValueKey, newVal) 146 } 147 148 // MakeSequenceKeyVal returns the key and value of a sequence being set 149 // with newVal. 150 func MakeSequenceKeyVal( 151 codec keys.SQLCodec, sequence *TableDescriptor, newVal int64, isCalled bool, 152 ) ([]byte, int64, error) { 153 opts := sequence.SequenceOpts 154 if newVal > opts.MaxValue || newVal < opts.MinValue { 155 return nil, 0, pgerror.Newf( 156 pgcode.NumericValueOutOfRange, 157 `value %d is out of bounds for sequence "%s" (%d..%d)`, 158 newVal, sequence.Name, opts.MinValue, opts.MaxValue, 159 ) 160 } 161 if !isCalled { 162 newVal = newVal - sequence.SequenceOpts.Increment 163 } 164 165 seqValueKey := codec.SequenceKey(uint32(sequence.ID)) 166 return seqValueKey, newVal, nil 167 } 168 169 // GetSequenceValue returns the current value of the sequence. 170 func (p *planner) GetSequenceValue( 171 ctx context.Context, codec keys.SQLCodec, desc *sqlbase.ImmutableTableDescriptor, 172 ) (int64, error) { 173 if desc.SequenceOpts == nil { 174 return 0, errors.New("descriptor is not a sequence") 175 } 176 keyValue, err := p.txn.Get(ctx, codec.SequenceKey(uint32(desc.ID))) 177 if err != nil { 178 return 0, err 179 } 180 return keyValue.ValueInt(), nil 181 } 182 183 func readOnlyError(s string) error { 184 return pgerror.Newf(pgcode.ReadOnlySQLTransaction, 185 "cannot execute %s in a read-only transaction", s) 186 } 187 188 // assignSequenceOptions moves options from the AST node to the sequence options descriptor, 189 // starting with defaults and overriding them with user-provided options. 190 func assignSequenceOptions( 191 opts *sqlbase.TableDescriptor_SequenceOpts, 192 optsNode tree.SequenceOptions, 193 setDefaults bool, 194 params *runParams, 195 sequenceID sqlbase.ID, 196 ) error { 197 // All other defaults are dependent on the value of increment, 198 // i.e. whether the sequence is ascending or descending. 199 for _, option := range optsNode { 200 if option.Name == tree.SeqOptIncrement { 201 opts.Increment = *option.IntVal 202 } 203 } 204 if opts.Increment == 0 { 205 return pgerror.New( 206 pgcode.InvalidParameterValue, "INCREMENT must not be zero") 207 } 208 isAscending := opts.Increment > 0 209 210 // Set increment-dependent defaults. 211 if setDefaults { 212 if isAscending { 213 opts.MinValue = 1 214 opts.MaxValue = math.MaxInt64 215 opts.Start = opts.MinValue 216 } else { 217 opts.MinValue = math.MinInt64 218 opts.MaxValue = -1 219 opts.Start = opts.MaxValue 220 } 221 } 222 223 // Fill in all other options. 224 optionsSeen := map[string]bool{} 225 for _, option := range optsNode { 226 // Error on duplicate options. 227 _, seenBefore := optionsSeen[option.Name] 228 if seenBefore { 229 return pgerror.New(pgcode.Syntax, "conflicting or redundant options") 230 } 231 optionsSeen[option.Name] = true 232 233 switch option.Name { 234 case tree.SeqOptCycle: 235 return unimplemented.NewWithIssue(20961, 236 "CYCLE option is not supported") 237 case tree.SeqOptNoCycle: 238 // Do nothing; this is the default. 239 case tree.SeqOptCache: 240 v := *option.IntVal 241 switch { 242 case v < 1: 243 return pgerror.Newf(pgcode.InvalidParameterValue, 244 "CACHE (%d) must be greater than zero", v) 245 case v == 1: 246 // Do nothing; this is the default. 247 case v > 1: 248 return unimplemented.NewWithIssuef(32567, 249 "CACHE values larger than 1 are not supported, found %d", v) 250 } 251 case tree.SeqOptIncrement: 252 // Do nothing; this has already been set. 253 case tree.SeqOptMinValue: 254 // A value of nil represents the user explicitly saying `NO MINVALUE`. 255 if option.IntVal != nil { 256 opts.MinValue = *option.IntVal 257 } 258 case tree.SeqOptMaxValue: 259 // A value of nil represents the user explicitly saying `NO MAXVALUE`. 260 if option.IntVal != nil { 261 opts.MaxValue = *option.IntVal 262 } 263 case tree.SeqOptStart: 264 opts.Start = *option.IntVal 265 case tree.SeqOptVirtual: 266 opts.Virtual = true 267 case tree.SeqOptOwnedBy: 268 if params == nil { 269 return pgerror.Newf(pgcode.Internal, 270 "Trying to add/remove Sequence Owner without access to context") 271 } 272 // The owner is being removed 273 if option.ColumnItemVal == nil { 274 if err := removeSequenceOwnerIfExists(params.ctx, params.p, sequenceID, opts); err != nil { 275 return err 276 } 277 } else { 278 // The owner is being added/modified 279 tableDesc, col, err := resolveColumnItemToDescriptors( 280 params.ctx, params.p, option.ColumnItemVal, 281 ) 282 if err != nil { 283 return err 284 } 285 // We only want to trigger schema changes if the owner is not what we 286 // want it to be. 287 if opts.SequenceOwner.OwnerTableID != tableDesc.ID || 288 opts.SequenceOwner.OwnerColumnID != col.ID { 289 if err := removeSequenceOwnerIfExists(params.ctx, params.p, sequenceID, opts); err != nil { 290 return err 291 } 292 err := addSequenceOwner(params.ctx, params.p, tableDesc, col, sequenceID, opts) 293 if err != nil { 294 return err 295 } 296 } 297 } 298 } 299 } 300 301 // If start option not specified, set it to MinValue (for ascending sequences) 302 // or MaxValue (for descending sequences). 303 if _, startSeen := optionsSeen[tree.SeqOptStart]; !startSeen { 304 if opts.Increment > 0 { 305 opts.Start = opts.MinValue 306 } else { 307 opts.Start = opts.MaxValue 308 } 309 } 310 311 if opts.Start > opts.MaxValue { 312 return pgerror.Newf( 313 pgcode.InvalidParameterValue, 314 "START value (%d) cannot be greater than MAXVALUE (%d)", opts.Start, opts.MaxValue) 315 } 316 if opts.Start < opts.MinValue { 317 return pgerror.Newf( 318 pgcode.InvalidParameterValue, 319 "START value (%d) cannot be less than MINVALUE (%d)", opts.Start, opts.MinValue) 320 } 321 322 return nil 323 } 324 325 func removeSequenceOwnerIfExists( 326 ctx context.Context, 327 p *planner, 328 sequenceID sqlbase.ID, 329 opts *sqlbase.TableDescriptor_SequenceOpts, 330 ) error { 331 if opts.SequenceOwner.Equal(sqlbase.TableDescriptor_SequenceOpts_SequenceOwner{}) { 332 return nil 333 } 334 tableDesc, err := p.Tables().GetMutableTableVersionByID(ctx, opts.SequenceOwner.OwnerTableID, p.txn) 335 if err != nil { 336 return err 337 } 338 col, err := tableDesc.FindColumnByID(opts.SequenceOwner.OwnerColumnID) 339 if err != nil { 340 return err 341 } 342 // Find an item in colDesc.OwnsSequenceIds which references SequenceID. 343 refIdx := -1 344 for i, id := range col.OwnsSequenceIds { 345 if id == sequenceID { 346 refIdx = i 347 } 348 } 349 if refIdx == -1 { 350 return errors.AssertionFailedf("couldn't find reference from column to this sequence") 351 } 352 col.OwnsSequenceIds = append(col.OwnsSequenceIds[:refIdx], col.OwnsSequenceIds[refIdx+1:]...) 353 // TODO (lucy): Have more consistent/informative names for dependent jobs. 354 if err := p.writeSchemaChange( 355 ctx, tableDesc, sqlbase.InvalidMutationID, "removing sequence owner", 356 ); err != nil { 357 return err 358 } 359 // Reset the SequenceOwner to empty 360 opts.SequenceOwner.Reset() 361 return nil 362 } 363 364 func resolveColumnItemToDescriptors( 365 ctx context.Context, p *planner, columnItem *tree.ColumnItem, 366 ) (*MutableTableDescriptor, *sqlbase.ColumnDescriptor, error) { 367 var tableName tree.TableName 368 if columnItem.TableName != nil { 369 tableName = columnItem.TableName.ToTableName() 370 } 371 372 tableDesc, err := p.ResolveMutableTableDescriptor(ctx, &tableName, true /* required */, resolver.ResolveRequireTableDesc) 373 if err != nil { 374 return nil, nil, err 375 } 376 col, _, err := tableDesc.FindColumnByName(columnItem.ColumnName) 377 if err != nil { 378 return nil, nil, err 379 } 380 return tableDesc, col, nil 381 } 382 383 func addSequenceOwner( 384 ctx context.Context, 385 p *planner, 386 tableDesc *MutableTableDescriptor, 387 col *sqlbase.ColumnDescriptor, 388 sequenceID sqlbase.ID, 389 opts *sqlbase.TableDescriptor_SequenceOpts, 390 ) error { 391 col.OwnsSequenceIds = append(col.OwnsSequenceIds, sequenceID) 392 393 opts.SequenceOwner.OwnerColumnID = col.ID 394 opts.SequenceOwner.OwnerTableID = tableDesc.GetID() 395 // TODO (lucy): Have more consistent/informative names for dependent jobs. 396 return p.writeSchemaChange( 397 ctx, tableDesc, sqlbase.InvalidMutationID, "adding sequence owner", 398 ) 399 } 400 401 // maybeAddSequenceDependencies adds references between the column and sequence descriptors, 402 // if the column has a DEFAULT expression that uses one or more sequences. (Usually just one, 403 // e.g. `DEFAULT nextval('my_sequence')`. 404 // The passed-in column descriptor is mutated, and the modified sequence descriptors are returned. 405 func maybeAddSequenceDependencies( 406 ctx context.Context, 407 sc resolver.SchemaResolver, 408 tableDesc *sqlbase.MutableTableDescriptor, 409 col *sqlbase.ColumnDescriptor, 410 expr tree.TypedExpr, 411 backrefs map[sqlbase.ID]*sqlbase.MutableTableDescriptor, 412 ) ([]*MutableTableDescriptor, error) { 413 seqNames, err := getUsedSequenceNames(expr) 414 if err != nil { 415 return nil, err 416 } 417 var seqDescs []*MutableTableDescriptor 418 for _, seqName := range seqNames { 419 parsedSeqName, err := parser.ParseTableName(seqName) 420 if err != nil { 421 return nil, err 422 } 423 tn := parsedSeqName.ToTableName() 424 425 var seqDesc *MutableTableDescriptor 426 p, ok := sc.(*planner) 427 if ok { 428 seqDesc, err = p.ResolveMutableTableDescriptor(ctx, &tn, true /*required*/, resolver.ResolveRequireSequenceDesc) 429 if err != nil { 430 return nil, err 431 } 432 } else { 433 // This is only executed via IMPORT which uses its own resolver. 434 seqDesc, err = resolver.ResolveMutableExistingTableObject(ctx, sc, &tn, true /*required*/, resolver.ResolveRequireSequenceDesc) 435 if err != nil { 436 return nil, err 437 } 438 } 439 // If we had already modified this Sequence as part of this transaction, 440 // we only want to modify a single instance of it instead of overwriting it. 441 // So replace seqDesc with the descriptor that was previously modified. 442 if prev, ok := backrefs[seqDesc.ID]; ok { 443 seqDesc = prev 444 } 445 col.UsesSequenceIds = append(col.UsesSequenceIds, seqDesc.ID) 446 // Add reference from sequence descriptor to column. 447 refIdx := -1 448 for i, reference := range seqDesc.DependedOnBy { 449 if reference.ID == tableDesc.ID { 450 refIdx = i 451 } 452 } 453 if refIdx == -1 { 454 seqDesc.DependedOnBy = append(seqDesc.DependedOnBy, sqlbase.TableDescriptor_Reference{ 455 ID: tableDesc.ID, 456 ColumnIDs: []sqlbase.ColumnID{col.ID}, 457 }) 458 } else { 459 seqDesc.DependedOnBy[refIdx].ColumnIDs = append(seqDesc.DependedOnBy[refIdx].ColumnIDs, col.ID) 460 } 461 seqDescs = append(seqDescs, seqDesc) 462 } 463 return seqDescs, nil 464 } 465 466 // dropSequencesOwnedByCol drops all the sequences from col.OwnsSequenceIDs. 467 // Called when the respective column (or the whole table) is being dropped. 468 func (p *planner) dropSequencesOwnedByCol( 469 ctx context.Context, col *sqlbase.ColumnDescriptor, 470 ) error { 471 for _, sequenceID := range col.OwnsSequenceIds { 472 seqDesc, err := p.Tables().GetMutableTableVersionByID(ctx, sequenceID, p.txn) 473 if err != nil { 474 return err 475 } 476 jobDesc := fmt.Sprintf("removing sequence %q dependent on column %q which is being dropped", 477 seqDesc.Name, col.ColName()) 478 if err := p.dropSequenceImpl( 479 ctx, seqDesc, true /* queueJob */, jobDesc, tree.DropRestrict, 480 ); err != nil { 481 return err 482 } 483 } 484 return nil 485 } 486 487 // removeSequenceDependencies: 488 // - removes the reference from the column descriptor to the sequence descriptor. 489 // - removes the reference from the sequence descriptor to the column descriptor. 490 // - writes the sequence descriptor and notifies a schema change. 491 // The column descriptor is mutated but not saved to persistent storage; the caller must save it. 492 func (p *planner) removeSequenceDependencies( 493 ctx context.Context, tableDesc *sqlbase.MutableTableDescriptor, col *sqlbase.ColumnDescriptor, 494 ) error { 495 for _, sequenceID := range col.UsesSequenceIds { 496 // Get the sequence descriptor so we can remove the reference from it. 497 seqDesc, err := p.Tables().GetMutableTableVersionByID(ctx, sequenceID, p.txn) 498 if err != nil { 499 return err 500 } 501 // Find the item in seqDesc.DependedOnBy which references tableDesc and col. 502 refTableIdx := -1 503 refColIdx := -1 504 found: 505 for i, reference := range seqDesc.DependedOnBy { 506 if reference.ID == tableDesc.ID { 507 refTableIdx = i 508 for j, colRefID := range seqDesc.DependedOnBy[i].ColumnIDs { 509 if colRefID == col.ID { 510 refColIdx = j 511 break found 512 } 513 // Before #40852, columnIDs stored in the SeqDesc were 0 as they hadn't 514 // been allocated then. The 0 check prevents older descs from breaking. 515 // Do not break though, as we still want to search in case the actual ID 516 // exists. 517 if colRefID == 0 { 518 refColIdx = j 519 } 520 } 521 } 522 } 523 if refColIdx == -1 { 524 return errors.AssertionFailedf("couldn't find reference from sequence to this column") 525 } 526 // Remove the column ID from the sequence descriptors list of things that 527 // depend on it. If the column was the only column that depended on the 528 // sequence, remove the table reference from the sequence as well. 529 seqDesc.DependedOnBy[refTableIdx].ColumnIDs = append( 530 seqDesc.DependedOnBy[refTableIdx].ColumnIDs[:refColIdx], 531 seqDesc.DependedOnBy[refTableIdx].ColumnIDs[refColIdx+1:]...) 532 533 if len(seqDesc.DependedOnBy[refTableIdx].ColumnIDs) == 0 { 534 seqDesc.DependedOnBy = append( 535 seqDesc.DependedOnBy[:refTableIdx], 536 seqDesc.DependedOnBy[refTableIdx+1:]...) 537 } 538 539 jobDesc := fmt.Sprintf("removing sequence %q dependent on column %q which is being dropped", 540 seqDesc.Name, col.ColName()) 541 if err := p.writeSchemaChange( 542 ctx, seqDesc, sqlbase.InvalidMutationID, jobDesc, 543 ); err != nil { 544 return err 545 } 546 } 547 // Remove the reference from the column descriptor to the sequence descriptor. 548 col.UsesSequenceIds = []sqlbase.ID{} 549 return nil 550 } 551 552 // getUsedSequenceNames returns the name of the sequence passed to 553 // a call to nextval in the given expression, or nil if there is 554 // no call to nextval. 555 // e.g. nextval('foo') => "foo"; <some other expression> => nil 556 func getUsedSequenceNames(defaultExpr tree.TypedExpr) ([]string, error) { 557 searchPath := sessiondata.SearchPath{} 558 var names []string 559 _, err := tree.SimpleVisit( 560 defaultExpr, 561 func(expr tree.Expr) (recurse bool, newExpr tree.Expr, err error) { 562 switch t := expr.(type) { 563 case *tree.FuncExpr: 564 def, err := t.Func.Resolve(searchPath) 565 if err != nil { 566 return false, expr, err 567 } 568 if def.Name == "nextval" { 569 arg := t.Exprs[0] 570 switch a := arg.(type) { 571 case *tree.DString: 572 names = append(names, string(*a)) 573 } 574 } 575 } 576 return true, expr, nil 577 }, 578 ) 579 if err != nil { 580 return nil, err 581 } 582 return names, nil 583 }