github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/alter_table.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 "bytes" 15 "context" 16 gojson "encoding/json" 17 "fmt" 18 19 "github.com/cockroachdb/cockroach/pkg/keys" 20 "github.com/cockroachdb/cockroach/pkg/security" 21 "github.com/cockroachdb/cockroach/pkg/server/telemetry" 22 "github.com/cockroachdb/cockroach/pkg/sql/catalog/resolver" 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/schemaexpr" 27 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 28 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 29 "github.com/cockroachdb/cockroach/pkg/sql/sqltelemetry" 30 "github.com/cockroachdb/cockroach/pkg/sql/stats" 31 "github.com/cockroachdb/cockroach/pkg/sql/types" 32 "github.com/cockroachdb/cockroach/pkg/util/protoutil" 33 "github.com/cockroachdb/errors" 34 "github.com/gogo/protobuf/proto" 35 ) 36 37 type alterTableNode struct { 38 n *tree.AlterTable 39 tableDesc *MutableTableDescriptor 40 // statsData is populated with data for "alter table inject statistics" 41 // commands - the JSON stats expressions. 42 // It is parallel with n.Cmds (for the inject stats commands). 43 statsData map[int]tree.TypedExpr 44 } 45 46 // AlterTable applies a schema change on a table. 47 // Privileges: CREATE on table. 48 // notes: postgres requires CREATE on the table. 49 // mysql requires ALTER, CREATE, INSERT on the table. 50 func (p *planner) AlterTable(ctx context.Context, n *tree.AlterTable) (planNode, error) { 51 tableDesc, err := p.ResolveMutableTableDescriptorEx( 52 ctx, n.Table, !n.IfExists, resolver.ResolveRequireTableDesc, 53 ) 54 if errors.Is(err, resolver.ErrNoPrimaryKey) { 55 if len(n.Cmds) > 0 && isAlterCmdValidWithoutPrimaryKey(n.Cmds[0]) { 56 tableDesc, err = p.ResolveMutableTableDescriptorExAllowNoPrimaryKey( 57 ctx, n.Table, !n.IfExists, resolver.ResolveRequireTableDesc, 58 ) 59 } 60 } 61 if err != nil { 62 return nil, err 63 } 64 65 if tableDesc == nil { 66 return newZeroNode(nil /* columns */), nil 67 } 68 69 if err := p.CheckPrivilege(ctx, tableDesc, privilege.CREATE); err != nil { 70 return nil, err 71 } 72 73 n.HoistAddColumnConstraints() 74 75 // See if there's any "inject statistics" in the query and type check the 76 // expressions. 77 statsData := make(map[int]tree.TypedExpr) 78 for i, cmd := range n.Cmds { 79 injectStats, ok := cmd.(*tree.AlterTableInjectStats) 80 if !ok { 81 continue 82 } 83 typedExpr, err := p.analyzeExpr( 84 ctx, injectStats.Stats, 85 nil, /* sources - no name resolution */ 86 tree.IndexedVarHelper{}, 87 types.Jsonb, true, /* requireType */ 88 "INJECT STATISTICS" /* typingContext */) 89 if err != nil { 90 return nil, err 91 } 92 statsData[i] = typedExpr 93 } 94 95 return &alterTableNode{ 96 n: n, 97 tableDesc: tableDesc, 98 statsData: statsData, 99 }, nil 100 } 101 102 func isAlterCmdValidWithoutPrimaryKey(cmd tree.AlterTableCmd) bool { 103 switch t := cmd.(type) { 104 case *tree.AlterTableAlterPrimaryKey: 105 return true 106 case *tree.AlterTableAddConstraint: 107 cs, ok := t.ConstraintDef.(*tree.UniqueConstraintTableDef) 108 if ok && cs.PrimaryKey { 109 return true 110 } 111 default: 112 return false 113 } 114 return false 115 } 116 117 // ReadingOwnWrites implements the planNodeReadingOwnWrites interface. 118 // This is because ALTER TABLE performs multiple KV operations on descriptors 119 // and expects to see its own writes. 120 func (n *alterTableNode) ReadingOwnWrites() {} 121 122 func (n *alterTableNode) startExec(params runParams) error { 123 telemetry.Inc(sqltelemetry.SchemaChangeAlterCounter("table")) 124 125 // Commands can either change the descriptor directly (for 126 // alterations that don't require a backfill) or add a mutation to 127 // the list. 128 descriptorChanged := false 129 origNumMutations := len(n.tableDesc.Mutations) 130 var droppedViews []string 131 resolved := params.p.ResolvedName(n.n.Table) 132 tn, ok := resolved.(*tree.TableName) 133 if !ok { 134 return errors.AssertionFailedf( 135 "%q was not resolved as a table but is %T", resolved, resolved) 136 } 137 138 for i, cmd := range n.n.Cmds { 139 telemetry.Inc(cmd.TelemetryCounter()) 140 141 if !n.tableDesc.HasPrimaryKey() && !isAlterCmdValidWithoutPrimaryKey(cmd) { 142 return errors.Newf("table %q does not have a primary key, cannot perform%s", n.tableDesc.Name, tree.AsString(cmd)) 143 } 144 145 switch t := cmd.(type) { 146 case *tree.AlterTableAddColumn: 147 d := t.ColumnDef 148 version := params.ExecCfg().Settings.Version.ActiveVersionOrEmpty(params.ctx) 149 toType, err := tree.ResolveType(params.ctx, d.Type, params.p.semaCtx.GetTypeResolver()) 150 if err != nil { 151 return err 152 } 153 if supported, err := isTypeSupportedInVersion(version, toType); err != nil { 154 return err 155 } else if !supported { 156 return pgerror.Newf( 157 pgcode.FeatureNotSupported, 158 "type %s is not supported until version upgrade is finalized", 159 toType.SQLString(), 160 ) 161 } 162 163 newDef, seqDbDesc, seqName, seqOpts, err := params.p.processSerialInColumnDef(params.ctx, d, tn) 164 if err != nil { 165 return err 166 } 167 if seqName != nil { 168 if err := doCreateSequence( 169 params, 170 n.n.String(), 171 seqDbDesc, 172 n.tableDesc.GetParentSchemaID(), 173 seqName, 174 n.tableDesc.Temporary, 175 seqOpts, 176 tree.AsStringWithFQNames(n.n, params.Ann()), 177 ); err != nil { 178 return err 179 } 180 } 181 d = newDef 182 incTelemetryForNewColumn(d) 183 184 col, idx, expr, err := sqlbase.MakeColumnDefDescs(params.ctx, d, ¶ms.p.semaCtx, params.EvalContext()) 185 if err != nil { 186 return err 187 } 188 // If the new column has a DEFAULT expression that uses a sequence, add references between 189 // its descriptor and this column descriptor. 190 if d.HasDefaultExpr() { 191 changedSeqDescs, err := maybeAddSequenceDependencies( 192 params.ctx, params.p, n.tableDesc, col, expr, nil, 193 ) 194 if err != nil { 195 return err 196 } 197 for _, changedSeqDesc := range changedSeqDescs { 198 if err := params.p.writeSchemaChange( 199 params.ctx, changedSeqDesc, sqlbase.InvalidMutationID, tree.AsStringWithFQNames(n.n, params.Ann()), 200 ); err != nil { 201 return err 202 } 203 } 204 } 205 206 // We're checking to see if a user is trying add a non-nullable column without a default to a 207 // non empty table by scanning the primary index span with a limit of 1 to see if any key exists. 208 if !col.Nullable && (col.DefaultExpr == nil && !col.IsComputed()) { 209 span := n.tableDesc.PrimaryIndexSpan(params.ExecCfg().Codec) 210 kvs, err := params.p.txn.Scan(params.ctx, span.Key, span.EndKey, 1) 211 if err != nil { 212 return err 213 } 214 if len(kvs) > 0 { 215 return sqlbase.NewNonNullViolationError(col.Name) 216 } 217 } 218 _, err = n.tableDesc.FindActiveColumnByName(string(d.Name)) 219 if m := n.tableDesc.FindColumnMutationByName(d.Name); m != nil { 220 switch m.Direction { 221 case sqlbase.DescriptorMutation_ADD: 222 return pgerror.Newf(pgcode.DuplicateColumn, 223 "duplicate: column %q in the middle of being added, not yet public", 224 col.Name) 225 case sqlbase.DescriptorMutation_DROP: 226 return pgerror.Newf(pgcode.ObjectNotInPrerequisiteState, 227 "column %q being dropped, try again later", col.Name) 228 default: 229 if err != nil { 230 return errors.AssertionFailedf( 231 "mutation in state %s, direction %s, and no column descriptor", 232 errors.Safe(m.State), errors.Safe(m.Direction)) 233 } 234 } 235 } 236 if err == nil { 237 if t.IfNotExists { 238 continue 239 } 240 return sqlbase.NewColumnAlreadyExistsError(string(d.Name), n.tableDesc.Name) 241 } 242 243 n.tableDesc.AddColumnMutation(col, sqlbase.DescriptorMutation_ADD) 244 if idx != nil { 245 if err := n.tableDesc.AddIndexMutation(idx, sqlbase.DescriptorMutation_ADD); err != nil { 246 return err 247 } 248 } 249 if d.HasColumnFamily() { 250 err := n.tableDesc.AddColumnToFamilyMaybeCreate( 251 col.Name, string(d.Family.Name), d.Family.Create, 252 d.Family.IfNotExists) 253 if err != nil { 254 return err 255 } 256 } 257 258 if d.IsComputed() { 259 computedColValidator := schemaexpr.NewComputedColumnValidator(params.ctx, n.tableDesc, ¶ms.p.semaCtx) 260 if err := computedColValidator.Validate(d); err != nil { 261 return err 262 } 263 } 264 265 case *tree.AlterTableAddConstraint: 266 switch d := t.ConstraintDef.(type) { 267 case *tree.UniqueConstraintTableDef: 268 if d.PrimaryKey { 269 // We only support "adding" a primary key when we are using the 270 // default rowid primary index or if a DROP PRIMARY KEY statement 271 // was processed before this statement. If a DROP PRIMARY KEY 272 // statement was processed, then n.tableDesc.HasPrimaryKey() = false. 273 if n.tableDesc.HasPrimaryKey() && !n.tableDesc.IsPrimaryIndexDefaultRowID() { 274 return pgerror.Newf(pgcode.InvalidTableDefinition, 275 "multiple primary keys for table %q are not allowed", n.tableDesc.Name) 276 } 277 278 // Translate this operation into an ALTER PRIMARY KEY command. 279 alterPK := &tree.AlterTableAlterPrimaryKey{ 280 Columns: d.Columns, 281 Sharded: d.Sharded, 282 Interleave: d.Interleave, 283 } 284 if err := params.p.AlterPrimaryKey(params.ctx, n.tableDesc, alterPK); err != nil { 285 return err 286 } 287 continue 288 } 289 idx := sqlbase.IndexDescriptor{ 290 Name: string(d.Name), 291 Unique: true, 292 StoreColumnNames: d.Storing.ToStrings(), 293 } 294 if err := idx.FillColumns(d.Columns); err != nil { 295 return err 296 } 297 if d.PartitionBy != nil { 298 partitioning, err := CreatePartitioning( 299 params.ctx, params.p.ExecCfg().Settings, 300 params.EvalContext(), n.tableDesc, &idx, d.PartitionBy) 301 if err != nil { 302 return err 303 } 304 idx.Partitioning = partitioning 305 } 306 _, dropped, err := n.tableDesc.FindIndexByName(string(d.Name)) 307 if err == nil { 308 if dropped { 309 return pgerror.Newf(pgcode.ObjectNotInPrerequisiteState, 310 "index %q being dropped, try again later", d.Name) 311 } 312 } 313 if err := n.tableDesc.AddIndexMutation(&idx, sqlbase.DescriptorMutation_ADD); err != nil { 314 return err 315 } 316 317 case *tree.CheckConstraintTableDef: 318 info, err := n.tableDesc.GetConstraintInfo(params.ctx, nil, params.ExecCfg().Codec) 319 if err != nil { 320 return err 321 } 322 ckBuilder := schemaexpr.NewCheckConstraintBuilder(params.ctx, *tn, n.tableDesc, ¶ms.p.semaCtx) 323 for k := range info { 324 ckBuilder.MarkNameInUse(k) 325 } 326 ck, err := ckBuilder.Build(d) 327 if err != nil { 328 return err 329 } 330 if t.ValidationBehavior == tree.ValidationDefault { 331 ck.Validity = sqlbase.ConstraintValidity_Validating 332 } else { 333 ck.Validity = sqlbase.ConstraintValidity_Unvalidated 334 } 335 n.tableDesc.AddCheckMutation(ck, sqlbase.DescriptorMutation_ADD) 336 337 case *tree.ForeignKeyConstraintTableDef: 338 for _, colName := range d.FromCols { 339 col, err := n.tableDesc.FindActiveOrNewColumnByName(colName) 340 if err != nil { 341 return err 342 } 343 344 if err := col.CheckCanBeFKRef(); err != nil { 345 return err 346 } 347 } 348 affected := make(map[sqlbase.ID]*sqlbase.MutableTableDescriptor) 349 350 // If there are any FKs, we will need to update the table descriptor of the 351 // depended-on table (to register this table against its DependedOnBy field). 352 // This descriptor must be looked up uncached, and we'll allow FK dependencies 353 // on tables that were just added. See the comment at the start of 354 // the global-scope resolveFK(). 355 // TODO(vivek): check if the cache can be used. 356 var err error 357 params.p.runWithOptions(resolveFlags{skipCache: true}, func() { 358 // Check whether the table is empty, and pass the result to resolveFK(). If 359 // the table is empty, then resolveFK will automatically add the necessary 360 // index for a fk constraint if the index does not exist. 361 span := n.tableDesc.PrimaryIndexSpan(params.ExecCfg().Codec) 362 kvs, scanErr := params.p.txn.Scan(params.ctx, span.Key, span.EndKey, 1) 363 if scanErr != nil { 364 err = scanErr 365 return 366 } 367 var tableState FKTableState 368 if len(kvs) == 0 { 369 tableState = EmptyTable 370 } else { 371 tableState = NonEmptyTable 372 } 373 err = params.p.resolveFK(params.ctx, n.tableDesc, d, affected, tableState, t.ValidationBehavior) 374 }) 375 if err != nil { 376 return err 377 } 378 descriptorChanged = true 379 for _, updated := range affected { 380 if err := params.p.writeSchemaChange( 381 params.ctx, updated, sqlbase.InvalidMutationID, tree.AsStringWithFQNames(n.n, params.Ann()), 382 ); err != nil { 383 return err 384 } 385 } 386 // TODO(lucy): Validate() can't be called here because it reads the 387 // referenced table descs, which may have to be upgraded to the new FK 388 // representation. That requires reading the original table descriptor 389 // (which the backreference points to) from KV, but we haven't written 390 // the updated table desc yet. We can restore the call to Validate() 391 // after running a migration of all table descriptors, making it 392 // unnecessary to read the original table desc from KV. 393 // if err := n.tableDesc.Validate(params.ctx, params.p.txn); err != nil { 394 // return err 395 // } 396 397 default: 398 return errors.AssertionFailedf( 399 "unsupported constraint: %T", t.ConstraintDef) 400 } 401 402 case *tree.AlterTableAlterPrimaryKey: 403 if err := params.p.AlterPrimaryKey(params.ctx, n.tableDesc, t); err != nil { 404 return err 405 } 406 // Mark descriptorChanged so that a mutation job is scheduled at the end of startExec. 407 descriptorChanged = true 408 409 case *tree.AlterTableDropColumn: 410 if params.SessionData().SafeUpdates { 411 return pgerror.DangerousStatementf("ALTER TABLE DROP COLUMN will remove all data in that column") 412 } 413 414 colToDrop, dropped, err := n.tableDesc.FindColumnByName(t.Column) 415 if err != nil { 416 if t.IfExists { 417 // Noop. 418 continue 419 } 420 return err 421 } 422 if dropped { 423 continue 424 } 425 426 // If the dropped column uses a sequence, remove references to it from that sequence. 427 if len(colToDrop.UsesSequenceIds) > 0 { 428 if err := params.p.removeSequenceDependencies(params.ctx, n.tableDesc, colToDrop); err != nil { 429 return err 430 } 431 } 432 433 // You can't remove a column that owns a sequence that is depended on 434 // by another column 435 if err := params.p.canRemoveAllColumnOwnedSequences(params.ctx, n.tableDesc, colToDrop, t.DropBehavior); err != nil { 436 return err 437 } 438 439 if err := params.p.dropSequencesOwnedByCol(params.ctx, colToDrop); err != nil { 440 return err 441 } 442 443 // You can't drop a column depended on by a view unless CASCADE was 444 // specified. 445 for _, ref := range n.tableDesc.DependedOnBy { 446 found := false 447 for _, colID := range ref.ColumnIDs { 448 if colID == colToDrop.ID { 449 found = true 450 break 451 } 452 } 453 if !found { 454 continue 455 } 456 err := params.p.canRemoveDependentViewGeneric( 457 params.ctx, "column", string(t.Column), n.tableDesc.ParentID, ref, t.DropBehavior, 458 ) 459 if err != nil { 460 return err 461 } 462 viewDesc, err := params.p.getViewDescForCascade( 463 params.ctx, "column", string(t.Column), n.tableDesc.ParentID, ref.ID, t.DropBehavior, 464 ) 465 if err != nil { 466 return err 467 } 468 jobDesc := fmt.Sprintf("removing view %q dependent on column %q which is being dropped", 469 viewDesc.Name, colToDrop.ColName()) 470 droppedViews, err = params.p.removeDependentView(params.ctx, n.tableDesc, viewDesc, jobDesc) 471 if err != nil { 472 return err 473 } 474 } 475 476 // We cannot remove this column if there are computed columns that use it. 477 computedColValidator := schemaexpr.NewComputedColumnValidator(params.ctx, n.tableDesc, ¶ms.p.semaCtx) 478 if err := computedColValidator.ValidateNoDependents(colToDrop); err != nil { 479 return err 480 } 481 482 if n.tableDesc.PrimaryIndex.ContainsColumnID(colToDrop.ID) { 483 return pgerror.Newf(pgcode.InvalidColumnReference, 484 "column %q is referenced by the primary key", colToDrop.Name) 485 } 486 for _, idx := range n.tableDesc.AllNonDropIndexes() { 487 // We automatically drop indexes on that column that only 488 // index that column (and no other columns). If CASCADE is 489 // specified, we also drop other indices that refer to this 490 // column. The criteria to determine whether an index "only 491 // indexes that column": 492 // 493 // Assume a table created with CREATE TABLE foo (a INT, b INT). 494 // Then assume the user issues ALTER TABLE foo DROP COLUMN a. 495 // 496 // INDEX i1 ON foo(a) -> i1 deleted 497 // INDEX i2 ON foo(a) STORING(b) -> i2 deleted 498 // INDEX i3 ON foo(a, b) -> i3 not deleted unless CASCADE is specified. 499 // INDEX i4 ON foo(b) STORING(a) -> i4 not deleted unless CASCADE is specified. 500 501 // containsThisColumn becomes true if the index is defined 502 // over the column being dropped. 503 containsThisColumn := false 504 // containsOnlyThisColumn becomes false if the index also 505 // includes non-PK columns other than the one being dropped. 506 containsOnlyThisColumn := true 507 508 // Analyze the index. 509 for _, id := range idx.ColumnIDs { 510 if id == colToDrop.ID { 511 containsThisColumn = true 512 } else { 513 containsOnlyThisColumn = false 514 } 515 } 516 for _, id := range idx.ExtraColumnIDs { 517 if n.tableDesc.PrimaryIndex.ContainsColumnID(id) { 518 // All secondary indices necessary contain the PK 519 // columns, too. (See the comments on the definition of 520 // IndexDescriptor). The presence of a PK column in the 521 // secondary index should thus not be seen as a 522 // sufficient reason to reject the DROP. 523 continue 524 } 525 if id == colToDrop.ID { 526 containsThisColumn = true 527 } 528 } 529 // The loop above this comment is for the old STORING encoding. The 530 // loop below is for the new encoding (where the STORING columns are 531 // always in the value part of a KV). 532 for _, id := range idx.StoreColumnIDs { 533 if id == colToDrop.ID { 534 containsThisColumn = true 535 } 536 } 537 538 // Perform the DROP. 539 if containsThisColumn { 540 if containsOnlyThisColumn || t.DropBehavior == tree.DropCascade { 541 jobDesc := fmt.Sprintf("removing index %q dependent on column %q which is being"+ 542 " dropped; full details: %s", idx.Name, colToDrop.ColName(), 543 tree.AsStringWithFQNames(n.n, params.Ann())) 544 if err := params.p.dropIndexByName( 545 params.ctx, tn, tree.UnrestrictedName(idx.Name), n.tableDesc, false, 546 t.DropBehavior, ignoreIdxConstraint, jobDesc, 547 ); err != nil { 548 return err 549 } 550 } else { 551 return pgerror.Newf(pgcode.InvalidColumnReference, 552 "column %q is referenced by existing index %q", colToDrop.Name, idx.Name) 553 } 554 } 555 } 556 557 // Drop check constraints which reference the column. 558 // Note that foreign key constraints are dropped as part of dropping 559 // indexes on the column. In the future, when FKs no longer depend on 560 // indexes in the same way, FKs will have to be dropped separately here. 561 validChecks := n.tableDesc.Checks[:0] 562 for _, check := range n.tableDesc.AllActiveAndInactiveChecks() { 563 if used, err := check.UsesColumn(n.tableDesc.TableDesc(), colToDrop.ID); err != nil { 564 return err 565 } else if used { 566 if check.Validity == sqlbase.ConstraintValidity_Validating { 567 return pgerror.Newf(pgcode.ObjectNotInPrerequisiteState, 568 "referencing constraint %q in the middle of being added, try again later", check.Name) 569 } 570 } else { 571 validChecks = append(validChecks, check) 572 } 573 } 574 575 if len(validChecks) != len(n.tableDesc.Checks) { 576 n.tableDesc.Checks = validChecks 577 descriptorChanged = true 578 } 579 580 if err != nil { 581 return err 582 } 583 if err := params.p.removeColumnComment(params.ctx, n.tableDesc.ID, colToDrop.ID); err != nil { 584 return err 585 } 586 587 found := false 588 for i := range n.tableDesc.Columns { 589 if n.tableDesc.Columns[i].ID == colToDrop.ID { 590 n.tableDesc.AddColumnMutation(colToDrop, sqlbase.DescriptorMutation_DROP) 591 // Use [:i:i] to prevent reuse of existing slice, or outstanding refs 592 // to ColumnDescriptors may unexpectedly change. 593 n.tableDesc.Columns = append(n.tableDesc.Columns[:i:i], n.tableDesc.Columns[i+1:]...) 594 found = true 595 break 596 } 597 } 598 if !found { 599 return pgerror.Newf(pgcode.ObjectNotInPrerequisiteState, 600 "column %q in the middle of being added, try again later", t.Column) 601 } 602 if err := n.tableDesc.Validate(params.ctx, params.p.txn, params.ExecCfg().Codec); err != nil { 603 return err 604 } 605 606 case *tree.AlterTableDropConstraint: 607 info, err := n.tableDesc.GetConstraintInfo(params.ctx, nil, params.ExecCfg().Codec) 608 if err != nil { 609 return err 610 } 611 name := string(t.Constraint) 612 details, ok := info[name] 613 if !ok { 614 if t.IfExists { 615 continue 616 } 617 return pgerror.Newf(pgcode.UndefinedObject, 618 "constraint %q does not exist", t.Constraint) 619 } 620 if err := n.tableDesc.DropConstraint( 621 params.ctx, 622 name, details, 623 func(desc *sqlbase.MutableTableDescriptor, ref *sqlbase.ForeignKeyConstraint) error { 624 return params.p.removeFKBackReference(params.ctx, desc, ref) 625 }, params.ExecCfg().Settings); err != nil { 626 return err 627 } 628 descriptorChanged = true 629 if err := n.tableDesc.Validate(params.ctx, params.p.txn, params.ExecCfg().Codec); err != nil { 630 return err 631 } 632 633 case *tree.AlterTableValidateConstraint: 634 info, err := n.tableDesc.GetConstraintInfo(params.ctx, nil, params.ExecCfg().Codec) 635 if err != nil { 636 return err 637 } 638 name := string(t.Constraint) 639 constraint, ok := info[name] 640 if !ok { 641 return pgerror.Newf(pgcode.UndefinedObject, 642 "constraint %q does not exist", t.Constraint) 643 } 644 if !constraint.Unvalidated { 645 continue 646 } 647 switch constraint.Kind { 648 case sqlbase.ConstraintTypeCheck: 649 found := false 650 var ck *sqlbase.TableDescriptor_CheckConstraint 651 for _, c := range n.tableDesc.Checks { 652 // If the constraint is still being validated, don't allow VALIDATE CONSTRAINT to run 653 if c.Name == name && c.Validity != sqlbase.ConstraintValidity_Validating { 654 found = true 655 ck = c 656 break 657 } 658 } 659 if !found { 660 return pgerror.Newf(pgcode.ObjectNotInPrerequisiteState, 661 "constraint %q in the middle of being added, try again later", t.Constraint) 662 } 663 if err := validateCheckInTxn( 664 params.ctx, params.p.LeaseMgr(), params.EvalContext(), n.tableDesc, params.EvalContext().Txn, name, 665 ); err != nil { 666 return err 667 } 668 ck.Validity = sqlbase.ConstraintValidity_Validated 669 670 case sqlbase.ConstraintTypeFK: 671 var foundFk *sqlbase.ForeignKeyConstraint 672 for i := range n.tableDesc.OutboundFKs { 673 fk := &n.tableDesc.OutboundFKs[i] 674 // If the constraint is still being validated, don't allow VALIDATE CONSTRAINT to run 675 if fk.Name == name && fk.Validity != sqlbase.ConstraintValidity_Validating { 676 foundFk = fk 677 break 678 } 679 } 680 if foundFk == nil { 681 return pgerror.Newf(pgcode.ObjectNotInPrerequisiteState, 682 "constraint %q in the middle of being added, try again later", t.Constraint) 683 } 684 if err := validateFkInTxn( 685 params.ctx, params.p.LeaseMgr(), params.EvalContext(), n.tableDesc, params.EvalContext().Txn, name, 686 ); err != nil { 687 return err 688 } 689 foundFk.Validity = sqlbase.ConstraintValidity_Validated 690 691 default: 692 return pgerror.Newf(pgcode.WrongObjectType, 693 "constraint %q of relation %q is not a foreign key or check constraint", 694 tree.ErrString(&t.Constraint), tree.ErrString(n.n.Table)) 695 } 696 descriptorChanged = true 697 698 case tree.ColumnMutationCmd: 699 // Column mutations 700 col, dropped, err := n.tableDesc.FindColumnByName(t.GetColumn()) 701 if err != nil { 702 return err 703 } 704 if dropped { 705 return pgerror.Newf(pgcode.ObjectNotInPrerequisiteState, 706 "column %q in the middle of being dropped", t.GetColumn()) 707 } 708 // Apply mutations to copy of column descriptor. 709 if err := applyColumnMutation(params.ctx, n.tableDesc, col, t, params, n.n.Cmds); err != nil { 710 return err 711 } 712 descriptorChanged = true 713 714 case *tree.AlterTablePartitionBy: 715 partitioning, err := CreatePartitioning( 716 params.ctx, params.p.ExecCfg().Settings, 717 params.EvalContext(), 718 n.tableDesc, &n.tableDesc.PrimaryIndex, t.PartitionBy) 719 if err != nil { 720 return err 721 } 722 descriptorChanged = !proto.Equal( 723 &n.tableDesc.PrimaryIndex.Partitioning, 724 &partitioning, 725 ) 726 err = deleteRemovedPartitionZoneConfigs( 727 params.ctx, params.p.txn, 728 n.tableDesc.TableDesc(), &n.tableDesc.PrimaryIndex, &n.tableDesc.PrimaryIndex.Partitioning, 729 &partitioning, params.extendedEvalCtx.ExecCfg, 730 ) 731 if err != nil { 732 return err 733 } 734 n.tableDesc.PrimaryIndex.Partitioning = partitioning 735 736 case *tree.AlterTableSetAudit: 737 var err error 738 descriptorChanged, err = params.p.setAuditMode(params.ctx, n.tableDesc.TableDesc(), t.Mode) 739 if err != nil { 740 return err 741 } 742 743 case *tree.AlterTableInjectStats: 744 sd, ok := n.statsData[i] 745 if !ok { 746 return errors.AssertionFailedf("missing stats data") 747 } 748 if !params.p.EvalContext().TxnImplicit { 749 return errors.New("cannot inject statistics in an explicit transaction") 750 } 751 if err := injectTableStats(params, n.tableDesc.TableDesc(), sd); err != nil { 752 return err 753 } 754 755 case *tree.AlterTableRenameColumn: 756 const allowRenameOfShardColumn = false 757 descChanged, err := params.p.renameColumn(params.ctx, n.tableDesc, 758 &t.Column, &t.NewName, allowRenameOfShardColumn) 759 if err != nil { 760 return err 761 } 762 descriptorChanged = descChanged 763 764 case *tree.AlterTableRenameConstraint: 765 info, err := n.tableDesc.GetConstraintInfo(params.ctx, nil, params.ExecCfg().Codec) 766 if err != nil { 767 return err 768 } 769 details, ok := info[string(t.Constraint)] 770 if !ok { 771 return pgerror.Newf(pgcode.UndefinedObject, 772 "constraint %q does not exist", tree.ErrString(&t.Constraint)) 773 } 774 if t.Constraint == t.NewName { 775 // Nothing to do. 776 break 777 } 778 779 if _, ok := info[string(t.NewName)]; ok { 780 return pgerror.Newf(pgcode.DuplicateObject, 781 "duplicate constraint name: %q", tree.ErrString(&t.NewName)) 782 } 783 784 if err := params.p.CheckPrivilege(params.ctx, n.tableDesc, privilege.CREATE); err != nil { 785 return err 786 } 787 788 depViewRenameError := func(objType string, refTableID sqlbase.ID) error { 789 return params.p.dependentViewRenameError(params.ctx, 790 objType, tree.ErrString(&t.NewName), n.tableDesc.ParentID, refTableID) 791 } 792 793 if err := n.tableDesc.RenameConstraint( 794 details, string(t.Constraint), string(t.NewName), depViewRenameError, func(desc *MutableTableDescriptor, ref *sqlbase.ForeignKeyConstraint, newName string) error { 795 return params.p.updateFKBackReferenceName(params.ctx, desc, ref, newName) 796 }); err != nil { 797 return err 798 } 799 descriptorChanged = true 800 801 default: 802 return errors.AssertionFailedf("unsupported alter command: %T", cmd) 803 } 804 805 // Allocate IDs now, so new IDs are available to subsequent commands 806 if err := n.tableDesc.AllocateIDs(); err != nil { 807 return err 808 } 809 } 810 // Were some changes made? 811 // 812 // This is only really needed for the unittests that add dummy mutations 813 // before calling ALTER TABLE commands. We do not want to apply those 814 // dummy mutations. Most tests trigger errors above 815 // this line, but tests that run redundant operations like dropping 816 // a column when it's already dropped will hit this condition and exit. 817 addedMutations := len(n.tableDesc.Mutations) > origNumMutations 818 if !addedMutations && !descriptorChanged { 819 return nil 820 } 821 822 mutationID := sqlbase.InvalidMutationID 823 if addedMutations { 824 mutationID = n.tableDesc.ClusterVersion.NextMutationID 825 } 826 if err := params.p.writeSchemaChange( 827 params.ctx, n.tableDesc, mutationID, tree.AsStringWithFQNames(n.n, params.Ann()), 828 ); err != nil { 829 return err 830 } 831 832 // Record this table alteration in the event log. This is an auditable log 833 // event and is recorded in the same transaction as the table descriptor 834 // update. 835 return MakeEventLogger(params.extendedEvalCtx.ExecCfg).InsertEventRecord( 836 params.ctx, 837 params.p.txn, 838 EventLogAlterTable, 839 int32(n.tableDesc.ID), 840 int32(params.extendedEvalCtx.NodeID.SQLInstanceID()), 841 struct { 842 TableName string 843 Statement string 844 User string 845 MutationID uint32 846 CascadeDroppedViews []string 847 }{params.p.ResolvedName(n.n.Table).FQString(), n.n.String(), 848 params.SessionData().User, uint32(mutationID), droppedViews}, 849 ) 850 } 851 852 func (p *planner) setAuditMode( 853 ctx context.Context, desc *sqlbase.TableDescriptor, auditMode tree.AuditMode, 854 ) (bool, error) { 855 // An auditing config change is itself auditable! 856 // We record the event even if the permission check below fails: 857 // auditing wants to know who tried to change the settings. 858 p.curPlan.auditEvents = append(p.curPlan.auditEvents, 859 auditEvent{desc: desc, writing: true}) 860 861 // We require root for now. Later maybe use a different permission? 862 if err := p.RequireAdminRole(ctx, "change auditing settings on a table"); err != nil { 863 return false, err 864 } 865 866 telemetry.Inc(sqltelemetry.SchemaSetAuditModeCounter(auditMode.TelemetryName())) 867 868 return desc.SetAuditMode(auditMode) 869 } 870 871 func (n *alterTableNode) Next(runParams) (bool, error) { return false, nil } 872 func (n *alterTableNode) Values() tree.Datums { return tree.Datums{} } 873 func (n *alterTableNode) Close(context.Context) {} 874 875 // addIndexMutationWithSpecificPrimaryKey adds an index mutation into the given table descriptor, but sets up 876 // the index with ExtraColumnIDs from the given index, rather than the table's primary key. 877 func addIndexMutationWithSpecificPrimaryKey( 878 table *sqlbase.MutableTableDescriptor, 879 toAdd *sqlbase.IndexDescriptor, 880 primary *sqlbase.IndexDescriptor, 881 ) error { 882 // Reset the ID so that a call to AllocateIDs will set up the index. 883 toAdd.ID = 0 884 if err := table.AddIndexMutation(toAdd, sqlbase.DescriptorMutation_ADD); err != nil { 885 return err 886 } 887 if err := table.AllocateIDs(); err != nil { 888 return err 889 } 890 // Use the columns in the given primary index to construct this indexes ExtraColumnIDs list. 891 toAdd.ExtraColumnIDs = nil 892 for _, colID := range primary.ColumnIDs { 893 if !toAdd.ContainsColumnID(colID) { 894 toAdd.ExtraColumnIDs = append(toAdd.ExtraColumnIDs, colID) 895 } 896 } 897 return nil 898 } 899 900 // applyColumnMutation applies the mutation specified in `mut` to the given 901 // columnDescriptor, and saves the containing table descriptor. If the column's 902 // dependencies on sequences change, it updates them as well. 903 func applyColumnMutation( 904 ctx context.Context, 905 tableDesc *sqlbase.MutableTableDescriptor, 906 col *sqlbase.ColumnDescriptor, 907 mut tree.ColumnMutationCmd, 908 params runParams, 909 cmds tree.AlterTableCmds, 910 ) error { 911 switch t := mut.(type) { 912 case *tree.AlterTableAlterColumnType: 913 return AlterColumnType(ctx, tableDesc, col, t, params, cmds) 914 915 case *tree.AlterTableSetDefault: 916 if len(col.UsesSequenceIds) > 0 { 917 if err := params.p.removeSequenceDependencies(params.ctx, tableDesc, col); err != nil { 918 return err 919 } 920 } 921 if t.Default == nil { 922 col.DefaultExpr = nil 923 } else { 924 colDatumType := col.Type 925 expr, err := sqlbase.SanitizeVarFreeExpr( 926 params.ctx, t.Default, colDatumType, "DEFAULT", ¶ms.p.semaCtx, true, /* allowImpure */ 927 ) 928 if err != nil { 929 return err 930 } 931 s := tree.Serialize(t.Default) 932 col.DefaultExpr = &s 933 934 // Add references to the sequence descriptors this column is now using. 935 changedSeqDescs, err := maybeAddSequenceDependencies( 936 params.ctx, params.p, tableDesc, col, expr, nil, /* backrefs */ 937 ) 938 if err != nil { 939 return err 940 } 941 for _, changedSeqDesc := range changedSeqDescs { 942 // TODO (lucy): Have more consistent/informative names for dependent jobs. 943 if err := params.p.writeSchemaChange( 944 params.ctx, changedSeqDesc, sqlbase.InvalidMutationID, "updating dependent sequence", 945 ); err != nil { 946 return err 947 } 948 } 949 } 950 951 case *tree.AlterTableSetNotNull: 952 if !col.Nullable { 953 return nil 954 } 955 // See if there's already a mutation to add a not null constraint 956 for i := range tableDesc.Mutations { 957 if constraint := tableDesc.Mutations[i].GetConstraint(); constraint != nil && 958 constraint.ConstraintType == sqlbase.ConstraintToUpdate_NOT_NULL && 959 constraint.NotNullColumn == col.ID { 960 if tableDesc.Mutations[i].Direction == sqlbase.DescriptorMutation_ADD { 961 return pgerror.Newf(pgcode.ObjectNotInPrerequisiteState, 962 "constraint in the middle of being added") 963 } 964 return pgerror.Newf(pgcode.ObjectNotInPrerequisiteState, 965 "constraint in the middle of being dropped, try again later") 966 } 967 } 968 969 info, err := tableDesc.GetConstraintInfo(params.ctx, nil, params.ExecCfg().Codec) 970 if err != nil { 971 return err 972 } 973 inuseNames := make(map[string]struct{}, len(info)) 974 for k := range info { 975 inuseNames[k] = struct{}{} 976 } 977 check := sqlbase.MakeNotNullCheckConstraint(col.Name, col.ID, inuseNames, sqlbase.ConstraintValidity_Validating) 978 tableDesc.AddNotNullMutation(check, sqlbase.DescriptorMutation_ADD) 979 980 case *tree.AlterTableDropNotNull: 981 if col.Nullable { 982 return nil 983 } 984 985 // Prevent a column in a primary key from becoming non-null. 986 if tableDesc.PrimaryIndex.ContainsColumnID(col.ID) { 987 return pgerror.Newf(pgcode.InvalidTableDefinition, 988 `column "%s" is in a primary index`, col.Name) 989 } 990 991 // See if there's already a mutation to add/drop a not null constraint. 992 for i := range tableDesc.Mutations { 993 if constraint := tableDesc.Mutations[i].GetConstraint(); constraint != nil && 994 constraint.ConstraintType == sqlbase.ConstraintToUpdate_NOT_NULL && 995 constraint.NotNullColumn == col.ID { 996 if tableDesc.Mutations[i].Direction == sqlbase.DescriptorMutation_ADD { 997 return pgerror.Newf(pgcode.ObjectNotInPrerequisiteState, 998 "constraint in the middle of being added, try again later") 999 } 1000 return pgerror.Newf(pgcode.ObjectNotInPrerequisiteState, 1001 "constraint in the middle of being dropped") 1002 } 1003 } 1004 info, err := tableDesc.GetConstraintInfo(params.ctx, nil, params.ExecCfg().Codec) 1005 if err != nil { 1006 return err 1007 } 1008 inuseNames := make(map[string]struct{}, len(info)) 1009 for k := range info { 1010 inuseNames[k] = struct{}{} 1011 } 1012 col.Nullable = true 1013 1014 // Add a check constraint equivalent to the non-null constraint and drop 1015 // it in the schema changer. 1016 check := sqlbase.MakeNotNullCheckConstraint(col.Name, col.ID, inuseNames, sqlbase.ConstraintValidity_Dropping) 1017 tableDesc.Checks = append(tableDesc.Checks, check) 1018 tableDesc.AddNotNullMutation(check, sqlbase.DescriptorMutation_DROP) 1019 1020 case *tree.AlterTableDropStored: 1021 if !col.IsComputed() { 1022 return pgerror.Newf(pgcode.InvalidColumnDefinition, 1023 "column %q is not a computed column", col.Name) 1024 } 1025 col.ComputeExpr = nil 1026 } 1027 return nil 1028 } 1029 1030 func labeledRowValues(cols []sqlbase.ColumnDescriptor, values tree.Datums) string { 1031 var s bytes.Buffer 1032 for i := range cols { 1033 if i != 0 { 1034 s.WriteString(`, `) 1035 } 1036 s.WriteString(cols[i].Name) 1037 s.WriteString(`=`) 1038 s.WriteString(values[i].String()) 1039 } 1040 return s.String() 1041 } 1042 1043 // injectTableStats implements the INJECT STATISTICS command, which deletes any 1044 // existing statistics on the table and replaces them with the statistics in the 1045 // given json object (in the same format as the result of SHOW STATISTICS USING 1046 // JSON). This is useful for reproducing planning issues without importing the 1047 // data. 1048 func injectTableStats( 1049 params runParams, desc *sqlbase.TableDescriptor, statsExpr tree.TypedExpr, 1050 ) error { 1051 val, err := statsExpr.Eval(params.EvalContext()) 1052 if err != nil { 1053 return err 1054 } 1055 if val == tree.DNull { 1056 return pgerror.New(pgcode.Syntax, 1057 "statistics cannot be NULL") 1058 } 1059 jsonStr := val.(*tree.DJSON).JSON.String() 1060 var jsonStats []stats.JSONStatistic 1061 if err := gojson.Unmarshal([]byte(jsonStr), &jsonStats); err != nil { 1062 return err 1063 } 1064 1065 // First, delete all statistics for the table. 1066 if _ /* rows */, err := params.extendedEvalCtx.ExecCfg.InternalExecutor.Exec( 1067 params.ctx, 1068 "delete-stats", 1069 params.EvalContext().Txn, 1070 `DELETE FROM system.table_statistics WHERE "tableID" = $1`, desc.ID, 1071 ); err != nil { 1072 return errors.Wrapf(err, "failed to delete old stats") 1073 } 1074 1075 // Insert each statistic. 1076 for i := range jsonStats { 1077 s := &jsonStats[i] 1078 h, err := s.GetHistogram(¶ms.p.semaCtx, params.EvalContext()) 1079 if err != nil { 1080 return err 1081 } 1082 // histogram will be passed to the INSERT statement; we want it to be a 1083 // nil interface{} if we don't generate a histogram. 1084 var histogram interface{} 1085 if h != nil { 1086 histogram, err = protoutil.Marshal(h) 1087 if err != nil { 1088 return err 1089 } 1090 } 1091 1092 columnIDs := tree.NewDArray(types.Int) 1093 for _, colName := range s.Columns { 1094 colDesc, _, err := desc.FindColumnByName(tree.Name(colName)) 1095 if err != nil { 1096 return err 1097 } 1098 if err := columnIDs.Append(tree.NewDInt(tree.DInt(colDesc.ID))); err != nil { 1099 return err 1100 } 1101 } 1102 var name interface{} 1103 if s.Name != "" { 1104 name = s.Name 1105 } 1106 if _ /* rows */, err := params.extendedEvalCtx.ExecCfg.InternalExecutor.Exec( 1107 params.ctx, 1108 "insert-stats", 1109 params.EvalContext().Txn, 1110 `INSERT INTO system.table_statistics ( 1111 "tableID", 1112 "name", 1113 "columnIDs", 1114 "createdAt", 1115 "rowCount", 1116 "distinctCount", 1117 "nullCount", 1118 histogram 1119 ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`, 1120 desc.ID, 1121 name, 1122 columnIDs, 1123 s.CreatedAt, 1124 s.RowCount, 1125 s.DistinctCount, 1126 s.NullCount, 1127 histogram, 1128 ); err != nil { 1129 return errors.Wrapf(err, "failed to insert stats") 1130 } 1131 } 1132 1133 // Invalidate the local cache synchronously; this guarantees that the next 1134 // statement in the same session won't use a stale cache (whereas the gossip 1135 // update is handled asynchronously). 1136 params.extendedEvalCtx.ExecCfg.TableStatsCache.InvalidateTableStats(params.ctx, desc.ID) 1137 1138 if g, ok := params.extendedEvalCtx.ExecCfg.Gossip.Optional(47925); ok { 1139 return stats.GossipTableStatAdded(g, desc.ID) 1140 } 1141 return nil 1142 } 1143 1144 func (p *planner) removeColumnComment( 1145 ctx context.Context, tableID sqlbase.ID, columnID sqlbase.ColumnID, 1146 ) error { 1147 _, err := p.ExtendedEvalContext().ExecCfg.InternalExecutor.ExecEx( 1148 ctx, 1149 "delete-column-comment", 1150 p.txn, 1151 sqlbase.InternalExecutorSessionDataOverride{User: security.RootUser}, 1152 "DELETE FROM system.comments WHERE type=$1 AND object_id=$2 AND sub_id=$3", 1153 keys.ColumnCommentType, 1154 tableID, 1155 columnID) 1156 1157 return err 1158 } 1159 1160 // updateFKBackReferenceName updates the name of a foreign key reference on 1161 // the referenced table descriptor. 1162 // TODO (lucy): This method is meant to be analogous to removeFKBackReference, 1163 // in that it only updates the backreference, but we should refactor/unify all 1164 // the places where we update both FKs and their backreferences, so that callers 1165 // don't have to manually take care of updating both table descriptors. 1166 func (p *planner) updateFKBackReferenceName( 1167 ctx context.Context, 1168 tableDesc *sqlbase.MutableTableDescriptor, 1169 ref *sqlbase.ForeignKeyConstraint, 1170 newName string, 1171 ) error { 1172 var referencedTableDesc *sqlbase.MutableTableDescriptor 1173 // We don't want to lookup/edit a second copy of the same table. 1174 if tableDesc.ID == ref.ReferencedTableID { 1175 referencedTableDesc = tableDesc 1176 } else { 1177 lookup, err := p.Tables().GetMutableTableVersionByID(ctx, ref.ReferencedTableID, p.txn) 1178 if err != nil { 1179 return errors.Errorf("error resolving referenced table ID %d: %v", ref.ReferencedTableID, err) 1180 } 1181 referencedTableDesc = lookup 1182 } 1183 if referencedTableDesc.Dropped() { 1184 // The referenced table is being dropped. No need to modify it further. 1185 return nil 1186 } 1187 for i := range referencedTableDesc.InboundFKs { 1188 backref := &referencedTableDesc.InboundFKs[i] 1189 if backref.Name == ref.Name && backref.OriginTableID == tableDesc.ID { 1190 backref.Name = newName 1191 // TODO (lucy): Have more consistent/informative names for dependent jobs. 1192 return p.writeSchemaChange( 1193 ctx, referencedTableDesc, sqlbase.InvalidMutationID, "updating referenced table", 1194 ) 1195 } 1196 } 1197 return errors.Errorf("missing backreference for foreign key %s", ref.Name) 1198 }