Skip to content

Commit 22e79b6

Browse files
committed
schemachanger/scplan: add deprules to eval zone cfgs in seqNum order
This patch adds deprules to ensure that zone configs are depended by each other in increasing`seqNum` order. Epic: none Fixes: #129482 Release note: None
1 parent f2906ea commit 22e79b6

File tree

4 files changed

+303
-0
lines changed

4 files changed

+303
-0
lines changed

pkg/sql/schemachanger/scplan/internal/rules/current/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ go_library(
1010
"dep_add_index_and_constraint.go",
1111
"dep_add_trigger.go",
1212
"dep_alter_column_type.go",
13+
"dep_configure_zone.go",
1314
"dep_create.go",
1415
"dep_create_function.go",
1516
"dep_create_policy.go",
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// Copyright 2025 The Cockroach Authors.
2+
//
3+
// Use of this software is governed by the CockroachDB Software License
4+
// included in the /LICENSE file.
5+
6+
package current
7+
8+
import (
9+
"github.com/cockroachdb/cockroach/pkg/sql/schemachanger/rel"
10+
"github.com/cockroachdb/cockroach/pkg/sql/schemachanger/scpb"
11+
. "github.com/cockroachdb/cockroach/pkg/sql/schemachanger/scplan/internal/rules"
12+
"github.com/cockroachdb/cockroach/pkg/sql/schemachanger/scplan/internal/scgraph"
13+
"github.com/cockroachdb/cockroach/pkg/sql/schemachanger/screl"
14+
)
15+
16+
// The following set of rules ensure that zone configs depend on each other in
17+
// increasing seqNum order.
18+
19+
func init() {
20+
// Table zone configs
21+
registerDepRule(
22+
"ensure table zone configs are in increasing seqNum order",
23+
scgraph.Precedence,
24+
"later-seqNum", "earlier-seqNum",
25+
func(from, to NodeVars) rel.Clauses {
26+
status := rel.Var("status")
27+
return rel.Clauses{
28+
from.Type((*scpb.TableZoneConfig)(nil)),
29+
from.JoinTargetNode(),
30+
to.Type((*scpb.TableZoneConfig)(nil)),
31+
// Join on the target ID to ensure we're only comparing zone configs
32+
// for the same object (database, table, index, etc.)
33+
JoinOnDescID(from, to, "seqnum"),
34+
ToPublicOrTransient(from, to),
35+
status.Entities(screl.CurrentStatus, from.Node, to.Node),
36+
FilterElements("SmallerSeqNumFirst", from, to, func(from, to *scpb.TableZoneConfig) bool {
37+
return from.SeqNum < to.SeqNum
38+
}),
39+
}
40+
})
41+
42+
// Database zone configs
43+
registerDepRule(
44+
"ensure database zone configs are in increasing seqNum order",
45+
scgraph.Precedence,
46+
"later-seqNum", "earlier-seqNum",
47+
func(from, to NodeVars) rel.Clauses {
48+
status := rel.Var("status")
49+
return rel.Clauses{
50+
from.Type((*scpb.DatabaseZoneConfig)(nil)),
51+
from.JoinTargetNode(),
52+
to.Type((*scpb.DatabaseZoneConfig)(nil)),
53+
JoinOnDescID(from, to, "seqnum"),
54+
ToPublicOrTransient(from, to),
55+
status.Entities(screl.CurrentStatus, from.Node, to.Node),
56+
FilterElements("SmallerSeqNumFirst", from, to, func(from, to *scpb.DatabaseZoneConfig) bool {
57+
return from.SeqNum < to.SeqNum
58+
}),
59+
}
60+
})
61+
62+
// Named range zone configs
63+
registerDepRule(
64+
"ensure named range zone configs are in increasing seqNum order",
65+
scgraph.Precedence,
66+
"later-seqNum", "earlier-seqNum",
67+
func(from, to NodeVars) rel.Clauses {
68+
status := rel.Var("status")
69+
return rel.Clauses{
70+
from.Type((*scpb.NamedRangeZoneConfig)(nil)),
71+
from.JoinTargetNode(),
72+
to.Type((*scpb.NamedRangeZoneConfig)(nil)),
73+
JoinOnDescID(from, to, "seqnum"),
74+
ToPublicOrTransient(from, to),
75+
status.Entities(screl.CurrentStatus, from.Node, to.Node),
76+
FilterElements("SmallerSeqNumFirst", from, to, func(from, to *scpb.NamedRangeZoneConfig) bool {
77+
return from.SeqNum < to.SeqNum
78+
}),
79+
}
80+
})
81+
82+
// Index zone configs
83+
registerDepRule(
84+
"ensure index zone configs are in increasing seqNum order",
85+
scgraph.Precedence,
86+
"later-seqNum", "earlier-seqNum",
87+
func(from, to NodeVars) rel.Clauses {
88+
status := rel.Var("status")
89+
return rel.Clauses{
90+
from.Type((*scpb.IndexZoneConfig)(nil)),
91+
from.JoinTargetNode(),
92+
to.Type((*scpb.IndexZoneConfig)(nil)),
93+
JoinOnDescID(from, to, "seqnum"),
94+
// Join on index ID to ensure we're only comparing zone configs
95+
// for the same index
96+
JoinOnIndexID(from, to, "table-id", "index-id"),
97+
ToPublicOrTransient(from, to),
98+
status.Entities(screl.CurrentStatus, from.Node, to.Node),
99+
FilterElements("SmallerSeqNumFirst", from, to, func(from, to *scpb.IndexZoneConfig) bool {
100+
return from.SeqNum < to.SeqNum
101+
}),
102+
}
103+
})
104+
105+
// Partition zone configs
106+
registerDepRule(
107+
"ensure partition zone configs are in increasing seqNum order",
108+
scgraph.Precedence,
109+
"later-seqNum", "earlier-seqNum",
110+
func(from, to NodeVars) rel.Clauses {
111+
status := rel.Var("status")
112+
return rel.Clauses{
113+
from.Type((*scpb.PartitionZoneConfig)(nil)),
114+
from.JoinTargetNode(),
115+
to.Type((*scpb.PartitionZoneConfig)(nil)),
116+
JoinOnDescID(from, to, "seqnum"),
117+
// Join on index ID and partition name to ensure we're only comparing
118+
// zone configs for the same partition
119+
JoinOnIndexID(from, to, "table-id", "index-id"),
120+
JoinOnPartitionName(from, to, "table-id", "index-id", "partition-name"),
121+
ToPublicOrTransient(from, to),
122+
status.Entities(screl.CurrentStatus, from.Node, to.Node),
123+
FilterElements("SmallerSeqNumFirst", from, to, func(from, to *scpb.PartitionZoneConfig) bool {
124+
return from.SeqNum < to.SeqNum
125+
}),
126+
}
127+
})
128+
}

pkg/sql/schemachanger/scplan/internal/rules/current/testdata/deprules

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3479,6 +3479,84 @@ deprules
34793479
- SmallerColumnIDFirst(*scpb.Column, *scpb.Column)($later-column, $earlier-column)
34803480
- joinTargetNode($later-column, $later-column-Target, $later-column-Node)
34813481
- joinTargetNode($earlier-column, $earlier-column-Target, $earlier-column-Node)
3482+
- name: ensure database zone configs are in increasing seqNum order
3483+
from: later-seqNum-Node
3484+
kind: Precedence
3485+
to: earlier-seqNum-Node
3486+
query:
3487+
- $later-seqNum[Type] = '*scpb.DatabaseZoneConfig'
3488+
- joinTargetNode($later-seqNum, $later-seqNum-Target, $later-seqNum-Node)
3489+
- $earlier-seqNum[Type] = '*scpb.DatabaseZoneConfig'
3490+
- joinOnDescID($later-seqNum, $earlier-seqNum, $seqnum)
3491+
- ToPublicOrTransient($later-seqNum-Target, $earlier-seqNum-Target)
3492+
- $later-seqNum-Node[CurrentStatus] = $status
3493+
- $earlier-seqNum-Node[CurrentStatus] = $status
3494+
- SmallerSeqNumFirst(*scpb.DatabaseZoneConfig, *scpb.DatabaseZoneConfig)($later-seqNum, $earlier-seqNum)
3495+
- joinTargetNode($later-seqNum, $later-seqNum-Target, $later-seqNum-Node)
3496+
- joinTargetNode($earlier-seqNum, $earlier-seqNum-Target, $earlier-seqNum-Node)
3497+
- name: ensure index zone configs are in increasing seqNum order
3498+
from: later-seqNum-Node
3499+
kind: Precedence
3500+
to: earlier-seqNum-Node
3501+
query:
3502+
- $later-seqNum[Type] = '*scpb.IndexZoneConfig'
3503+
- joinTargetNode($later-seqNum, $later-seqNum-Target, $later-seqNum-Node)
3504+
- $earlier-seqNum[Type] = '*scpb.IndexZoneConfig'
3505+
- joinOnDescID($later-seqNum, $earlier-seqNum, $seqnum)
3506+
- joinOnIndexID($later-seqNum, $earlier-seqNum, $table-id, $index-id)
3507+
- ToPublicOrTransient($later-seqNum-Target, $earlier-seqNum-Target)
3508+
- $later-seqNum-Node[CurrentStatus] = $status
3509+
- $earlier-seqNum-Node[CurrentStatus] = $status
3510+
- SmallerSeqNumFirst(*scpb.IndexZoneConfig, *scpb.IndexZoneConfig)($later-seqNum, $earlier-seqNum)
3511+
- joinTargetNode($later-seqNum, $later-seqNum-Target, $later-seqNum-Node)
3512+
- joinTargetNode($earlier-seqNum, $earlier-seqNum-Target, $earlier-seqNum-Node)
3513+
- name: ensure named range zone configs are in increasing seqNum order
3514+
from: later-seqNum-Node
3515+
kind: Precedence
3516+
to: earlier-seqNum-Node
3517+
query:
3518+
- $later-seqNum[Type] = '*scpb.NamedRangeZoneConfig'
3519+
- joinTargetNode($later-seqNum, $later-seqNum-Target, $later-seqNum-Node)
3520+
- $earlier-seqNum[Type] = '*scpb.NamedRangeZoneConfig'
3521+
- joinOnDescID($later-seqNum, $earlier-seqNum, $seqnum)
3522+
- ToPublicOrTransient($later-seqNum-Target, $earlier-seqNum-Target)
3523+
- $later-seqNum-Node[CurrentStatus] = $status
3524+
- $earlier-seqNum-Node[CurrentStatus] = $status
3525+
- SmallerSeqNumFirst(*scpb.NamedRangeZoneConfig, *scpb.NamedRangeZoneConfig)($later-seqNum, $earlier-seqNum)
3526+
- joinTargetNode($later-seqNum, $later-seqNum-Target, $later-seqNum-Node)
3527+
- joinTargetNode($earlier-seqNum, $earlier-seqNum-Target, $earlier-seqNum-Node)
3528+
- name: ensure partition zone configs are in increasing seqNum order
3529+
from: later-seqNum-Node
3530+
kind: Precedence
3531+
to: earlier-seqNum-Node
3532+
query:
3533+
- $later-seqNum[Type] = '*scpb.PartitionZoneConfig'
3534+
- joinTargetNode($later-seqNum, $later-seqNum-Target, $later-seqNum-Node)
3535+
- $earlier-seqNum[Type] = '*scpb.PartitionZoneConfig'
3536+
- joinOnDescID($later-seqNum, $earlier-seqNum, $seqnum)
3537+
- joinOnIndexID($later-seqNum, $earlier-seqNum, $table-id, $index-id)
3538+
- joinOnPartitionName($later-seqNum, $earlier-seqNum, $table-id, $index-id, $partition-name)
3539+
- ToPublicOrTransient($later-seqNum-Target, $earlier-seqNum-Target)
3540+
- $later-seqNum-Node[CurrentStatus] = $status
3541+
- $earlier-seqNum-Node[CurrentStatus] = $status
3542+
- SmallerSeqNumFirst(*scpb.PartitionZoneConfig, *scpb.PartitionZoneConfig)($later-seqNum, $earlier-seqNum)
3543+
- joinTargetNode($later-seqNum, $later-seqNum-Target, $later-seqNum-Node)
3544+
- joinTargetNode($earlier-seqNum, $earlier-seqNum-Target, $earlier-seqNum-Node)
3545+
- name: ensure table zone configs are in increasing seqNum order
3546+
from: later-seqNum-Node
3547+
kind: Precedence
3548+
to: earlier-seqNum-Node
3549+
query:
3550+
- $later-seqNum[Type] = '*scpb.TableZoneConfig'
3551+
- joinTargetNode($later-seqNum, $later-seqNum-Target, $later-seqNum-Node)
3552+
- $earlier-seqNum[Type] = '*scpb.TableZoneConfig'
3553+
- joinOnDescID($later-seqNum, $earlier-seqNum, $seqnum)
3554+
- ToPublicOrTransient($later-seqNum-Target, $earlier-seqNum-Target)
3555+
- $later-seqNum-Node[CurrentStatus] = $status
3556+
- $earlier-seqNum-Node[CurrentStatus] = $status
3557+
- SmallerSeqNumFirst(*scpb.TableZoneConfig, *scpb.TableZoneConfig)($later-seqNum, $earlier-seqNum)
3558+
- joinTargetNode($later-seqNum, $later-seqNum-Target, $later-seqNum-Node)
3559+
- joinTargetNode($earlier-seqNum, $earlier-seqNum-Target, $earlier-seqNum-Node)
34823560
- name: function name should be set before parent ids
34833561
from: function-name-Node
34843562
kind: Precedence
@@ -8150,6 +8228,84 @@ deprules
81508228
- SmallerColumnIDFirst(*scpb.Column, *scpb.Column)($later-column, $earlier-column)
81518229
- joinTargetNode($later-column, $later-column-Target, $later-column-Node)
81528230
- joinTargetNode($earlier-column, $earlier-column-Target, $earlier-column-Node)
8231+
- name: ensure database zone configs are in increasing seqNum order
8232+
from: later-seqNum-Node
8233+
kind: Precedence
8234+
to: earlier-seqNum-Node
8235+
query:
8236+
- $later-seqNum[Type] = '*scpb.DatabaseZoneConfig'
8237+
- joinTargetNode($later-seqNum, $later-seqNum-Target, $later-seqNum-Node)
8238+
- $earlier-seqNum[Type] = '*scpb.DatabaseZoneConfig'
8239+
- joinOnDescID($later-seqNum, $earlier-seqNum, $seqnum)
8240+
- ToPublicOrTransient($later-seqNum-Target, $earlier-seqNum-Target)
8241+
- $later-seqNum-Node[CurrentStatus] = $status
8242+
- $earlier-seqNum-Node[CurrentStatus] = $status
8243+
- SmallerSeqNumFirst(*scpb.DatabaseZoneConfig, *scpb.DatabaseZoneConfig)($later-seqNum, $earlier-seqNum)
8244+
- joinTargetNode($later-seqNum, $later-seqNum-Target, $later-seqNum-Node)
8245+
- joinTargetNode($earlier-seqNum, $earlier-seqNum-Target, $earlier-seqNum-Node)
8246+
- name: ensure index zone configs are in increasing seqNum order
8247+
from: later-seqNum-Node
8248+
kind: Precedence
8249+
to: earlier-seqNum-Node
8250+
query:
8251+
- $later-seqNum[Type] = '*scpb.IndexZoneConfig'
8252+
- joinTargetNode($later-seqNum, $later-seqNum-Target, $later-seqNum-Node)
8253+
- $earlier-seqNum[Type] = '*scpb.IndexZoneConfig'
8254+
- joinOnDescID($later-seqNum, $earlier-seqNum, $seqnum)
8255+
- joinOnIndexID($later-seqNum, $earlier-seqNum, $table-id, $index-id)
8256+
- ToPublicOrTransient($later-seqNum-Target, $earlier-seqNum-Target)
8257+
- $later-seqNum-Node[CurrentStatus] = $status
8258+
- $earlier-seqNum-Node[CurrentStatus] = $status
8259+
- SmallerSeqNumFirst(*scpb.IndexZoneConfig, *scpb.IndexZoneConfig)($later-seqNum, $earlier-seqNum)
8260+
- joinTargetNode($later-seqNum, $later-seqNum-Target, $later-seqNum-Node)
8261+
- joinTargetNode($earlier-seqNum, $earlier-seqNum-Target, $earlier-seqNum-Node)
8262+
- name: ensure named range zone configs are in increasing seqNum order
8263+
from: later-seqNum-Node
8264+
kind: Precedence
8265+
to: earlier-seqNum-Node
8266+
query:
8267+
- $later-seqNum[Type] = '*scpb.NamedRangeZoneConfig'
8268+
- joinTargetNode($later-seqNum, $later-seqNum-Target, $later-seqNum-Node)
8269+
- $earlier-seqNum[Type] = '*scpb.NamedRangeZoneConfig'
8270+
- joinOnDescID($later-seqNum, $earlier-seqNum, $seqnum)
8271+
- ToPublicOrTransient($later-seqNum-Target, $earlier-seqNum-Target)
8272+
- $later-seqNum-Node[CurrentStatus] = $status
8273+
- $earlier-seqNum-Node[CurrentStatus] = $status
8274+
- SmallerSeqNumFirst(*scpb.NamedRangeZoneConfig, *scpb.NamedRangeZoneConfig)($later-seqNum, $earlier-seqNum)
8275+
- joinTargetNode($later-seqNum, $later-seqNum-Target, $later-seqNum-Node)
8276+
- joinTargetNode($earlier-seqNum, $earlier-seqNum-Target, $earlier-seqNum-Node)
8277+
- name: ensure partition zone configs are in increasing seqNum order
8278+
from: later-seqNum-Node
8279+
kind: Precedence
8280+
to: earlier-seqNum-Node
8281+
query:
8282+
- $later-seqNum[Type] = '*scpb.PartitionZoneConfig'
8283+
- joinTargetNode($later-seqNum, $later-seqNum-Target, $later-seqNum-Node)
8284+
- $earlier-seqNum[Type] = '*scpb.PartitionZoneConfig'
8285+
- joinOnDescID($later-seqNum, $earlier-seqNum, $seqnum)
8286+
- joinOnIndexID($later-seqNum, $earlier-seqNum, $table-id, $index-id)
8287+
- joinOnPartitionName($later-seqNum, $earlier-seqNum, $table-id, $index-id, $partition-name)
8288+
- ToPublicOrTransient($later-seqNum-Target, $earlier-seqNum-Target)
8289+
- $later-seqNum-Node[CurrentStatus] = $status
8290+
- $earlier-seqNum-Node[CurrentStatus] = $status
8291+
- SmallerSeqNumFirst(*scpb.PartitionZoneConfig, *scpb.PartitionZoneConfig)($later-seqNum, $earlier-seqNum)
8292+
- joinTargetNode($later-seqNum, $later-seqNum-Target, $later-seqNum-Node)
8293+
- joinTargetNode($earlier-seqNum, $earlier-seqNum-Target, $earlier-seqNum-Node)
8294+
- name: ensure table zone configs are in increasing seqNum order
8295+
from: later-seqNum-Node
8296+
kind: Precedence
8297+
to: earlier-seqNum-Node
8298+
query:
8299+
- $later-seqNum[Type] = '*scpb.TableZoneConfig'
8300+
- joinTargetNode($later-seqNum, $later-seqNum-Target, $later-seqNum-Node)
8301+
- $earlier-seqNum[Type] = '*scpb.TableZoneConfig'
8302+
- joinOnDescID($later-seqNum, $earlier-seqNum, $seqnum)
8303+
- ToPublicOrTransient($later-seqNum-Target, $earlier-seqNum-Target)
8304+
- $later-seqNum-Node[CurrentStatus] = $status
8305+
- $earlier-seqNum-Node[CurrentStatus] = $status
8306+
- SmallerSeqNumFirst(*scpb.TableZoneConfig, *scpb.TableZoneConfig)($later-seqNum, $earlier-seqNum)
8307+
- joinTargetNode($later-seqNum, $later-seqNum-Target, $later-seqNum-Node)
8308+
- joinTargetNode($earlier-seqNum, $earlier-seqNum-Target, $earlier-seqNum-Node)
81538309
- name: function name should be set before parent ids
81548310
from: function-name-Node
81558311
kind: Precedence

pkg/sql/schemachanger/scplan/internal/rules/helpers.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,13 @@ func JoinOnPolicyID(a, b NodeVars, relationIDVar, policyID rel.Var) rel.Clause {
134134
return joinOnPolicyIDUntyped(a.El, b.El, relationIDVar, policyID)
135135
}
136136

137+
// JoinOnPartitionName joins elements on partition name.
138+
func JoinOnPartitionName(
139+
a, b NodeVars, relationIDVar, indexIDVar, partitionNameVar rel.Var,
140+
) rel.Clause {
141+
return joinOnPartitionNameUntyped(a.El, b.El, relationIDVar, indexIDVar, partitionNameVar)
142+
}
143+
137144
// ColumnInIndex requires that a column exists within an index.
138145
func ColumnInIndex(
139146
indexColumn, index NodeVars, relationIDVar, columnIDVar, indexIDVar rel.Var,
@@ -344,6 +351,17 @@ var (
344351
}
345352
},
346353
)
354+
joinOnPartitionNameUntyped = screl.Schema.Def5(
355+
"joinOnPartitionName", "a", "b", "desc-id", "index-id", "partition-name", func(
356+
a, b, descID, indexID, partitionName rel.Var,
357+
) rel.Clauses {
358+
return rel.Clauses{
359+
JoinOnDescIDUntyped(a, b, descID),
360+
indexID.Entities(screl.IndexID, a, b),
361+
partitionName.Entities(screl.PartitionName, a, b),
362+
}
363+
},
364+
)
347365

348366
columnInIndexUntyped = screl.Schema.Def5(
349367
"ColumnInIndex",

0 commit comments

Comments
 (0)