diff --git a/pkg/ccl/changefeedccl/avro_test.go b/pkg/ccl/changefeedccl/avro_test.go index 4d518f90443a..ca693be62c23 100644 --- a/pkg/ccl/changefeedccl/avro_test.go +++ b/pkg/ccl/changefeedccl/avro_test.go @@ -47,12 +47,12 @@ func parseTableDesc(createTableStmt string) (*sqlbase.TableDescriptor, error) { st := cluster.MakeTestingClusterSettings() const parentID = sqlbase.ID(keys.MaxReservedDescID + 1) const tableID = sqlbase.ID(keys.MaxReservedDescID + 2) - tableDesc, err := importccl.MakeSimpleTableDescriptor( + mutDesc, err := importccl.MakeSimpleTableDescriptor( ctx, st, createTable, parentID, tableID, importccl.NoFKs, hlc.UnixNano()) if err != nil { return nil, err } - return tableDesc, tableDesc.ValidateTable(st) + return mutDesc.TableDesc(), mutDesc.TableDesc().ValidateTable(st) } func parseValues(tableDesc *sqlbase.TableDescriptor, values string) ([]sqlbase.EncDatumRow, error) { diff --git a/pkg/ccl/importccl/import_stmt.go b/pkg/ccl/importccl/import_stmt.go index dc1feec12a7d..5234d45fa3cd 100644 --- a/pkg/ccl/importccl/import_stmt.go +++ b/pkg/ccl/importccl/import_stmt.go @@ -136,7 +136,7 @@ type fkHandler struct { // NoFKs is used by formats that do not support FKs. var NoFKs = fkHandler{resolver: make(fkResolver)} -// MakeSimpleTableDescriptor creates a TableDescriptor from a CreateTable parse +// MakeSimpleTableDescriptor creates a MutableTableDescriptor from a CreateTable parse // node without the full machinery. Many parts of the syntax are unsupported // (see the implementation and TestMakeSimpleTableDescriptorErrors for details), // but this is enough for our csv IMPORT and for some unit tests. @@ -152,7 +152,7 @@ func MakeSimpleTableDescriptor( tableID sqlbase.ID, fks fkHandler, walltime int64, -) (*sqlbase.TableDescriptor, error) { +) (*sqlbase.MutableTableDescriptor, error) { create.HoistConstraints() if create.IfNotExists { return nil, pgerror.Unimplemented("import.if-no-exists", "unsupported IF NOT EXISTS") @@ -204,7 +204,7 @@ func MakeSimpleTableDescriptor( Context: ctx, Sequence: &importSequenceOperators{}, } - affected := make(map[sqlbase.ID]*sqlbase.TableDescriptor) + affected := make(map[sqlbase.ID]*sqlbase.MutableTableDescriptor) tableDesc, err := sql.MakeTableDesc( ctx, @@ -223,7 +223,7 @@ func MakeSimpleTableDescriptor( if err != nil { return nil, err } - if err := fixDescriptorFKState(&tableDesc); err != nil { + if err := fixDescriptorFKState(tableDesc.TableDesc()); err != nil { return nil, err } @@ -293,7 +293,7 @@ func (so *importSequenceOperators) SetSequenceValue( return errSequenceOperators } -type fkResolver map[string]*sqlbase.TableDescriptor +type fkResolver map[string]*sqlbase.MutableTableDescriptor var _ sql.SchemaResolver = fkResolver{} @@ -772,7 +772,7 @@ func importPlanHook( if err != nil { return err } - tableDescs = []*sqlbase.TableDescriptor{tbl} + tableDescs = []*sqlbase.TableDescriptor{tbl.TableDesc()} descStr, err := importJobDescription(importStmt, create.Defs, files, opts) if err != nil { return err diff --git a/pkg/ccl/importccl/import_stmt_test.go b/pkg/ccl/importccl/import_stmt_test.go index a475199e71f1..46df08513cbe 100644 --- a/pkg/ccl/importccl/import_stmt_test.go +++ b/pkg/ccl/importccl/import_stmt_test.go @@ -1461,7 +1461,7 @@ func BenchmarkConvertRecord(b *testing.B) { } }() - c := &csvInputReader{recordCh: recordCh, tableDesc: tableDesc} + c := &csvInputReader{recordCh: recordCh, tableDesc: tableDesc.TableDesc()} // start up workers. for i := 0; i < runtime.NumCPU(); i++ { group.Go(func() error { diff --git a/pkg/ccl/importccl/load.go b/pkg/ccl/importccl/load.go index 8770b1f46716..b92b578d46dd 100644 --- a/pkg/ccl/importccl/load.go +++ b/pkg/ccl/importccl/load.go @@ -157,7 +157,7 @@ func Load( // rejected during restore. st := cluster.MakeTestingClusterSettings() - affected := make(map[sqlbase.ID]*sqlbase.TableDescriptor) + affected := make(map[sqlbase.ID]*sqlbase.MutableTableDescriptor) // A nil txn is safe because it is only used by sql.MakeTableDesc, which // only uses txn for resolving FKs and interleaved tables, neither of which // are present here. Ditto for the schema accessor. @@ -170,7 +170,7 @@ func Load( return backupccl.BackupDescriptor{}, errors.Wrap(err, "make table desc") } - tableDesc = &desc + tableDesc = desc.TableDesc() tableDescs[tableName] = tableDesc backup.Descriptors = append(backup.Descriptors, sqlbase.Descriptor{ Union: &sqlbase.Descriptor_Table{Table: tableDesc}, diff --git a/pkg/ccl/importccl/read_import_mysql.go b/pkg/ccl/importccl/read_import_mysql.go index e544acd1812e..b59d55f75420 100644 --- a/pkg/ccl/importccl/read_import_mysql.go +++ b/pkg/ccl/importccl/read_import_mysql.go @@ -370,8 +370,8 @@ func mysqlTableToCockroach( if err != nil { return nil, nil, err } - seqDesc = &desc - fks.resolver[seqName] = seqDesc + seqDesc = desc.TableDesc() + fks.resolver[seqName] = &desc id++ } @@ -454,9 +454,9 @@ func mysqlTableToCockroach( } fks.resolver[desc.Name] = desc if seqDesc != nil { - return []*sqlbase.TableDescriptor{seqDesc, desc}, fkDefs, nil + return []*sqlbase.TableDescriptor{seqDesc, desc.TableDesc()}, fkDefs, nil } - return []*sqlbase.TableDescriptor{desc}, fkDefs, nil + return []*sqlbase.TableDescriptor{desc.TableDesc()}, fkDefs, nil } func mysqlActionToCockroach(action mysql.ReferenceAction) tree.ReferenceAction { @@ -474,18 +474,18 @@ func mysqlActionToCockroach(action mysql.ReferenceAction) tree.ReferenceAction { } type delayedFK struct { - tbl *sqlbase.TableDescriptor + tbl *sqlbase.MutableTableDescriptor def *tree.ForeignKeyConstraintTableDef } func addDelayedFKs(ctx context.Context, defs []delayedFK, resolver fkResolver) error { for _, def := range defs { if err := sql.ResolveFK( - ctx, nil, resolver, def.tbl, def.def, map[sqlbase.ID]*sqlbase.TableDescriptor{}, sqlbase.ConstraintValidity_Validated, + ctx, nil, resolver, def.tbl, def.def, map[sqlbase.ID]*sqlbase.MutableTableDescriptor{}, sqlbase.ConstraintValidity_Validated, ); err != nil { return err } - if err := fixDescriptorFKState(def.tbl); err != nil { + if err := fixDescriptorFKState(def.tbl.TableDesc()); err != nil { return err } if err := def.tbl.AllocateIDs(); err != nil { diff --git a/pkg/ccl/importccl/read_import_mysql_test.go b/pkg/ccl/importccl/read_import_mysql_test.go index 77d343f35c12..a9bb24983645 100644 --- a/pkg/ccl/importccl/read_import_mysql_test.go +++ b/pkg/ccl/importccl/read_import_mysql_test.go @@ -74,10 +74,10 @@ func descForTable( if err != nil { t.Fatalf("could not interpret %q: %v", create, err) } - if err := fixDescriptorFKState(table); err != nil { + if err := fixDescriptorFKState(table.TableDesc()); err != nil { t.Fatal(err) } - return table + return table.TableDesc() } func TestMysqldumpDataReader(t *testing.T) { @@ -173,7 +173,7 @@ func TestMysqldumpSchemaReader(t *testing.T) { referencedSimple := descForTable(t, readFile(t, `simple.cockroach-schema.sql`), expectedParent, 52, NoFKs) fks := fkHandler{ allowed: true, - resolver: fkResolver(map[string]*sqlbase.TableDescriptor{referencedSimple.Name: referencedSimple}), + resolver: fkResolver(map[string]*sqlbase.MutableTableDescriptor{referencedSimple.Name: sql.NewMutableTableDescriptor(*referencedSimple)}), } t.Run("simple", func(t *testing.T) { diff --git a/pkg/ccl/importccl/read_import_pgdump.go b/pkg/ccl/importccl/read_import_pgdump.go index 6cf5887fa141..f516db5a0c5f 100644 --- a/pkg/ccl/importccl/read_import_pgdump.go +++ b/pkg/ccl/importccl/read_import_pgdump.go @@ -245,9 +245,9 @@ func readPostgresCreateTable( return nil, err } fks.resolver[desc.Name] = &desc - ret = append(ret, &desc) + ret = append(ret, desc.TableDesc()) } - backrefs := make(map[sqlbase.ID]*sqlbase.TableDescriptor) + backrefs := make(map[sqlbase.ID]*sqlbase.MutableTableDescriptor) for _, create := range createTbl { if create == nil { continue @@ -260,7 +260,7 @@ func readPostgresCreateTable( } fks.resolver[desc.Name] = desc backrefs[desc.ID] = desc - ret = append(ret, desc) + ret = append(ret, desc.TableDesc()) } for name, constraints := range tableFKs { desc := fks.resolver[name] @@ -272,7 +272,7 @@ func readPostgresCreateTable( return nil, err } } - if err := fixDescriptorFKState(desc); err != nil { + if err := fixDescriptorFKState(desc.TableDesc()); err != nil { return nil, err } } diff --git a/pkg/ccl/partitionccl/partition_test.go b/pkg/ccl/partitionccl/partition_test.go index dbfbc3b8ca95..002808d0f140 100644 --- a/pkg/ccl/partitionccl/partition_test.go +++ b/pkg/ccl/partitionccl/partition_test.go @@ -125,11 +125,12 @@ func (t *partitioningTest) parse() error { } st := cluster.MakeTestingClusterSettings() const parentID, tableID = keys.MinUserDescID, keys.MinUserDescID + 1 - t.parsed.tableDesc, err = importccl.MakeSimpleTableDescriptor( + mutDesc, err := importccl.MakeSimpleTableDescriptor( ctx, st, createTable, parentID, tableID, importccl.NoFKs, hlc.UnixNano()) if err != nil { return err } + t.parsed.tableDesc = mutDesc.TableDesc() if err := t.parsed.tableDesc.ValidateTable(st); err != nil { return err } diff --git a/pkg/sql/alter_index.go b/pkg/sql/alter_index.go index 6f929ae80a01..5749e3824f60 100644 --- a/pkg/sql/alter_index.go +++ b/pkg/sql/alter_index.go @@ -72,7 +72,7 @@ func (n *alterIndexNode) startExec(params runParams) error { ) err = deleteRemovedPartitionZoneConfigs( params.ctx, params.p.txn, - n.tableDesc, n.indexDesc, + n.tableDesc.TableDesc(), n.indexDesc, &n.indexDesc.Partitioning, &partitioning, params.extendedEvalCtx.ExecCfg, ) diff --git a/pkg/sql/alter_table.go b/pkg/sql/alter_table.go index f49adf2217c1..9a39db7260cb 100644 --- a/pkg/sql/alter_table.go +++ b/pkg/sql/alter_table.go @@ -386,7 +386,7 @@ func (n *alterTableNode) startExec(params runParams) error { // Drop check constraints which reference the column. validChecks := n.tableDesc.Checks[:0] for _, check := range n.tableDesc.Checks { - if used, err := check.UsesColumn(n.tableDesc, col.ID); err != nil { + if used, err := check.UsesColumn(n.tableDesc.TableDesc(), col.ID); err != nil { return err } else if !used { validChecks = append(validChecks, check) @@ -479,7 +479,7 @@ func (n *alterTableNode) startExec(params runParams) error { } ck := n.tableDesc.Checks[idx] if err := params.p.validateCheckExpr( - params.ctx, ck.Expr, &n.n.Table, n.tableDesc, + params.ctx, ck.Expr, &n.n.Table, n.tableDesc.TableDesc(), ); err != nil { return err } @@ -503,7 +503,7 @@ func (n *alterTableNode) startExec(params runParams) error { if err != nil { panic(err) } - if err := params.p.validateForeignKey(params.ctx, n.tableDesc, idx); err != nil { + if err := params.p.validateForeignKey(params.ctx, n.tableDesc.TableDesc(), idx); err != nil { return err } idx.ForeignKey.Validity = sqlbase.ConstraintValidity_Validated @@ -542,7 +542,7 @@ func (n *alterTableNode) startExec(params runParams) error { ) err = deleteRemovedPartitionZoneConfigs( params.ctx, params.p.txn, - n.tableDesc, &n.tableDesc.PrimaryIndex, &n.tableDesc.PrimaryIndex.Partitioning, + n.tableDesc.TableDesc(), &n.tableDesc.PrimaryIndex, &n.tableDesc.PrimaryIndex.Partitioning, &partitioning, params.extendedEvalCtx.ExecCfg, ) if err != nil { @@ -552,7 +552,7 @@ func (n *alterTableNode) startExec(params runParams) error { case *tree.AlterTableSetAudit: var err error - descriptorChanged, err = params.p.setAuditMode(params.ctx, n.tableDesc, t.Mode) + descriptorChanged, err = params.p.setAuditMode(params.ctx, n.tableDesc.TableDesc(), t.Mode) if err != nil { return err } @@ -562,7 +562,7 @@ func (n *alterTableNode) startExec(params runParams) error { if !ok { return pgerror.NewAssertionErrorf("missing stats data") } - if err := injectTableStats(params, n.tableDesc, sd); err != nil { + if err := injectTableStats(params, n.tableDesc.TableDesc(), sd); err != nil { return err } diff --git a/pkg/sql/authorization.go b/pkg/sql/authorization.go index 6c1789984843..98fa6366c4b6 100644 --- a/pkg/sql/authorization.go +++ b/pkg/sql/authorization.go @@ -173,11 +173,12 @@ func (p *planner) MemberOfWithAdminOption( ctx context.Context, member string, ) (map[string]bool, error) { // Lookup table version. - tableDesc, _, err := p.PhysicalSchemaAccessor().GetObjectDesc(&roleMembersTableName, + objDesc, _, err := p.PhysicalSchemaAccessor().GetObjectDesc(&roleMembersTableName, p.ObjectLookupFlags(ctx, true /*required*/)) if err != nil { return nil, err } + tableDesc := objDesc.TableDesc() tableVersion := tableDesc.Version // We loop in case the table version changes while we're looking up memberships. diff --git a/pkg/sql/backfill.go b/pkg/sql/backfill.go index dbfe780c4d54..9d13aa125c80 100644 --- a/pkg/sql/backfill.go +++ b/pkg/sql/backfill.go @@ -499,7 +499,7 @@ func runSchemaChangesInTxn( tc *TableCollection, execCfg *ExecutorConfig, evalCtx *tree.EvalContext, - tableDesc *sqlbase.TableDescriptor, + tableDesc *sqlbase.MutableTableDescriptor, traceKV bool, ) error { if len(tableDesc.DrainingNames) > 0 { @@ -531,13 +531,13 @@ func runSchemaChangesInTxn( if doneColumnBackfill || !sqlbase.ColumnNeedsBackfill(m.GetColumn()) { break } - if err := columnBackfillInTxn(ctx, txn, tc, evalCtx, tableDesc, traceKV); err != nil { + if err := columnBackfillInTxn(ctx, txn, tc, evalCtx, tableDesc.TableDesc(), traceKV); err != nil { return err } doneColumnBackfill = true case *sqlbase.DescriptorMutation_Index: - if err := indexBackfillInTxn(ctx, txn, tableDesc, traceKV); err != nil { + if err := indexBackfillInTxn(ctx, txn, tableDesc.TableDesc(), traceKV); err != nil { return err } @@ -552,13 +552,13 @@ func runSchemaChangesInTxn( if doneColumnBackfill { break } - if err := columnBackfillInTxn(ctx, txn, tc, evalCtx, tableDesc, traceKV); err != nil { + if err := columnBackfillInTxn(ctx, txn, tc, evalCtx, tableDesc.TableDesc(), traceKV); err != nil { return err } doneColumnBackfill = true case *sqlbase.DescriptorMutation_Index: - if err := indexTruncateInTxn(ctx, txn, execCfg, tableDesc, traceKV); err != nil { + if err := indexTruncateInTxn(ctx, txn, execCfg, tableDesc.TableDesc(), traceKV); err != nil { return err } @@ -616,7 +616,7 @@ func columnBackfillInTxn( "table %s not created in the same transaction as id = %d", tableDesc.Name, k) } table := tc.getUncommittedTableByID(k) - otherTableDescs = append(otherTableDescs, *table) + otherTableDescs = append(otherTableDescs, table.TableDescriptor) } sp := tableDesc.PrimaryIndexSpan() for sp.Key != nil { diff --git a/pkg/sql/create_table.go b/pkg/sql/create_table.go index 0aaf8b0cffff..95721c3fe657 100644 --- a/pkg/sql/create_table.go +++ b/pkg/sql/create_table.go @@ -199,7 +199,7 @@ func (n *createTableNode) startExec(params runParams) error { // Instantiate a row inserter and table writer. It has a 1-1 // mapping to the definitions in the descriptor. ri, err := row.MakeInserter( - params.p.txn, &desc, nil, desc.Columns, row.SkipFKs, ¶ms.p.alloc) + params.p.txn, desc.TableDesc(), nil, desc.Columns, row.SkipFKs, ¶ms.p.alloc) if err != nil { return err } @@ -388,7 +388,7 @@ func ResolveFK( } } - target, err := ResolveExistingObject(ctx, sc, &d.Table, true /*required*/, requireTableDesc) + target, err := ResolveMutableExistingObject(ctx, sc, &d.Table, true /*required*/, requireTableDesc) if err != nil { return err } @@ -483,7 +483,7 @@ func ResolveFK( if d.Actions.Delete == tree.SetNull || d.Actions.Update == tree.SetNull { for _, sourceColumn := range srcCols { if !sourceColumn.Nullable { - col := qualifyFKColErrorWithDB(ctx, txn, tbl, sourceColumn.Name) + col := qualifyFKColErrorWithDB(ctx, txn, tbl.TableDesc(), sourceColumn.Name) return pgerror.NewErrorf(pgerror.CodeInvalidForeignKeyError, "cannot add a SET NULL cascading action on column %q which has a NOT NULL constraint", col, ) @@ -496,7 +496,7 @@ func ResolveFK( if d.Actions.Delete == tree.SetDefault || d.Actions.Update == tree.SetDefault { for _, sourceColumn := range srcCols { if sourceColumn.DefaultExpr == nil { - col := qualifyFKColErrorWithDB(ctx, txn, tbl, sourceColumn.Name) + col := qualifyFKColErrorWithDB(ctx, txn, tbl.TableDesc(), sourceColumn.Name) return pgerror.NewErrorf(pgerror.CodeInvalidForeignKeyError, "cannot add a SET DEFAULT cascading action on column %q which has no DEFAULT expression", col, ) @@ -750,7 +750,7 @@ func (p *planner) finalizeInterleave( ancestorTable = desc } else { var err error - ancestorTable, err = sqlbase.GetTableDescFromID(ctx, p.txn, ancestor.TableID) + ancestorTable, err = p.Tables().getMutableTableVersionByID(ctx, ancestor.TableID, p.txn) if err != nil { return err } @@ -808,6 +808,12 @@ var CreatePartitioningCCL = func( "creating or manipulating partitions requires a CCL binary")) } +// NewMutableTableDescriptor returns a MutableTableDescriptor from the +// given TableDescriptor. +func NewMutableTableDescriptor(tbl sqlbase.TableDescriptor) *sqlbase.MutableTableDescriptor { + return &sqlbase.MutableTableDescriptor{TableDescriptor: tbl} +} + // InitTableDescriptor returns a blank TableDescriptor. func InitTableDescriptor( id, parentID sqlbase.ID, @@ -815,7 +821,7 @@ func InitTableDescriptor( creationTime hlc.Timestamp, privileges *sqlbase.PrivilegeDescriptor, ) sqlbase.MutableTableDescriptor { - return sqlbase.MutableTableDescriptor{ + return *NewMutableTableDescriptor(sqlbase.TableDescriptor{ ID: id, Name: name, ParentID: parentID, @@ -823,7 +829,7 @@ func InitTableDescriptor( Version: 1, ModificationTime: creationTime, Privileges: privileges, - } + }) } // makeTableDescIfAs is the MakeTableDesc method for when we have a table @@ -1115,7 +1121,7 @@ func MakeTableDesc( // table. fkResolver := &fkSelfResolver{ SchemaResolver: vt, - newTableDesc: &desc, + newTableDesc: desc.TableDesc(), newTableName: &n.Table, } diff --git a/pkg/sql/create_view.go b/pkg/sql/create_view.go index b57bb8ab0f60..564961a31284 100644 --- a/pkg/sql/create_view.go +++ b/pkg/sql/create_view.go @@ -154,7 +154,11 @@ func (n *createViewNode) startExec(params runParams) error { // Persist the back-references in all referenced table descriptors. for _, updated := range n.planDeps { - backrefDesc := *updated.desc + backrefID := updated.desc.ID + backRefMutable := params.p.Tables().getUncommittedTableByID(backrefID) + if backRefMutable == nil { + backRefMutable = NewMutableTableDescriptor(*updated.desc) + } for _, dep := range updated.deps { // The logical plan constructor merely registered the dependencies. // It did not populate the "ID" field of TableDescriptor_Reference, @@ -162,9 +166,9 @@ func (n *createViewNode) startExec(params runParams) error { // yet known. // We need to do it here. dep.ID = desc.ID - backrefDesc.DependedOnBy = append(backrefDesc.DependedOnBy, dep) + backRefMutable.DependedOnBy = append(backRefMutable.DependedOnBy, dep) } - if err := params.p.writeSchemaChange(params.ctx, &backrefDesc, sqlbase.InvalidMutationID); err != nil { + if err := params.p.writeSchemaChange(params.ctx, backRefMutable, sqlbase.InvalidMutationID); err != nil { return err } } diff --git a/pkg/sql/descriptor.go b/pkg/sql/descriptor.go index 23cc24962650..cf79541cf262 100644 --- a/pkg/sql/descriptor.go +++ b/pkg/sql/descriptor.go @@ -123,19 +123,29 @@ func (p *planner) createDescriptorWithID( b.CPut(idKey, descID, nil) b.CPut(descKey, descDesc, nil) - desc, ok := descriptor.(*sqlbase.TableDescriptor) - if ok { - if err := desc.ValidateTable(st); err != nil { + isTable := false + var mutDesc *sqlbase.MutableTableDescriptor + switch d := descriptor.(type) { + case *sqlbase.MutableTableDescriptor: + mutDesc = d + isTable = true + case *sqlbase.TableDescriptor: + mutDesc = NewMutableTableDescriptor(*d) + isTable = true + } + + if isTable { + if err := mutDesc.ValidateTable(st); err != nil { return err } - p.Tables().addUncommittedTable(*desc) + p.Tables().addUncommittedTable(*mutDesc) } if err := p.txn.Run(ctx, b); err != nil { return err } - if ok && desc.Adding() { - p.queueSchemaChange(desc, sqlbase.InvalidMutationID) + if isTable && mutDesc.Adding() { + p.queueSchemaChange(mutDesc.TableDesc(), sqlbase.InvalidMutationID) } return nil } diff --git a/pkg/sql/drop_database.go b/pkg/sql/drop_database.go index 3b7a8739c672..1589435573d6 100644 --- a/pkg/sql/drop_database.go +++ b/pkg/sql/drop_database.go @@ -237,7 +237,7 @@ func (p *planner) accumulateDependentTables( ) error { for _, ref := range desc.DependedOnBy { dependentTables[ref.ID] = true - dependentDesc, err := sqlbase.GetTableDescFromID(ctx, p.txn, ref.ID) + dependentDesc, err := p.Tables().getMutableTableVersionByID(ctx, ref.ID, p.txn) if err != nil { return err } diff --git a/pkg/sql/drop_index.go b/pkg/sql/drop_index.go index c85d812d1e60..4e381c20e0ef 100644 --- a/pkg/sql/drop_index.go +++ b/pkg/sql/drop_index.go @@ -139,7 +139,7 @@ func (p *planner) dropIndexByName( for _, s := range zone.Subzones { if s.IndexID != uint32(idx.ID) { _, err = GenerateSubzoneSpans( - p.ExecCfg().Settings, p.ExecCfg().ClusterID(), tableDesc, zone.Subzones, false /* newSubzones */) + p.ExecCfg().Settings, p.ExecCfg().ClusterID(), tableDesc.TableDesc(), zone.Subzones, false /* newSubzones */) if sqlbase.IsCCLRequiredError(err) { return sqlbase.NewCCLRequiredError(fmt.Errorf("schema change requires a CCL binary "+ "because table %q has at least one remaining index or partition with a zone config", diff --git a/pkg/sql/drop_table.go b/pkg/sql/drop_table.go index 5d9d319336fd..2e1df66f1195 100644 --- a/pkg/sql/drop_table.go +++ b/pkg/sql/drop_table.go @@ -179,7 +179,7 @@ func (p *planner) prepareDrop( func (p *planner) canRemoveFK( ctx context.Context, from string, ref sqlbase.ForeignKeyReference, behavior tree.DropBehavior, ) (*sqlbase.MutableTableDescriptor, error) { - table, err := sqlbase.GetTableDescFromID(ctx, p.txn, ref.Table) + table, err := p.Tables().getMutableTableVersionByID(ctx, ref.Table, p.txn) if err != nil { return nil, err } @@ -195,7 +195,7 @@ func (p *planner) canRemoveFK( func (p *planner) canRemoveInterleave( ctx context.Context, from string, ref sqlbase.ForeignKeyReference, behavior tree.DropBehavior, ) error { - table, err := sqlbase.GetTableDescFromID(ctx, p.txn, ref.Table) + table, err := p.Tables().getMutableTableVersionByID(ctx, ref.Table, p.txn) if err != nil { return err } @@ -217,7 +217,7 @@ func (p *planner) removeFK( ) error { if table == nil { var err error - table, err = sqlbase.GetTableDescFromID(ctx, p.txn, ref.Table) + table, err = p.Tables().getMutableTableVersionByID(ctx, ref.Table, p.txn) if err != nil { return err } @@ -235,7 +235,7 @@ func (p *planner) removeFK( } func (p *planner) removeInterleave(ctx context.Context, ref sqlbase.ForeignKeyReference) error { - table, err := sqlbase.GetTableDescFromID(ctx, p.txn, ref.Table) + table, err := p.Tables().getMutableTableVersionByID(ctx, ref.Table, p.txn) if err != nil { return err } @@ -367,7 +367,7 @@ func (p *planner) initiateDropTable( for _, m := range tableDesc.Mutations { if id != m.MutationID { id = m.MutationID - jobID, err := getJobIDForMutationWithDescriptor(ctx, tableDesc, id) + jobID, err := getJobIDForMutationWithDescriptor(ctx, tableDesc.TableDesc(), id) if err != nil { return err } @@ -405,7 +405,7 @@ func (p *planner) removeFKBackReference( if tableDesc.ID == idx.ForeignKey.Table { t = tableDesc } else { - lookup, err := sqlbase.GetTableDescFromID(ctx, p.txn, idx.ForeignKey.Table) + lookup, err := p.Tables().getMutableTableVersionByID(ctx, idx.ForeignKey.Table, p.txn) if err != nil { return errors.Errorf("error resolving referenced table ID %d: %v", idx.ForeignKey.Table, err) } @@ -438,7 +438,7 @@ func (p *planner) removeInterleaveBackReference( if ancestor.TableID == tableDesc.ID { t = tableDesc } else { - lookup, err := sqlbase.GetTableDescFromID(ctx, p.txn, ancestor.TableID) + lookup, err := p.Tables().getMutableTableVersionByID(ctx, ancestor.TableID, p.txn) if err != nil { return errors.Errorf("error resolving referenced table ID %d: %v", ancestor.TableID, err) } diff --git a/pkg/sql/drop_view.go b/pkg/sql/drop_view.go index 34d1d925fa89..3fab5ff8da64 100644 --- a/pkg/sql/drop_view.go +++ b/pkg/sql/drop_view.go @@ -176,7 +176,7 @@ func (p *planner) dropViewImpl( // Remove back-references from the tables/views this view depends on. for _, depID := range viewDesc.DependsOn { - dependencyDesc, err := sqlbase.GetTableDescFromID(ctx, p.txn, depID) + dependencyDesc, err := p.Tables().getMutableTableVersionByID(ctx, depID, p.txn) if err != nil { return cascadeDroppedViews, errors.Errorf("error resolving dependency relation ID %d: %v", depID, err) @@ -224,7 +224,7 @@ func (p *planner) getViewDescForCascade( parentID, viewID sqlbase.ID, behavior tree.DropBehavior, ) (*sqlbase.MutableTableDescriptor, error) { - viewDesc, err := sqlbase.GetTableDescFromID(ctx, p.txn, viewID) + viewDesc, err := p.Tables().getMutableTableVersionByID(ctx, viewID, p.txn) if err != nil { log.Warningf(ctx, "unable to retrieve descriptor for view %d: %v", viewID, err) return nil, errors.Wrapf(err, "error resolving dependent view ID %d", viewID) @@ -233,7 +233,7 @@ func (p *planner) getViewDescForCascade( viewName := viewDesc.Name if viewDesc.ParentID != parentID { var err error - viewName, err = p.getQualifiedTableName(ctx, viewDesc) + viewName, err = p.getQualifiedTableName(ctx, viewDesc.TableDesc()) if err != nil { log.Warningf(ctx, "unable to retrieve qualified name of view %d: %v", viewID, err) msg := fmt.Sprintf("cannot drop %s %q because a view depends on it", typeName, objName) diff --git a/pkg/sql/grant_revoke.go b/pkg/sql/grant_revoke.go index affabea3920e..5e6237ab8c79 100644 --- a/pkg/sql/grant_revoke.go +++ b/pkg/sql/grant_revoke.go @@ -111,7 +111,7 @@ func (p *planner) changePrivileges( descKey := sqlbase.MakeDescMetadataKey(descriptor.GetID()) b.Put(descKey, sqlbase.WrapDescriptor(descriptor)) - case *sqlbase.TableDescriptor: + case *sqlbase.MutableTableDescriptor: if !d.Dropped() { if err := p.writeSchemaChangeToBatch( ctx, d, sqlbase.InvalidMutationID, b); err != nil { diff --git a/pkg/sql/logical_schema_accessors.go b/pkg/sql/logical_schema_accessors.go index ebc3b830ce04..2a651743a65e 100644 --- a/pkg/sql/logical_schema_accessors.go +++ b/pkg/sql/logical_schema_accessors.go @@ -66,7 +66,7 @@ func (l *LogicalSchemaAccessor) GetObjectNames( // GetObjectDesc implements the ObjectAccessor interface. func (l *LogicalSchemaAccessor) GetObjectDesc( name *ObjectName, flags ObjectLookupFlags, -) (*ObjectDescriptor, *DatabaseDescriptor, error) { +) (ObjectDescriptor, *DatabaseDescriptor, error) { if scEntry, ok := l.vt.getVirtualSchemaEntry(name.Schema()); ok { tableName := name.Table() if t, ok := scEntry.defs[tableName]; ok { diff --git a/pkg/sql/physical_schema_accessors.go b/pkg/sql/physical_schema_accessors.go index ae7daf72b0fd..f1e8af210e3e 100644 --- a/pkg/sql/physical_schema_accessors.go +++ b/pkg/sql/physical_schema_accessors.go @@ -107,7 +107,7 @@ func (a UncachedPhysicalAccessor) GetObjectNames( // GetObjectDesc implements the SchemaAccessor interface. func (a UncachedPhysicalAccessor) GetObjectDesc( name *ObjectName, flags ObjectLookupFlags, -) (*ObjectDescriptor, *DatabaseDescriptor, error) { +) (ObjectDescriptor, *DatabaseDescriptor, error) { // At this point, only the public schema is recognized. if name.Schema() != tree.PublicSchema { if flags.required { @@ -131,25 +131,18 @@ func (a UncachedPhysicalAccessor) GetObjectDesc( if err != nil { return nil, nil, err } - if !found { - desc = nil - } else { - // We have a descriptor. Is it in the right state? - if err := filterTableState(desc); err != nil { - // No: let's see the flag. - if err == errTableAdding { - // We'll keep that despite the ADD state. - return desc, dbDesc, nil - } - // Bad state: the descriptor is essentially invisible. - desc = nil + if found { + // We have a descriptor. Is it in the right state? We'll keep if + // in the ADD state. + if err := filterTableState(desc); err == nil || err == errTableAdding { + return desc, dbDesc, nil } } - if desc == nil && flags.required { + if flags.required { return nil, nil, sqlbase.NewUndefinedRelationError(name) } - return desc, dbDesc, nil + return nil, nil, nil } // CachedPhysicalAccessor adds a cache on top of any SchemaAccessor. @@ -194,6 +187,6 @@ func (a *CachedPhysicalAccessor) GetDatabaseDesc( // GetObjectDesc implements the SchemaAccessor interface. func (a *CachedPhysicalAccessor) GetObjectDesc( name *ObjectName, flags ObjectLookupFlags, -) (*ObjectDescriptor, *DatabaseDescriptor, error) { +) (ObjectDescriptor, *DatabaseDescriptor, error) { return a.tc.getTableVersion(flags.ctx, name, flags) } diff --git a/pkg/sql/relocate.go b/pkg/sql/relocate.go index ed5adb3741dd..08bda48ea01e 100644 --- a/pkg/sql/relocate.go +++ b/pkg/sql/relocate.go @@ -104,7 +104,7 @@ func (p *planner) Relocate(ctx context.Context, n *tree.Relocate) (planNode, err return &relocateNode{ relocateLease: n.RelocateLease, - tableDesc: tableDesc, + tableDesc: tableDesc.TableDesc(), index: index, rows: rows, run: relocateRun{ diff --git a/pkg/sql/rename_database.go b/pkg/sql/rename_database.go index 5cb7277ffe4c..0c639f1581f5 100644 --- a/pkg/sql/rename_database.go +++ b/pkg/sql/rename_database.go @@ -90,14 +90,15 @@ func (n *renameDatabaseNode) startExec(params runParams) error { } lookupFlags.required = false for i := range tbNames { - tbDesc, _, err := phyAccessor.GetObjectDesc(&tbNames[i], + objDesc, _, err := phyAccessor.GetObjectDesc(&tbNames[i], ObjectLookupFlags{CommonLookupFlags: lookupFlags}) if err != nil { return err } - if tbDesc == nil { + if objDesc == nil { continue } + tbDesc := objDesc.TableDesc() if len(tbDesc.DependedOnBy) > 0 { viewDesc, err := sqlbase.GetTableDescFromID(ctx, p.txn, tbDesc.DependedOnBy[0].ID) if err != nil { diff --git a/pkg/sql/resolver.go b/pkg/sql/resolver.go index 3e7140cc4779..5b8783386bf8 100644 --- a/pkg/sql/resolver.go +++ b/pkg/sql/resolver.go @@ -93,7 +93,39 @@ func GetObjectNames( // if no object is found. func ResolveExistingObject( ctx context.Context, sc SchemaResolver, tn *ObjectName, required bool, requiredType requiredType, -) (res *ObjectDescriptor, err error) { +) (res *TableDescriptor, err error) { + desc, err := resolveExistingObjectImpl(ctx, sc, tn, required, false /* requiredMutable */, requiredType) + if err != nil || desc == nil { + return nil, err + } + return desc.(*TableDescriptor), nil +} + +// ResolveMutableExistingObject looks up an existing mutable object. +// If required is true, an error is returned if the object does not exist. +// Optionally, if a desired descriptor type is specified, that type is checked. +// +// The object name is modified in-place with the result of the name +// resolution, if successful. It is not modified in case of error or +// if no object is found. +func ResolveMutableExistingObject( + ctx context.Context, sc SchemaResolver, tn *ObjectName, required bool, requiredType requiredType, +) (res *MutableTableDescriptor, err error) { + desc, err := resolveExistingObjectImpl(ctx, sc, tn, required, true /* requiredMutable */, requiredType) + if err != nil || desc == nil { + return nil, err + } + return desc.(*MutableTableDescriptor), nil +} + +func resolveExistingObjectImpl( + ctx context.Context, + sc SchemaResolver, + tn *ObjectName, + required bool, + requiredMutable bool, + requiredType requiredType, +) (res tree.NameResolutionResult, err error) { found, descI, err := tn.ResolveExisting(ctx, sc, sc.CurrentDatabase(), sc.CurrentSearchPath()) if err != nil { return nil, err @@ -104,22 +136,31 @@ func ResolveExistingObject( } return nil, nil } - desc := descI.(*ObjectDescriptor) + obj := descI.(ObjectDescriptor) + goodType := true switch requiredType { case requireTableDesc: - goodType = desc.IsTable() + goodType = obj.TableDesc().IsTable() case requireViewDesc: - goodType = desc.IsView() + goodType = obj.TableDesc().IsView() case requireTableOrViewDesc: - goodType = desc.IsTable() || desc.IsView() + goodType = obj.TableDesc().IsTable() || obj.TableDesc().IsView() case requireSequenceDesc: - goodType = desc.IsSequence() + goodType = obj.TableDesc().IsSequence() } if !goodType { return nil, sqlbase.NewWrongObjectTypeError(tn, requiredTypeNames[requiredType]) } - return desc, nil + + if requiredMutable { + if mutDesc, ok := descI.(*MutableTableDescriptor); ok { + return mutDesc, nil + } + return NewMutableTableDescriptor(*descI.(*TableDescriptor)), nil + } + + return obj.TableDesc(), nil } // runWithOptions sets the provided resolution flags for the @@ -150,7 +191,7 @@ func (p *planner) ResolveMutableTableDescriptor( ctx context.Context, tn *ObjectName, required bool, requiredType requiredType, ) (table *MutableTableDescriptor, err error) { p.runWithOptions(resolveFlags{skipCache: true}, func() { - table, err = ResolveExistingObject(ctx, p, tn, required, requiredType) + table, err = ResolveMutableExistingObject(ctx, p, tn, required, requiredType) }) return table, err } @@ -291,8 +332,7 @@ func getDescriptorsFromTargetList( return nil, err } for i := range tableNames { - descriptor, _, err := p.LogicalSchemaAccessor().GetObjectDesc(&tableNames[i], - p.ObjectLookupFlags(ctx, true /*required*/)) + descriptor, err := ResolveMutableExistingObject(ctx, p, &tableNames[i], true, anyDescType) if err != nil { return nil, err } @@ -328,17 +368,19 @@ func (p *planner) getQualifiedTableName( // error will be returned, otherwise the TableName and descriptor // returned will be nil. func findTableContainingIndex( - sc SchemaAccessor, + ctx context.Context, + sc SchemaResolver, dbName, scName string, idxName tree.UnrestrictedName, lookupFlags CommonLookupFlags, ) (result *tree.TableName, desc *MutableTableDescriptor, err error) { - dbDesc, err := sc.GetDatabaseDesc(dbName, lookupFlags) + sa := sc.LogicalSchemaAccessor() + dbDesc, err := sa.GetDatabaseDesc(dbName, lookupFlags) if dbDesc == nil || err != nil { return nil, nil, err } - tns, err := sc.GetObjectNames(dbDesc, scName, + tns, err := sa.GetObjectNames(dbDesc, scName, DatabaseListFlags{CommonLookupFlags: lookupFlags, explicitPrefix: true}) if err != nil { return nil, nil, err @@ -349,7 +391,7 @@ func findTableContainingIndex( tblLookupFlags.required = false for i := range tns { tn := &tns[i] - tableDesc, _, err := sc.GetObjectDesc(tn, tblLookupFlags) + tableDesc, err := ResolveMutableExistingObject(ctx, sc, tn, true, anyDescType) if err != nil { return nil, nil, err } @@ -402,7 +444,7 @@ func expandIndexName( tn = &index.Table if !index.SearchTable { // The index and its table prefix must exist already. Resolve the table. - desc, err = ResolveExistingObject(ctx, sc, tn, requireTable, requireTableDesc) + desc, err = ResolveMutableExistingObject(ctx, sc, tn, requireTable, requireTableDesc) if err != nil { return nil, nil, err } @@ -438,8 +480,7 @@ func expandIndexName( lookupFlags := sc.CommonLookupFlags(ctx, requireTable) var foundTn *tree.TableName - foundTn, desc, err = findTableContainingIndex( - sc.LogicalSchemaAccessor(), tn.Catalog(), tn.Schema(), index.Index, lookupFlags) + foundTn, desc, err = findTableContainingIndex(ctx, sc, tn.Catalog(), tn.Schema(), index.Index, lookupFlags) if err != nil { return nil, nil, err } else if foundTn != nil { diff --git a/pkg/sql/scatter.go b/pkg/sql/scatter.go index 3c36b23f0197..19109f0816f7 100644 --- a/pkg/sql/scatter.go +++ b/pkg/sql/scatter.go @@ -97,11 +97,11 @@ func (p *planner) Scatter(ctx context.Context, n *tree.Scatter) (planNode, error } } - span.Key, err = getRowKey(tableDesc, index, fromVals) + span.Key, err = getRowKey(tableDesc.TableDesc(), index, fromVals) if err != nil { return nil, err } - span.EndKey, err = getRowKey(tableDesc, index, toVals) + span.EndKey, err = getRowKey(tableDesc.TableDesc(), index, toVals) if err != nil { return nil, err } diff --git a/pkg/sql/schema_accessors.go b/pkg/sql/schema_accessors.go index 23d1c7d2edbc..6717a0bf8b09 100644 --- a/pkg/sql/schema_accessors.go +++ b/pkg/sql/schema_accessors.go @@ -45,9 +45,6 @@ type ( // UncachedDatabaseDescriptor is provided for convenience and to make the // interface definitions below more intuitive. UncachedDatabaseDescriptor = sqlbase.DatabaseDescriptor - // ObjectDescriptor is provided for convenience and to make the - // interface definitions below more intuitive. - ObjectDescriptor = sqlbase.TableDescriptor // MutableTableDescriptor is provided for convenience and to make the // interface definitions below more intuitive. MutableTableDescriptor = sqlbase.MutableTableDescriptor @@ -69,6 +66,14 @@ type ( TableNames = tree.TableNames ) +// ObjectDescriptor provides table information for results from a name lookup. +type ObjectDescriptor interface { + tree.NameResolutionResult + + // TableDesc returns the underlying table descriptor. + TableDesc() *TableDescriptor +} + // SchemaAccessor provides access to database descriptors. type SchemaAccessor interface { // GetDatabaseDesc looks up a database by name and returns its @@ -95,7 +100,7 @@ type SchemaAccessor interface { // It is not guaranteed to be non-nil even if the first return value // is non-nil. Callers that need a database descriptor can use that // to avoid an extra roundtrip through a DatabaseAccessor. - GetObjectDesc(name *ObjectName, flags ObjectLookupFlags) (*ObjectDescriptor, *DatabaseDescriptor, error) + GetObjectDesc(name *ObjectName, flags ObjectLookupFlags) (ObjectDescriptor, *DatabaseDescriptor, error) } // CommonLookupFlags is the common set of flags for the various accessor interfaces. diff --git a/pkg/sql/scrub.go b/pkg/sql/scrub.go index b2ee5239e8d3..52da3d57fd73 100644 --- a/pkg/sql/scrub.go +++ b/pkg/sql/scrub.go @@ -177,11 +177,12 @@ func (n *scrubNode) startScrubDatabase(ctx context.Context, p *planner, name *tr for i := range tbNames { tableName := &tbNames[i] - tableDesc, _, err := p.LogicalSchemaAccessor().GetObjectDesc( + objDesc, _, err := p.LogicalSchemaAccessor().GetObjectDesc( tableName, p.ObjectLookupFlags(ctx, true /*required*/)) if err != nil { return err } + tableDesc := objDesc.TableDesc() // Skip non-tables and don't throw an error if we encounter one. if !tableDesc.IsTable() { continue diff --git a/pkg/sql/sequence.go b/pkg/sql/sequence.go index 4d0f5fc2da55..eb3a067c404d 100644 --- a/pkg/sql/sequence.go +++ b/pkg/sql/sequence.go @@ -298,20 +298,20 @@ func maybeAddSequenceDependencies( col *sqlbase.ColumnDescriptor, expr tree.TypedExpr, evalCtx *tree.EvalContext, -) ([]*sqlbase.MutableTableDescriptor, error) { +) ([]*MutableTableDescriptor, error) { ctx := evalCtx.Ctx() seqNames, err := getUsedSequenceNames(expr) if err != nil { return nil, err } - var seqDescs []*sqlbase.MutableTableDescriptor + var seqDescs []*MutableTableDescriptor for _, seqName := range seqNames { parsedSeqName, err := evalCtx.Sequence.ParseQualifiedTableName(ctx, seqName) if err != nil { return nil, err } - var seqDesc *sqlbase.MutableTableDescriptor + var seqDesc *MutableTableDescriptor p, ok := sc.(*planner) if ok { seqDesc, err = p.ResolveMutableTableDescriptor(ctx, parsedSeqName, true /*required*/, requireSequenceDesc) @@ -320,7 +320,7 @@ func maybeAddSequenceDependencies( } } else { // This is only executed via IMPORT which uses its own resolver. - seqDesc, err = ResolveExistingObject(ctx, sc, parsedSeqName, true /*required*/, requireSequenceDesc) + seqDesc, err = ResolveMutableExistingObject(ctx, sc, parsedSeqName, true /*required*/, requireSequenceDesc) if err != nil { return nil, err } @@ -346,8 +346,8 @@ func removeSequenceDependencies( ) error { for _, sequenceID := range col.UsesSequenceIds { // Get the sequence descriptor so we can remove the reference from it. - seqDesc := sqlbase.TableDescriptor{} - if err := getDescriptorByID(params.ctx, params.p.txn, sequenceID, &seqDesc); err != nil { + seqDesc, err := params.p.Tables().getMutableTableVersionByID(params.ctx, sequenceID, params.p.txn) + if err != nil { return err } // Find an item in seqDesc.DependedOnBy which references tableDesc. @@ -361,7 +361,7 @@ func removeSequenceDependencies( return pgerror.NewAssertionErrorf("couldn't find reference from sequence to this column") } seqDesc.DependedOnBy = append(seqDesc.DependedOnBy[:refIdx], seqDesc.DependedOnBy[refIdx+1:]...) - if err := params.p.writeSchemaChange(params.ctx, &seqDesc, sqlbase.InvalidMutationID); err != nil { + if err := params.p.writeSchemaChange(params.ctx, seqDesc, sqlbase.InvalidMutationID); err != nil { return err } } diff --git a/pkg/sql/split.go b/pkg/sql/split.go index b1fa0dbde608..5d3270684197 100644 --- a/pkg/sql/split.go +++ b/pkg/sql/split.go @@ -79,7 +79,7 @@ func (p *planner) Split(ctx context.Context, n *tree.Split) (planNode, error) { return &splitNode{ force: p.SessionData().ForceSplitAt, - tableDesc: tableDesc, + tableDesc: tableDesc.TableDesc(), index: index, rows: rows, }, nil diff --git a/pkg/sql/sqlbase/metadata.go b/pkg/sql/sqlbase/metadata.go index a564d9a26386..fc03b879846b 100644 --- a/pkg/sql/sqlbase/metadata.go +++ b/pkg/sql/sqlbase/metadata.go @@ -54,6 +54,8 @@ type DescriptorProto interface { func WrapDescriptor(descriptor DescriptorProto) *Descriptor { desc := &Descriptor{} switch t := descriptor.(type) { + case *MutableTableDescriptor: + desc.Union = &Descriptor_Table{Table: &t.TableDescriptor} case *TableDescriptor: desc.Union = &Descriptor_Table{Table: t} case *DatabaseDescriptor: diff --git a/pkg/sql/sqlbase/structured.go b/pkg/sql/sqlbase/structured.go index aafc02266352..cea8ebd59fd8 100644 --- a/pkg/sql/sqlbase/structured.go +++ b/pkg/sql/sqlbase/structured.go @@ -105,7 +105,9 @@ type MutationID uint32 // MutableTableDescriptor is a custom type for TableDescriptors // going through mutations. -type MutableTableDescriptor = TableDescriptor +type MutableTableDescriptor struct { + TableDescriptor +} // InvalidMutationID is the uninitialised mutation id. const InvalidMutationID MutationID = 0 @@ -2509,3 +2511,13 @@ func (desc *TableDescriptor) FindAllReferences() (map[ID]struct{}, error) { } return refs, nil } + +// TableDesc implements the ObjectDescriptor interface. +func (desc *TableDescriptor) TableDesc() *TableDescriptor { + return desc +} + +// TableDesc implements the ObjectDescriptor interface. +func (desc *MutableTableDescriptor) TableDesc() *TableDescriptor { + return &desc.TableDescriptor +} diff --git a/pkg/sql/table.go b/pkg/sql/table.go index c6072716f90f..15f30b22b115 100644 --- a/pkg/sql/table.go +++ b/pkg/sql/table.go @@ -204,7 +204,7 @@ type dbCacheSubscriber interface { // TODO(vivek): Allow cached descriptors for AS OF SYSTEM TIME queries. func (tc *TableCollection) getTableVersion( ctx context.Context, tn *tree.TableName, flags ObjectLookupFlags, -) (*sqlbase.TableDescriptor, *sqlbase.DatabaseDescriptor, error) { +) (ObjectDescriptor, *sqlbase.DatabaseDescriptor, error) { if log.V(2) { log.Infof(ctx, "planner acquiring lease on table '%s'", tn) } @@ -343,7 +343,7 @@ func (tc *TableCollection) getTableVersionByID( tree.NewUnqualifiedTableName(tree.Name(fmt.Sprintf("", tableID))), ) } - return table, nil + return table.TableDesc(), nil } } @@ -383,6 +383,24 @@ func (tc *TableCollection) getTableVersionByID( return table, nil } +// getMutableTableVersionByID is a variant of sqlbase.GetTableDescFromID which returns a mutable +// table descriptor of the table modified in the same transaction. +func (tc *TableCollection) getMutableTableVersionByID( + ctx context.Context, tableID sqlbase.ID, txn *client.Txn, +) (*sqlbase.MutableTableDescriptor, error) { + log.VEventf(ctx, 2, "planner getting mutable table on table ID %d", tableID) + + if table := tc.getUncommittedTableByID(tableID); table != nil { + log.VEventf(ctx, 2, "found uncommitted table %d", tableID) + return table, nil + } + table, err := sqlbase.GetTableDescFromID(ctx, txn, tableID) + if err != nil { + return nil, err + } + return NewMutableTableDescriptor(*table), nil +} + func (tc *TableCollection) releaseLeases(ctx context.Context) { if len(tc.leasedTables) > 0 { log.VEventf(ctx, 2, "releasing %d tables", len(tc.leasedTables)) @@ -533,7 +551,7 @@ func (tc *TableCollection) getUncommittedDatabaseID( // still exist). func (tc *TableCollection) getUncommittedTable( dbID sqlbase.ID, tn *tree.TableName, required bool, -) (refuseFurtherLookup bool, table *sqlbase.TableDescriptor, err error) { +) (refuseFurtherLookup bool, table *sqlbase.MutableTableDescriptor, err error) { // Walk latest to earliest so that a DROP TABLE followed by a CREATE TABLE // with the same name will result in the CREATE TABLE being seen. for i := len(tc.uncommittedTables) - 1; i >= 0; i-- { @@ -561,7 +579,7 @@ func (tc *TableCollection) getUncommittedTable( if table.Name == string(tn.TableName) && table.ParentID == dbID { // Right state? - if err = filterTableState(table); err != nil && err != errTableAdding { + if err = filterTableState(table.TableDesc()); err != nil && err != errTableAdding { if !required { // If it's not required here, we simply say we don't have it. err = nil @@ -578,7 +596,7 @@ func (tc *TableCollection) getUncommittedTable( return false, nil, nil } -func (tc *TableCollection) getUncommittedTableByID(id sqlbase.ID) *sqlbase.TableDescriptor { +func (tc *TableCollection) getUncommittedTableByID(id sqlbase.ID) *sqlbase.MutableTableDescriptor { // Walk latest to earliest so that a DROP TABLE followed by a CREATE TABLE // with the same name will result in the CREATE TABLE being seen. for i := len(tc.uncommittedTables) - 1; i >= 0; i-- { @@ -801,13 +819,13 @@ func (p *planner) writeTableDescToBatch( // If the descriptor version had been incremented before it would have // been placed in the uncommitted tables list. if p.Tables().getUncommittedTableByID(tableDesc.ID) == nil { - if err := incrementVersion(ctx, tableDesc, p.txn); err != nil { + if err := incrementVersion(ctx, tableDesc.TableDesc(), p.txn); err != nil { return err } } // Schedule a schema changer for later. - p.queueSchemaChange(tableDesc, mutationID) + p.queueSchemaChange(tableDesc.TableDesc(), mutationID) } if err := tableDesc.ValidateTable(p.extendedEvalCtx.Settings); err != nil { diff --git a/pkg/sql/testutils.go b/pkg/sql/testutils.go index 37720b496254..e35823dabdf9 100644 --- a/pkg/sql/testutils.go +++ b/pkg/sql/testutils.go @@ -40,7 +40,7 @@ func CreateTestTableDescriptor( } semaCtx := tree.MakeSemaContext(false /* privileged */) evalCtx := tree.MakeTestingEvalContext(st) - return MakeTableDesc( + desc, err := MakeTableDesc( ctx, nil, /* txn */ nil, /* vt */ @@ -53,6 +53,7 @@ func CreateTestTableDescriptor( &semaCtx, &evalCtx, ) + return desc.TableDescriptor, err } func makeTestingExtendedEvalContext(st *cluster.Settings) extendedEvalContext { diff --git a/pkg/sql/truncate.go b/pkg/sql/truncate.go index ed011e134462..8ba4bc85bd5d 100644 --- a/pkg/sql/truncate.go +++ b/pkg/sql/truncate.go @@ -108,7 +108,7 @@ func (t *truncateNode) startExec(params runParams) error { if _, ok := toTruncate[ref.Table]; ok { return nil } - other, err := sqlbase.GetTableDescFromID(ctx, p.txn, ref.Table) + other, err := p.Tables().getMutableTableVersionByID(ctx, ref.Table, p.txn) if err != nil { return err } @@ -119,7 +119,7 @@ func (t *truncateNode) startExec(params runParams) error { if err := p.CheckPrivilege(ctx, other, privilege.DROP); err != nil { return err } - otherName, err := p.getQualifiedTableName(ctx, other) + otherName, err := p.getQualifiedTableName(ctx, other.TableDesc()) if err != nil { return err } @@ -186,12 +186,12 @@ func (p *planner) truncateTable( ) error { // Read the table descriptor because it might have changed // while another table in the truncation list was truncated. - tableDesc, err := sqlbase.GetTableDescFromID(ctx, p.txn, id) + tableDesc, err := p.Tables().getMutableTableVersionByID(ctx, id, p.txn) if err != nil { return err } tableDesc.DropJobID = dropJobID - newTableDesc := *tableDesc + newTableDesc := NewMutableTableDescriptor(tableDesc.TableDescriptor) newTableDesc.ReplacementOf = sqlbase.TableDescriptor_Replacement{ ID: id, Time: p.txn.CommitTimestamp(), } @@ -210,7 +210,7 @@ func (p *planner) truncateTable( // structured.proto // // TODO(vivek): Fix properly along with #12123. - zoneKey, nameKey, _ := GetKeysForTableDescriptor(tableDesc) + zoneKey, nameKey, _ := GetKeysForTableDescriptor(tableDesc.TableDesc()) b := &client.Batch{} // Use CPut because we want to remove a specific name -> id map. if traceKV { @@ -250,7 +250,7 @@ func (p *planner) truncateTable( // Reassign all self references. if changed, err := reassignReferencedTables( - []*sqlbase.MutableTableDescriptor{&newTableDesc}, tableDesc.ID, newID, + []*sqlbase.MutableTableDescriptor{newTableDesc}, tableDesc.ID, newID, ); err != nil { return err } else if changed { @@ -270,7 +270,7 @@ func (p *planner) truncateTable( tKey := tableKey{parentID: newTableDesc.ParentID, name: newTableDesc.Name} key := tKey.Key() if err := p.createDescriptorWithID( - ctx, key, newID, &newTableDesc, p.ExtendedEvalContext().Settings); err != nil { + ctx, key, newID, newTableDesc, p.ExtendedEvalContext().Settings); err != nil { return err } @@ -309,7 +309,7 @@ func (p *planner) findAllReferences( if id == table.ID { continue } - t, err := sqlbase.GetTableDescFromID(ctx, p.txn, id) + t, err := p.Tables().getMutableTableVersionByID(ctx, id, p.txn) if err != nil { return nil, err } diff --git a/pkg/sql/user.go b/pkg/sql/user.go index 716c95dcc7ef..89d7f8b801e1 100644 --- a/pkg/sql/user.go +++ b/pkg/sql/user.go @@ -72,12 +72,7 @@ var roleMembersTableName = tree.MakeTableName("system", "role_members") // BumpRoleMembershipTableVersion increases the table version for the // role membership table. func (p *planner) BumpRoleMembershipTableVersion(ctx context.Context) error { - var tableDesc *TableDescriptor - var err error - p.runWithOptions(resolveFlags{skipCache: true}, func() { - tableDesc, _, err = p.PhysicalSchemaAccessor().GetObjectDesc(&roleMembersTableName, - p.ObjectLookupFlags(ctx, true /*required*/)) - }) + tableDesc, err := p.ResolveMutableTableDescriptor(ctx, &roleMembersTableName, true, anyDescType) if err != nil { return err } diff --git a/pkg/sql/virtual_schema.go b/pkg/sql/virtual_schema.go index 21047e17fb6e..30dde86fabc6 100644 --- a/pkg/sql/virtual_schema.go +++ b/pkg/sql/virtual_schema.go @@ -111,7 +111,7 @@ func (t virtualSchemaTable) initVirtualTableDesc( // Virtual tables never use SERIAL so we need not process SERIAL // types here. - return MakeTableDesc( + mutDesc, err := MakeTableDesc( ctx, nil, /* txn */ nil, /* vt */ @@ -125,6 +125,7 @@ func (t virtualSchemaTable) initVirtualTableDesc( nil, /* semaCtx */ nil, /* evalCtx */ ) + return mutDesc.TableDescriptor, err } // getSchema is part of the virtualSchemaDef interface. @@ -143,7 +144,7 @@ func (v virtualSchemaView) initVirtualTableDesc( create := stmt.(*tree.CreateView) - return MakeViewTableDesc( + mutDesc, err := MakeViewTableDesc( create, v.resultColumns, 0, @@ -153,6 +154,7 @@ func (v virtualSchemaView) initVirtualTableDesc( nil, // semaCtx nil, // evalCtx ) + return mutDesc.TableDescriptor, err } // virtualSchemas holds a slice of statically registered virtualSchema objects. diff --git a/pkg/sql/zone_config.go b/pkg/sql/zone_config.go index deed7d3d0aee..83805b3a15a7 100644 --- a/pkg/sql/zone_config.go +++ b/pkg/sql/zone_config.go @@ -249,9 +249,13 @@ func zoneSpecifierNotFoundError(zs tree.ZoneSpecifier) error { // Returns res = nil if the zone specifier is not for a table or index. func (p *planner) resolveTableForZone( ctx context.Context, zs *tree.ZoneSpecifier, -) (res *MutableTableDescriptor, err error) { +) (res *TableDescriptor, err error) { if zs.TargetsIndex() { - _, res, err = expandMutableIndexName(ctx, p, &zs.TableOrIndex, true /* requireTable */) + var mutRes *MutableTableDescriptor + _, mutRes, err = expandMutableIndexName(ctx, p, &zs.TableOrIndex, true /* requireTable */) + if mutRes != nil { + res = mutRes.TableDesc() + } } else if zs.TargetsTable() { p.runWithOptions(resolveFlags{skipCache: true}, func() { res, err = ResolveExistingObject(