From 38531fad1318699d534950bf9f1c861d9cd8bd0a Mon Sep 17 00:00:00 2001 From: Faizan Qazi Date: Wed, 26 May 2021 15:23:14 -0400 Subject: [PATCH] sql: Add unit tests for planning inside the new schema changer Previously, the new schema changer did not have any unit tests covering the planning capability. This was inadequate, because we had no way of detect if plans were regressing with changes or enhancements. To address this, this patch adds basic tests to see if the operators/dependencies for a given command are sane. Release note: None --- pkg/sql/schemachanger/scgraphviz/graphviz.go | 12 +- pkg/sql/schemachanger/scplan/main_test.go | 31 + pkg/sql/schemachanger/scplan/plan.go | 23 +- pkg/sql/schemachanger/scplan/plan_test.go | 213 +++++++ .../schemachanger/scplan/testdata/alter_table | 559 ++++++++++++++++++ .../scplan/testdata/drop_sequence | 88 +++ 6 files changed, 912 insertions(+), 14 deletions(-) create mode 100644 pkg/sql/schemachanger/scplan/main_test.go create mode 100644 pkg/sql/schemachanger/scplan/plan_test.go create mode 100644 pkg/sql/schemachanger/scplan/testdata/alter_table create mode 100644 pkg/sql/schemachanger/scplan/testdata/drop_sequence diff --git a/pkg/sql/schemachanger/scgraphviz/graphviz.go b/pkg/sql/schemachanger/scgraphviz/graphviz.go index ab9de8098e16..e3c1fd2ae4bd 100644 --- a/pkg/sql/schemachanger/scgraphviz/graphviz.go +++ b/pkg/sql/schemachanger/scgraphviz/graphviz.go @@ -161,11 +161,11 @@ func htmlLabel(o interface{}) dot.HTML { return dot.HTML(buf.String()) } -// toMap converts a struct to a map, field by field. If at any point a protobuf +// ToMap converts a struct to a map, field by field. If at any point a protobuf // message is encountered, it is converted to a map using jsonpb to marshal it // to json and then marshaling it back to a map. This approach allows zero // values to be effectively omitted. -func toMap(v interface{}) (interface{}, error) { +func ToMap(v interface{}) (interface{}, error) { if v == nil { return nil, nil } @@ -202,7 +202,7 @@ func toMap(v interface{}) (interface{}, error) { continue } var err error - if m[vt.Field(i).Name], err = toMap(vvf.Interface()); err != nil { + if m[vt.Field(i).Name], err = ToMap(vvf.Interface()); err != nil { return nil, err } } @@ -231,7 +231,7 @@ var objectTemplate = template.Must(template.New("obj").Funcs(template.FuncMap{ "isStruct": func(v interface{}) bool { return reflect.ValueOf(v).Kind() == reflect.Struct }, - "toMap": toMap, + "ToMap": ToMap, }).Parse(` {{- define "key" -}} @@ -271,7 +271,7 @@ var objectTemplate = template.Must(template.New("obj").Funcs(template.FuncMap{ {{- typeOf . -}} -{{- template "mapVal" (toMap $v) -}} +{{- template "mapVal" (ToMap $v) -}} {{- else -}} -{{- template "val" $v -}} @@ -291,7 +291,7 @@ var objectTemplate = template.Must(template.New("obj").Funcs(template.FuncMap{ {{- template "header" . -}}
-{{- template "mapVal" (toMap .) -}} +{{- template "mapVal" (ToMap .) -}}
`)) diff --git a/pkg/sql/schemachanger/scplan/main_test.go b/pkg/sql/schemachanger/scplan/main_test.go new file mode 100644 index 000000000000..0fcc82ddb345 --- /dev/null +++ b/pkg/sql/schemachanger/scplan/main_test.go @@ -0,0 +1,31 @@ +// Copyright 2021 The Cockroach Authors. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +package scplan_test + +import ( + "os" + "testing" + + "github.com/cockroachdb/cockroach/pkg/security" + "github.com/cockroachdb/cockroach/pkg/security/securitytest" + "github.com/cockroachdb/cockroach/pkg/server" + "github.com/cockroachdb/cockroach/pkg/testutils/serverutils" + "github.com/cockroachdb/cockroach/pkg/testutils/testcluster" + "github.com/cockroachdb/cockroach/pkg/util/randutil" +) + +func TestMain(m *testing.M) { + security.SetAssetLoader(securitytest.EmbeddedAssets) + randutil.SeedForTests() + serverutils.InitTestServerFactory(server.TestServerFactory) + serverutils.InitTestClusterFactory(testcluster.TestClusterFactory) + os.Exit(m.Run()) +} diff --git a/pkg/sql/schemachanger/scplan/plan.go b/pkg/sql/schemachanger/scplan/plan.go index 2b4814478c83..655ce82c9633 100644 --- a/pkg/sql/schemachanger/scplan/plan.go +++ b/pkg/sql/schemachanger/scplan/plan.go @@ -56,6 +56,9 @@ type Params struct { // // This doesn't do anything right now. CreatedDescriptorIDs catalog.DescriptorIDSet + // DisableOpRandomization disables randomization for the final set of + // operations. + DisableOpRandomization bool } // A Plan is a schema change plan, primarily containing ops to be executed that @@ -110,7 +113,7 @@ func MakePlan(initialStates []*scpb.Node, params Params) (_ Plan, err error) { }); err != nil { return Plan{}, err } - stages := buildStages(initialStates, g) + stages := buildStages(initialStates, g, params) return Plan{ Params: params, InitialNodes: initialStates, @@ -119,7 +122,7 @@ func MakePlan(initialStates []*scpb.Node, params Params) (_ Plan, err error) { }, nil } -func buildStages(init []*scpb.Node, g *scgraph.Graph) []Stage { +func buildStages(init []*scpb.Node, g *scgraph.Graph, params Params) []Stage { // TODO(ajwerner): deal with the case where the target state was // fulfilled by something that preceded the initial state. cur := init @@ -236,12 +239,15 @@ func buildStages(init []*scpb.Node, g *scgraph.Graph) []Stage { // be order independent, however we will // try to execute non-failing ones first. opsSlice := s.Ops.Slice() - rand.Seed(timeutil.Now().UnixNano()) - rand.Shuffle(len(opsSlice), func(i, j int) { - tmp := opsSlice[i] - opsSlice[i] = opsSlice[j] - opsSlice[j] = tmp - }) + if !params.DisableOpRandomization { + + rand.Seed(timeutil.Now().UnixNano()) + rand.Shuffle(len(opsSlice), func(i, j int) { + tmp := opsSlice[i] + opsSlice[i] = opsSlice[j] + opsSlice[j] = tmp + }) + } // Place non-revertible operations at the end sort.SliceStable(opsSlice, func(i, j int) bool { if opsSlice[i].Revertible() == opsSlice[j].Revertible() { @@ -251,6 +257,7 @@ func buildStages(init []*scpb.Node, g *scgraph.Graph) []Stage { }) stages = append(stages, s) cur = s.After + } return stages } diff --git a/pkg/sql/schemachanger/scplan/plan_test.go b/pkg/sql/schemachanger/scplan/plan_test.go new file mode 100644 index 000000000000..e0a155d9e86b --- /dev/null +++ b/pkg/sql/schemachanger/scplan/plan_test.go @@ -0,0 +1,213 @@ +// Copyright 2021 The Cockroach Authors. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +package scplan_test + +import ( + "context" + "fmt" + "path/filepath" + "strings" + "testing" + + "github.com/cockroachdb/cockroach/pkg/base" + "github.com/cockroachdb/cockroach/pkg/kv" + "github.com/cockroachdb/cockroach/pkg/security" + "github.com/cockroachdb/cockroach/pkg/sql" + "github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb" + "github.com/cockroachdb/cockroach/pkg/sql/catalog/descs" + "github.com/cockroachdb/cockroach/pkg/sql/catalog/resolver" + "github.com/cockroachdb/cockroach/pkg/sql/parser" + "github.com/cockroachdb/cockroach/pkg/sql/schemachanger/scbuild" + "github.com/cockroachdb/cockroach/pkg/sql/schemachanger/scgraph" + "github.com/cockroachdb/cockroach/pkg/sql/schemachanger/scgraphviz" + "github.com/cockroachdb/cockroach/pkg/sql/schemachanger/scpb" + "github.com/cockroachdb/cockroach/pkg/sql/schemachanger/scplan" + "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" + "github.com/cockroachdb/cockroach/pkg/sql/sessiondatapb" + "github.com/cockroachdb/cockroach/pkg/testutils/serverutils" + "github.com/cockroachdb/cockroach/pkg/testutils/sqlutils" + "github.com/cockroachdb/cockroach/pkg/util/leaktest" + "github.com/cockroachdb/cockroach/pkg/util/log" + "github.com/cockroachdb/datadriven" + "github.com/stretchr/testify/require" + "gopkg.in/yaml.v2" +) + +func TestPlanAlterTable(t *testing.T) { + defer leaktest.AfterTest(t)() + defer log.Scope(t).Close(t) + ctx := context.Background() + + datadriven.Walk(t, filepath.Join("testdata"), func(t *testing.T, path string) { + s, sqlDB, _ := serverutils.StartServer(t, base.TestServerArgs{}) + defer s.Stopper().Stop(ctx) + + tdb := sqlutils.MakeSQLRunner(sqlDB) + run := func(t *testing.T, d *datadriven.TestData) string { + switch d.Cmd { + case "create-view": + fallthrough + case "create-sequence": + fallthrough + case "create-table": + stmts, err := parser.Parse(d.Input) + require.NoError(t, err) + require.Len(t, stmts, 1) + tableName := "" + switch node := stmts[0].AST.(type) { + case *tree.CreateTable: + tableName = node.Table.String() + case *tree.CreateSequence: + tableName = node.Name.String() + case *tree.CreateView: + tableName = node.Name.String() + default: + t.Fatal("not a CREATE TABLE/SEQUENCE/VIEW statement") + } + tdb.Exec(t, d.Input) + + var tableID descpb.ID + tdb.QueryRow(t, `SELECT $1::regclass::int`, tableName).Scan(&tableID) + if tableID == 0 { + t.Fatalf("failed to read ID of new table %s", tableName) + } + t.Logf("created relation with id %d", tableID) + + return "" + case "deps": + fallthrough + case "ops": + deps, cleanup := newTestingPlanDeps(s) + defer cleanup() + + stmts, err := parser.Parse(d.Input) + require.NoError(t, err) + var outputNodes []*scpb.Node + for i := range stmts { + outputNodes, err = scbuild.Build(ctx, stmts[i].AST, *deps, outputNodes) + require.NoError(t, err) + } + + plan, err := scplan.MakePlan(outputNodes, + scplan.Params{ + ExecutionPhase: scplan.PostCommitPhase, + DisableOpRandomization: true, + }) + require.NoError(t, err) + + if d.Cmd == "ops" { + return marshalOps(t, &plan) + } + return marshalDeps(t, &plan) + case "unimplemented": + deps, cleanup := newTestingPlanDeps(s) + defer cleanup() + + stmts, err := parser.Parse(d.Input) + require.NoError(t, err) + require.Len(t, stmts, 1) + + stmt := stmts[0] + alter, ok := stmt.AST.(*tree.AlterTable) + require.Truef(t, ok, "not an ALTER TABLE statement: %s", stmt.SQL) + _, err = scbuild.Build(ctx, alter, *deps, nil) + require.Truef(t, scbuild.HasNotImplemented(err), "expected unimplemented, got %v", err) + return "" + + default: + return fmt.Sprintf("unknown command: %s", d.Cmd) + } + } + datadriven.RunTest(t, path, run) + }) +} + +// indentText indents text for formatting out marshalled data. +func indentText(input string, tab string) (final string) { + split := strings.Split(input, "\n") + for idx, line := range split { + if len(line) == 0 { + continue + } + final += tab + line + if idx != len(split)-1 { + final = final + "\n" + } + } + return final +} + +// marshalDeps marshals dependencies in scplan.Plan to a string. +func marshalDeps(t *testing.T, plan *scplan.Plan) string { + stages := "" + convertNode := func(node *scpb.Node) string { + depMap, err := scgraphviz.ToMap(node) + require.NoError(t, err) + data, err := yaml.Marshal(depMap) + require.NoError(t, err) + return string(data) + } + + plan.Graph.ForEachNode(func(n *scpb.Node) error { + return plan.Graph.ForEachDepEdgeFrom(n, func(de *scgraph.DepEdge) error { + stages += fmt.Sprintf("Dependency From:\n%sTo:\n%s", + indentText(convertNode(de.To()), " "), + indentText(convertNode(de.From()), " ")) + return nil + }) + }) + return stages +} + +// marshalOps marshals operations in scplan.Plan to a string. +func marshalOps(t *testing.T, plan *scplan.Plan) string { + stages := "" + for stageIdx, stage := range plan.Stages { + stages += fmt.Sprintf("Stage %d\n", stageIdx) + stageOps := "" + for _, op := range stage.Ops.Slice() { + opMap, err := scgraphviz.ToMap(op) + require.NoError(t, err) + data, err := yaml.Marshal(opMap) + require.NoError(t, err) + stageOps += fmt.Sprintf("%T\n%s", op, indentText(string(data), " ")) + } + stages += indentText(stageOps, " ") + } + return stages +} + +func newTestingPlanDeps(s serverutils.TestServerInterface) (*scbuild.Dependencies, func()) { + execCfg := s.ExecutorConfig().(sql.ExecutorConfig) + ip, cleanup := sql.NewInternalPlanner( + "test", + kv.NewTxn(context.Background(), s.DB(), s.NodeID()), + security.RootUserName(), + &sql.MemoryMetrics{}, + &execCfg, + // Setting the database on the session data to "defaultdb" in the obvious + // way doesn't seem to do what we want. + sessiondatapb.SessionData{}, + ) + planner := ip.(interface { + resolver.SchemaResolver + SemaCtx() *tree.SemaContext + EvalContext() *tree.EvalContext + Descriptors() *descs.Collection + }) + buildDeps := scbuild.Dependencies{ + Res: planner, + SemaCtx: planner.SemaCtx(), + EvalCtx: planner.EvalContext(), + Descs: planner.Descriptors(), + } + return &buildDeps, cleanup +} diff --git a/pkg/sql/schemachanger/scplan/testdata/alter_table b/pkg/sql/schemachanger/scplan/testdata/alter_table new file mode 100644 index 000000000000..1f4cb2cce9f5 --- /dev/null +++ b/pkg/sql/schemachanger/scplan/testdata/alter_table @@ -0,0 +1,559 @@ +create-table +CREATE TABLE defaultdb.foo (i INT PRIMARY KEY) +---- + +ops +ALTER TABLE defaultdb.foo ADD COLUMN j INT +---- +Stage 0 + *scop.MakeAddedColumnDeleteOnly + Column: + ID: 2 + Name: j + Nullable: true + Type: + family: IntFamily + oid: 20 + width: 64 + FamilyName: primary + TableID: 52 + *scop.MakeAddedIndexDeleteOnly + Index: + EncodingType: 1 + ID: 2 + KeyColumnDirections: + - 0 + KeyColumnIDs: + - 1 + KeyColumnNames: + - i + Name: new_primary_key + StoreColumnIDs: + - 2 + StoreColumnNames: + - j + Unique: true + Version: 3 + TableID: 52 +Stage 1 + *scop.MakeAddedColumnDeleteAndWriteOnly + ColumnID: 2 + TableID: 52 + *scop.MakeAddedIndexDeleteAndWriteOnly + IndexID: 2 + TableID: 52 +Stage 2 + scop.BackfillIndex + IndexID: 2 + TableID: 52 +Stage 3 + scop.ValidateUniqueIndex + IndexID: 2 + PrimaryIndexID: 1 + TableID: 52 +Stage 4 + *scop.MakeColumnPublic + ColumnID: 2 + TableID: 52 + *scop.MakeAddedPrimaryIndexPublic + Index: + ID: 2 + KeyColumnDirections: + - 0 + KeyColumnIDs: + - 1 + KeyColumnNames: + - i + Name: new_primary_key + Unique: true + Version: 3 + TableID: 52 + *scop.MakeDroppedPrimaryIndexDeleteAndWriteOnly + Index: + EncodingType: 1 + ID: 1 + KeyColumnDirections: + - 0 + KeyColumnIDs: + - 1 + KeyColumnNames: + - i + Name: primary + Unique: true + Version: 3 + TableID: 52 +Stage 5 + *scop.MakeDroppedIndexDeleteOnly + IndexID: 1 + TableID: 52 +Stage 6 + *scop.MakeIndexAbsent + IndexID: 1 + TableID: 52 + +ops +ALTER TABLE defaultdb.foo ADD COLUMN j INT DEFAULT 123 +---- +Stage 0 + *scop.MakeAddedColumnDeleteOnly + Column: + DefaultExpr: 123:::INT8 + ID: 2 + Name: j + Nullable: true + Type: + family: IntFamily + oid: 20 + width: 64 + FamilyName: primary + TableID: 52 + *scop.MakeAddedIndexDeleteOnly + Index: + EncodingType: 1 + ID: 2 + KeyColumnDirections: + - 0 + KeyColumnIDs: + - 1 + KeyColumnNames: + - i + Name: new_primary_key + StoreColumnIDs: + - 2 + StoreColumnNames: + - j + Unique: true + Version: 3 + TableID: 52 +Stage 1 + *scop.MakeAddedColumnDeleteAndWriteOnly + ColumnID: 2 + TableID: 52 + *scop.MakeAddedIndexDeleteAndWriteOnly + IndexID: 2 + TableID: 52 +Stage 2 + scop.BackfillIndex + IndexID: 2 + TableID: 52 +Stage 3 + scop.ValidateUniqueIndex + IndexID: 2 + PrimaryIndexID: 1 + TableID: 52 +Stage 4 + *scop.MakeColumnPublic + ColumnID: 2 + TableID: 52 + *scop.MakeAddedPrimaryIndexPublic + Index: + ID: 2 + KeyColumnDirections: + - 0 + KeyColumnIDs: + - 1 + KeyColumnNames: + - i + Name: new_primary_key + Unique: true + Version: 3 + TableID: 52 + *scop.MakeDroppedPrimaryIndexDeleteAndWriteOnly + Index: + EncodingType: 1 + ID: 1 + KeyColumnDirections: + - 0 + KeyColumnIDs: + - 1 + KeyColumnNames: + - i + Name: primary + Unique: true + Version: 3 + TableID: 52 +Stage 5 + *scop.MakeDroppedIndexDeleteOnly + IndexID: 1 + TableID: 52 +Stage 6 + *scop.MakeIndexAbsent + IndexID: 1 + TableID: 52 + +ops +ALTER TABLE defaultdb.foo ADD COLUMN j INT DEFAULT 123; +ALTER TABLE defaultdb.foo ADD COLUMN k INT DEFAULT 456; +---- +Stage 0 + *scop.MakeAddedColumnDeleteOnly + Column: + DefaultExpr: 123:::INT8 + ID: 2 + Name: j + Nullable: true + Type: + family: IntFamily + oid: 20 + width: 64 + FamilyName: primary + TableID: 52 + *scop.MakeAddedIndexDeleteOnly + Index: + EncodingType: 1 + ID: 2 + KeyColumnDirections: + - 0 + KeyColumnIDs: + - 1 + KeyColumnNames: + - i + Name: new_primary_key + StoreColumnIDs: + - 2 + - 3 + StoreColumnNames: + - j + - k + Unique: true + Version: 3 + TableID: 52 + *scop.MakeAddedColumnDeleteOnly + Column: + DefaultExpr: 456:::INT8 + ID: 3 + Name: k + Nullable: true + Type: + family: IntFamily + oid: 20 + width: 64 + FamilyName: primary + TableID: 52 +Stage 1 + *scop.MakeAddedColumnDeleteAndWriteOnly + ColumnID: 2 + TableID: 52 + *scop.MakeAddedIndexDeleteAndWriteOnly + IndexID: 2 + TableID: 52 + *scop.MakeAddedColumnDeleteAndWriteOnly + ColumnID: 3 + TableID: 52 +Stage 2 + scop.BackfillIndex + IndexID: 2 + TableID: 52 +Stage 3 + scop.ValidateUniqueIndex + IndexID: 2 + PrimaryIndexID: 1 + TableID: 52 +Stage 4 + *scop.MakeColumnPublic + ColumnID: 2 + TableID: 52 + *scop.MakeAddedPrimaryIndexPublic + Index: + ID: 2 + KeyColumnDirections: + - 0 + KeyColumnIDs: + - 1 + KeyColumnNames: + - i + Name: new_primary_key + Unique: true + Version: 3 + TableID: 52 + *scop.MakeDroppedPrimaryIndexDeleteAndWriteOnly + Index: + EncodingType: 1 + ID: 1 + KeyColumnDirections: + - 0 + KeyColumnIDs: + - 1 + KeyColumnNames: + - i + Name: primary + Unique: true + Version: 3 + TableID: 52 + *scop.MakeColumnPublic + ColumnID: 3 + TableID: 52 +Stage 5 + *scop.MakeDroppedIndexDeleteOnly + IndexID: 1 + TableID: 52 +Stage 6 + *scop.MakeIndexAbsent + IndexID: 1 + TableID: 52 + +ops +ALTER TABLE defaultdb.foo ADD COLUMN a INT AS (i+1) STORED +---- +Stage 0 + *scop.MakeAddedColumnDeleteOnly + Column: + ComputeExpr: i + 1:::INT8 + ID: 2 + Name: a + Nullable: true + Type: + family: IntFamily + oid: 20 + width: 64 + FamilyName: primary + TableID: 52 + *scop.MakeAddedIndexDeleteOnly + Index: + EncodingType: 1 + ID: 2 + KeyColumnDirections: + - 0 + KeyColumnIDs: + - 1 + KeyColumnNames: + - i + Name: new_primary_key + StoreColumnIDs: + - 2 + StoreColumnNames: + - a + Unique: true + Version: 3 + TableID: 52 +Stage 1 + *scop.MakeAddedColumnDeleteAndWriteOnly + ColumnID: 2 + TableID: 52 + *scop.MakeAddedIndexDeleteAndWriteOnly + IndexID: 2 + TableID: 52 +Stage 2 + scop.BackfillIndex + IndexID: 2 + TableID: 52 +Stage 3 + scop.ValidateUniqueIndex + IndexID: 2 + PrimaryIndexID: 1 + TableID: 52 +Stage 4 + *scop.MakeColumnPublic + ColumnID: 2 + TableID: 52 + *scop.MakeAddedPrimaryIndexPublic + Index: + ID: 2 + KeyColumnDirections: + - 0 + KeyColumnIDs: + - 1 + KeyColumnNames: + - i + Name: new_primary_key + Unique: true + Version: 3 + TableID: 52 + *scop.MakeDroppedPrimaryIndexDeleteAndWriteOnly + Index: + EncodingType: 1 + ID: 1 + KeyColumnDirections: + - 0 + KeyColumnIDs: + - 1 + KeyColumnNames: + - i + Name: primary + Unique: true + Version: 3 + TableID: 52 +Stage 5 + *scop.MakeDroppedIndexDeleteOnly + IndexID: 1 + TableID: 52 +Stage 6 + *scop.MakeIndexAbsent + IndexID: 1 + TableID: 52 + + +create-table +CREATE TABLE defaultdb.bar (j INT); +---- + +ops +ALTER TABLE defaultdb.foo ADD COLUMN a INT; +ALTER TABLE defaultdb.bar ADD COLUMN b INT; +---- +Stage 0 + *scop.MakeAddedColumnDeleteOnly + Column: + ID: 2 + Name: a + Nullable: true + Type: + family: IntFamily + oid: 20 + width: 64 + FamilyName: primary + TableID: 52 + *scop.MakeAddedIndexDeleteOnly + Index: + EncodingType: 1 + ID: 2 + KeyColumnDirections: + - 0 + KeyColumnIDs: + - 1 + KeyColumnNames: + - i + Name: new_primary_key + StoreColumnIDs: + - 2 + StoreColumnNames: + - a + Unique: true + Version: 3 + TableID: 52 + *scop.MakeAddedColumnDeleteOnly + Column: + ID: 3 + Name: b + Nullable: true + Type: + family: IntFamily + oid: 20 + width: 64 + FamilyName: primary + TableID: 53 + *scop.MakeAddedIndexDeleteOnly + Index: + EncodingType: 1 + ID: 2 + KeyColumnDirections: + - 0 + KeyColumnIDs: + - 2 + KeyColumnNames: + - rowid + Name: new_primary_key + StoreColumnIDs: + - 1 + - 3 + StoreColumnNames: + - j + - b + Unique: true + TableID: 53 +Stage 1 + *scop.MakeAddedColumnDeleteAndWriteOnly + ColumnID: 2 + TableID: 52 + *scop.MakeAddedIndexDeleteAndWriteOnly + IndexID: 2 + TableID: 52 + *scop.MakeAddedColumnDeleteAndWriteOnly + ColumnID: 3 + TableID: 53 + *scop.MakeAddedIndexDeleteAndWriteOnly + IndexID: 2 + TableID: 53 +Stage 2 + scop.BackfillIndex + IndexID: 2 + TableID: 52 + scop.BackfillIndex + IndexID: 2 + TableID: 53 +Stage 3 + scop.ValidateUniqueIndex + IndexID: 2 + PrimaryIndexID: 1 + TableID: 52 + scop.ValidateUniqueIndex + IndexID: 2 + PrimaryIndexID: 1 + TableID: 53 +Stage 4 + *scop.MakeColumnPublic + ColumnID: 2 + TableID: 52 + *scop.MakeAddedPrimaryIndexPublic + Index: + ID: 2 + KeyColumnDirections: + - 0 + KeyColumnIDs: + - 1 + KeyColumnNames: + - i + Name: new_primary_key + Unique: true + Version: 3 + TableID: 52 + *scop.MakeDroppedPrimaryIndexDeleteAndWriteOnly + Index: + EncodingType: 1 + ID: 1 + KeyColumnDirections: + - 0 + KeyColumnIDs: + - 1 + KeyColumnNames: + - i + Name: primary + Unique: true + Version: 3 + TableID: 52 + *scop.MakeColumnPublic + ColumnID: 3 + TableID: 53 + *scop.MakeAddedPrimaryIndexPublic + Index: + ID: 2 + KeyColumnDirections: + - 0 + KeyColumnIDs: + - 2 + KeyColumnNames: + - rowid + Name: new_primary_key + Unique: true + TableID: 53 + *scop.MakeDroppedPrimaryIndexDeleteAndWriteOnly + Index: + EncodingType: 1 + ID: 1 + KeyColumnDirections: + - 0 + KeyColumnIDs: + - 2 + KeyColumnNames: + - rowid + Name: primary + StoreColumnIDs: + - 1 + StoreColumnNames: + - j + Unique: true + TableID: 53 +Stage 5 + *scop.MakeDroppedIndexDeleteOnly + IndexID: 1 + TableID: 52 + *scop.MakeDroppedIndexDeleteOnly + IndexID: 1 + TableID: 53 +Stage 6 + *scop.MakeIndexAbsent + IndexID: 1 + TableID: 52 + *scop.MakeIndexAbsent + IndexID: 1 + TableID: 53 diff --git a/pkg/sql/schemachanger/scplan/testdata/drop_sequence b/pkg/sql/schemachanger/scplan/testdata/drop_sequence new file mode 100644 index 000000000000..ffc8a5072b76 --- /dev/null +++ b/pkg/sql/schemachanger/scplan/testdata/drop_sequence @@ -0,0 +1,88 @@ +create-sequence +CREATE SEQUENCE defaultdb.SQ1 +---- + +ops +DROP SEQUENCE defaultdb.SQ1 CASCADE +---- +Stage 0 + *scop.CreateGcJobForDescriptor + DescID: 52 + *scop.MarkDescriptorAsDropped + TableID: 52 +Stage 1 + *scop.CreateGcJobForDescriptor + DescID: 52 + *scop.DrainDescriptorName + TableID: 52 + +create-table +CREATE TABLE defaultdb.blog_posts (id INT PRIMARY KEY, val int DEFAULT nextval('defaultdb.sq1'), title text) +---- + +create-table +CREATE TABLE defaultdb.blog_posts2 (id INT PRIMARY KEY, val int DEFAULT nextval('defaultdb.sq1'), title text) +---- + +ops +DROP SEQUENCE defaultdb.SQ1 CASCADE +---- +Stage 0 + *scop.RemoveColumnDefaultExpression + ColumnID: 2 + TableID: 53 + *scop.UpdateRelationDeps + TableID: 53 + *scop.RemoveColumnDefaultExpression + ColumnID: 2 + TableID: 54 + *scop.UpdateRelationDeps + TableID: 54 + *scop.CreateGcJobForDescriptor + DescID: 52 + *scop.MarkDescriptorAsDropped + TableID: 52 +Stage 1 + *scop.CreateGcJobForDescriptor + DescID: 52 + *scop.DrainDescriptorName + TableID: 52 + + +deps +DROP SEQUENCE defaultdb.SQ1 CASCADE +---- +Dependency From: + State: 1 + Target: + direction: DROP + elementProto: + defaultExpression: + columnId: 2 + tableId: 53 + usesSequenceIDs: + - 52 +To: + State: 2 + Target: + direction: DROP + elementProto: + table: + tableId: 52 +Dependency From: + State: 1 + Target: + direction: DROP + elementProto: + defaultExpression: + columnId: 2 + tableId: 54 + usesSequenceIDs: + - 52 +To: + State: 2 + Target: + direction: DROP + elementProto: + table: + tableId: 52