@@ -14,6 +14,7 @@ import (
14
14
"github.com/cockroachdb/cockroach/pkg/keys"
15
15
"github.com/cockroachdb/cockroach/pkg/roachpb"
16
16
"github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb"
17
+ "github.com/cockroachdb/cockroach/pkg/testutils"
17
18
"github.com/cockroachdb/cockroach/pkg/util/hlc"
18
19
"github.com/cockroachdb/cockroach/pkg/util/leaktest"
19
20
"github.com/cockroachdb/cockroach/pkg/util/log"
@@ -33,7 +34,7 @@ func TestAggregatorFrontier(t *testing.T) {
33
34
f , err := resolvedspan .NewAggregatorFrontier (
34
35
statementTime ,
35
36
initialHighwater ,
36
- mockDecoder {},
37
+ mockCodec {},
37
38
false , /* perTableTracking */
38
39
makeSpan ("a" , "f" ),
39
40
)
@@ -79,7 +80,7 @@ func TestAggregatorFrontier(t *testing.T) {
79
80
f , err = resolvedspan .NewAggregatorFrontier (
80
81
statementTime ,
81
82
initialHighwater ,
82
- mockDecoder {},
83
+ mockCodec {},
83
84
false , /* perTableTracking */
84
85
makeSpan ("a" , "f" ),
85
86
)
@@ -105,7 +106,7 @@ func TestCoordinatorFrontier(t *testing.T) {
105
106
f , err := resolvedspan .NewCoordinatorFrontier (
106
107
statementTime ,
107
108
initialHighwater ,
108
- mockDecoder {},
109
+ mockCodec {},
109
110
false , /* perTableTracking */
110
111
makeSpan ("a" , "f" ),
111
112
)
@@ -154,7 +155,7 @@ func TestCoordinatorFrontier(t *testing.T) {
154
155
f , err = resolvedspan .NewCoordinatorFrontier (
155
156
statementTime ,
156
157
initialHighwater ,
157
- mockDecoder {},
158
+ mockCodec {},
158
159
false , /* perTableTracking */
159
160
makeSpan ("a" , "f" ),
160
161
)
@@ -264,7 +265,7 @@ func TestAggregatorFrontier_ForwardResolvedSpan(t *testing.T) {
264
265
f , err := resolvedspan .NewAggregatorFrontier (
265
266
hlc.Timestamp {},
266
267
hlc.Timestamp {},
267
- mockDecoder {},
268
+ mockCodec {},
268
269
false , /* perTableTracking */
269
270
makeSpan ("a" , "f" ),
270
271
)
@@ -308,14 +309,28 @@ func TestAggregatorFrontier_ForwardResolvedSpan(t *testing.T) {
308
309
})
309
310
}
310
311
311
- // mockDecoder is a simple TablePrefixDecoder for testing
312
+ // mockCodec is a simple TableCodec for testing
312
313
// that treats all keys as table ID 1.
313
- type mockDecoder struct {}
314
+ type mockCodec struct {}
314
315
315
- func (mockDecoder ) DecodeTablePrefix (key roachpb.Key ) ([]byte , uint32 , error ) {
316
+ var _ resolvedspan.TableCodec = mockCodec {}
317
+
318
+ // DecodeTablePrefix implements TableCodec.
319
+ func (mockCodec ) DecodeTablePrefix (key roachpb.Key ) ([]byte , uint32 , error ) {
316
320
return key , 1 , nil
317
321
}
318
322
323
+ // TableSpan implements TableCodec.
324
+ func (mockCodec ) TableSpan (tableID uint32 ) roachpb.Span {
325
+ if tableID == 1 {
326
+ // Since the mock codec treats all keys as belonging to table ID 1,
327
+ // we return the everything span so that all keys will be considered
328
+ // a part of the table.
329
+ return keys .EverythingSpan
330
+ }
331
+ panic ("mock codec only handles table ID 1" )
332
+ }
333
+
319
334
func TestFrontierPerTableResolvedTimestamps (t * testing.T ) {
320
335
defer leaktest .AfterTest (t )()
321
336
defer log .Scope (t ).Close (t )
@@ -335,6 +350,10 @@ func TestFrontierPerTableResolvedTimestamps(t *testing.T) {
335
350
336
351
// Helper to create spans for tables.
337
352
tableSpan := func (tableID uint32 ) roachpb.Span {
353
+ // Randomly choose either the full table span or an index span.
354
+ if rnd .Float64 () < 0.5 {
355
+ return codec .TableSpan (tableID )
356
+ }
338
357
prefix := codec .IndexPrefix (tableID , 1 /* indexID */ )
339
358
return roachpb.Span {
340
359
Key : prefix ,
@@ -432,3 +451,82 @@ func TestFrontierPerTableResolvedTimestamps(t *testing.T) {
432
451
})
433
452
}
434
453
}
454
+
455
+ func TestFrontierForwardFullTableSpan (t * testing.T ) {
456
+ defer leaktest .AfterTest (t )()
457
+ defer log .Scope (t ).Close (t )
458
+
459
+ testutils .RunValues (t , "frontier type" , []string {"aggregator" , "coordinator" },
460
+ func (t * testing.T , frontierType string ) {
461
+ rnd , _ := randutil .NewPseudoRand ()
462
+
463
+ // Randomly use either the system codec or a tenant codec.
464
+ codec := func () keys.SQLCodec {
465
+ if rnd .Float64 () < 0.5 {
466
+ tenantID := roachpb .MustMakeTenantID (uint64 (1 + rnd .Intn (10 )))
467
+ return keys .MakeSQLCodec (tenantID )
468
+ }
469
+ return keys .SystemSQLCodec
470
+ }()
471
+
472
+ key := func (base roachpb.Key , suffix string ) roachpb.Key {
473
+ result := make ([]byte , len (base )+ len (suffix ))
474
+ copy (result , base )
475
+ copy (result [len (base ):], suffix )
476
+ return result
477
+ }
478
+
479
+ // Create spans for tables 109 and 110.
480
+ // These table IDs were specifically chosen because 109->110
481
+ // is the boundary for when table IDs go from single-byte to
482
+ // multi-byte encodings.
483
+ table109Span := codec .TableSpan (109 )
484
+ table110Span := codec .TableSpan (110 )
485
+ require .True (t , len (table110Span .Key ) == len (table109Span .Key )+ 1 )
486
+
487
+ // Create several subspans within each table.
488
+ tableSpans := []roachpb.Span {
489
+ {Key : key (table109Span .Key , "a" ), EndKey : key (table109Span .Key , "c" )},
490
+ {Key : key (table109Span .Key , "e" ), EndKey : key (table109Span .Key , "g" )},
491
+ {Key : key (table110Span .Key , "b" ), EndKey : key (table110Span .Key , "d" )},
492
+ {Key : key (table110Span .Key , "f" ), EndKey : key (table110Span .Key , "k" )},
493
+ }
494
+
495
+ statementTime := makeTS (5 )
496
+ var initialHighWater hlc.Timestamp
497
+
498
+ f , err := func () (span.Frontier , error ) {
499
+ switch frontierType {
500
+ case "aggregator" :
501
+ return resolvedspan .NewAggregatorFrontier (
502
+ statementTime ,
503
+ initialHighWater ,
504
+ codec ,
505
+ true , /* perTableTracking */
506
+ tableSpans ... ,
507
+ )
508
+ case "coordinator" :
509
+ return resolvedspan .NewCoordinatorFrontier (
510
+ statementTime ,
511
+ initialHighWater ,
512
+ codec ,
513
+ true , /* perTableTracking */
514
+ tableSpans ... ,
515
+ )
516
+ default :
517
+ t .Fatalf ("unknown frontier type: %s" , frontierType )
518
+ }
519
+ panic ("unreachable" )
520
+ }()
521
+ require .NoError (t , err )
522
+ require .Equal (t , initialHighWater , f .Frontier ())
523
+
524
+ // Forward both tables to timestamp 20.
525
+ targetTimestamp := makeTS (20 )
526
+ for _ , tableSpan := range []roachpb.Span {table109Span , table110Span } {
527
+ _ , err := f .Forward (tableSpan , targetTimestamp )
528
+ require .NoError (t , err )
529
+ }
530
+ require .Equal (t , targetTimestamp , f .Frontier ())
531
+ })
532
+ }
0 commit comments