diff --git a/pkg/sql/logictest/testdata/logic_test/new_schema_changer b/pkg/sql/logictest/testdata/logic_test/new_schema_changer index ea9999f69123..801ab21990f1 100644 --- a/pkg/sql/logictest/testdata/logic_test/new_schema_changer +++ b/pkg/sql/logictest/testdata/logic_test/new_schema_changer @@ -36,7 +36,7 @@ EXPLAIN (DDL, VERBOSE) ALTER TABLE foo ADD COLUMN j INT │ │ │ │ ABSENT → PUBLIC │ │ │ │ │ │ │ └── • SameStagePrecedence dependency from PUBLIC ColumnName:{DescID: 106, Name: j, ColumnID: 2} -│ │ │ rule: "column named right before column becomes public" +│ │ │ rule: "column named right before column type becomes public" │ │ │ │ │ └── • PrimaryIndex:{DescID: 106, IndexID: 2, ConstraintID: 1, TemporaryIndexID: 3} │ │ │ ABSENT → BACKFILL_ONLY @@ -429,6 +429,7 @@ EXPLAIN (DDL, VERBOSE) ALTER TABLE foo ADD COLUMN j INT + statement ok ALTER TABLE foo ADD COLUMN j INT diff --git a/pkg/sql/schemachanger/rel/database.go b/pkg/sql/schemachanger/rel/database.go index 3782351d7006..1bc87bac2b36 100644 --- a/pkg/sql/schemachanger/rel/database.go +++ b/pkg/sql/schemachanger/rel/database.go @@ -261,6 +261,12 @@ func (t *Database) chooseIndex( if best >= 0 && overlap.len() <= bestOverlap.len() { continue } + // Only allow queries to proceed with no index overlap if this is the + // zero-attribute index, which implies the database creator accepts bad + // query plans. + if overlap == 0 && len(dims[i].attrs) > 0 { + continue + } if !dims[i].exists.isContainedIn(m.union(hasAttrs)) { continue } diff --git a/pkg/sql/schemachanger/rel/internal/cyclegraphtest/tests.go b/pkg/sql/schemachanger/rel/internal/cyclegraphtest/tests.go index 31c8c49724fc..9397588978a7 100644 --- a/pkg/sql/schemachanger/rel/internal/cyclegraphtest/tests.go +++ b/pkg/sql/schemachanger/rel/internal/cyclegraphtest/tests.go @@ -66,6 +66,7 @@ var ( {container1, message1}, {container2, message2}, }, + UnsatisfiableIndexes: []int{1}, }, { Name: "oneOf member", diff --git a/pkg/sql/schemachanger/rel/internal/entitynodetest/tests.go b/pkg/sql/schemachanger/rel/internal/entitynodetest/tests.go index 89fc49459a40..5077ef5885c0 100644 --- a/pkg/sql/schemachanger/rel/internal/entitynodetest/tests.go +++ b/pkg/sql/schemachanger/rel/internal/entitynodetest/tests.go @@ -100,6 +100,7 @@ var ( { Name: "a fields", Query: rel.Clauses{ + v("a").Type((*entity)(nil)), v("a").AttrEq(i16, int16(1)), v("a").AttrEqVar(i8, "ai8"), v("a").AttrEqVar(pi8, "api8"), @@ -109,7 +110,7 @@ var ( Results: [][]interface{}{ {a, int8(1), int8(1)}, }, - UnsatisfiableIndexes: []int{2}, + UnsatisfiableIndexes: []int{1, 2, 3, 5, 6}, }, { Name: "a-c-b join", @@ -125,7 +126,7 @@ var ( Results: [][]interface{}{ {a, b, c}, }, - UnsatisfiableIndexes: []int{2, 3}, + UnsatisfiableIndexes: []int{2, 3, 4, 5, 6}, }, { Name: "nil values don't show up", @@ -137,7 +138,7 @@ var ( Results: [][]interface{}{ {a}, }, - UnsatisfiableIndexes: []int{2}, + UnsatisfiableIndexes: []int{2, 4, 5, 6}, }, { Name: "nil values don't show up, scalar pointers same as pointers", @@ -149,7 +150,7 @@ var ( Results: [][]interface{}{ {a}, }, - UnsatisfiableIndexes: []int{2}, + UnsatisfiableIndexes: []int{2, 4, 5, 6}, }, { Name: "list all the values", @@ -163,7 +164,7 @@ var ( {b, int8(2)}, {c, int8(2)}, }, - UnsatisfiableIndexes: []int{2, 3}, + UnsatisfiableIndexes: []int{1, 2, 3, 4, 5, 6}, }, { Name: "list all the values with type constraint", @@ -178,6 +179,7 @@ var ( {b, int8(2)}, {c, int8(2)}, }, + UnsatisfiableIndexes: []int{1, 2, 3, 5, 6}, }, { Name: "nodes with elements where i8=2", @@ -192,7 +194,7 @@ var ( {nb, b}, {nc, c}, }, - UnsatisfiableIndexes: []int{2, 3}, + UnsatisfiableIndexes: []int{2, 3, 4, 5, 6}, }, { Name: "list all the i8 values", @@ -209,6 +211,7 @@ var ( {int8(2)}, {int8(2)}, }, + UnsatisfiableIndexes: []int{1, 2, 3, 5, 6}, }, { Name: "use a filter", @@ -223,7 +226,7 @@ var ( Results: [][]interface{}{ {a}, }, - UnsatisfiableIndexes: []int{2, 3}, + UnsatisfiableIndexes: []int{1, 2, 3, 4, 5, 6}, }, { Name: "types of all the entities", @@ -240,7 +243,7 @@ var ( {nb, reflect.TypeOf((*node)(nil))}, {nc, reflect.TypeOf((*node)(nil))}, }, - UnsatisfiableIndexes: []int{2, 3}, + UnsatisfiableIndexes: []int{1, 2, 3, 4, 5, 6}, }, { Name: "nodes by type", @@ -255,7 +258,7 @@ var ( Results: [][]interface{}{ {na, nb, nc, a}, }, - UnsatisfiableIndexes: []int{2, 3}, + UnsatisfiableIndexes: []int{1, 2, 3, 4, 5, 6}, }, { Name: "list nodes", @@ -269,6 +272,7 @@ var ( {nb}, {nc}, }, + UnsatisfiableIndexes: []int{1, 2, 3, 5, 6}, }, { Name: "basic any", @@ -285,6 +289,7 @@ var ( {nb}, {nc}, }, + UnsatisfiableIndexes: []int{1, 2, 3, 5, 6}, }, { Name: "self eq value", @@ -296,7 +301,7 @@ var ( Results: [][]interface{}{ {c}, }, - UnsatisfiableIndexes: []int{2, 3}, + UnsatisfiableIndexes: []int{1, 2, 3}, }, { Name: "contradiction due to missing attribute", @@ -307,7 +312,7 @@ var ( Entities: []v{"entity"}, ResVars: []v{"entity", "pi8"}, Results: [][]interface{}{}, - UnsatisfiableIndexes: []int{2}, + UnsatisfiableIndexes: []int{1, 2, 3}, }, { Name: "self eq self", @@ -319,7 +324,7 @@ var ( Results: [][]interface{}{ {a}, {b}, {c}, {na}, {nb}, {nc}, }, - UnsatisfiableIndexes: []int{2, 3}, + UnsatisfiableIndexes: []int{1, 2, 3, 4, 5, 6}, }, { Name: "variable type mismatch", @@ -345,7 +350,7 @@ var ( {na, a, na, a}, {na, a, nc, c}, }, - UnsatisfiableIndexes: []int{2, 3}, + UnsatisfiableIndexes: []int{1, 2, 3, 4, 5, 6}, }, { Name: "entity bound via variable with ne filter", @@ -365,7 +370,7 @@ var ( Results: [][]interface{}{ {na, a, nc, c}, }, - UnsatisfiableIndexes: []int{2, 3}, + UnsatisfiableIndexes: []int{1, 2, 3, 4, 5, 6}, }, { Name: "any value type mismatch", @@ -385,7 +390,7 @@ var ( Entities: []v{"e"}, ResVars: []v{"e", "i8"}, Results: [][]interface{}{}, - UnsatisfiableIndexes: []int{2, 3}, + UnsatisfiableIndexes: []int{1, 2, 3, 4, 5, 6}, }, { Name: "pointer scalar values any", @@ -397,7 +402,7 @@ var ( Results: [][]interface{}{ {a}, {b}, {c}, }, - UnsatisfiableIndexes: []int{2, 3}, + UnsatisfiableIndexes: []int{2, 3, 4, 5, 6}, }, { Name: "pointer scalar values", @@ -409,7 +414,7 @@ var ( Results: [][]interface{}{ {a}, }, - UnsatisfiableIndexes: []int{2, 3}, + UnsatisfiableIndexes: []int{2, 3, 4, 5, 6}, }, { Name: "nil pointer scalar values any", @@ -433,7 +438,7 @@ var ( Entities: []v{"e"}, ResVars: []v{"e"}, Results: [][]interface{}{}, - UnsatisfiableIndexes: []int{2, 3}, + UnsatisfiableIndexes: []int{2, 3, 4, 5, 6}, }, { Name: "any clause no match on variable eq", @@ -444,7 +449,7 @@ var ( Entities: []v{"e"}, ResVars: []v{"e", "i8"}, Results: [][]interface{}{}, - UnsatisfiableIndexes: []int{2, 3}, + UnsatisfiableIndexes: []int{1, 2, 3, 4, 5, 6}, }, }, }, diff --git a/pkg/sql/schemachanger/rel/reltest/database.go b/pkg/sql/schemachanger/rel/reltest/database.go index 97ebabeeea89..fb004db399c7 100644 --- a/pkg/sql/schemachanger/rel/reltest/database.go +++ b/pkg/sql/schemachanger/rel/reltest/database.go @@ -64,7 +64,7 @@ type QueryTest struct { func (tc DatabaseTest) run(t *testing.T, s Suite) { for i, databaseIndexes := range tc.databaseIndexes() { - t.Run(fmt.Sprintf("%v", databaseIndexes), func(t *testing.T) { + t.Run(fmt.Sprintf("%v", i), func(t *testing.T) { db, err := rel.NewDatabase(s.Schema, databaseIndexes...) require.NoError(t, err) for _, k := range tc.Data { diff --git a/pkg/sql/schemachanger/rel/testdata/cyclegraph b/pkg/sql/schemachanger/rel/testdata/cyclegraph index c1099909d60f..32b7c0a8af50 100755 --- a/pkg/sql/schemachanger/rel/testdata/cyclegraph +++ b/pkg/sql/schemachanger/rel/testdata/cyclegraph @@ -24,6 +24,7 @@ queries: results: - [container1, message1] - [container2, message2] + unsatisfiableIndexes: [1] oneOf member: query: - $c[s] = struct1(message1) diff --git a/pkg/sql/schemachanger/rel/testdata/entitynode b/pkg/sql/schemachanger/rel/testdata/entitynode index b499ddd103dd..e3bf283b075a 100755 --- a/pkg/sql/schemachanger/rel/testdata/entitynode +++ b/pkg/sql/schemachanger/rel/testdata/entitynode @@ -40,6 +40,7 @@ queries: queries: a fields: query: + - $a[Type] = '*entitynodetest.entity' - $a[i16] = 1 - $a[i8] = $ai8 - $a[pi8] = $api8 @@ -47,7 +48,7 @@ queries: result-vars: [$a, $ai8, $api8] results: - [a, 1, 1] - unsatisfiableIndexes: [2] + unsatisfiableIndexes: [1, 2, 3, 5, 6] a-c-b join: query: - $a[i8] = 1 @@ -59,7 +60,7 @@ queries: result-vars: [$a, $b, $c] results: - [a, b, c] - unsatisfiableIndexes: [2, 3] + unsatisfiableIndexes: [2, 3, 4, 5, 6] nil values don't show up: query: - $value[pi8] = 1 @@ -67,7 +68,7 @@ queries: result-vars: [$value] results: - [a] - unsatisfiableIndexes: [2] + unsatisfiableIndexes: [2, 4, 5, 6] nil values don't show up, scalar pointers same as pointers: query: - $value[pi8] = 1 @@ -75,7 +76,7 @@ queries: result-vars: [$value] results: - [a] - unsatisfiableIndexes: [2] + unsatisfiableIndexes: [2, 4, 5, 6] list all the values: query: - $value[i8] = $i8 @@ -85,7 +86,7 @@ queries: - [a, 1] - [b, 2] - [c, 2] - unsatisfiableIndexes: [2, 3] + unsatisfiableIndexes: [1, 2, 3, 4, 5, 6] list all the values with type constraint: query: - $value[i8] = $i8 @@ -96,6 +97,7 @@ queries: - [a, 1] - [b, 2] - [c, 2] + unsatisfiableIndexes: [1, 2, 3, 5, 6] nodes with elements where i8=2: query: - $i8 = 2 @@ -106,7 +108,7 @@ queries: results: - [nb, b] - [nc, c] - unsatisfiableIndexes: [2, 3] + unsatisfiableIndexes: [2, 3, 4, 5, 6] list all the i8 values: query: - $value[i8] = $i8 @@ -117,6 +119,7 @@ queries: - [1] - [2] - [2] + unsatisfiableIndexes: [1, 2, 3, 5, 6] use a filter: query: - $value[Self] = $_ @@ -125,7 +128,7 @@ queries: result-vars: [$value] results: - [a] - unsatisfiableIndexes: [2, 3] + unsatisfiableIndexes: [1, 2, 3, 4, 5, 6] types of all the entities: query: - $value[Type] = $typ @@ -138,7 +141,7 @@ queries: - [na, '*entitynodetest.node'] - [nb, '*entitynodetest.node'] - [nc, '*entitynodetest.node'] - unsatisfiableIndexes: [2, 3] + unsatisfiableIndexes: [1, 2, 3, 4, 5, 6] nodes by type: query: - $na[Type] = '*entitynodetest.node' @@ -149,7 +152,7 @@ queries: result-vars: [$na, $nb, $nc, $a] results: - [na, nb, nc, a] - unsatisfiableIndexes: [2, 3] + unsatisfiableIndexes: [1, 2, 3, 4, 5, 6] list nodes: query: - $n[Type] = '*entitynodetest.node' @@ -159,6 +162,7 @@ queries: - [na] - [nb] - [nc] + unsatisfiableIndexes: [1, 2, 3, 5, 6] basic any: query: - $entity[Type] IN ['*entitynodetest.node', '*entitynodetest.entity'] @@ -171,6 +175,7 @@ queries: - [na] - [nb] - [nc] + unsatisfiableIndexes: [1, 2, 3, 5, 6] self eq value: query: - '$entity[Self] = {i8: 2, pi8: null, i16: 1}' @@ -178,7 +183,7 @@ queries: result-vars: [$entity] results: - [c] - unsatisfiableIndexes: [2, 3] + unsatisfiableIndexes: [1, 2, 3] contradiction due to missing attribute: query: - '$entity[Self] = {i8: 2, pi8: null, i16: 1}' @@ -186,7 +191,7 @@ queries: entities: [$entity] result-vars: [$entity, $pi8] results: [] - unsatisfiableIndexes: [2] + unsatisfiableIndexes: [1, 2, 3] self eq self: query: - $entity[Self] = $entity @@ -199,7 +204,7 @@ queries: - [na] - [nb] - [nc] - unsatisfiableIndexes: [2, 3] + unsatisfiableIndexes: [1, 2, 3, 4, 5, 6] variable type mismatch: query: - $entity[pi8] = 0 @@ -216,7 +221,7 @@ queries: results: - [na, a, na, a] - [na, a, nc, c] - unsatisfiableIndexes: [2, 3] + unsatisfiableIndexes: [1, 2, 3, 4, 5, 6] entity bound via variable with ne filter: query: - $n1[value] = $e1 @@ -229,7 +234,7 @@ queries: result-vars: [$n1, $e1, $n2, $e2] results: - [na, a, nc, c] - unsatisfiableIndexes: [2, 3] + unsatisfiableIndexes: [1, 2, 3, 4, 5, 6] any value type mismatch: query: - $value[i8] IN [1, 2, 1] @@ -241,7 +246,7 @@ queries: entities: [$e] result-vars: [$e, $i8] results: [] - unsatisfiableIndexes: [2, 3] + unsatisfiableIndexes: [1, 2, 3, 4, 5, 6] pointer scalar values any: query: - $e[i8] IN [1, 2] @@ -251,7 +256,7 @@ queries: - [a] - [b] - [c] - unsatisfiableIndexes: [2, 3] + unsatisfiableIndexes: [2, 3, 4, 5, 6] pointer scalar values: query: - $e[i8] = 1 @@ -259,7 +264,7 @@ queries: result-vars: [$e] results: - [a] - unsatisfiableIndexes: [2, 3] + unsatisfiableIndexes: [2, 3, 4, 5, 6] nil pointer scalar values any: query: - $e[i8] IN [1, 1, null] @@ -274,7 +279,7 @@ queries: entities: [$e] result-vars: [$e] results: [] - unsatisfiableIndexes: [2, 3] + unsatisfiableIndexes: [2, 3, 4, 5, 6] any clause no match on variable eq: query: - $e[i8] = $i8 @@ -282,5 +287,5 @@ queries: entities: [$e] result-vars: [$e, $i8] results: [] - unsatisfiableIndexes: [2, 3] + unsatisfiableIndexes: [1, 2, 3, 4, 5, 6] comparisons: [] diff --git a/pkg/sql/schemachanger/scplan/internal/rules/dep_drop.go b/pkg/sql/schemachanger/scplan/internal/rules/dep_drop.go index a74e00d06033..dedea36f9c87 100644 --- a/pkg/sql/schemachanger/scplan/internal/rules/dep_drop.go +++ b/pkg/sql/schemachanger/scplan/internal/rules/dep_drop.go @@ -11,6 +11,7 @@ package rules import ( + "github.com/cockroachdb/cockroach/pkg/sql/schemachanger/rel" "github.com/cockroachdb/cockroach/pkg/sql/schemachanger/scpb" "github.com/cockroachdb/cockroach/pkg/sql/schemachanger/scplan/internal/scgraph" "github.com/cockroachdb/cockroach/pkg/sql/schemachanger/screl" @@ -22,53 +23,69 @@ import ( // which were placed in these elements' state transition definitions in opgen. func init() { - depRule( + registerDepRule( "view drops before the types, views and tables it depends on", scgraph.Precedence, - scpb.ToAbsent, - element(scpb.Status_DROPPED, - (*scpb.View)(nil), - ), - element(scpb.Status_DROPPED, - (*scpb.AliasType)(nil), - (*scpb.EnumType)(nil), - (*scpb.View)(nil), - (*scpb.Table)(nil), - ), - ).withFilter("view-depends-on", func(view *scpb.View, dep scpb.Element) bool { - depID := screl.GetDescID(dep) - return idInIDs(view.UsesRelationIDs, depID) || idInIDs(view.UsesTypeIDs, depID) - }).register() + "view", "dependents", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.View)(nil)), + to.Type( + (*scpb.AliasType)(nil), + (*scpb.EnumType)(nil), + (*scpb.View)(nil), + (*scpb.Table)(nil), + ), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatusEq(fromNode, toNode, scpb.Status_DROPPED), + rel.Filter("ViewDependsOn", from, to)(func( + view *scpb.View, dep scpb.Element, + ) bool { + depID := screl.GetDescID(dep) + return idInIDs(view.UsesRelationIDs, depID) || idInIDs(view.UsesTypeIDs, depID) + }), + } + }, + ) - depRule( + registerDepRule( "alias type drops before the types it depends on", scgraph.Precedence, - scpb.ToAbsent, - element(scpb.Status_DROPPED, - (*scpb.AliasType)(nil), - ), - element(scpb.Status_DROPPED, - (*scpb.AliasType)(nil), - (*scpb.EnumType)(nil), - ), - ).withFilter("alias-type-depends-on", func(alias *scpb.AliasType, dep scpb.Element) bool { - depID := screl.GetDescID(dep) - return alias.TypeID != depID && idInIDs(alias.ClosedTypeIDs, depID) - }).register() + "alias", "alias-dep", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.AliasType)(nil)), + to.Type((*scpb.AliasType)(nil), (*scpb.EnumType)(nil)), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatusEq(fromNode, toNode, scpb.Status_DROPPED), + rel.Filter("aliasTypeDependsOn", from, to)(func( + alias *scpb.AliasType, dep scpb.Element, + ) bool { + depID := screl.GetDescID(dep) + return alias.TypeID != depID && idInIDs(alias.ClosedTypeIDs, depID) + }), + } + }, + ) - depRule( + registerDepRule( "array type drops right before its element enum type", scgraph.SameStagePrecedence, - scpb.ToAbsent, - element(scpb.Status_DROPPED, - (*scpb.AliasType)(nil), - ), - element(scpb.Status_DROPPED, - (*scpb.EnumType)(nil), - ), - ).withFilter("join-array-type-with-element-type", func(arrayType *scpb.AliasType, enumType *scpb.EnumType) bool { - return arrayType.TypeID == enumType.ArrayTypeID - }).register() + "alias", "enum", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.AliasType)(nil)), + to.Type((*scpb.EnumType)(nil)), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatusEq(fromNode, toNode, scpb.Status_DROPPED), + rel.Filter("joinArrayTypeWithEnumType", from, to)(func( + arrayType *scpb.AliasType, enumType *scpb.EnumType, + ) bool { + return arrayType.TypeID == enumType.ArrayTypeID + }), + } + }, + ) } // These rules ensure that non-descriptor elements reach the ABSENT state before @@ -78,164 +95,238 @@ func init() { // This rule implicitly defines a precedence relationship which ensures that // a schema reaches DROPPED before its parent database does. - depRule( + registerDepRule( "schema dropped before parent database", scgraph.Precedence, - scpb.ToAbsent, - element(scpb.Status_ABSENT, - (*scpb.SchemaParent)(nil), - ), - element(scpb.Status_DROPPED, - (*scpb.Database)(nil), - ), - ).withJoinFromReferencedDescIDWithToDescID().register() + "schema-parent", "database", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.SchemaParent)(nil)), + to.Type((*scpb.Database)(nil)), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatus(fromNode, scpb.Status_ABSENT), + currentStatus(toNode, scpb.Status_DROPPED), + joinOn(from, screl.ReferencedDescID, to, screl.DescID, "desc-id"), + } + }, + ) // This rule implicitly defines a precedence relationship which ensures that // an object reaches DROPPED before its parent schema does. - depRule( + registerDepRule( "object dropped before parent schema", scgraph.Precedence, - scpb.ToAbsent, - element(scpb.Status_ABSENT, - (*scpb.ObjectParent)(nil), - ), - element(scpb.Status_DROPPED, - (*scpb.Schema)(nil), - ), - ).withJoinFromReferencedDescIDWithToDescID().register() + "object-parent", "schema", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.ObjectParent)(nil)), + to.Type((*scpb.Schema)(nil)), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatus(fromNode, scpb.Status_ABSENT), + currentStatus(toNode, scpb.Status_DROPPED), + joinOn(from, screl.ReferencedDescID, to, screl.DescID, "desc-id"), + } + }, + ) - depRule( + registerDepRule( "secondary region locality removed before dropping multi-region enum type", scgraph.Precedence, - scpb.ToAbsent, - element(scpb.Status_ABSENT, - (*scpb.TableLocalitySecondaryRegion)(nil), - ), - element(scpb.Status_DROPPED, - (*scpb.EnumType)(nil), - ), - ).withJoinFromReferencedDescIDWithToDescID().register() + "secondary-region", "enum-type", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.TableLocalitySecondaryRegion)(nil)), + to.Type((*scpb.EnumType)(nil)), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatus(fromNode, scpb.Status_ABSENT), + currentStatus(toNode, scpb.Status_DROPPED), + joinOn(from, screl.ReferencedDescID, to, screl.DescID, "desc-id"), + } + }, + ) - depRule( + registerDepRule( "check constraint removed before dropping dependent types and sequences", scgraph.Precedence, - scpb.ToAbsent, - element(scpb.Status_ABSENT, - (*scpb.CheckConstraint)(nil), - ), - element(scpb.Status_DROPPED, - (*scpb.AliasType)(nil), - (*scpb.EnumType)(nil), - (*scpb.Sequence)(nil), - ), - ).withFilter("check-constraint-depends-on", func(check *scpb.CheckConstraint, dep scpb.Element) bool { - depID := screl.GetDescID(dep) - return idInIDs(check.UsesTypeIDs, depID) || idInIDs(check.UsesSequenceIDs, depID) - }).register() + "check-constraint", "dependent", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.CheckConstraint)(nil)), + to.Type( + (*scpb.AliasType)(nil), + (*scpb.EnumType)(nil), + (*scpb.Sequence)(nil), + ), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatus(fromNode, scpb.Status_ABSENT), + currentStatus(toNode, scpb.Status_DROPPED), + rel.Filter("checkConstraintDependsOn", from, to)(func( + check *scpb.CheckConstraint, dep scpb.Element, + ) bool { + depID := screl.GetDescID(dep) + return idInIDs(check.UsesTypeIDs, depID) || idInIDs(check.UsesSequenceIDs, depID) + }), + } + }, + ) - depRule( + registerDepRule( "FK removed before dropping dependent table", scgraph.Precedence, - scpb.ToAbsent, - element(scpb.Status_ABSENT, - (*scpb.ForeignKeyConstraint)(nil), - ), - element(scpb.Status_DROPPED, - (*scpb.Table)(nil), - ), - ).withJoinFromReferencedDescIDWithToDescID().register() + "foreign-key", "table", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.ForeignKeyConstraint)(nil)), + to.Type((*scpb.Table)(nil)), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatus(fromNode, scpb.Status_ABSENT), + currentStatus(toNode, scpb.Status_DROPPED), + joinOn(from, screl.ReferencedDescID, to, screl.DescID, "desc-id"), + } + }, + ) - depRule( + registerDepRule( "index partial predicate removed before dropping dependent types", scgraph.Precedence, - scpb.ToAbsent, - element(scpb.Status_ABSENT, - (*scpb.SecondaryIndexPartial)(nil), - ), - element(scpb.Status_DROPPED, - (*scpb.AliasType)(nil), - (*scpb.EnumType)(nil), - ), - ).withFilter("index-partial-depends-on", func(ip *scpb.SecondaryIndexPartial, dep scpb.Element) bool { - return idInIDs(ip.UsesTypeIDs, screl.GetDescID(dep)) - }).register() + "index-partial", "dependent-type", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.SecondaryIndexPartial)(nil)), + to.Type((*scpb.AliasType)(nil), (*scpb.EnumType)(nil)), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatus(fromNode, scpb.Status_ABSENT), + currentStatus(toNode, scpb.Status_DROPPED), + rel.Filter("indexPartialDependsOn", from, to)(func( + ip *scpb.SecondaryIndexPartial, dep scpb.Element, + ) bool { + return idInIDs(ip.UsesTypeIDs, screl.GetDescID(dep)) + }), + } + }, + ) - depRule( + registerDepRule( "column type removed before dropping dependent types", scgraph.Precedence, - scpb.ToAbsent, - element(scpb.Status_ABSENT, - (*scpb.ColumnType)(nil), - ), - element(scpb.Status_DROPPED, - (*scpb.AliasType)(nil), - (*scpb.EnumType)(nil), - ), - ).withFilter("column-type-depends-on", func(cd *scpb.ColumnType, dep scpb.Element) bool { - depID := screl.GetDescID(dep) - if ce := cd.ComputeExpr; ce != nil && idInIDs(ce.UsesTypeIDs, depID) { - return true - } - return idInIDs(cd.ClosedTypeIDs, depID) - }).register() + "column-type", "dependent-type", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.ColumnType)(nil)), + to.Type((*scpb.AliasType)(nil), (*scpb.EnumType)(nil)), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatus(fromNode, scpb.Status_ABSENT), + currentStatus(toNode, scpb.Status_DROPPED), + rel.Filter("columnTypeDependsOn", from, to)(func( + cd *scpb.ColumnType, dep scpb.Element, + ) bool { + depID := screl.GetDescID(dep) + if ce := cd.ComputeExpr; ce != nil && idInIDs(ce.UsesTypeIDs, depID) { + return true + } + return idInIDs(cd.ClosedTypeIDs, depID) + }), + } + }, + ) - depRule( + registerDepRule( "column DEFAULT removed before dropping dependent types and sequences", scgraph.Precedence, - scpb.ToAbsent, - element(scpb.Status_ABSENT, - (*scpb.ColumnDefaultExpression)(nil), - ), - element(scpb.Status_DROPPED, - (*scpb.AliasType)(nil), - (*scpb.EnumType)(nil), - (*scpb.Sequence)(nil), - ), - ).withFilter("column-default-depends-on", func(cd *scpb.ColumnDefaultExpression, dep scpb.Element) bool { - depID := screl.GetDescID(dep) - return idInIDs(cd.UsesTypeIDs, depID) || idInIDs(cd.UsesSequenceIDs, depID) - }).register() + "default-expr", "dependent", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.ColumnDefaultExpression)(nil)), + to.Type( + (*scpb.AliasType)(nil), + (*scpb.EnumType)(nil), + (*scpb.Sequence)(nil), + ), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatus(fromNode, scpb.Status_ABSENT), + currentStatus(toNode, scpb.Status_DROPPED), + rel.Filter("columnDefaultDependsOn", from, to)(func( + cd *scpb.ColumnDefaultExpression, dep scpb.Element, + ) bool { + depID := screl.GetDescID(dep) + return idInIDs(cd.UsesTypeIDs, depID) || idInIDs(cd.UsesSequenceIDs, depID) + }), + } + }, + ) - depRule( + registerDepRule( "column ON UPDATE removed before dropping dependent types and sequences", scgraph.Precedence, - scpb.ToAbsent, - element(scpb.Status_ABSENT, - (*scpb.ColumnOnUpdateExpression)(nil), - ), - element(scpb.Status_DROPPED, - (*scpb.AliasType)(nil), - (*scpb.EnumType)(nil), - (*scpb.Sequence)(nil), - ), - ).withFilter("column-on-update-depends-on", func(cu *scpb.ColumnOnUpdateExpression, dep scpb.Element) bool { - depID := screl.GetDescID(dep) - return idInIDs(cu.UsesTypeIDs, depID) || idInIDs(cu.UsesSequenceIDs, depID) - }).register() + "on-update-expr", "dependent", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.ColumnOnUpdateExpression)(nil)), + to.Type( + (*scpb.AliasType)(nil), + (*scpb.EnumType)(nil), + (*scpb.Sequence)(nil), + ), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatus(fromNode, scpb.Status_ABSENT), + currentStatus(toNode, scpb.Status_DROPPED), + rel.Filter("columnOnUpdateDependsOn", from, to)(func( + cu *scpb.ColumnOnUpdateExpression, dep scpb.Element, + ) bool { + depID := screl.GetDescID(dep) + return idInIDs(cu.UsesTypeIDs, depID) || idInIDs(cu.UsesSequenceIDs, depID) + }), + } + }, + ) - depRule( + registerDepRule( "sequence ownership removed before dropping sequence", scgraph.Precedence, - scpb.ToAbsent, - element(scpb.Status_ABSENT, - (*scpb.SequenceOwner)(nil), - ), - element(scpb.Status_DROPPED, - (*scpb.Sequence)(nil), - ), - ).withJoinFromReferencedDescIDWithToDescID().register() + "sequence-owner", "sequence", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.SequenceOwner)(nil)), + to.Type((*scpb.Sequence)(nil)), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatus(fromNode, scpb.Status_ABSENT), + currentStatus(toNode, scpb.Status_DROPPED), + joinOn(from, screl.ReferencedDescID, to, screl.DescID, "desc-id"), + } - depRule( + }, + ) + + registerDepRule( + "database region config removed before dropping multi-region enum type", + scgraph.Precedence, + "region-config", "enum-type", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.DatabaseRegionConfig)(nil)), + to.Type((*scpb.EnumType)(nil)), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatus(fromNode, scpb.Status_ABSENT), + currentStatus(toNode, scpb.Status_DROPPED), + joinOn(from, screl.ReferencedDescID, to, screl.DescID, "desc-id"), + } + }, + ) + + registerDepRule( "database region config removed before dropping multi-region enum type", scgraph.Precedence, - scpb.ToAbsent, - element(scpb.Status_ABSENT, - (*scpb.DatabaseRegionConfig)(nil), - ), - element(scpb.Status_DROPPED, - (*scpb.EnumType)(nil), - ), - ).withJoinFromReferencedDescIDWithToDescID().register() + "region-config", "enum-type", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.DatabaseRegionConfig)(nil)), + to.Type((*scpb.EnumType)(nil)), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatus(fromNode, scpb.Status_ABSENT), + currentStatus(toNode, scpb.Status_DROPPED), + joinOn(from, screl.ReferencedDescID, to, screl.DescID, "desc-id"), + } + }) } @@ -249,75 +340,86 @@ func init() { // interfere with the event logging op which is tied to the descriptor element // removal. func init() { - depRule( + registerDepRule( "dependent element removal before descriptor drop", scgraph.Precedence, - scpb.ToAbsent, - element(scpb.Status_ABSENT, - // Table elements. - (*scpb.ColumnFamily)(nil), - (*scpb.UniqueWithoutIndexConstraint)(nil), - (*scpb.CheckConstraint)(nil), - (*scpb.ForeignKeyConstraint)(nil), - (*scpb.TableComment)(nil), - // Multi-region elements. - (*scpb.TableLocalityGlobal)(nil), - (*scpb.TableLocalityPrimaryRegion)(nil), - (*scpb.TableLocalitySecondaryRegion)(nil), - (*scpb.TableLocalityRegionalByRow)(nil), - // Column elements. - (*scpb.ColumnName)(nil), - (*scpb.ColumnDefaultExpression)(nil), - (*scpb.ColumnOnUpdateExpression)(nil), - (*scpb.ColumnComment)(nil), - (*scpb.SequenceOwner)(nil), - // Index elements. - (*scpb.IndexName)(nil), - (*scpb.IndexPartitioning)(nil), - (*scpb.IndexComment)(nil), - // Constraint elements. - (*scpb.ConstraintName)(nil), - (*scpb.ConstraintComment)(nil), - // Common elements. - (*scpb.Namespace)(nil), - (*scpb.Owner)(nil), - (*scpb.UserPrivileges)(nil), - // Database elements. - (*scpb.DatabaseRoleSetting)(nil), - (*scpb.DatabaseRegionConfig)(nil), - (*scpb.DatabaseComment)(nil), - // Schema elements. - (*scpb.SchemaParent)(nil), - (*scpb.SchemaComment)(nil), - // Object elements. - (*scpb.ObjectParent)(nil), - ), - element(scpb.Status_DROPPED, - (*scpb.Database)(nil), - (*scpb.Schema)(nil), - (*scpb.Table)(nil), - (*scpb.View)(nil), - (*scpb.Sequence)(nil), - (*scpb.AliasType)(nil), - (*scpb.EnumType)(nil), - ), - screl.DescID, - ).register() + "element", "relation", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type( + (*scpb.ColumnFamily)(nil), + (*scpb.UniqueWithoutIndexConstraint)(nil), + (*scpb.CheckConstraint)(nil), + (*scpb.ForeignKeyConstraint)(nil), + (*scpb.TableComment)(nil), + // Multi-region elements. + (*scpb.TableLocalityGlobal)(nil), + (*scpb.TableLocalityPrimaryRegion)(nil), + (*scpb.TableLocalitySecondaryRegion)(nil), + (*scpb.TableLocalityRegionalByRow)(nil), + // Column elements. + (*scpb.ColumnName)(nil), + (*scpb.ColumnDefaultExpression)(nil), + (*scpb.ColumnOnUpdateExpression)(nil), + (*scpb.ColumnComment)(nil), + (*scpb.SequenceOwner)(nil), + // Index elements. + (*scpb.IndexName)(nil), + (*scpb.IndexPartitioning)(nil), + (*scpb.IndexComment)(nil), + // Constraint elements. + (*scpb.ConstraintName)(nil), + (*scpb.ConstraintComment)(nil), + // Common elements. + (*scpb.Namespace)(nil), + (*scpb.Owner)(nil), + (*scpb.UserPrivileges)(nil), + // Database elements. + (*scpb.DatabaseRoleSetting)(nil), + (*scpb.DatabaseRegionConfig)(nil), + (*scpb.DatabaseComment)(nil), + // Schema elements. + (*scpb.SchemaParent)(nil), + (*scpb.SchemaComment)(nil), + // Object elements. + (*scpb.ObjectParent)(nil), + ), + to.Type( + (*scpb.Database)(nil), + (*scpb.Schema)(nil), + (*scpb.Table)(nil), + (*scpb.View)(nil), + (*scpb.Sequence)(nil), + (*scpb.AliasType)(nil), + (*scpb.EnumType)(nil), + ), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatus(fromNode, scpb.Status_ABSENT), + currentStatus(toNode, scpb.Status_DROPPED), + join(from, to, screl.DescID, "desc-id"), + } + }) - depRule( + registerDepRule( "dependent element removal right after descriptor removal", scgraph.SameStagePrecedence, - scpb.ToAbsent, - element(scpb.Status_ABSENT, - (*scpb.Table)(nil), - (*scpb.View)(nil), - ), - element(scpb.Status_ABSENT, - (*scpb.Column)(nil), - (*scpb.PrimaryIndex)(nil), - (*scpb.SecondaryIndex)(nil), - (*scpb.RowLevelTTL)(nil), - ), - screl.DescID, - ).register() + "relation", "element", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type( + (*scpb.Table)(nil), + (*scpb.View)(nil), + ), + to.Type( + (*scpb.Column)(nil), + (*scpb.PrimaryIndex)(nil), + (*scpb.SecondaryIndex)(nil), + (*scpb.RowLevelTTL)(nil), + ), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatusEq(fromNode, toNode, scpb.Status_ABSENT), + join(from, to, screl.DescID, "desc-id"), + } + }, + ) } diff --git a/pkg/sql/schemachanger/scplan/internal/rules/dep_index_and_column.go b/pkg/sql/schemachanger/scplan/internal/rules/dep_index_and_column.go index bb159e2d5e76..4aba1466e077 100644 --- a/pkg/sql/schemachanger/scplan/internal/rules/dep_index_and_column.go +++ b/pkg/sql/schemachanger/scplan/internal/rules/dep_index_and_column.go @@ -22,33 +22,26 @@ import ( // old primary index starts getting removed, effectively swapping one for the // other. func init() { - newIndex, newIndexTarget, newIndexNode := targetNodeVars("new-index") - oldIndex, oldIndexTarget, oldIndexNode := targetNodeVars("old-index") - var tableID rel.Var = "table-id" - registerDepRule( "primary index swap", scgraph.SameStagePrecedence, - oldIndexNode, newIndexNode, - screl.MustQuery( - newIndex.Type((*scpb.PrimaryIndex)(nil)), - oldIndex.Type((*scpb.PrimaryIndex)(nil)), - tableID.Entities(screl.DescID, newIndex, oldIndex), - - rel.Filter( - "new-primary-index-depends-on-old", newIndex, oldIndex, - )(func(add, drop *scpb.PrimaryIndex) bool { - return add.SourceIndexID == drop.IndexID - }), - - screl.JoinTargetNode(newIndex, newIndexTarget, newIndexNode), - newIndexTarget.AttrEq(screl.TargetStatus, scpb.Status_PUBLIC), - newIndexNode.AttrEq(screl.CurrentStatus, scpb.Status_PUBLIC), - - screl.JoinTargetNode(oldIndex, oldIndexTarget, oldIndexNode), - oldIndexTarget.AttrEq(screl.TargetStatus, scpb.Status_ABSENT), - oldIndexNode.AttrEq(screl.CurrentStatus, scpb.Status_VALIDATED), - ), + "old-index", "new-index", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.PrimaryIndex)(nil)), + to.Type((*scpb.PrimaryIndex)(nil)), + join(from, to, screl.DescID, "table-id"), + targetStatus(fromTarget, scpb.ToAbsent), + targetStatus(toTarget, scpb.ToPublic), + currentStatus(fromNode, scpb.Status_VALIDATED), + currentStatus(toNode, scpb.Status_PUBLIC), + rel.Filter( + "new-primary-index-depends-on-old", to, from, + )(func(add, drop *scpb.PrimaryIndex) bool { + return add.SourceIndexID == drop.IndexID + }), + } + }, ) } @@ -56,155 +49,167 @@ func init() { // partitioning, etc. appear once the index reaches a suitable state. // Vice-versa for index removal. func init() { - depRule( + registerDepRule( "index existence precedes index dependents", scgraph.Precedence, - scpb.ToPublic, - element(scpb.Status_BACKFILL_ONLY, - (*scpb.PrimaryIndex)(nil), - (*scpb.SecondaryIndex)(nil), - ), - element(scpb.Status_PUBLIC, - (*scpb.IndexName)(nil), - (*scpb.IndexPartitioning)(nil), - (*scpb.IndexComment)(nil), - ), - screl.DescID, - screl.IndexID, - ).register() + "index", "index-dependent", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type( + (*scpb.PrimaryIndex)(nil), + (*scpb.SecondaryIndex)(nil), + ), + to.Type( + (*scpb.IndexName)(nil), + (*scpb.IndexPartitioning)(nil), + (*scpb.IndexComment)(nil), + ), + joinOnIndexID(from, to), + targetStatusEq(fromTarget, toTarget, scpb.ToPublic), + currentStatus(fromNode, scpb.Status_BACKFILL_ONLY), + currentStatus(toNode, scpb.Status_PUBLIC), + } + }) - (&depRuleSpec{ - ruleName: "partitioning set right after temp index existence", - edgeKind: scgraph.SameStagePrecedence, - fromTargetStatus: scpb.Transient.Status(), - toTargetStatus: scpb.ToPublic.Status(), - from: element(scpb.Status_DELETE_ONLY, - (*scpb.TemporaryIndex)(nil), - ), - to: element(scpb.Status_PUBLIC, - (*scpb.IndexPartitioning)(nil), - ), - joinAttrs: []screl.Attr{ - screl.DescID, - screl.IndexID, - }, - }).register() + registerDepRule( + "partitioning set right after temp index existence", + scgraph.SameStagePrecedence, + "temp-index", "index-partitioning", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.TemporaryIndex)(nil)), + to.Type((*scpb.IndexPartitioning)(nil)), + joinOnIndexID(from, to), + targetStatus(fromTarget, scpb.Transient), + targetStatus(toTarget, scpb.ToPublic), + currentStatus(fromNode, scpb.Status_DELETE_ONLY), + currentStatus(toNode, scpb.Status_PUBLIC), + } + }) - depRule( + registerDepRule( "partial predicate set right after secondary index existence", scgraph.SameStagePrecedence, - scpb.ToPublic, - element(scpb.Status_BACKFILL_ONLY, - (*scpb.SecondaryIndex)(nil), - ), - element(scpb.Status_PUBLIC, - (*scpb.SecondaryIndexPartial)(nil), - ), - screl.DescID, - screl.IndexID, - ).register() + "index", "index-predicate", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.SecondaryIndex)(nil)), + to.Type((*scpb.SecondaryIndexPartial)(nil)), + joinOnIndexID(from, to), + targetStatusEq(fromTarget, toTarget, scpb.ToPublic), + currentStatus(fromNode, scpb.Status_BACKFILL_ONLY), + currentStatus(to, scpb.Status_PUBLIC), + join(from, to, screl.DescID, "desc-id"), + join(from, to, screl.IndexID, "index-id"), + } + }) - depRule( + registerDepRule( "dependents existence precedes writes to index", scgraph.Precedence, - scpb.ToPublic, - element(scpb.Status_PUBLIC, - (*scpb.IndexPartitioning)(nil), - (*scpb.IndexComment)(nil), - ), - element(scpb.Status_WRITE_ONLY, - (*scpb.PrimaryIndex)(nil), - (*scpb.SecondaryIndex)(nil), - ), - screl.DescID, - screl.IndexID, - ).register() - - depRule( + "child", "index", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type( + (*scpb.IndexPartitioning)(nil), + (*scpb.IndexComment)(nil), + ), + to.Type( + (*scpb.PrimaryIndex)(nil), + (*scpb.SecondaryIndex)(nil), + ), + joinOnIndexID(from, to), + targetStatusEq(fromTarget, toTarget, scpb.ToPublic), + currentStatus(fromNode, scpb.Status_PUBLIC), + currentStatus(toNode, scpb.Status_WRITE_ONLY), + } + }, + ) + registerDepRule( "index named right before index becomes public", scgraph.SameStagePrecedence, - scpb.ToPublic, - element(scpb.Status_PUBLIC, - (*scpb.IndexName)(nil), - ), - element(scpb.Status_PUBLIC, - (*scpb.PrimaryIndex)(nil), - (*scpb.SecondaryIndex)(nil), - ), - screl.DescID, - screl.IndexID, - ).register() + "index-name", "index", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.IndexName)(nil)), + to.Type( + (*scpb.PrimaryIndex)(nil), + (*scpb.SecondaryIndex)(nil), + ), + targetStatusEq(fromTarget, toTarget, scpb.ToPublic), + currentStatusEq(fromNode, toNode, scpb.Status_PUBLIC), + joinOnIndexID(from, to), + } + }, + ) - depRule( + registerDepRule( "dependents removed after index no longer public", scgraph.Precedence, - scpb.ToAbsent, - element(scpb.Status_VALIDATED, - (*scpb.PrimaryIndex)(nil), - (*scpb.SecondaryIndex)(nil), - ), - element(scpb.Status_ABSENT, - (*scpb.IndexName)(nil), - (*scpb.IndexPartitioning)(nil), - (*scpb.SecondaryIndexPartial)(nil), - (*scpb.IndexComment)(nil), - ), - screl.DescID, - screl.IndexID, - ).register() + "index", "child", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type( + (*scpb.PrimaryIndex)(nil), + (*scpb.SecondaryIndex)(nil), + ), + to.Type( + (*scpb.IndexName)(nil), + (*scpb.IndexPartitioning)(nil), + (*scpb.SecondaryIndexPartial)(nil), + (*scpb.IndexComment)(nil), + ), + joinOnIndexID(from, to), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatus(fromNode, scpb.Status_VALIDATED), + currentStatus(toNode, scpb.Status_ABSENT), + } + }, + ) - depRule( + registerDepRule( "dependents removed before index", scgraph.Precedence, - scpb.ToAbsent, - element(scpb.Status_ABSENT, - (*scpb.IndexName)(nil), - (*scpb.IndexPartitioning)(nil), - (*scpb.SecondaryIndexPartial)(nil), - (*scpb.IndexComment)(nil), - ), - element(scpb.Status_ABSENT, - (*scpb.PrimaryIndex)(nil), - (*scpb.SecondaryIndex)(nil), - ), - screl.DescID, - screl.IndexID, - ).register() + "dependent", "index", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type( + (*scpb.IndexName)(nil), + (*scpb.IndexPartitioning)(nil), + (*scpb.SecondaryIndexPartial)(nil), + (*scpb.IndexComment)(nil), + ), + to.Type( + (*scpb.PrimaryIndex)(nil), + (*scpb.SecondaryIndex)(nil), + ), + joinOnIndexID(from, to), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatusEq(fromNode, toNode, scpb.Status_ABSENT), + } + }, + ) } // These rules ensure that before an offline-backfilled index can begin // backfilling, the corresponding temporary index exists in WRITE_ONLY. func init() { - var ( - from, fromTarget, fromNode = targetNodeVars("from") - to, toTarget, toNode = targetNodeVars("to") - descID, tempIndexID rel.Var = "desc-id", "temp-index-id" - ) registerDepRule( "temp index is WRITE_ONLY before backfill", scgraph.Precedence, - fromNode, toNode, - screl.MustQuery( - from.Type( - (*scpb.TemporaryIndex)(nil), - ), - to.Type( - (*scpb.PrimaryIndex)(nil), - (*scpb.SecondaryIndex)(nil), - ), - descID.Entities(screl.DescID, from, to), - to.AttrEqVar(screl.TemporaryIndexID, tempIndexID), - from.AttrEqVar(screl.IndexID, tempIndexID), - - fromTarget.AttrEq(screl.TargetStatus, scpb.Transient.Status()), - toTarget.AttrEq(screl.TargetStatus, scpb.ToPublic.Status()), - - fromNode.AttrEq(screl.CurrentStatus, scpb.Status_WRITE_ONLY), - toNode.AttrEq(screl.CurrentStatus, scpb.Status_BACKFILLED), - - screl.JoinTargetNode(from, fromTarget, fromNode), - screl.JoinTargetNode(to, toTarget, toNode), - ), + "temp", "index", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.TemporaryIndex)(nil)), + to.Type((*scpb.PrimaryIndex)(nil), (*scpb.SecondaryIndex)(nil)), + join(from, to, screl.DescID, "desc-id"), + joinOn(from, screl.IndexID, to, screl.TemporaryIndexID, "temp-index-id"), + targetStatus(fromTarget, scpb.Transient), + targetStatus(toTarget, scpb.ToPublic), + currentStatus(fromNode, scpb.Status_WRITE_ONLY), + currentStatus(toNode, scpb.Status_BACKFILLED), + } + }, ) } @@ -212,129 +217,152 @@ func init() { // DEFAULT expression, etc. appear once the column reaches a suitable state. // Vice-versa for column removal. func init() { - depRule( + registerDepRule( "column name set right after column existence", scgraph.SameStagePrecedence, - scpb.ToPublic, - element(scpb.Status_DELETE_ONLY, - (*scpb.Column)(nil), - ), - element(scpb.Status_PUBLIC, - (*scpb.ColumnName)(nil), - ), - screl.DescID, - screl.ColumnID, - ).register() + "column", "column-name", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.Column)(nil)), + to.Type((*scpb.ColumnName)(nil)), + targetStatusEq(fromTarget, toTarget, scpb.ToPublic), + currentStatus(fromNode, scpb.Status_DELETE_ONLY), + currentStatus(toNode, scpb.Status_PUBLIC), + joinOnColumnID(from, to), + } + }, + ) - depRule( + registerDepRule( "column existence precedes column dependents", scgraph.Precedence, - scpb.ToPublic, - element(scpb.Status_DELETE_ONLY, - (*scpb.Column)(nil), - ), - element(scpb.Status_PUBLIC, - (*scpb.ColumnName)(nil), - (*scpb.ColumnDefaultExpression)(nil), - (*scpb.ColumnOnUpdateExpression)(nil), - (*scpb.ColumnComment)(nil), - ), - screl.DescID, - screl.ColumnID, - ).register() + "column", "dependent", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.Column)(nil)), + to.Type( + (*scpb.ColumnName)(nil), + (*scpb.ColumnDefaultExpression)(nil), + (*scpb.ColumnOnUpdateExpression)(nil), + (*scpb.ColumnComment)(nil), + ), + joinOnColumnID(from, to), + targetStatusEq(fromTarget, toTarget, scpb.ToPublic), + currentStatus(fromNode, scpb.Status_DELETE_ONLY), + currentStatus(toNode, scpb.Status_PUBLIC), + } + }, + ) - depRule( + registerDepRule( "DEFAULT or ON UPDATE existence precedes writes to column", scgraph.Precedence, - scpb.ToPublic, - element(scpb.Status_PUBLIC, - (*scpb.ColumnDefaultExpression)(nil), - (*scpb.ColumnOnUpdateExpression)(nil), - ), - element(scpb.Status_WRITE_ONLY, - (*scpb.Column)(nil), - ), - screl.DescID, - screl.ColumnID, - ).register() + "expr", "column", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type( + (*scpb.ColumnDefaultExpression)(nil), + (*scpb.ColumnOnUpdateExpression)(nil), + ), + to.Type((*scpb.Column)(nil)), + joinOnColumnID(from, to), + targetStatusEq(fromTarget, toTarget, scpb.ToPublic), + currentStatus(fromNode, scpb.Status_PUBLIC), + currentStatus(toNode, scpb.Status_WRITE_ONLY), + } + }, + ) - depRule( - "column named right before column becomes public", + registerDepRule( + "column named right before column type becomes public", scgraph.SameStagePrecedence, - scpb.ToPublic, - element(scpb.Status_PUBLIC, - (*scpb.ColumnName)(nil), - ), - element(scpb.Status_PUBLIC, - (*scpb.ColumnType)(nil), - ), - screl.DescID, - screl.ColumnID, - ).register() + "column-name", "column-type", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.ColumnName)(nil)), + to.Type((*scpb.ColumnType)(nil)), + joinOnColumnID(from, to), + targetStatusEq(fromTarget, toTarget, scpb.ToPublic), + currentStatusEq(fromNode, toNode, scpb.Status_PUBLIC), + } + }, + ) - depRule( - "column dependents exist before column becomes public", + // The comment is all that is remaining column dependents now that the name + // and the DEFAULT and ON UPDATE expressions have already been dealt with. + registerDepRule( + "column comment exists before column becomes public", scgraph.Precedence, - scpb.ToPublic, - element(scpb.Status_PUBLIC, - // These are all remaining column dependents now that the name and the - // DEFAULT and ON UPDATE expressions have already been dealt with. - (*scpb.ColumnComment)(nil), - ), - element(scpb.Status_PUBLIC, - (*scpb.Column)(nil), - ), - screl.DescID, - screl.ColumnID, - ).register() + "column-comment", "column", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.ColumnComment)(nil)), + to.Type((*scpb.Column)(nil)), + joinOnColumnID(from, to), + targetStatusEq(fromTarget, toTarget, scpb.ToPublic), + currentStatusEq(fromNode, toNode, scpb.Status_PUBLIC), + } + }, + ) - depRule( + registerDepRule( "column dependents removed after column no longer public", scgraph.Precedence, - scpb.ToAbsent, - element(scpb.Status_WRITE_ONLY, - (*scpb.Column)(nil), - ), - element(scpb.Status_ABSENT, - (*scpb.ColumnType)(nil), - (*scpb.ColumnName)(nil), - (*scpb.ColumnComment)(nil), - ), - screl.DescID, - screl.ColumnID, - ).register() + "column", "dependent", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.Column)(nil)), + to.Type( + (*scpb.ColumnType)(nil), + (*scpb.ColumnName)(nil), + (*scpb.ColumnComment)(nil), + ), + joinOnColumnID(from, to), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatus(fromNode, scpb.Status_WRITE_ONLY), + currentStatus(toNode, scpb.Status_ABSENT), + } + }, + ) - depRule( + registerDepRule( "column type dependents removed right before column type", scgraph.SameStagePrecedence, - scpb.ToAbsent, - element(scpb.Status_ABSENT, - (*scpb.SequenceOwner)(nil), - (*scpb.ColumnDefaultExpression)(nil), - (*scpb.ColumnOnUpdateExpression)(nil), - ), - element(scpb.Status_ABSENT, - (*scpb.ColumnType)(nil), - ), - screl.DescID, - screl.ColumnID, - ).register() + "dependent", "column-type", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type( + (*scpb.SequenceOwner)(nil), + (*scpb.ColumnDefaultExpression)(nil), + (*scpb.ColumnOnUpdateExpression)(nil), + ), + to.Type((*scpb.ColumnType)(nil)), + joinOnColumnID(from, to), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatusEq(fromNode, toNode, scpb.Status_ABSENT), + } + }, + ) - depRule( + registerDepRule( "dependents removed before column", scgraph.Precedence, - scpb.ToAbsent, - element(scpb.Status_ABSENT, - (*scpb.ColumnName)(nil), - (*scpb.ColumnType)(nil), - (*scpb.ColumnComment)(nil), - ), - element(scpb.Status_ABSENT, - (*scpb.Column)(nil), - ), - screl.DescID, - screl.ColumnID, - ).register() + "dependent", "column", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type( + (*scpb.ColumnName)(nil), + (*scpb.ColumnType)(nil), + (*scpb.ColumnComment)(nil), + ), + to.Type((*scpb.Column)(nil)), + joinOnColumnID(from, to), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatusEq(fromNode, toNode, scpb.Status_ABSENT), + } + }, + ) + } // Special cases for removal of column types and index partial predicates, @@ -358,37 +386,45 @@ func init() { // TODO(postamar): express this rule in a saner way func init() { - depRule( + registerDepRule( "column type removed right before column when not dropping relation", scgraph.SameStagePrecedence, - scpb.ToAbsent, - element(scpb.Status_ABSENT, - (*scpb.ColumnType)(nil), - ), - element(scpb.Status_ABSENT, - (*scpb.Column)(nil), - ), - screl.DescID, - screl.ColumnID, - ).withFilter("parent-relation-is-not-dropped", func(ct *scpb.ColumnType, _ *scpb.Column) bool { - return !ct.IsRelationBeingDropped - }).register() + "column-type", "column", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.ColumnType)(nil)), + to.Type((*scpb.Column)(nil)), + joinOnColumnID(from, to), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatusEq(fromNode, toNode, scpb.Status_ABSENT), + rel.Filter("columnTypeIsNotBeingDropped", from)(func( + ct *scpb.ColumnType, + ) bool { + return !ct.IsRelationBeingDropped + }), + } + }, + ) - depRule( + registerDepRule( "partial predicate removed right before secondary index when not dropping relation", scgraph.SameStagePrecedence, - scpb.ToAbsent, - element(scpb.Status_ABSENT, - (*scpb.SecondaryIndexPartial)(nil), - ), - element(scpb.Status_ABSENT, - (*scpb.SecondaryIndex)(nil), - ), - screl.DescID, - screl.IndexID, - ).withFilter("parent-relation-is-not-dropped", func(ip *scpb.SecondaryIndexPartial, _ *scpb.SecondaryIndex) bool { - return !ip.IsRelationBeingDropped - }).register() + "partial-predicate", "index", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.SecondaryIndexPartial)(nil)), + to.Type((*scpb.SecondaryIndex)(nil)), + joinOnIndexID(from, to), + targetStatusEq(fromTarget, toTarget, scpb.ToAbsent), + currentStatusEq(fromNode, toNode, scpb.Status_ABSENT), + rel.Filter("secondaryIndexPartialIsNotBeingDropped", from)(func( + ip *scpb.SecondaryIndexPartial, + ) bool { + return !ip.IsRelationBeingDropped + }), + } + }, + ) } // These rules ensure that columns and indexes containing these columns @@ -420,99 +456,79 @@ func init() { columnInList(from.ColumnID, idx.KeySuffixColumnIDs) } - column, columnTarget, columnNode := targetNodeVars("column") - index, indexTarget, indexNode := targetNodeVars("index") - var tableID, status, targetStatus rel.Var = "table-id", "status", "target-status" registerDepRule( "column depends on primary index", scgraph.Precedence, - indexNode, columnNode, - screl.MustQuery( - status.In(scpb.Status_WRITE_ONLY, scpb.Status_PUBLIC), - targetStatus.Eq(scpb.Status_PUBLIC), - - column.Type((*scpb.Column)(nil)), - index.Type((*scpb.PrimaryIndex)(nil)), - - tableID.Entities(screl.DescID, column, index), - - rel.Filter("column-featured-in-index", column, index)(columnInIndex), - - targetStatus.Entities(screl.TargetStatus, columnTarget, indexTarget), - status.Entities(screl.CurrentStatus, columnNode, indexNode), - - screl.JoinTargetNode(column, columnTarget, columnNode), - screl.JoinTargetNode(index, indexTarget, indexNode), - ), + "index", "column", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + var status rel.Var = "status" + return rel.Clauses{ + from.Type((*scpb.PrimaryIndex)(nil)), + to.Type((*scpb.Column)(nil)), + targetStatusEq(fromTarget, toTarget, scpb.ToPublic), + join(from, to, screl.DescID, "table-id"), + rel.Filter("columnFeaturedInIndex", to, from)(columnInIndex), + status.In(scpb.Status_WRITE_ONLY, scpb.Status_PUBLIC), + status.Entities(screl.CurrentStatus, fromNode, toNode), + } + }, ) - depRule( + registerDepRule( "column existence precedes index existence", scgraph.Precedence, - scpb.ToPublic, - element(scpb.Status_DELETE_ONLY, - (*scpb.Column)(nil), - ), - element(scpb.Status_BACKFILL_ONLY, - (*scpb.PrimaryIndex)(nil), - (*scpb.SecondaryIndex)(nil), - ), - screl.DescID, - ).withFilter("column-featured-in-index", columnInIndex).register() + "column", "index", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.Column)(nil)), + to.Type((*scpb.PrimaryIndex)(nil), (*scpb.SecondaryIndex)(nil)), + targetStatusEq(fromTarget, toTarget, scpb.ToPublic), + currentStatus(fromNode, scpb.Status_DELETE_ONLY), + currentStatus(toNode, scpb.Status_BACKFILL_ONLY), + join(from, to, screl.DescID, "table-id"), + rel.Filter("columnFeaturedInIndex", from, to)(columnInIndex), + } + }, + ) registerDepRule( "column existence precedes temporary index existence", scgraph.Precedence, - columnNode, indexNode, - screl.MustQuery( - index.Type((*scpb.TemporaryIndex)(nil)), - column.Type((*scpb.Column)(nil)), - - tableID.Entities(screl.DescID, column, index), - - indexTarget.AttrEq(screl.TargetStatus, scpb.Status_TRANSIENT_ABSENT), - columnTarget.AttrEq(screl.TargetStatus, scpb.Status_PUBLIC), - columnNode.AttrEq(screl.CurrentStatus, scpb.Status_DELETE_ONLY), - indexNode.AttrEq(screl.CurrentStatus, scpb.Status_DELETE_ONLY), - - rel.Filter("column-featured-in-index", column, index)(columnInIndex), - - screl.JoinTargetNode(column, columnTarget, columnNode), - screl.JoinTargetNode(index, indexTarget, indexNode), - ), + "column", "temp-index", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + return rel.Clauses{ + from.Type((*scpb.Column)(nil)), + to.Type((*scpb.TemporaryIndex)(nil)), + join(from, to, screl.DescID, "table-id"), + targetStatus(fromTarget, scpb.ToPublic), + targetStatus(toTarget, scpb.Transient), + currentStatusEq(fromNode, toNode, scpb.Status_DELETE_ONLY), + rel.Filter("columnFeaturedInIndex", from, to)(columnInIndex), + } + }, ) - } // This rule ensures that columns depend on each other in increasing order. func init() { - laterCol, laterColTarget, laterColNode := targetNodeVars("laterColumn") - earlierCol, earlierColTarget, earlierColNode := targetNodeVars("earlierColumn") - var tableID, status, targetStatus rel.Var = "table-id", "status", "target-status" - isLaterColumn := func(from *scpb.Column, to *scpb.Column) bool { - return from.ColumnID < to.ColumnID - } - registerDepRule( "ensure columns are in increasing order", scgraph.SameStagePrecedence, - laterColNode, earlierColNode, - screl.MustQuery( - status.In(scpb.Status_WRITE_ONLY, scpb.Status_PUBLIC), - targetStatus.Eq(scpb.Status_PUBLIC), - - laterCol.Type((*scpb.Column)(nil)), - earlierCol.Type((*scpb.Column)(nil)), - - tableID.Entities(screl.DescID, laterCol, earlierCol), - - rel.Filter("column-later-column-is-greater", laterCol, earlierCol)(isLaterColumn), - - targetStatus.Entities(screl.TargetStatus, laterColTarget, earlierColTarget), - status.Entities(screl.CurrentStatus, laterColNode, earlierColNode), - - screl.JoinTargetNode(laterCol, laterColTarget, laterColNode), - screl.JoinTargetNode(earlierCol, earlierColTarget, earlierColNode), - ), - ) + "later-column", "earlier-column", + func(from, fromTarget, fromNode, to, toTarget, toNode rel.Var) rel.Clauses { + status := rel.Var("status") + return rel.Clauses{ + from.Type((*scpb.Column)(nil)), + to.Type((*scpb.Column)(nil)), + join(from, to, screl.DescID, "table-id"), + targetStatusEq(fromTarget, toTarget, scpb.ToPublic), + status.In(scpb.Status_WRITE_ONLY, scpb.Status_PUBLIC), + status.Entities(screl.CurrentStatus, fromNode, toNode), + rel.Filter("columnHasSmallerID", from, to)(func( + from *scpb.Column, to *scpb.Column, + ) bool { + return from.ColumnID < to.ColumnID + }), + } + }) } diff --git a/pkg/sql/schemachanger/scplan/internal/rules/helpers.go b/pkg/sql/schemachanger/scplan/internal/rules/helpers.go index d4d5ebf4e2a8..2259ca3993c1 100644 --- a/pkg/sql/schemachanger/scplan/internal/rules/helpers.go +++ b/pkg/sql/schemachanger/scplan/internal/rules/helpers.go @@ -14,9 +14,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb" "github.com/cockroachdb/cockroach/pkg/sql/schemachanger/rel" "github.com/cockroachdb/cockroach/pkg/sql/schemachanger/scpb" - "github.com/cockroachdb/cockroach/pkg/sql/schemachanger/scplan/internal/scgraph" "github.com/cockroachdb/cockroach/pkg/sql/schemachanger/screl" - "github.com/cockroachdb/errors" ) func idInIDs(objects []descpb.ID, id descpb.ID) bool { @@ -32,93 +30,43 @@ func targetNodeVars(el rel.Var) (element, target, node rel.Var) { return el, el + "-target", el + "-node" } -type depRuleSpec struct { - ruleName scgraph.RuleName - edgeKind scgraph.DepEdgeKind - fromTargetStatus scpb.Status - toTargetStatus scpb.Status - from, to elementSpec - joinAttrs []screl.Attr - joinReferencingDescID bool - filterLabel string - filter interface{} +func currentStatus(node rel.Var, status scpb.Status) rel.Clause { + return node.AttrEq(screl.CurrentStatus, status) } -func depRule( - ruleName scgraph.RuleName, - edgeKind scgraph.DepEdgeKind, - targetStatus scpb.TargetStatus, - from, to elementSpec, - joinAttrs ...screl.Attr, -) depRuleSpec { - return depRuleSpec{ - ruleName: ruleName, - edgeKind: edgeKind, - fromTargetStatus: targetStatus.Status(), - toTargetStatus: targetStatus.Status(), - from: from, - to: to, - joinAttrs: joinAttrs, - } +func targetStatus(target rel.Var, status scpb.TargetStatus) rel.Clause { + return target.AttrEq(screl.TargetStatus, status.Status()) } -type elementSpec struct { - status scpb.Status - types []interface{} +func targetStatusEq(aTarget, bTarget rel.Var, status scpb.TargetStatus) rel.Clause { + return rel.And(targetStatus(aTarget, status), targetStatus(bTarget, status)) } -func element(status scpb.Status, types ...interface{}) elementSpec { - return elementSpec{ - status: status, - types: types, - } +func currentStatusEq(aNode, bNode rel.Var, status scpb.Status) rel.Clause { + return rel.And(currentStatus(aNode, status), currentStatus(bNode, status)) } -func (d depRuleSpec) withFilter(label string, predicate interface{}) depRuleSpec { - d.filterLabel = label - d.filter = predicate - return d +func join(a, b rel.Var, attr rel.Attr, eqVarName rel.Var) rel.Clause { + return joinOn(a, attr, b, attr, eqVarName) } -func (d depRuleSpec) withJoinFromReferencedDescIDWithToDescID() depRuleSpec { - d.joinReferencingDescID = true - return d +func joinOn(a rel.Var, aAttr rel.Attr, b rel.Var, bAttr rel.Attr, eqVarName rel.Var) rel.Clause { + return rel.And( + a.AttrEqVar(aAttr, eqVarName), + b.AttrEqVar(bAttr, eqVarName), + ) } -func (d depRuleSpec) register() { - var ( - from, fromTarget, fromNode = targetNodeVars("from") - to, toTarget, toNode = targetNodeVars("to") +func joinOnIndexID(a, b rel.Var) rel.Clause { + return rel.And( + join(a, b, screl.DescID, "desc-id"), + join(a, b, screl.IndexID, "index-id"), ) - if from == to { - panic(errors.AssertionFailedf("elements cannot share same label %q", from)) - } - c := rel.Clauses{ - from.Type(d.from.types[0], d.from.types[1:]...), - fromTarget.AttrEq(screl.TargetStatus, d.fromTargetStatus), - to.Type(d.to.types[0], d.to.types[1:]...), - toTarget.AttrEq(screl.TargetStatus, d.toTargetStatus), - - fromNode.AttrEq(screl.CurrentStatus, d.from.status), - toNode.AttrEq(screl.CurrentStatus, d.to.status), - - screl.JoinTargetNode(from, fromTarget, fromNode), - screl.JoinTargetNode(to, toTarget, toNode), - } - for _, attr := range d.joinAttrs { - v := rel.Var(attr.String() + "-join-var") - c = append(c, from.AttrEqVar(attr, v), to.AttrEqVar(attr, v)) - } - if d.joinReferencingDescID { - v := rel.Var("joined-from-ref-desc-id-with-to-desc-id-var") - c = append(c, from.AttrEqVar(screl.ReferencedDescID, v), to.AttrEqVar(screl.DescID, v)) - } - - c = append(c, from.AttrEqVar(screl.DescID, "var-to-tell-rel-from-is-an-element")) - c = append(c, to.AttrEqVar(screl.DescID, "var-to-tell-rel-to-is-an-element")) +} - if d.filter != nil { - c = append(c, rel.Filter(d.filterLabel, from, to)(d.filter)) - } - registerDepRule(d.ruleName, d.edgeKind, fromNode, toNode, screl.MustQuery(c...)) +func joinOnColumnID(a, b rel.Var) rel.Clause { + return rel.And( + join(a, b, screl.DescID, "desc-id"), + join(a, b, screl.ColumnID, "column-id"), + ) } diff --git a/pkg/sql/schemachanger/scplan/internal/rules/registry.go b/pkg/sql/schemachanger/scplan/internal/rules/registry.go index d9618cd290cf..66e298dfc711 100644 --- a/pkg/sql/schemachanger/scplan/internal/rules/registry.go +++ b/pkg/sql/schemachanger/scplan/internal/rules/registry.go @@ -104,16 +104,34 @@ type registeredOpRule struct { } // registerDepRule registers a rule from which a set of dependency edges will -// be derived in a graph. +// be derived in a graph. The edge will be formed from the node containing +// the fromEl entity to the node containing the toEl entity. func registerDepRule( - rn scgraph.RuleName, edgeKind scgraph.DepEdgeKind, from, to rel.Var, query *rel.Query, + ruleName scgraph.RuleName, + kind scgraph.DepEdgeKind, + fromEl, toEl string, + def func( + from, fromTarget, fromNode, + to, toTarget, toNode rel.Var, + ) rel.Clauses, ) { + var ( + from, fromTarget, fromNode = targetNodeVars(rel.Var(fromEl)) + to, toTarget, toNode = targetNodeVars(rel.Var(toEl)) + ) + c := def(from, fromTarget, fromNode, to, toTarget, toNode) + c = append(c, + screl.JoinTargetNode(from, fromTarget, fromNode), + screl.JoinTargetNode(to, toTarget, toNode), + from.AttrEqVar(screl.DescID, "var-to-tell-rel-from-is-an-element"), + to.AttrEqVar(screl.DescID, "var-to-tell-rel-to-is-an-element"), + ) registry.depRules = append(registry.depRules, registeredDepRule{ - name: rn, - kind: edgeKind, - from: from, - to: to, - q: query, + name: ruleName, + kind: kind, + from: fromNode, + to: toNode, + q: screl.MustQuery(c...), }) } diff --git a/pkg/sql/schemachanger/scplan/internal/rules/testdata/deprules b/pkg/sql/schemachanger/scplan/internal/rules/testdata/deprules index fa65e1113987..64b2821f1134 100644 --- a/pkg/sql/schemachanger/scplan/internal/rules/testdata/deprules +++ b/pkg/sql/schemachanger/scplan/internal/rules/testdata/deprules @@ -1,853 +1,907 @@ deprules ---- - name: view drops before the types, views and tables it depends on - from: from-node + from: view-node kind: Precedence - to: to-node - query: - - $from[Type] = '*scpb.View' - - $from-target[TargetStatus] = ABSENT - - $to[Type] IN ['*scpb.AliasType', '*scpb.EnumType', '*scpb.View', '*scpb.Table'] - - $to-target[TargetStatus] = ABSENT - - $from-node[CurrentStatus] = DROPPED - - $to-node[CurrentStatus] = DROPPED - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element - - view-depends-on(*scpb.View, scpb.Element)($from, $to) + to: dependents-node + query: + - $view[Type] = '*scpb.View' + - $dependents[Type] IN ['*scpb.AliasType', '*scpb.EnumType', '*scpb.View', '*scpb.Table'] + - $view-target[TargetStatus] = ABSENT + - $dependents-target[TargetStatus] = ABSENT + - $view-node[CurrentStatus] = DROPPED + - $dependents-node[CurrentStatus] = DROPPED + - ViewDependsOn(*scpb.View, scpb.Element)($view, $dependents) + - $view-target[Type] = '*scpb.Target' + - $view-target[Element] = $view + - $view-node[Type] = '*screl.Node' + - $view-node[Target] = $view-target + - $dependents-target[Type] = '*scpb.Target' + - $dependents-target[Element] = $dependents + - $dependents-node[Type] = '*screl.Node' + - $dependents-node[Target] = $dependents-target + - $view[DescID] = $var-to-tell-rel-from-is-an-element + - $dependents[DescID] = $var-to-tell-rel-to-is-an-element - name: alias type drops before the types it depends on - from: from-node + from: alias-node kind: Precedence - to: to-node - query: - - $from[Type] = '*scpb.AliasType' - - $from-target[TargetStatus] = ABSENT - - $to[Type] IN ['*scpb.AliasType', '*scpb.EnumType'] - - $to-target[TargetStatus] = ABSENT - - $from-node[CurrentStatus] = DROPPED - - $to-node[CurrentStatus] = DROPPED - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element - - alias-type-depends-on(*scpb.AliasType, scpb.Element)($from, $to) + to: alias-dep-node + query: + - $alias[Type] = '*scpb.AliasType' + - $alias-dep[Type] IN ['*scpb.AliasType', '*scpb.EnumType'] + - $alias-target[TargetStatus] = ABSENT + - $alias-dep-target[TargetStatus] = ABSENT + - $alias-node[CurrentStatus] = DROPPED + - $alias-dep-node[CurrentStatus] = DROPPED + - aliasTypeDependsOn(*scpb.AliasType, scpb.Element)($alias, $alias-dep) + - $alias-target[Type] = '*scpb.Target' + - $alias-target[Element] = $alias + - $alias-node[Type] = '*screl.Node' + - $alias-node[Target] = $alias-target + - $alias-dep-target[Type] = '*scpb.Target' + - $alias-dep-target[Element] = $alias-dep + - $alias-dep-node[Type] = '*screl.Node' + - $alias-dep-node[Target] = $alias-dep-target + - $alias[DescID] = $var-to-tell-rel-from-is-an-element + - $alias-dep[DescID] = $var-to-tell-rel-to-is-an-element - name: array type drops right before its element enum type - from: from-node + from: alias-node kind: SameStagePrecedence - to: to-node - query: - - $from[Type] = '*scpb.AliasType' - - $from-target[TargetStatus] = ABSENT - - $to[Type] = '*scpb.EnumType' - - $to-target[TargetStatus] = ABSENT - - $from-node[CurrentStatus] = DROPPED - - $to-node[CurrentStatus] = DROPPED - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element - - join-array-type-with-element-type(*scpb.AliasType, *scpb.EnumType)($from, $to) + to: enum-node + query: + - $alias[Type] = '*scpb.AliasType' + - $enum[Type] = '*scpb.EnumType' + - $alias-target[TargetStatus] = ABSENT + - $enum-target[TargetStatus] = ABSENT + - $alias-node[CurrentStatus] = DROPPED + - $enum-node[CurrentStatus] = DROPPED + - joinArrayTypeWithEnumType(*scpb.AliasType, *scpb.EnumType)($alias, $enum) + - $alias-target[Type] = '*scpb.Target' + - $alias-target[Element] = $alias + - $alias-node[Type] = '*screl.Node' + - $alias-node[Target] = $alias-target + - $enum-target[Type] = '*scpb.Target' + - $enum-target[Element] = $enum + - $enum-node[Type] = '*screl.Node' + - $enum-node[Target] = $enum-target + - $alias[DescID] = $var-to-tell-rel-from-is-an-element + - $enum[DescID] = $var-to-tell-rel-to-is-an-element - name: schema dropped before parent database - from: from-node + from: schema-parent-node kind: Precedence - to: to-node - query: - - $from[Type] = '*scpb.SchemaParent' - - $from-target[TargetStatus] = ABSENT - - $to[Type] = '*scpb.Database' - - $to-target[TargetStatus] = ABSENT - - $from-node[CurrentStatus] = ABSENT - - $to-node[CurrentStatus] = DROPPED - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[ReferencedDescID] = $joined-from-ref-desc-id-with-to-desc-id-var - - $to[DescID] = $joined-from-ref-desc-id-with-to-desc-id-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element + to: database-node + query: + - $schema-parent[Type] = '*scpb.SchemaParent' + - $database[Type] = '*scpb.Database' + - $schema-parent-target[TargetStatus] = ABSENT + - $database-target[TargetStatus] = ABSENT + - $schema-parent-node[CurrentStatus] = ABSENT + - $database-node[CurrentStatus] = DROPPED + - $schema-parent[ReferencedDescID] = $desc-id + - $database[DescID] = $desc-id + - $schema-parent-target[Type] = '*scpb.Target' + - $schema-parent-target[Element] = $schema-parent + - $schema-parent-node[Type] = '*screl.Node' + - $schema-parent-node[Target] = $schema-parent-target + - $database-target[Type] = '*scpb.Target' + - $database-target[Element] = $database + - $database-node[Type] = '*screl.Node' + - $database-node[Target] = $database-target + - $schema-parent[DescID] = $var-to-tell-rel-from-is-an-element + - $database[DescID] = $var-to-tell-rel-to-is-an-element - name: object dropped before parent schema - from: from-node + from: object-parent-node kind: Precedence - to: to-node - query: - - $from[Type] = '*scpb.ObjectParent' - - $from-target[TargetStatus] = ABSENT - - $to[Type] = '*scpb.Schema' - - $to-target[TargetStatus] = ABSENT - - $from-node[CurrentStatus] = ABSENT - - $to-node[CurrentStatus] = DROPPED - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[ReferencedDescID] = $joined-from-ref-desc-id-with-to-desc-id-var - - $to[DescID] = $joined-from-ref-desc-id-with-to-desc-id-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element + to: schema-node + query: + - $object-parent[Type] = '*scpb.ObjectParent' + - $schema[Type] = '*scpb.Schema' + - $object-parent-target[TargetStatus] = ABSENT + - $schema-target[TargetStatus] = ABSENT + - $object-parent-node[CurrentStatus] = ABSENT + - $schema-node[CurrentStatus] = DROPPED + - $object-parent[ReferencedDescID] = $desc-id + - $schema[DescID] = $desc-id + - $object-parent-target[Type] = '*scpb.Target' + - $object-parent-target[Element] = $object-parent + - $object-parent-node[Type] = '*screl.Node' + - $object-parent-node[Target] = $object-parent-target + - $schema-target[Type] = '*scpb.Target' + - $schema-target[Element] = $schema + - $schema-node[Type] = '*screl.Node' + - $schema-node[Target] = $schema-target + - $object-parent[DescID] = $var-to-tell-rel-from-is-an-element + - $schema[DescID] = $var-to-tell-rel-to-is-an-element - name: secondary region locality removed before dropping multi-region enum type - from: from-node + from: secondary-region-node kind: Precedence - to: to-node - query: - - $from[Type] = '*scpb.TableLocalitySecondaryRegion' - - $from-target[TargetStatus] = ABSENT - - $to[Type] = '*scpb.EnumType' - - $to-target[TargetStatus] = ABSENT - - $from-node[CurrentStatus] = ABSENT - - $to-node[CurrentStatus] = DROPPED - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[ReferencedDescID] = $joined-from-ref-desc-id-with-to-desc-id-var - - $to[DescID] = $joined-from-ref-desc-id-with-to-desc-id-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element + to: enum-type-node + query: + - $secondary-region[Type] = '*scpb.TableLocalitySecondaryRegion' + - $enum-type[Type] = '*scpb.EnumType' + - $secondary-region-target[TargetStatus] = ABSENT + - $enum-type-target[TargetStatus] = ABSENT + - $secondary-region-node[CurrentStatus] = ABSENT + - $enum-type-node[CurrentStatus] = DROPPED + - $secondary-region[ReferencedDescID] = $desc-id + - $enum-type[DescID] = $desc-id + - $secondary-region-target[Type] = '*scpb.Target' + - $secondary-region-target[Element] = $secondary-region + - $secondary-region-node[Type] = '*screl.Node' + - $secondary-region-node[Target] = $secondary-region-target + - $enum-type-target[Type] = '*scpb.Target' + - $enum-type-target[Element] = $enum-type + - $enum-type-node[Type] = '*screl.Node' + - $enum-type-node[Target] = $enum-type-target + - $secondary-region[DescID] = $var-to-tell-rel-from-is-an-element + - $enum-type[DescID] = $var-to-tell-rel-to-is-an-element - name: check constraint removed before dropping dependent types and sequences - from: from-node + from: check-constraint-node kind: Precedence - to: to-node - query: - - $from[Type] = '*scpb.CheckConstraint' - - $from-target[TargetStatus] = ABSENT - - $to[Type] IN ['*scpb.AliasType', '*scpb.EnumType', '*scpb.Sequence'] - - $to-target[TargetStatus] = ABSENT - - $from-node[CurrentStatus] = ABSENT - - $to-node[CurrentStatus] = DROPPED - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element - - check-constraint-depends-on(*scpb.CheckConstraint, scpb.Element)($from, $to) + to: dependent-node + query: + - $check-constraint[Type] = '*scpb.CheckConstraint' + - $dependent[Type] IN ['*scpb.AliasType', '*scpb.EnumType', '*scpb.Sequence'] + - $check-constraint-target[TargetStatus] = ABSENT + - $dependent-target[TargetStatus] = ABSENT + - $check-constraint-node[CurrentStatus] = ABSENT + - $dependent-node[CurrentStatus] = DROPPED + - checkConstraintDependsOn(*scpb.CheckConstraint, scpb.Element)($check-constraint, $dependent) + - $check-constraint-target[Type] = '*scpb.Target' + - $check-constraint-target[Element] = $check-constraint + - $check-constraint-node[Type] = '*screl.Node' + - $check-constraint-node[Target] = $check-constraint-target + - $dependent-target[Type] = '*scpb.Target' + - $dependent-target[Element] = $dependent + - $dependent-node[Type] = '*screl.Node' + - $dependent-node[Target] = $dependent-target + - $check-constraint[DescID] = $var-to-tell-rel-from-is-an-element + - $dependent[DescID] = $var-to-tell-rel-to-is-an-element - name: FK removed before dropping dependent table - from: from-node + from: foreign-key-node kind: Precedence - to: to-node - query: - - $from[Type] = '*scpb.ForeignKeyConstraint' - - $from-target[TargetStatus] = ABSENT - - $to[Type] = '*scpb.Table' - - $to-target[TargetStatus] = ABSENT - - $from-node[CurrentStatus] = ABSENT - - $to-node[CurrentStatus] = DROPPED - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[ReferencedDescID] = $joined-from-ref-desc-id-with-to-desc-id-var - - $to[DescID] = $joined-from-ref-desc-id-with-to-desc-id-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element + to: table-node + query: + - $foreign-key[Type] = '*scpb.ForeignKeyConstraint' + - $table[Type] = '*scpb.Table' + - $foreign-key-target[TargetStatus] = ABSENT + - $table-target[TargetStatus] = ABSENT + - $foreign-key-node[CurrentStatus] = ABSENT + - $table-node[CurrentStatus] = DROPPED + - $foreign-key[ReferencedDescID] = $desc-id + - $table[DescID] = $desc-id + - $foreign-key-target[Type] = '*scpb.Target' + - $foreign-key-target[Element] = $foreign-key + - $foreign-key-node[Type] = '*screl.Node' + - $foreign-key-node[Target] = $foreign-key-target + - $table-target[Type] = '*scpb.Target' + - $table-target[Element] = $table + - $table-node[Type] = '*screl.Node' + - $table-node[Target] = $table-target + - $foreign-key[DescID] = $var-to-tell-rel-from-is-an-element + - $table[DescID] = $var-to-tell-rel-to-is-an-element - name: index partial predicate removed before dropping dependent types - from: from-node + from: index-partial-node kind: Precedence - to: to-node - query: - - $from[Type] = '*scpb.SecondaryIndexPartial' - - $from-target[TargetStatus] = ABSENT - - $to[Type] IN ['*scpb.AliasType', '*scpb.EnumType'] - - $to-target[TargetStatus] = ABSENT - - $from-node[CurrentStatus] = ABSENT - - $to-node[CurrentStatus] = DROPPED - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element - - index-partial-depends-on(*scpb.SecondaryIndexPartial, scpb.Element)($from, $to) + to: dependent-type-node + query: + - $index-partial[Type] = '*scpb.SecondaryIndexPartial' + - $dependent-type[Type] IN ['*scpb.AliasType', '*scpb.EnumType'] + - $index-partial-target[TargetStatus] = ABSENT + - $dependent-type-target[TargetStatus] = ABSENT + - $index-partial-node[CurrentStatus] = ABSENT + - $dependent-type-node[CurrentStatus] = DROPPED + - indexPartialDependsOn(*scpb.SecondaryIndexPartial, scpb.Element)($index-partial, $dependent-type) + - $index-partial-target[Type] = '*scpb.Target' + - $index-partial-target[Element] = $index-partial + - $index-partial-node[Type] = '*screl.Node' + - $index-partial-node[Target] = $index-partial-target + - $dependent-type-target[Type] = '*scpb.Target' + - $dependent-type-target[Element] = $dependent-type + - $dependent-type-node[Type] = '*screl.Node' + - $dependent-type-node[Target] = $dependent-type-target + - $index-partial[DescID] = $var-to-tell-rel-from-is-an-element + - $dependent-type[DescID] = $var-to-tell-rel-to-is-an-element - name: column type removed before dropping dependent types - from: from-node + from: column-type-node kind: Precedence - to: to-node - query: - - $from[Type] = '*scpb.ColumnType' - - $from-target[TargetStatus] = ABSENT - - $to[Type] IN ['*scpb.AliasType', '*scpb.EnumType'] - - $to-target[TargetStatus] = ABSENT - - $from-node[CurrentStatus] = ABSENT - - $to-node[CurrentStatus] = DROPPED - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element - - column-type-depends-on(*scpb.ColumnType, scpb.Element)($from, $to) + to: dependent-type-node + query: + - $column-type[Type] = '*scpb.ColumnType' + - $dependent-type[Type] IN ['*scpb.AliasType', '*scpb.EnumType'] + - $column-type-target[TargetStatus] = ABSENT + - $dependent-type-target[TargetStatus] = ABSENT + - $column-type-node[CurrentStatus] = ABSENT + - $dependent-type-node[CurrentStatus] = DROPPED + - columnTypeDependsOn(*scpb.ColumnType, scpb.Element)($column-type, $dependent-type) + - $column-type-target[Type] = '*scpb.Target' + - $column-type-target[Element] = $column-type + - $column-type-node[Type] = '*screl.Node' + - $column-type-node[Target] = $column-type-target + - $dependent-type-target[Type] = '*scpb.Target' + - $dependent-type-target[Element] = $dependent-type + - $dependent-type-node[Type] = '*screl.Node' + - $dependent-type-node[Target] = $dependent-type-target + - $column-type[DescID] = $var-to-tell-rel-from-is-an-element + - $dependent-type[DescID] = $var-to-tell-rel-to-is-an-element - name: column DEFAULT removed before dropping dependent types and sequences - from: from-node + from: default-expr-node kind: Precedence - to: to-node - query: - - $from[Type] = '*scpb.ColumnDefaultExpression' - - $from-target[TargetStatus] = ABSENT - - $to[Type] IN ['*scpb.AliasType', '*scpb.EnumType', '*scpb.Sequence'] - - $to-target[TargetStatus] = ABSENT - - $from-node[CurrentStatus] = ABSENT - - $to-node[CurrentStatus] = DROPPED - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element - - column-default-depends-on(*scpb.ColumnDefaultExpression, scpb.Element)($from, $to) + to: dependent-node + query: + - $default-expr[Type] = '*scpb.ColumnDefaultExpression' + - $dependent[Type] IN ['*scpb.AliasType', '*scpb.EnumType', '*scpb.Sequence'] + - $default-expr-target[TargetStatus] = ABSENT + - $dependent-target[TargetStatus] = ABSENT + - $default-expr-node[CurrentStatus] = ABSENT + - $dependent-node[CurrentStatus] = DROPPED + - columnDefaultDependsOn(*scpb.ColumnDefaultExpression, scpb.Element)($default-expr, $dependent) + - $default-expr-target[Type] = '*scpb.Target' + - $default-expr-target[Element] = $default-expr + - $default-expr-node[Type] = '*screl.Node' + - $default-expr-node[Target] = $default-expr-target + - $dependent-target[Type] = '*scpb.Target' + - $dependent-target[Element] = $dependent + - $dependent-node[Type] = '*screl.Node' + - $dependent-node[Target] = $dependent-target + - $default-expr[DescID] = $var-to-tell-rel-from-is-an-element + - $dependent[DescID] = $var-to-tell-rel-to-is-an-element - name: column ON UPDATE removed before dropping dependent types and sequences - from: from-node + from: on-update-expr-node kind: Precedence - to: to-node - query: - - $from[Type] = '*scpb.ColumnOnUpdateExpression' - - $from-target[TargetStatus] = ABSENT - - $to[Type] IN ['*scpb.AliasType', '*scpb.EnumType', '*scpb.Sequence'] - - $to-target[TargetStatus] = ABSENT - - $from-node[CurrentStatus] = ABSENT - - $to-node[CurrentStatus] = DROPPED - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element - - column-on-update-depends-on(*scpb.ColumnOnUpdateExpression, scpb.Element)($from, $to) + to: dependent-node + query: + - $on-update-expr[Type] = '*scpb.ColumnOnUpdateExpression' + - $dependent[Type] IN ['*scpb.AliasType', '*scpb.EnumType', '*scpb.Sequence'] + - $on-update-expr-target[TargetStatus] = ABSENT + - $dependent-target[TargetStatus] = ABSENT + - $on-update-expr-node[CurrentStatus] = ABSENT + - $dependent-node[CurrentStatus] = DROPPED + - columnOnUpdateDependsOn(*scpb.ColumnOnUpdateExpression, scpb.Element)($on-update-expr, $dependent) + - $on-update-expr-target[Type] = '*scpb.Target' + - $on-update-expr-target[Element] = $on-update-expr + - $on-update-expr-node[Type] = '*screl.Node' + - $on-update-expr-node[Target] = $on-update-expr-target + - $dependent-target[Type] = '*scpb.Target' + - $dependent-target[Element] = $dependent + - $dependent-node[Type] = '*screl.Node' + - $dependent-node[Target] = $dependent-target + - $on-update-expr[DescID] = $var-to-tell-rel-from-is-an-element + - $dependent[DescID] = $var-to-tell-rel-to-is-an-element - name: sequence ownership removed before dropping sequence - from: from-node + from: sequence-owner-node kind: Precedence - to: to-node - query: - - $from[Type] = '*scpb.SequenceOwner' - - $from-target[TargetStatus] = ABSENT - - $to[Type] = '*scpb.Sequence' - - $to-target[TargetStatus] = ABSENT - - $from-node[CurrentStatus] = ABSENT - - $to-node[CurrentStatus] = DROPPED - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[ReferencedDescID] = $joined-from-ref-desc-id-with-to-desc-id-var - - $to[DescID] = $joined-from-ref-desc-id-with-to-desc-id-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element + to: sequence-node + query: + - $sequence-owner[Type] = '*scpb.SequenceOwner' + - $sequence[Type] = '*scpb.Sequence' + - $sequence-owner-target[TargetStatus] = ABSENT + - $sequence-target[TargetStatus] = ABSENT + - $sequence-owner-node[CurrentStatus] = ABSENT + - $sequence-node[CurrentStatus] = DROPPED + - $sequence-owner[ReferencedDescID] = $desc-id + - $sequence[DescID] = $desc-id + - $sequence-owner-target[Type] = '*scpb.Target' + - $sequence-owner-target[Element] = $sequence-owner + - $sequence-owner-node[Type] = '*screl.Node' + - $sequence-owner-node[Target] = $sequence-owner-target + - $sequence-target[Type] = '*scpb.Target' + - $sequence-target[Element] = $sequence + - $sequence-node[Type] = '*screl.Node' + - $sequence-node[Target] = $sequence-target + - $sequence-owner[DescID] = $var-to-tell-rel-from-is-an-element + - $sequence[DescID] = $var-to-tell-rel-to-is-an-element - name: database region config removed before dropping multi-region enum type - from: from-node + from: region-config-node kind: Precedence - to: to-node - query: - - $from[Type] = '*scpb.DatabaseRegionConfig' - - $from-target[TargetStatus] = ABSENT - - $to[Type] = '*scpb.EnumType' - - $to-target[TargetStatus] = ABSENT - - $from-node[CurrentStatus] = ABSENT - - $to-node[CurrentStatus] = DROPPED - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[ReferencedDescID] = $joined-from-ref-desc-id-with-to-desc-id-var - - $to[DescID] = $joined-from-ref-desc-id-with-to-desc-id-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element + to: enum-type-node + query: + - $region-config[Type] = '*scpb.DatabaseRegionConfig' + - $enum-type[Type] = '*scpb.EnumType' + - $region-config-target[TargetStatus] = ABSENT + - $enum-type-target[TargetStatus] = ABSENT + - $region-config-node[CurrentStatus] = ABSENT + - $enum-type-node[CurrentStatus] = DROPPED + - $region-config[ReferencedDescID] = $desc-id + - $enum-type[DescID] = $desc-id + - $region-config-target[Type] = '*scpb.Target' + - $region-config-target[Element] = $region-config + - $region-config-node[Type] = '*screl.Node' + - $region-config-node[Target] = $region-config-target + - $enum-type-target[Type] = '*scpb.Target' + - $enum-type-target[Element] = $enum-type + - $enum-type-node[Type] = '*screl.Node' + - $enum-type-node[Target] = $enum-type-target + - $region-config[DescID] = $var-to-tell-rel-from-is-an-element + - $enum-type[DescID] = $var-to-tell-rel-to-is-an-element +- name: database region config removed before dropping multi-region enum type + from: region-config-node + kind: Precedence + to: enum-type-node + query: + - $region-config[Type] = '*scpb.DatabaseRegionConfig' + - $enum-type[Type] = '*scpb.EnumType' + - $region-config-target[TargetStatus] = ABSENT + - $enum-type-target[TargetStatus] = ABSENT + - $region-config-node[CurrentStatus] = ABSENT + - $enum-type-node[CurrentStatus] = DROPPED + - $region-config[ReferencedDescID] = $desc-id + - $enum-type[DescID] = $desc-id + - $region-config-target[Type] = '*scpb.Target' + - $region-config-target[Element] = $region-config + - $region-config-node[Type] = '*screl.Node' + - $region-config-node[Target] = $region-config-target + - $enum-type-target[Type] = '*scpb.Target' + - $enum-type-target[Element] = $enum-type + - $enum-type-node[Type] = '*screl.Node' + - $enum-type-node[Target] = $enum-type-target + - $region-config[DescID] = $var-to-tell-rel-from-is-an-element + - $enum-type[DescID] = $var-to-tell-rel-to-is-an-element - name: dependent element removal before descriptor drop - from: from-node + from: element-node kind: Precedence - to: to-node - query: - - $from[Type] IN ['*scpb.ColumnFamily', '*scpb.UniqueWithoutIndexConstraint', '*scpb.CheckConstraint', '*scpb.ForeignKeyConstraint', '*scpb.TableComment', '*scpb.TableLocalityGlobal', '*scpb.TableLocalityPrimaryRegion', '*scpb.TableLocalitySecondaryRegion', '*scpb.TableLocalityRegionalByRow', '*scpb.ColumnName', '*scpb.ColumnDefaultExpression', '*scpb.ColumnOnUpdateExpression', '*scpb.ColumnComment', '*scpb.SequenceOwner', '*scpb.IndexName', '*scpb.IndexPartitioning', '*scpb.IndexComment', '*scpb.ConstraintName', '*scpb.ConstraintComment', '*scpb.Namespace', '*scpb.Owner', '*scpb.UserPrivileges', '*scpb.DatabaseRoleSetting', '*scpb.DatabaseRegionConfig', '*scpb.DatabaseComment', '*scpb.SchemaParent', '*scpb.SchemaComment', '*scpb.ObjectParent'] - - $from-target[TargetStatus] = ABSENT - - $to[Type] IN ['*scpb.Database', '*scpb.Schema', '*scpb.Table', '*scpb.View', '*scpb.Sequence', '*scpb.AliasType', '*scpb.EnumType'] - - $to-target[TargetStatus] = ABSENT - - $from-node[CurrentStatus] = ABSENT - - $to-node[CurrentStatus] = DROPPED - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $DescID-join-var - - $to[DescID] = $DescID-join-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element + to: relation-node + query: + - $element[Type] IN ['*scpb.ColumnFamily', '*scpb.UniqueWithoutIndexConstraint', '*scpb.CheckConstraint', '*scpb.ForeignKeyConstraint', '*scpb.TableComment', '*scpb.TableLocalityGlobal', '*scpb.TableLocalityPrimaryRegion', '*scpb.TableLocalitySecondaryRegion', '*scpb.TableLocalityRegionalByRow', '*scpb.ColumnName', '*scpb.ColumnDefaultExpression', '*scpb.ColumnOnUpdateExpression', '*scpb.ColumnComment', '*scpb.SequenceOwner', '*scpb.IndexName', '*scpb.IndexPartitioning', '*scpb.IndexComment', '*scpb.ConstraintName', '*scpb.ConstraintComment', '*scpb.Namespace', '*scpb.Owner', '*scpb.UserPrivileges', '*scpb.DatabaseRoleSetting', '*scpb.DatabaseRegionConfig', '*scpb.DatabaseComment', '*scpb.SchemaParent', '*scpb.SchemaComment', '*scpb.ObjectParent'] + - $relation[Type] IN ['*scpb.Database', '*scpb.Schema', '*scpb.Table', '*scpb.View', '*scpb.Sequence', '*scpb.AliasType', '*scpb.EnumType'] + - $element-target[TargetStatus] = ABSENT + - $relation-target[TargetStatus] = ABSENT + - $element-node[CurrentStatus] = ABSENT + - $relation-node[CurrentStatus] = DROPPED + - $element[DescID] = $desc-id + - $relation[DescID] = $desc-id + - $element-target[Type] = '*scpb.Target' + - $element-target[Element] = $element + - $element-node[Type] = '*screl.Node' + - $element-node[Target] = $element-target + - $relation-target[Type] = '*scpb.Target' + - $relation-target[Element] = $relation + - $relation-node[Type] = '*screl.Node' + - $relation-node[Target] = $relation-target + - $element[DescID] = $var-to-tell-rel-from-is-an-element + - $relation[DescID] = $var-to-tell-rel-to-is-an-element - name: dependent element removal right after descriptor removal - from: from-node + from: relation-node kind: SameStagePrecedence - to: to-node - query: - - $from[Type] IN ['*scpb.Table', '*scpb.View'] - - $from-target[TargetStatus] = ABSENT - - $to[Type] IN ['*scpb.Column', '*scpb.PrimaryIndex', '*scpb.SecondaryIndex', '*scpb.RowLevelTTL'] - - $to-target[TargetStatus] = ABSENT - - $from-node[CurrentStatus] = ABSENT - - $to-node[CurrentStatus] = ABSENT - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $DescID-join-var - - $to[DescID] = $DescID-join-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element + to: element-node + query: + - $relation[Type] IN ['*scpb.Table', '*scpb.View'] + - $element[Type] IN ['*scpb.Column', '*scpb.PrimaryIndex', '*scpb.SecondaryIndex', '*scpb.RowLevelTTL'] + - $relation-target[TargetStatus] = ABSENT + - $element-target[TargetStatus] = ABSENT + - $relation-node[CurrentStatus] = ABSENT + - $element-node[CurrentStatus] = ABSENT + - $relation[DescID] = $desc-id + - $element[DescID] = $desc-id + - $relation-target[Type] = '*scpb.Target' + - $relation-target[Element] = $relation + - $relation-node[Type] = '*screl.Node' + - $relation-node[Target] = $relation-target + - $element-target[Type] = '*scpb.Target' + - $element-target[Element] = $element + - $element-node[Type] = '*screl.Node' + - $element-node[Target] = $element-target + - $relation[DescID] = $var-to-tell-rel-from-is-an-element + - $element[DescID] = $var-to-tell-rel-to-is-an-element - name: primary index swap from: old-index-node kind: SameStagePrecedence to: new-index-node query: - - $new-index[Type] = '*scpb.PrimaryIndex' - $old-index[Type] = '*scpb.PrimaryIndex' - - $new-index[DescID] = $table-id + - $new-index[Type] = '*scpb.PrimaryIndex' - $old-index[DescID] = $table-id - - new-primary-index-depends-on-old(*scpb.PrimaryIndex, *scpb.PrimaryIndex)($new-index, $old-index) - - $new-index-target[Type] = '*scpb.Target' - - $new-index-target[Element] = $new-index - - $new-index-node[Type] = '*screl.Node' - - $new-index-node[Target] = $new-index-target + - $new-index[DescID] = $table-id + - $old-index-target[TargetStatus] = ABSENT - $new-index-target[TargetStatus] = PUBLIC + - $old-index-node[CurrentStatus] = VALIDATED - $new-index-node[CurrentStatus] = PUBLIC + - new-primary-index-depends-on-old(*scpb.PrimaryIndex, *scpb.PrimaryIndex)($new-index, $old-index) - $old-index-target[Type] = '*scpb.Target' - $old-index-target[Element] = $old-index - $old-index-node[Type] = '*screl.Node' - $old-index-node[Target] = $old-index-target - - $old-index-target[TargetStatus] = ABSENT - - $old-index-node[CurrentStatus] = VALIDATED + - $new-index-target[Type] = '*scpb.Target' + - $new-index-target[Element] = $new-index + - $new-index-node[Type] = '*screl.Node' + - $new-index-node[Target] = $new-index-target + - $old-index[DescID] = $var-to-tell-rel-from-is-an-element + - $new-index[DescID] = $var-to-tell-rel-to-is-an-element - name: index existence precedes index dependents - from: from-node + from: index-node kind: Precedence - to: to-node - query: - - $from[Type] IN ['*scpb.PrimaryIndex', '*scpb.SecondaryIndex'] - - $from-target[TargetStatus] = PUBLIC - - $to[Type] IN ['*scpb.IndexName', '*scpb.IndexPartitioning', '*scpb.IndexComment'] - - $to-target[TargetStatus] = PUBLIC - - $from-node[CurrentStatus] = BACKFILL_ONLY - - $to-node[CurrentStatus] = PUBLIC - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $DescID-join-var - - $to[DescID] = $DescID-join-var - - $from[IndexID] = $IndexID-join-var - - $to[IndexID] = $IndexID-join-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element + to: index-dependent-node + query: + - $index[Type] IN ['*scpb.PrimaryIndex', '*scpb.SecondaryIndex'] + - $index-dependent[Type] IN ['*scpb.IndexName', '*scpb.IndexPartitioning', '*scpb.IndexComment'] + - $index[DescID] = $desc-id + - $index-dependent[DescID] = $desc-id + - $index[IndexID] = $index-id + - $index-dependent[IndexID] = $index-id + - $index-target[TargetStatus] = PUBLIC + - $index-dependent-target[TargetStatus] = PUBLIC + - $index-node[CurrentStatus] = BACKFILL_ONLY + - $index-dependent-node[CurrentStatus] = PUBLIC + - $index-target[Type] = '*scpb.Target' + - $index-target[Element] = $index + - $index-node[Type] = '*screl.Node' + - $index-node[Target] = $index-target + - $index-dependent-target[Type] = '*scpb.Target' + - $index-dependent-target[Element] = $index-dependent + - $index-dependent-node[Type] = '*screl.Node' + - $index-dependent-node[Target] = $index-dependent-target + - $index[DescID] = $var-to-tell-rel-from-is-an-element + - $index-dependent[DescID] = $var-to-tell-rel-to-is-an-element - name: partitioning set right after temp index existence - from: from-node + from: temp-index-node kind: SameStagePrecedence - to: to-node - query: - - $from[Type] = '*scpb.TemporaryIndex' - - $from-target[TargetStatus] = TRANSIENT_ABSENT - - $to[Type] = '*scpb.IndexPartitioning' - - $to-target[TargetStatus] = PUBLIC - - $from-node[CurrentStatus] = DELETE_ONLY - - $to-node[CurrentStatus] = PUBLIC - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $DescID-join-var - - $to[DescID] = $DescID-join-var - - $from[IndexID] = $IndexID-join-var - - $to[IndexID] = $IndexID-join-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element + to: index-partitioning-node + query: + - $temp-index[Type] = '*scpb.TemporaryIndex' + - $index-partitioning[Type] = '*scpb.IndexPartitioning' + - $temp-index[DescID] = $desc-id + - $index-partitioning[DescID] = $desc-id + - $temp-index[IndexID] = $index-id + - $index-partitioning[IndexID] = $index-id + - $temp-index-target[TargetStatus] = TRANSIENT_ABSENT + - $index-partitioning-target[TargetStatus] = PUBLIC + - $temp-index-node[CurrentStatus] = DELETE_ONLY + - $index-partitioning-node[CurrentStatus] = PUBLIC + - $temp-index-target[Type] = '*scpb.Target' + - $temp-index-target[Element] = $temp-index + - $temp-index-node[Type] = '*screl.Node' + - $temp-index-node[Target] = $temp-index-target + - $index-partitioning-target[Type] = '*scpb.Target' + - $index-partitioning-target[Element] = $index-partitioning + - $index-partitioning-node[Type] = '*screl.Node' + - $index-partitioning-node[Target] = $index-partitioning-target + - $temp-index[DescID] = $var-to-tell-rel-from-is-an-element + - $index-partitioning[DescID] = $var-to-tell-rel-to-is-an-element - name: partial predicate set right after secondary index existence - from: from-node + from: index-node kind: SameStagePrecedence - to: to-node - query: - - $from[Type] = '*scpb.SecondaryIndex' - - $from-target[TargetStatus] = PUBLIC - - $to[Type] = '*scpb.SecondaryIndexPartial' - - $to-target[TargetStatus] = PUBLIC - - $from-node[CurrentStatus] = BACKFILL_ONLY - - $to-node[CurrentStatus] = PUBLIC - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $DescID-join-var - - $to[DescID] = $DescID-join-var - - $from[IndexID] = $IndexID-join-var - - $to[IndexID] = $IndexID-join-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element + to: index-predicate-node + query: + - $index[Type] = '*scpb.SecondaryIndex' + - $index-predicate[Type] = '*scpb.SecondaryIndexPartial' + - $index[DescID] = $desc-id + - $index-predicate[DescID] = $desc-id + - $index[IndexID] = $index-id + - $index-predicate[IndexID] = $index-id + - $index-target[TargetStatus] = PUBLIC + - $index-predicate-target[TargetStatus] = PUBLIC + - $index-node[CurrentStatus] = BACKFILL_ONLY + - $index-predicate[CurrentStatus] = PUBLIC + - $index[DescID] = $desc-id + - $index-predicate[DescID] = $desc-id + - $index[IndexID] = $index-id + - $index-predicate[IndexID] = $index-id + - $index-target[Type] = '*scpb.Target' + - $index-target[Element] = $index + - $index-node[Type] = '*screl.Node' + - $index-node[Target] = $index-target + - $index-predicate-target[Type] = '*scpb.Target' + - $index-predicate-target[Element] = $index-predicate + - $index-predicate-node[Type] = '*screl.Node' + - $index-predicate-node[Target] = $index-predicate-target + - $index[DescID] = $var-to-tell-rel-from-is-an-element + - $index-predicate[DescID] = $var-to-tell-rel-to-is-an-element - name: dependents existence precedes writes to index - from: from-node + from: child-node kind: Precedence - to: to-node - query: - - $from[Type] IN ['*scpb.IndexPartitioning', '*scpb.IndexComment'] - - $from-target[TargetStatus] = PUBLIC - - $to[Type] IN ['*scpb.PrimaryIndex', '*scpb.SecondaryIndex'] - - $to-target[TargetStatus] = PUBLIC - - $from-node[CurrentStatus] = PUBLIC - - $to-node[CurrentStatus] = WRITE_ONLY - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $DescID-join-var - - $to[DescID] = $DescID-join-var - - $from[IndexID] = $IndexID-join-var - - $to[IndexID] = $IndexID-join-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element + to: index-node + query: + - $child[Type] IN ['*scpb.IndexPartitioning', '*scpb.IndexComment'] + - $index[Type] IN ['*scpb.PrimaryIndex', '*scpb.SecondaryIndex'] + - $child[DescID] = $desc-id + - $index[DescID] = $desc-id + - $child[IndexID] = $index-id + - $index[IndexID] = $index-id + - $child-target[TargetStatus] = PUBLIC + - $index-target[TargetStatus] = PUBLIC + - $child-node[CurrentStatus] = PUBLIC + - $index-node[CurrentStatus] = WRITE_ONLY + - $child-target[Type] = '*scpb.Target' + - $child-target[Element] = $child + - $child-node[Type] = '*screl.Node' + - $child-node[Target] = $child-target + - $index-target[Type] = '*scpb.Target' + - $index-target[Element] = $index + - $index-node[Type] = '*screl.Node' + - $index-node[Target] = $index-target + - $child[DescID] = $var-to-tell-rel-from-is-an-element + - $index[DescID] = $var-to-tell-rel-to-is-an-element - name: index named right before index becomes public - from: from-node + from: index-name-node kind: SameStagePrecedence - to: to-node - query: - - $from[Type] = '*scpb.IndexName' - - $from-target[TargetStatus] = PUBLIC - - $to[Type] IN ['*scpb.PrimaryIndex', '*scpb.SecondaryIndex'] - - $to-target[TargetStatus] = PUBLIC - - $from-node[CurrentStatus] = PUBLIC - - $to-node[CurrentStatus] = PUBLIC - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $DescID-join-var - - $to[DescID] = $DescID-join-var - - $from[IndexID] = $IndexID-join-var - - $to[IndexID] = $IndexID-join-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element + to: index-node + query: + - $index-name[Type] = '*scpb.IndexName' + - $index[Type] IN ['*scpb.PrimaryIndex', '*scpb.SecondaryIndex'] + - $index-name-target[TargetStatus] = PUBLIC + - $index-target[TargetStatus] = PUBLIC + - $index-name-node[CurrentStatus] = PUBLIC + - $index-node[CurrentStatus] = PUBLIC + - $index-name[DescID] = $desc-id + - $index[DescID] = $desc-id + - $index-name[IndexID] = $index-id + - $index[IndexID] = $index-id + - $index-name-target[Type] = '*scpb.Target' + - $index-name-target[Element] = $index-name + - $index-name-node[Type] = '*screl.Node' + - $index-name-node[Target] = $index-name-target + - $index-target[Type] = '*scpb.Target' + - $index-target[Element] = $index + - $index-node[Type] = '*screl.Node' + - $index-node[Target] = $index-target + - $index-name[DescID] = $var-to-tell-rel-from-is-an-element + - $index[DescID] = $var-to-tell-rel-to-is-an-element - name: dependents removed after index no longer public - from: from-node + from: index-node kind: Precedence - to: to-node - query: - - $from[Type] IN ['*scpb.PrimaryIndex', '*scpb.SecondaryIndex'] - - $from-target[TargetStatus] = ABSENT - - $to[Type] IN ['*scpb.IndexName', '*scpb.IndexPartitioning', '*scpb.SecondaryIndexPartial', '*scpb.IndexComment'] - - $to-target[TargetStatus] = ABSENT - - $from-node[CurrentStatus] = VALIDATED - - $to-node[CurrentStatus] = ABSENT - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $DescID-join-var - - $to[DescID] = $DescID-join-var - - $from[IndexID] = $IndexID-join-var - - $to[IndexID] = $IndexID-join-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element + to: child-node + query: + - $index[Type] IN ['*scpb.PrimaryIndex', '*scpb.SecondaryIndex'] + - $child[Type] IN ['*scpb.IndexName', '*scpb.IndexPartitioning', '*scpb.SecondaryIndexPartial', '*scpb.IndexComment'] + - $index[DescID] = $desc-id + - $child[DescID] = $desc-id + - $index[IndexID] = $index-id + - $child[IndexID] = $index-id + - $index-target[TargetStatus] = ABSENT + - $child-target[TargetStatus] = ABSENT + - $index-node[CurrentStatus] = VALIDATED + - $child-node[CurrentStatus] = ABSENT + - $index-target[Type] = '*scpb.Target' + - $index-target[Element] = $index + - $index-node[Type] = '*screl.Node' + - $index-node[Target] = $index-target + - $child-target[Type] = '*scpb.Target' + - $child-target[Element] = $child + - $child-node[Type] = '*screl.Node' + - $child-node[Target] = $child-target + - $index[DescID] = $var-to-tell-rel-from-is-an-element + - $child[DescID] = $var-to-tell-rel-to-is-an-element - name: dependents removed before index - from: from-node + from: dependent-node kind: Precedence - to: to-node - query: - - $from[Type] IN ['*scpb.IndexName', '*scpb.IndexPartitioning', '*scpb.SecondaryIndexPartial', '*scpb.IndexComment'] - - $from-target[TargetStatus] = ABSENT - - $to[Type] IN ['*scpb.PrimaryIndex', '*scpb.SecondaryIndex'] - - $to-target[TargetStatus] = ABSENT - - $from-node[CurrentStatus] = ABSENT - - $to-node[CurrentStatus] = ABSENT - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $DescID-join-var - - $to[DescID] = $DescID-join-var - - $from[IndexID] = $IndexID-join-var - - $to[IndexID] = $IndexID-join-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element + to: index-node + query: + - $dependent[Type] IN ['*scpb.IndexName', '*scpb.IndexPartitioning', '*scpb.SecondaryIndexPartial', '*scpb.IndexComment'] + - $index[Type] IN ['*scpb.PrimaryIndex', '*scpb.SecondaryIndex'] + - $dependent[DescID] = $desc-id + - $index[DescID] = $desc-id + - $dependent[IndexID] = $index-id + - $index[IndexID] = $index-id + - $dependent-target[TargetStatus] = ABSENT + - $index-target[TargetStatus] = ABSENT + - $dependent-node[CurrentStatus] = ABSENT + - $index-node[CurrentStatus] = ABSENT + - $dependent-target[Type] = '*scpb.Target' + - $dependent-target[Element] = $dependent + - $dependent-node[Type] = '*screl.Node' + - $dependent-node[Target] = $dependent-target + - $index-target[Type] = '*scpb.Target' + - $index-target[Element] = $index + - $index-node[Type] = '*screl.Node' + - $index-node[Target] = $index-target + - $dependent[DescID] = $var-to-tell-rel-from-is-an-element + - $index[DescID] = $var-to-tell-rel-to-is-an-element - name: temp index is WRITE_ONLY before backfill - from: from-node + from: temp-node kind: Precedence - to: to-node - query: - - $from[Type] = '*scpb.TemporaryIndex' - - $to[Type] IN ['*scpb.PrimaryIndex', '*scpb.SecondaryIndex'] - - $from[DescID] = $desc-id - - $to[DescID] = $desc-id - - $to[TemporaryIndexID] = $temp-index-id - - $from[IndexID] = $temp-index-id - - $from-target[TargetStatus] = TRANSIENT_ABSENT - - $to-target[TargetStatus] = PUBLIC - - $from-node[CurrentStatus] = WRITE_ONLY - - $to-node[CurrentStatus] = BACKFILLED - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target + to: index-node + query: + - $temp[Type] = '*scpb.TemporaryIndex' + - $index[Type] IN ['*scpb.PrimaryIndex', '*scpb.SecondaryIndex'] + - $temp[DescID] = $desc-id + - $index[DescID] = $desc-id + - $temp[IndexID] = $temp-index-id + - $index[TemporaryIndexID] = $temp-index-id + - $temp-target[TargetStatus] = TRANSIENT_ABSENT + - $index-target[TargetStatus] = PUBLIC + - $temp-node[CurrentStatus] = WRITE_ONLY + - $index-node[CurrentStatus] = BACKFILLED + - $temp-target[Type] = '*scpb.Target' + - $temp-target[Element] = $temp + - $temp-node[Type] = '*screl.Node' + - $temp-node[Target] = $temp-target + - $index-target[Type] = '*scpb.Target' + - $index-target[Element] = $index + - $index-node[Type] = '*screl.Node' + - $index-node[Target] = $index-target + - $temp[DescID] = $var-to-tell-rel-from-is-an-element + - $index[DescID] = $var-to-tell-rel-to-is-an-element - name: column name set right after column existence - from: from-node + from: column-node kind: SameStagePrecedence - to: to-node - query: - - $from[Type] = '*scpb.Column' - - $from-target[TargetStatus] = PUBLIC - - $to[Type] = '*scpb.ColumnName' - - $to-target[TargetStatus] = PUBLIC - - $from-node[CurrentStatus] = DELETE_ONLY - - $to-node[CurrentStatus] = PUBLIC - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $DescID-join-var - - $to[DescID] = $DescID-join-var - - $from[ColumnID] = $ColumnID-join-var - - $to[ColumnID] = $ColumnID-join-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element + to: column-name-node + query: + - $column[Type] = '*scpb.Column' + - $column-name[Type] = '*scpb.ColumnName' + - $column-target[TargetStatus] = PUBLIC + - $column-name-target[TargetStatus] = PUBLIC + - $column-node[CurrentStatus] = DELETE_ONLY + - $column-name-node[CurrentStatus] = PUBLIC + - $column[DescID] = $desc-id + - $column-name[DescID] = $desc-id + - $column[ColumnID] = $column-id + - $column-name[ColumnID] = $column-id + - $column-target[Type] = '*scpb.Target' + - $column-target[Element] = $column + - $column-node[Type] = '*screl.Node' + - $column-node[Target] = $column-target + - $column-name-target[Type] = '*scpb.Target' + - $column-name-target[Element] = $column-name + - $column-name-node[Type] = '*screl.Node' + - $column-name-node[Target] = $column-name-target + - $column[DescID] = $var-to-tell-rel-from-is-an-element + - $column-name[DescID] = $var-to-tell-rel-to-is-an-element - name: column existence precedes column dependents - from: from-node + from: column-node kind: Precedence - to: to-node - query: - - $from[Type] = '*scpb.Column' - - $from-target[TargetStatus] = PUBLIC - - $to[Type] IN ['*scpb.ColumnName', '*scpb.ColumnDefaultExpression', '*scpb.ColumnOnUpdateExpression', '*scpb.ColumnComment'] - - $to-target[TargetStatus] = PUBLIC - - $from-node[CurrentStatus] = DELETE_ONLY - - $to-node[CurrentStatus] = PUBLIC - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $DescID-join-var - - $to[DescID] = $DescID-join-var - - $from[ColumnID] = $ColumnID-join-var - - $to[ColumnID] = $ColumnID-join-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element + to: dependent-node + query: + - $column[Type] = '*scpb.Column' + - $dependent[Type] IN ['*scpb.ColumnName', '*scpb.ColumnDefaultExpression', '*scpb.ColumnOnUpdateExpression', '*scpb.ColumnComment'] + - $column[DescID] = $desc-id + - $dependent[DescID] = $desc-id + - $column[ColumnID] = $column-id + - $dependent[ColumnID] = $column-id + - $column-target[TargetStatus] = PUBLIC + - $dependent-target[TargetStatus] = PUBLIC + - $column-node[CurrentStatus] = DELETE_ONLY + - $dependent-node[CurrentStatus] = PUBLIC + - $column-target[Type] = '*scpb.Target' + - $column-target[Element] = $column + - $column-node[Type] = '*screl.Node' + - $column-node[Target] = $column-target + - $dependent-target[Type] = '*scpb.Target' + - $dependent-target[Element] = $dependent + - $dependent-node[Type] = '*screl.Node' + - $dependent-node[Target] = $dependent-target + - $column[DescID] = $var-to-tell-rel-from-is-an-element + - $dependent[DescID] = $var-to-tell-rel-to-is-an-element - name: DEFAULT or ON UPDATE existence precedes writes to column - from: from-node + from: expr-node kind: Precedence - to: to-node - query: - - $from[Type] IN ['*scpb.ColumnDefaultExpression', '*scpb.ColumnOnUpdateExpression'] - - $from-target[TargetStatus] = PUBLIC - - $to[Type] = '*scpb.Column' - - $to-target[TargetStatus] = PUBLIC - - $from-node[CurrentStatus] = PUBLIC - - $to-node[CurrentStatus] = WRITE_ONLY - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $DescID-join-var - - $to[DescID] = $DescID-join-var - - $from[ColumnID] = $ColumnID-join-var - - $to[ColumnID] = $ColumnID-join-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element -- name: column named right before column becomes public - from: from-node + to: column-node + query: + - $expr[Type] IN ['*scpb.ColumnDefaultExpression', '*scpb.ColumnOnUpdateExpression'] + - $column[Type] = '*scpb.Column' + - $expr[DescID] = $desc-id + - $column[DescID] = $desc-id + - $expr[ColumnID] = $column-id + - $column[ColumnID] = $column-id + - $expr-target[TargetStatus] = PUBLIC + - $column-target[TargetStatus] = PUBLIC + - $expr-node[CurrentStatus] = PUBLIC + - $column-node[CurrentStatus] = WRITE_ONLY + - $expr-target[Type] = '*scpb.Target' + - $expr-target[Element] = $expr + - $expr-node[Type] = '*screl.Node' + - $expr-node[Target] = $expr-target + - $column-target[Type] = '*scpb.Target' + - $column-target[Element] = $column + - $column-node[Type] = '*screl.Node' + - $column-node[Target] = $column-target + - $expr[DescID] = $var-to-tell-rel-from-is-an-element + - $column[DescID] = $var-to-tell-rel-to-is-an-element +- name: column named right before column type becomes public + from: column-name-node kind: SameStagePrecedence - to: to-node - query: - - $from[Type] = '*scpb.ColumnName' - - $from-target[TargetStatus] = PUBLIC - - $to[Type] = '*scpb.ColumnType' - - $to-target[TargetStatus] = PUBLIC - - $from-node[CurrentStatus] = PUBLIC - - $to-node[CurrentStatus] = PUBLIC - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $DescID-join-var - - $to[DescID] = $DescID-join-var - - $from[ColumnID] = $ColumnID-join-var - - $to[ColumnID] = $ColumnID-join-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element -- name: column dependents exist before column becomes public - from: from-node + to: column-type-node + query: + - $column-name[Type] = '*scpb.ColumnName' + - $column-type[Type] = '*scpb.ColumnType' + - $column-name[DescID] = $desc-id + - $column-type[DescID] = $desc-id + - $column-name[ColumnID] = $column-id + - $column-type[ColumnID] = $column-id + - $column-name-target[TargetStatus] = PUBLIC + - $column-type-target[TargetStatus] = PUBLIC + - $column-name-node[CurrentStatus] = PUBLIC + - $column-type-node[CurrentStatus] = PUBLIC + - $column-name-target[Type] = '*scpb.Target' + - $column-name-target[Element] = $column-name + - $column-name-node[Type] = '*screl.Node' + - $column-name-node[Target] = $column-name-target + - $column-type-target[Type] = '*scpb.Target' + - $column-type-target[Element] = $column-type + - $column-type-node[Type] = '*screl.Node' + - $column-type-node[Target] = $column-type-target + - $column-name[DescID] = $var-to-tell-rel-from-is-an-element + - $column-type[DescID] = $var-to-tell-rel-to-is-an-element +- name: column comment exists before column becomes public + from: column-comment-node kind: Precedence - to: to-node - query: - - $from[Type] = '*scpb.ColumnComment' - - $from-target[TargetStatus] = PUBLIC - - $to[Type] = '*scpb.Column' - - $to-target[TargetStatus] = PUBLIC - - $from-node[CurrentStatus] = PUBLIC - - $to-node[CurrentStatus] = PUBLIC - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $DescID-join-var - - $to[DescID] = $DescID-join-var - - $from[ColumnID] = $ColumnID-join-var - - $to[ColumnID] = $ColumnID-join-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element + to: column-node + query: + - $column-comment[Type] = '*scpb.ColumnComment' + - $column[Type] = '*scpb.Column' + - $column-comment[DescID] = $desc-id + - $column[DescID] = $desc-id + - $column-comment[ColumnID] = $column-id + - $column[ColumnID] = $column-id + - $column-comment-target[TargetStatus] = PUBLIC + - $column-target[TargetStatus] = PUBLIC + - $column-comment-node[CurrentStatus] = PUBLIC + - $column-node[CurrentStatus] = PUBLIC + - $column-comment-target[Type] = '*scpb.Target' + - $column-comment-target[Element] = $column-comment + - $column-comment-node[Type] = '*screl.Node' + - $column-comment-node[Target] = $column-comment-target + - $column-target[Type] = '*scpb.Target' + - $column-target[Element] = $column + - $column-node[Type] = '*screl.Node' + - $column-node[Target] = $column-target + - $column-comment[DescID] = $var-to-tell-rel-from-is-an-element + - $column[DescID] = $var-to-tell-rel-to-is-an-element - name: column dependents removed after column no longer public - from: from-node + from: column-node kind: Precedence - to: to-node - query: - - $from[Type] = '*scpb.Column' - - $from-target[TargetStatus] = ABSENT - - $to[Type] IN ['*scpb.ColumnType', '*scpb.ColumnName', '*scpb.ColumnComment'] - - $to-target[TargetStatus] = ABSENT - - $from-node[CurrentStatus] = WRITE_ONLY - - $to-node[CurrentStatus] = ABSENT - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $DescID-join-var - - $to[DescID] = $DescID-join-var - - $from[ColumnID] = $ColumnID-join-var - - $to[ColumnID] = $ColumnID-join-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element + to: dependent-node + query: + - $column[Type] = '*scpb.Column' + - $dependent[Type] IN ['*scpb.ColumnType', '*scpb.ColumnName', '*scpb.ColumnComment'] + - $column[DescID] = $desc-id + - $dependent[DescID] = $desc-id + - $column[ColumnID] = $column-id + - $dependent[ColumnID] = $column-id + - $column-target[TargetStatus] = ABSENT + - $dependent-target[TargetStatus] = ABSENT + - $column-node[CurrentStatus] = WRITE_ONLY + - $dependent-node[CurrentStatus] = ABSENT + - $column-target[Type] = '*scpb.Target' + - $column-target[Element] = $column + - $column-node[Type] = '*screl.Node' + - $column-node[Target] = $column-target + - $dependent-target[Type] = '*scpb.Target' + - $dependent-target[Element] = $dependent + - $dependent-node[Type] = '*screl.Node' + - $dependent-node[Target] = $dependent-target + - $column[DescID] = $var-to-tell-rel-from-is-an-element + - $dependent[DescID] = $var-to-tell-rel-to-is-an-element - name: column type dependents removed right before column type - from: from-node + from: dependent-node kind: SameStagePrecedence - to: to-node - query: - - $from[Type] IN ['*scpb.SequenceOwner', '*scpb.ColumnDefaultExpression', '*scpb.ColumnOnUpdateExpression'] - - $from-target[TargetStatus] = ABSENT - - $to[Type] = '*scpb.ColumnType' - - $to-target[TargetStatus] = ABSENT - - $from-node[CurrentStatus] = ABSENT - - $to-node[CurrentStatus] = ABSENT - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $DescID-join-var - - $to[DescID] = $DescID-join-var - - $from[ColumnID] = $ColumnID-join-var - - $to[ColumnID] = $ColumnID-join-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element + to: column-type-node + query: + - $dependent[Type] IN ['*scpb.SequenceOwner', '*scpb.ColumnDefaultExpression', '*scpb.ColumnOnUpdateExpression'] + - $column-type[Type] = '*scpb.ColumnType' + - $dependent[DescID] = $desc-id + - $column-type[DescID] = $desc-id + - $dependent[ColumnID] = $column-id + - $column-type[ColumnID] = $column-id + - $dependent-target[TargetStatus] = ABSENT + - $column-type-target[TargetStatus] = ABSENT + - $dependent-node[CurrentStatus] = ABSENT + - $column-type-node[CurrentStatus] = ABSENT + - $dependent-target[Type] = '*scpb.Target' + - $dependent-target[Element] = $dependent + - $dependent-node[Type] = '*screl.Node' + - $dependent-node[Target] = $dependent-target + - $column-type-target[Type] = '*scpb.Target' + - $column-type-target[Element] = $column-type + - $column-type-node[Type] = '*screl.Node' + - $column-type-node[Target] = $column-type-target + - $dependent[DescID] = $var-to-tell-rel-from-is-an-element + - $column-type[DescID] = $var-to-tell-rel-to-is-an-element - name: dependents removed before column - from: from-node + from: dependent-node kind: Precedence - to: to-node - query: - - $from[Type] IN ['*scpb.ColumnName', '*scpb.ColumnType', '*scpb.ColumnComment'] - - $from-target[TargetStatus] = ABSENT - - $to[Type] = '*scpb.Column' - - $to-target[TargetStatus] = ABSENT - - $from-node[CurrentStatus] = ABSENT - - $to-node[CurrentStatus] = ABSENT - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $DescID-join-var - - $to[DescID] = $DescID-join-var - - $from[ColumnID] = $ColumnID-join-var - - $to[ColumnID] = $ColumnID-join-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element + to: column-node + query: + - $dependent[Type] IN ['*scpb.ColumnName', '*scpb.ColumnType', '*scpb.ColumnComment'] + - $column[Type] = '*scpb.Column' + - $dependent[DescID] = $desc-id + - $column[DescID] = $desc-id + - $dependent[ColumnID] = $column-id + - $column[ColumnID] = $column-id + - $dependent-target[TargetStatus] = ABSENT + - $column-target[TargetStatus] = ABSENT + - $dependent-node[CurrentStatus] = ABSENT + - $column-node[CurrentStatus] = ABSENT + - $dependent-target[Type] = '*scpb.Target' + - $dependent-target[Element] = $dependent + - $dependent-node[Type] = '*screl.Node' + - $dependent-node[Target] = $dependent-target + - $column-target[Type] = '*scpb.Target' + - $column-target[Element] = $column + - $column-node[Type] = '*screl.Node' + - $column-node[Target] = $column-target + - $dependent[DescID] = $var-to-tell-rel-from-is-an-element + - $column[DescID] = $var-to-tell-rel-to-is-an-element - name: column type removed right before column when not dropping relation - from: from-node + from: column-type-node kind: SameStagePrecedence - to: to-node - query: - - $from[Type] = '*scpb.ColumnType' - - $from-target[TargetStatus] = ABSENT - - $to[Type] = '*scpb.Column' - - $to-target[TargetStatus] = ABSENT - - $from-node[CurrentStatus] = ABSENT - - $to-node[CurrentStatus] = ABSENT - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $DescID-join-var - - $to[DescID] = $DescID-join-var - - $from[ColumnID] = $ColumnID-join-var - - $to[ColumnID] = $ColumnID-join-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element - - parent-relation-is-not-dropped(*scpb.ColumnType, *scpb.Column)($from, $to) + to: column-node + query: + - $column-type[Type] = '*scpb.ColumnType' + - $column[Type] = '*scpb.Column' + - $column-type[DescID] = $desc-id + - $column[DescID] = $desc-id + - $column-type[ColumnID] = $column-id + - $column[ColumnID] = $column-id + - $column-type-target[TargetStatus] = ABSENT + - $column-target[TargetStatus] = ABSENT + - $column-type-node[CurrentStatus] = ABSENT + - $column-node[CurrentStatus] = ABSENT + - columnTypeIsNotBeingDropped(*scpb.ColumnType)($column-type) + - $column-type-target[Type] = '*scpb.Target' + - $column-type-target[Element] = $column-type + - $column-type-node[Type] = '*screl.Node' + - $column-type-node[Target] = $column-type-target + - $column-target[Type] = '*scpb.Target' + - $column-target[Element] = $column + - $column-node[Type] = '*screl.Node' + - $column-node[Target] = $column-target + - $column-type[DescID] = $var-to-tell-rel-from-is-an-element + - $column[DescID] = $var-to-tell-rel-to-is-an-element - name: partial predicate removed right before secondary index when not dropping relation - from: from-node + from: partial-predicate-node kind: SameStagePrecedence - to: to-node - query: - - $from[Type] = '*scpb.SecondaryIndexPartial' - - $from-target[TargetStatus] = ABSENT - - $to[Type] = '*scpb.SecondaryIndex' - - $to-target[TargetStatus] = ABSENT - - $from-node[CurrentStatus] = ABSENT - - $to-node[CurrentStatus] = ABSENT - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $DescID-join-var - - $to[DescID] = $DescID-join-var - - $from[IndexID] = $IndexID-join-var - - $to[IndexID] = $IndexID-join-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element - - parent-relation-is-not-dropped(*scpb.SecondaryIndexPartial, *scpb.SecondaryIndex)($from, $to) + to: index-node + query: + - $partial-predicate[Type] = '*scpb.SecondaryIndexPartial' + - $index[Type] = '*scpb.SecondaryIndex' + - $partial-predicate[DescID] = $desc-id + - $index[DescID] = $desc-id + - $partial-predicate[IndexID] = $index-id + - $index[IndexID] = $index-id + - $partial-predicate-target[TargetStatus] = ABSENT + - $index-target[TargetStatus] = ABSENT + - $partial-predicate-node[CurrentStatus] = ABSENT + - $index-node[CurrentStatus] = ABSENT + - secondaryIndexPartialIsNotBeingDropped(*scpb.SecondaryIndexPartial)($partial-predicate) + - $partial-predicate-target[Type] = '*scpb.Target' + - $partial-predicate-target[Element] = $partial-predicate + - $partial-predicate-node[Type] = '*screl.Node' + - $partial-predicate-node[Target] = $partial-predicate-target + - $index-target[Type] = '*scpb.Target' + - $index-target[Element] = $index + - $index-node[Type] = '*screl.Node' + - $index-node[Target] = $index-target + - $partial-predicate[DescID] = $var-to-tell-rel-from-is-an-element + - $index[DescID] = $var-to-tell-rel-to-is-an-element - name: column depends on primary index from: index-node kind: Precedence to: column-node query: + - $index[Type] = '*scpb.PrimaryIndex' + - $column[Type] = '*scpb.Column' + - $index-target[TargetStatus] = PUBLIC + - $column-target[TargetStatus] = PUBLIC + - $index[DescID] = $table-id + - $column[DescID] = $table-id + - columnFeaturedInIndex(*scpb.Column, scpb.Element)($column, $index) - $status IN [WRITE_ONLY, PUBLIC] - - $target-status = PUBLIC + - $index-node[CurrentStatus] = $status + - $column-node[CurrentStatus] = $status + - $index-target[Type] = '*scpb.Target' + - $index-target[Element] = $index + - $index-node[Type] = '*screl.Node' + - $index-node[Target] = $index-target + - $column-target[Type] = '*scpb.Target' + - $column-target[Element] = $column + - $column-node[Type] = '*screl.Node' + - $column-node[Target] = $column-target + - $index[DescID] = $var-to-tell-rel-from-is-an-element + - $column[DescID] = $var-to-tell-rel-to-is-an-element +- name: column existence precedes index existence + from: column-node + kind: Precedence + to: index-node + query: - $column[Type] = '*scpb.Column' - - $index[Type] = '*scpb.PrimaryIndex' + - $index[Type] IN ['*scpb.PrimaryIndex', '*scpb.SecondaryIndex'] + - $column-target[TargetStatus] = PUBLIC + - $index-target[TargetStatus] = PUBLIC + - $column-node[CurrentStatus] = DELETE_ONLY + - $index-node[CurrentStatus] = BACKFILL_ONLY - $column[DescID] = $table-id - $index[DescID] = $table-id - - column-featured-in-index(*scpb.Column, scpb.Element)($column, $index) - - $column-target[TargetStatus] = $target-status - - $index-target[TargetStatus] = $target-status - - $column-node[CurrentStatus] = $status - - $index-node[CurrentStatus] = $status + - columnFeaturedInIndex(*scpb.Column, scpb.Element)($column, $index) - $column-target[Type] = '*scpb.Target' - $column-target[Element] = $column - $column-node[Type] = '*screl.Node' @@ -856,73 +910,54 @@ deprules - $index-target[Element] = $index - $index-node[Type] = '*screl.Node' - $index-node[Target] = $index-target -- name: column existence precedes index existence - from: from-node - kind: Precedence - to: to-node - query: - - $from[Type] = '*scpb.Column' - - $from-target[TargetStatus] = PUBLIC - - $to[Type] IN ['*scpb.PrimaryIndex', '*scpb.SecondaryIndex'] - - $to-target[TargetStatus] = PUBLIC - - $from-node[CurrentStatus] = DELETE_ONLY - - $to-node[CurrentStatus] = BACKFILL_ONLY - - $from-target[Type] = '*scpb.Target' - - $from-target[Element] = $from - - $from-node[Type] = '*screl.Node' - - $from-node[Target] = $from-target - - $to-target[Type] = '*scpb.Target' - - $to-target[Element] = $to - - $to-node[Type] = '*screl.Node' - - $to-node[Target] = $to-target - - $from[DescID] = $DescID-join-var - - $to[DescID] = $DescID-join-var - - $from[DescID] = $var-to-tell-rel-from-is-an-element - - $to[DescID] = $var-to-tell-rel-to-is-an-element - - column-featured-in-index(*scpb.Column, scpb.Element)($from, $to) + - $column[DescID] = $var-to-tell-rel-from-is-an-element + - $index[DescID] = $var-to-tell-rel-to-is-an-element - name: column existence precedes temporary index existence from: column-node kind: Precedence - to: index-node + to: temp-index-node query: - - $index[Type] = '*scpb.TemporaryIndex' - $column[Type] = '*scpb.Column' + - $temp-index[Type] = '*scpb.TemporaryIndex' - $column[DescID] = $table-id - - $index[DescID] = $table-id - - $index-target[TargetStatus] = TRANSIENT_ABSENT + - $temp-index[DescID] = $table-id - $column-target[TargetStatus] = PUBLIC + - $temp-index-target[TargetStatus] = TRANSIENT_ABSENT - $column-node[CurrentStatus] = DELETE_ONLY - - $index-node[CurrentStatus] = DELETE_ONLY - - column-featured-in-index(*scpb.Column, scpb.Element)($column, $index) + - $temp-index-node[CurrentStatus] = DELETE_ONLY + - columnFeaturedInIndex(*scpb.Column, scpb.Element)($column, $temp-index) - $column-target[Type] = '*scpb.Target' - $column-target[Element] = $column - $column-node[Type] = '*screl.Node' - $column-node[Target] = $column-target - - $index-target[Type] = '*scpb.Target' - - $index-target[Element] = $index - - $index-node[Type] = '*screl.Node' - - $index-node[Target] = $index-target + - $temp-index-target[Type] = '*scpb.Target' + - $temp-index-target[Element] = $temp-index + - $temp-index-node[Type] = '*screl.Node' + - $temp-index-node[Target] = $temp-index-target + - $column[DescID] = $var-to-tell-rel-from-is-an-element + - $temp-index[DescID] = $var-to-tell-rel-to-is-an-element - name: ensure columns are in increasing order - from: laterColumn-node + from: later-column-node kind: SameStagePrecedence - to: earlierColumn-node - query: + to: earlier-column-node + query: + - $later-column[Type] = '*scpb.Column' + - $earlier-column[Type] = '*scpb.Column' + - $later-column[DescID] = $table-id + - $earlier-column[DescID] = $table-id + - $later-column-target[TargetStatus] = PUBLIC + - $earlier-column-target[TargetStatus] = PUBLIC - $status IN [WRITE_ONLY, PUBLIC] - - $target-status = PUBLIC - - $laterColumn[Type] = '*scpb.Column' - - $earlierColumn[Type] = '*scpb.Column' - - $laterColumn[DescID] = $table-id - - $earlierColumn[DescID] = $table-id - - column-later-column-is-greater(*scpb.Column, *scpb.Column)($laterColumn, $earlierColumn) - - $laterColumn-target[TargetStatus] = $target-status - - $earlierColumn-target[TargetStatus] = $target-status - - $laterColumn-node[CurrentStatus] = $status - - $earlierColumn-node[CurrentStatus] = $status - - $laterColumn-target[Type] = '*scpb.Target' - - $laterColumn-target[Element] = $laterColumn - - $laterColumn-node[Type] = '*screl.Node' - - $laterColumn-node[Target] = $laterColumn-target - - $earlierColumn-target[Type] = '*scpb.Target' - - $earlierColumn-target[Element] = $earlierColumn - - $earlierColumn-node[Type] = '*screl.Node' - - $earlierColumn-node[Target] = $earlierColumn-target + - $later-column-node[CurrentStatus] = $status + - $earlier-column-node[CurrentStatus] = $status + - columnHasSmallerID(*scpb.Column, *scpb.Column)($later-column, $earlier-column) + - $later-column-target[Type] = '*scpb.Target' + - $later-column-target[Element] = $later-column + - $later-column-node[Type] = '*screl.Node' + - $later-column-node[Target] = $later-column-target + - $earlier-column-target[Type] = '*scpb.Target' + - $earlier-column-target[Element] = $earlier-column + - $earlier-column-node[Type] = '*screl.Node' + - $earlier-column-node[Target] = $earlier-column-target + - $later-column[DescID] = $var-to-tell-rel-from-is-an-element + - $earlier-column[DescID] = $var-to-tell-rel-to-is-an-element diff --git a/pkg/storage/mvcc.go b/pkg/storage/mvcc.go index b9aea767c388..faaf4b8048c2 100644 --- a/pkg/storage/mvcc.go +++ b/pkg/storage/mvcc.go @@ -1453,7 +1453,7 @@ func mvccPutInternal( iter.SeekGE(oldVersionKey) if valid, err := iter.Valid(); err != nil { return err - } else if !valid && !iter.UnsafeKey().Equal(oldVersionKey) { + } else if !valid || !iter.UnsafeKey().Equal(oldVersionKey) { return errors.Errorf("existing intent value missing: %s", oldVersionKey) }