@@ -14,6 +14,7 @@ import (
1414 "github.com/cockroachdb/cockroach/pkg/keys"
1515 "github.com/cockroachdb/cockroach/pkg/roachpb"
1616 "github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb"
17+ "github.com/cockroachdb/cockroach/pkg/testutils"
1718 "github.com/cockroachdb/cockroach/pkg/util/hlc"
1819 "github.com/cockroachdb/cockroach/pkg/util/leaktest"
1920 "github.com/cockroachdb/cockroach/pkg/util/log"
@@ -33,7 +34,7 @@ func TestAggregatorFrontier(t *testing.T) {
3334 f , err := resolvedspan .NewAggregatorFrontier (
3435 statementTime ,
3536 initialHighwater ,
36- mockDecoder {},
37+ mockCodec {},
3738 false , /* perTableTracking */
3839 makeSpan ("a" , "f" ),
3940 )
@@ -79,7 +80,7 @@ func TestAggregatorFrontier(t *testing.T) {
7980 f , err = resolvedspan .NewAggregatorFrontier (
8081 statementTime ,
8182 initialHighwater ,
82- mockDecoder {},
83+ mockCodec {},
8384 false , /* perTableTracking */
8485 makeSpan ("a" , "f" ),
8586 )
@@ -105,7 +106,7 @@ func TestCoordinatorFrontier(t *testing.T) {
105106 f , err := resolvedspan .NewCoordinatorFrontier (
106107 statementTime ,
107108 initialHighwater ,
108- mockDecoder {},
109+ mockCodec {},
109110 false , /* perTableTracking */
110111 makeSpan ("a" , "f" ),
111112 )
@@ -154,7 +155,7 @@ func TestCoordinatorFrontier(t *testing.T) {
154155 f , err = resolvedspan .NewCoordinatorFrontier (
155156 statementTime ,
156157 initialHighwater ,
157- mockDecoder {},
158+ mockCodec {},
158159 false , /* perTableTracking */
159160 makeSpan ("a" , "f" ),
160161 )
@@ -264,7 +265,7 @@ func TestAggregatorFrontier_ForwardResolvedSpan(t *testing.T) {
264265 f , err := resolvedspan .NewAggregatorFrontier (
265266 hlc.Timestamp {},
266267 hlc.Timestamp {},
267- mockDecoder {},
268+ mockCodec {},
268269 false , /* perTableTracking */
269270 makeSpan ("a" , "f" ),
270271 )
@@ -308,14 +309,28 @@ func TestAggregatorFrontier_ForwardResolvedSpan(t *testing.T) {
308309 })
309310}
310311
311- // mockDecoder is a simple TablePrefixDecoder for testing
312+ // mockCodec is a simple TableCodec for testing
312313// that treats all keys as table ID 1.
313- type mockDecoder struct {}
314+ type mockCodec struct {}
314315
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 ) {
316320 return key , 1 , nil
317321}
318322
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+
319334func TestFrontierPerTableResolvedTimestamps (t * testing.T ) {
320335 defer leaktest .AfterTest (t )()
321336 defer log .Scope (t ).Close (t )
@@ -335,6 +350,10 @@ func TestFrontierPerTableResolvedTimestamps(t *testing.T) {
335350
336351 // Helper to create spans for tables.
337352 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+ }
338357 prefix := codec .IndexPrefix (tableID , 1 /* indexID */ )
339358 return roachpb.Span {
340359 Key : prefix ,
@@ -432,3 +451,82 @@ func TestFrontierPerTableResolvedTimestamps(t *testing.T) {
432451 })
433452 }
434453}
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