Skip to content

Commit cada6b4

Browse files
craig[bot]annrpommgartnerandrewbaptist
committed
140167: sql: account for duplicate partition names in subzone span gen r=annrpom a=annrpom This patch fixes a bug during GenerateSubzoneSpans that does not correctly distinguish between partitions of the same name across indexes. The issue was introduced when we relaxed restrictions on partition name reuse across indexes of a table (#39332). Epic: [CRDB-43310](https://cockroachlabs.atlassian.net/browse/CRDB-43310) Fixes: #128692 Release note (bug fix): Configuring replication controls on a partition name of an index that is not unique across all indexes will correctly impact only that partition. 140218: sql: fix quoting of session settings in stmt bundle env.sql r=mgartner a=mgartner The values of session setting in the `env.sql` file of a statement bundle are now wrapped in single quotes if they contain whitespace. The statement bundle session setting tests have been updated to ensure that `env.sql` is parsable. Epic: None Release note: None 140244: storage: remove parameter from RegisterEngines r=RaduBerinde a=andrewbaptist Previously both the StoreSpec and the Engines were passed into RegisterEngines. With this change we get the directory directly from the Engine. Epic: none Release note: None Co-authored-by: Annie Pompa <[email protected]> Co-authored-by: Marcus Gartner <[email protected]> Co-authored-by: Andrew Baptist <[email protected]>
4 parents 281a25b + c308da0 + d75a19d + 4528fdc commit cada6b4

File tree

8 files changed

+77
-32
lines changed

8 files changed

+77
-32
lines changed

pkg/ccl/spanconfigccl/spanconfigsqltranslatorccl/testdata/partitions

+23
Original file line numberDiff line numberDiff line change
@@ -253,3 +253,26 @@ translate database=db table=part
253253
/Table/111/2/{51-60} range default
254254
/Table/111/2/6{0-1} num_replicas=11
255255
/Table/11{1/2/61-2} range default
256+
257+
exec-sql
258+
CREATE TABLE db.foo(i INT PRIMARY KEY, j INT) PARTITION BY LIST (i) (
259+
PARTITION p VALUES IN (1, 5)
260+
);
261+
CREATE INDEX idx ON db.foo(j) PARTITION BY LIST (j) (
262+
PARTITION p VALUES IN (2, 4)
263+
);
264+
ALTER PARTITION p OF INDEX db.foo@foo_pkey CONFIGURE ZONE USING gc.ttlseconds = 2;
265+
ALTER PARTITION p OF INDEX db.foo@idx CONFIGURE ZONE USING gc.ttlseconds = 5;
266+
----
267+
268+
translate database=db table=foo
269+
----
270+
/Table/112{-/1/1} range default
271+
/Table/112/1/{1-2} ttl_seconds=2
272+
/Table/112/1/{2-5} range default
273+
/Table/112/1/{5-6} ttl_seconds=2
274+
/Table/112/{1/6-2/2} range default
275+
/Table/112/2/{2-3} ttl_seconds=5
276+
/Table/112/2/{3-4} range default
277+
/Table/112/2/{4-5} ttl_seconds=5
278+
/Table/11{2/2/5-3} range default

pkg/server/debug/BUILD.bazel

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ go_library(
1212
importpath = "github.com/cockroachdb/cockroach/pkg/server/debug",
1313
visibility = ["//visibility:public"],
1414
deps = [
15-
"//pkg/base",
1615
"//pkg/base/serverident",
1716
"//pkg/kv/kvserver",
1817
"//pkg/kv/kvserver/closedts/sidetransport",

pkg/server/debug/server.go

+5-11
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import (
1414
"strconv"
1515
"strings"
1616

17-
"github.com/cockroachdb/cockroach/pkg/base"
1817
"github.com/cockroachdb/cockroach/pkg/base/serverident"
1918
"github.com/cockroachdb/cockroach/pkg/kv/kvserver"
2019
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/closedts/sidetransport"
@@ -251,12 +250,7 @@ func FormatLSMStats(stats map[roachpb.StoreID]string) string {
251250
}
252251

253252
// RegisterEngines setups up debug engine endpoints for the known storage engines.
254-
func (ds *Server) RegisterEngines(specs []base.StoreSpec, engines []storage.Engine) error {
255-
if len(specs) != len(engines) {
256-
// TODO(yevgeniy): Consider adding accessors to storage.Engine to get their path.
257-
return errors.New("number of store specs must match number of engines")
258-
}
259-
253+
func (ds *Server) RegisterEngines(engines []storage.Engine) error {
260254
ds.mux.HandleFunc("/debug/lsm", func(w http.ResponseWriter, req *http.Request) {
261255
stats, err := GetLSMStats(engines)
262256
if err != nil {
@@ -265,18 +259,18 @@ func (ds *Server) RegisterEngines(specs []base.StoreSpec, engines []storage.Engi
265259
fmt.Fprint(w, FormatLSMStats(stats))
266260
})
267261

268-
for i := 0; i < len(specs); i++ {
269-
if specs[i].InMemory {
262+
for _, eng := range engines {
263+
dir := eng.Env().Dir
264+
if dir == "" {
270265
// TODO(yevgeniy): Add plumbing to support LSM visualization for in memory engines.
271266
continue
272267
}
273268

274-
storeID, err := engines[i].GetStoreID()
269+
storeID, err := eng.GetStoreID()
275270
if err != nil {
276271
return err
277272
}
278273

279-
dir := specs[i].Path
280274
ds.mux.HandleFunc(fmt.Sprintf("/debug/lsm-viz/%d", storeID),
281275
func(w http.ResponseWriter, req *http.Request) {
282276
if err := analyzeLSM(dir, w); err != nil {

pkg/server/server.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -2103,7 +2103,7 @@ func (s *topLevelServer) PreStart(ctx context.Context) error {
21032103
}
21042104

21052105
// Register the engines debug endpoints.
2106-
if err := s.debug.RegisterEngines(s.cfg.Stores.Specs, s.engines); err != nil {
2106+
if err := s.debug.RegisterEngines(s.engines); err != nil {
21072107
return errors.Wrapf(err, "failed to register engines with debug server")
21082108
}
21092109

pkg/sql/explain_bundle.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,8 @@ func init() {
822822
binarySVForBundle = &st.SV
823823
}
824824

825+
var anyWhitespace = regexp.MustCompile(`\s+`)
826+
825827
// PrintSessionSettings appends information about all session variables that
826828
// differ from their defaults.
827829
//
@@ -900,7 +902,7 @@ func (c *stmtEnvCollector) PrintSessionSettings(w io.Writer, sv *settings.Values
900902
if skip && !all {
901903
continue
902904
}
903-
if _, ok := sessionVarNeedsEscaping[varName]; ok {
905+
if _, ok := sessionVarNeedsEscaping[varName]; ok || anyWhitespace.MatchString(value) {
904906
value = lexbase.EscapeSQLString(value)
905907
}
906908
if value == "" {

pkg/sql/explain_bundle_test.go

+5
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/cockroachdb/cockroach/pkg/kv"
2424
"github.com/cockroachdb/cockroach/pkg/kv/kvserver"
2525
"github.com/cockroachdb/cockroach/pkg/security/username"
26+
"github.com/cockroachdb/cockroach/pkg/sql/parser"
2627
"github.com/cockroachdb/cockroach/pkg/testutils"
2728
"github.com/cockroachdb/cockroach/pkg/testutils/pgtest"
2829
"github.com/cockroachdb/cockroach/pkg/testutils/serverutils"
@@ -222,6 +223,7 @@ CREATE TABLE users(id UUID DEFAULT gen_random_uuid() PRIMARY KEY, promo_id INT R
222223
{"testing_optimizer_random_seed", "123"},
223224
{"timezone", "+8"},
224225
{"unconstrained_non_covering_index_scan_enabled", "on"},
226+
{"default_transaction_isolation", "'read committed'"},
225227
}
226228
for _, tc := range testcases {
227229
t.Run(tc.sessionVar, func(t *testing.T) {
@@ -235,6 +237,9 @@ CREATE TABLE users(id UUID DEFAULT gen_random_uuid() PRIMARY KEY, promo_id INT R
235237
if reg.FindString(contents) == "" {
236238
return errors.Errorf("could not find 'SET %s' in env.sql", tc.sessionVar)
237239
}
240+
if _, err := parser.Parse(contents); err != nil {
241+
return errors.Wrap(err, "could not parse env.sql")
242+
}
238243
}
239244
return nil
240245
}, false, /* expectErrors */

pkg/sql/partition_utils.go

+20-9
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ import (
1818
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
1919
)
2020

21+
// partitionKey is used to group a partition's name and its index ID for
22+
// indexing into a map.
23+
type partitionKey struct {
24+
indexID descpb.IndexID
25+
name string
26+
}
27+
2128
// GenerateSubzoneSpans constructs from a TableDescriptor the entries mapping
2229
// zone config spans to subzones for use in the SubzoneSpans field of
2330
// zonepb.ZoneConfig. SubzoneSpans controls which splits are created, so only
@@ -76,10 +83,11 @@ func GenerateSubzoneSpans(
7683
a := &tree.DatumAlloc{}
7784

7885
subzoneIndexByIndexID := make(map[descpb.IndexID]int32)
79-
subzoneIndexByPartition := make(map[string]int32)
86+
subzoneIndexByPartition := make(map[partitionKey]int32)
8087
for i, subzone := range subzones {
8188
if len(subzone.PartitionName) > 0 {
82-
subzoneIndexByPartition[subzone.PartitionName] = int32(i)
89+
partKey := partitionKey{indexID: descpb.IndexID(subzone.IndexID), name: subzone.PartitionName}
90+
subzoneIndexByPartition[partKey] = int32(i)
8391
} else {
8492
subzoneIndexByIndexID[descpb.IndexID(subzone.IndexID)] = int32(i)
8593
}
@@ -140,7 +148,8 @@ func GenerateSubzoneSpans(
140148
}
141149
var ok bool
142150
if subzone := payloads[0].(zonepb.Subzone); len(subzone.PartitionName) > 0 {
143-
subzoneSpan.SubzoneIndex, ok = subzoneIndexByPartition[subzone.PartitionName]
151+
partKey := partitionKey{indexID: descpb.IndexID(subzone.IndexID), name: subzone.PartitionName}
152+
subzoneSpan.SubzoneIndex, ok = subzoneIndexByPartition[partKey]
144153
} else {
145154
subzoneSpan.SubzoneIndex, ok = subzoneIndexByIndexID[descpb.IndexID(subzone.IndexID)]
146155
}
@@ -165,7 +174,7 @@ func indexCoveringsForPartitioning(
165174
tableDesc catalog.TableDescriptor,
166175
idx catalog.Index,
167176
part catalog.Partitioning,
168-
relevantPartitions map[string]int32,
177+
relevantPartitions map[partitionKey]int32,
169178
prefixDatums []tree.Datum,
170179
) ([]covering.Covering, error) {
171180
if part.NumColumns() == 0 {
@@ -191,10 +200,11 @@ func indexCoveringsForPartitioning(
191200
if err != nil {
192201
return err
193202
}
194-
if _, ok := relevantPartitions[name]; ok {
203+
partKey := partitionKey{indexID: idx.GetID(), name: name}
204+
if _, ok := relevantPartitions[partKey]; ok {
195205
listCoverings[len(t.Datums)] = append(listCoverings[len(t.Datums)], covering.Range{
196206
Start: keyPrefix, End: roachpb.Key(keyPrefix).PrefixEnd(),
197-
Payload: zonepb.Subzone{PartitionName: name},
207+
Payload: zonepb.Subzone{IndexID: uint32(idx.GetID()), PartitionName: name},
198208
})
199209
}
200210
newPrefixDatums := append(prefixDatums, t.Datums...)
@@ -219,7 +229,8 @@ func indexCoveringsForPartitioning(
219229

220230
if part.NumRanges() > 0 {
221231
err := part.ForEachRange(func(name string, from, to []byte) error {
222-
if _, ok := relevantPartitions[name]; !ok {
232+
partKey := partitionKey{indexID: idx.GetID(), name: name}
233+
if _, ok := relevantPartitions[partKey]; !ok {
223234
return nil
224235
}
225236
_, fromKey, err := rowenc.DecodePartitionTuple(
@@ -232,10 +243,10 @@ func indexCoveringsForPartitioning(
232243
if err != nil {
233244
return err
234245
}
235-
if _, ok := relevantPartitions[name]; ok {
246+
if _, ok := relevantPartitions[partKey]; ok {
236247
coverings = append(coverings, covering.Covering{{
237248
Start: fromKey, End: toKey,
238-
Payload: zonepb.Subzone{PartitionName: name},
249+
Payload: zonepb.Subzone{IndexID: uint32(idx.GetID()), PartitionName: name},
239250
}})
240251
}
241252
return nil

pkg/sql/schemachanger/scbuild/internal/scbuildstmt/zone_config_helpers.go

+20-9
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,13 @@ func accumulateNewUniqueConstraints(currentZone, newZone *zonepb.ZoneConfig) []z
710710
return retConstraints
711711
}
712712

713+
// partitionKey is used to group a partition's name and its index ID for
714+
// indexing into a map.
715+
type partitionKey struct {
716+
indexID descpb.IndexID
717+
name string
718+
}
719+
713720
// generateSubzoneSpans constructs from a TableID the entries mapping
714721
// zone config spans to subzones for use in the SubzoneSpans field of
715722
// zonepb.ZoneConfig. SubzoneSpans controls which splits are created, so only
@@ -764,10 +771,11 @@ func generateSubzoneSpans(
764771
}
765772

766773
subzoneIndexByIndexID := make(map[descpb.IndexID]int32)
767-
subzoneIndexByPartition := make(map[string]int32)
774+
subzoneIndexByPartition := make(map[partitionKey]int32)
768775
for i, subzone := range subzones {
769776
if len(subzone.PartitionName) > 0 {
770-
subzoneIndexByPartition[subzone.PartitionName] = int32(i)
777+
partKey := partitionKey{indexID: descpb.IndexID(subzone.IndexID), name: subzone.PartitionName}
778+
subzoneIndexByPartition[partKey] = int32(i)
771779
} else {
772780
subzoneIndexByIndexID[descpb.IndexID(subzone.IndexID)] = int32(i)
773781
}
@@ -827,7 +835,8 @@ func generateSubzoneSpans(
827835
}
828836
var ok bool
829837
if subzone := payloads[0].(zonepb.Subzone); len(subzone.PartitionName) > 0 {
830-
subzoneSpan.SubzoneIndex, ok = subzoneIndexByPartition[subzone.PartitionName]
838+
partKey := partitionKey{indexID: descpb.IndexID(subzone.IndexID), name: subzone.PartitionName}
839+
subzoneSpan.SubzoneIndex, ok = subzoneIndexByPartition[partKey]
831840
} else {
832841
subzoneSpan.SubzoneIndex, ok = subzoneIndexByIndexID[descpb.IndexID(subzone.IndexID)]
833842
}
@@ -853,7 +862,7 @@ func indexCoveringsForPartitioning(
853862
indexID catid.IndexID,
854863
index []*scpb.IndexColumn,
855864
part catalog.Partitioning,
856-
relevantPartitions map[string]int32,
865+
relevantPartitions map[partitionKey]int32,
857866
prefixDatums []tree.Datum,
858867
) ([]covering.Covering, error) {
859868
if part.NumColumns() == 0 {
@@ -879,10 +888,11 @@ func indexCoveringsForPartitioning(
879888
if err != nil {
880889
return err
881890
}
882-
if _, ok := relevantPartitions[name]; ok {
891+
partKey := partitionKey{indexID: indexID, name: name}
892+
if _, ok := relevantPartitions[partKey]; ok {
883893
listCoverings[len(t.Datums)] = append(listCoverings[len(t.Datums)], covering.Range{
884894
Start: keyPrefix, End: roachpb.Key(keyPrefix).PrefixEnd(),
885-
Payload: zonepb.Subzone{PartitionName: name},
895+
Payload: zonepb.Subzone{IndexID: uint32(indexID), PartitionName: name},
886896
})
887897
}
888898
newPrefixDatums := append(prefixDatums, t.Datums...)
@@ -907,7 +917,8 @@ func indexCoveringsForPartitioning(
907917

908918
if part.NumRanges() > 0 {
909919
err := part.ForEachRange(func(name string, from, to []byte) error {
910-
if _, ok := relevantPartitions[name]; !ok {
920+
partKey := partitionKey{indexID: indexID, name: name}
921+
if _, ok := relevantPartitions[partKey]; !ok {
911922
return nil
912923
}
913924
_, fromKey, err := decodePartitionTuple(
@@ -920,10 +931,10 @@ func indexCoveringsForPartitioning(
920931
if err != nil {
921932
return err
922933
}
923-
if _, ok := relevantPartitions[name]; ok {
934+
if _, ok := relevantPartitions[partKey]; ok {
924935
coverings = append(coverings, covering.Covering{{
925936
Start: fromKey, End: toKey,
926-
Payload: zonepb.Subzone{PartitionName: name},
937+
Payload: zonepb.Subzone{IndexID: uint32(indexID), PartitionName: name},
927938
}})
928939
}
929940
return nil

0 commit comments

Comments
 (0)