@@ -26,6 +26,7 @@ import (
26
26
"github.com/pingcap/tidb/pkg/infoschema"
27
27
"github.com/pingcap/tidb/pkg/kv"
28
28
"github.com/pingcap/tidb/pkg/parser/model"
29
+ "github.com/pingcap/tidb/pkg/parser/mysql"
29
30
"github.com/pingcap/tidb/pkg/store/helper"
30
31
"github.com/pingcap/tidb/pkg/tablecodec"
31
32
"github.com/pingcap/tidb/pkg/testkit"
@@ -250,21 +251,21 @@ func createTTLTableWithSQL(t *testing.T, tk *testkit.TestKit, name string, sql s
250
251
return ttlTbl
251
252
}
252
253
253
- func checkRange (t * testing.T , r cache.ScanRange , start , end types.Datum ) {
254
+ func checkRange (t * testing.T , r cache.ScanRange , start , end types.Datum , msgAndArgs ... any ) {
254
255
if start .IsNull () {
255
- require .Nil (t , r .Start )
256
+ require .Nil (t , r .Start , msgAndArgs ... )
256
257
} else {
257
- require .Equal (t , 1 , len (r .Start ))
258
- require .Equal (t , start .Kind (), r .Start [0 ].Kind ())
259
- require .Equal (t , start .GetValue (), r .Start [0 ].GetValue ())
258
+ require .Equal (t , 1 , len (r .Start ), msgAndArgs ... )
259
+ require .Equal (t , start .Kind (), r .Start [0 ].Kind (), msgAndArgs ... )
260
+ require .Equal (t , start .GetValue (), r .Start [0 ].GetValue (), msgAndArgs ... )
260
261
}
261
262
262
263
if end .IsNull () {
263
- require .Nil (t , r .End )
264
+ require .Nil (t , r .End , msgAndArgs ... )
264
265
} else {
265
- require .Equal (t , 1 , len (r .End ))
266
- require .Equal (t , end .Kind (), r .End [0 ].Kind ())
267
- require .Equal (t , end .GetValue (), r .End [0 ].GetValue ())
266
+ require .Equal (t , 1 , len (r .End ), msgAndArgs ... )
267
+ require .Equal (t , end .Kind (), r .End [0 ].Kind (), msgAndArgs ... )
268
+ require .Equal (t , end .GetValue (), r .End [0 ].GetValue (), msgAndArgs ... )
268
269
}
269
270
}
270
271
@@ -516,47 +517,133 @@ func TestSplitTTLScanRangesWithBytes(t *testing.T) {
516
517
createTTLTable (t , tk , "t3" , "varchar(32) CHARACTER SET BINARY" ),
517
518
createTTLTable (t , tk , "t4" , "bit(32)" ),
518
519
create2PKTTLTable (t , tk , "t5" , "binary(32)" ),
520
+ createTTLTable (t , tk , "t6" , "char(32) CHARACTER SET UTF8MB4" ),
521
+ create2PKTTLTable (t , tk , "t7" , "char(32) CHARACTER SET gbk" ),
522
+ }
523
+
524
+ cases := []struct {
525
+ name string
526
+ regionEdges []kv.Handle
527
+ splitCnt int
528
+ binaryExpected [][]types.Datum
529
+ stringExpected [][]types.Datum
530
+ }{
531
+ {
532
+ name : "2 regions with binary split" ,
533
+ regionEdges : []kv.Handle {
534
+ bytesHandle (t , []byte {1 , 2 , 3 }),
535
+ },
536
+ splitCnt : 4 ,
537
+ binaryExpected : [][]types.Datum {
538
+ {types.Datum {}, types .NewBytesDatum ([]byte {1 , 2 , 3 })},
539
+ {types .NewBytesDatum ([]byte {1 , 2 , 3 }), types.Datum {}},
540
+ },
541
+ stringExpected : [][]types.Datum {
542
+ {types.Datum {}, types.Datum {}},
543
+ },
544
+ },
545
+ {
546
+ name : "6 regions with binary split" ,
547
+ regionEdges : []kv.Handle {
548
+ bytesHandle (t , []byte {1 , 2 , 3 }),
549
+ bytesHandle (t , []byte {1 , 2 , 3 , 4 }),
550
+ bytesHandle (t , []byte {1 , 2 , 3 , 4 , 5 }),
551
+ bytesHandle (t , []byte {1 , 2 , 4 }),
552
+ bytesHandle (t , []byte {1 , 2 , 5 }),
553
+ },
554
+ splitCnt : 4 ,
555
+ binaryExpected : [][]types.Datum {
556
+ {types.Datum {}, types .NewBytesDatum ([]byte {1 , 2 , 3 , 4 })},
557
+ {types .NewBytesDatum ([]byte {1 , 2 , 3 , 4 }), types .NewBytesDatum ([]byte {1 , 2 , 4 })},
558
+ {types .NewBytesDatum ([]byte {1 , 2 , 4 }), types .NewBytesDatum ([]byte {1 , 2 , 5 })},
559
+ {types .NewBytesDatum ([]byte {1 , 2 , 5 }), types.Datum {}},
560
+ },
561
+ stringExpected : [][]types.Datum {
562
+ {types.Datum {}, types.Datum {}},
563
+ },
564
+ },
565
+ {
566
+ name : "2 regions with utf8 split" ,
567
+ regionEdges : []kv.Handle {
568
+ bytesHandle (t , []byte ("中文" )),
569
+ },
570
+ splitCnt : 4 ,
571
+ binaryExpected : [][]types.Datum {
572
+ {types.Datum {}, types .NewBytesDatum ([]byte ("中文" ))},
573
+ {types .NewBytesDatum ([]byte ("中文" )), types.Datum {}},
574
+ },
575
+ stringExpected : [][]types.Datum {
576
+ {types.Datum {}, types.Datum {}},
577
+ },
578
+ },
579
+ {
580
+ name : "several regions with mixed split" ,
581
+ regionEdges : []kv.Handle {
582
+ bytesHandle (t , []byte ("abc" )),
583
+ bytesHandle (t , []byte ("ab\x7f 0" )),
584
+ bytesHandle (t , []byte ("ab\xff 0" )),
585
+ bytesHandle (t , []byte ("ac\x00 1" )),
586
+ bytesHandle (t , []byte ("ad\x0a 1" )),
587
+ bytesHandle (t , []byte ("ad23" )),
588
+ bytesHandle (t , []byte ("ad230\xff " )),
589
+ bytesHandle (t , []byte ("befh" )),
590
+ bytesHandle (t , []byte ("中文" )),
591
+ },
592
+ splitCnt : 10 ,
593
+ binaryExpected : [][]types.Datum {
594
+ {types.Datum {}, types .NewBytesDatum ([]byte ("abc" ))},
595
+ {types .NewBytesDatum ([]byte ("abc" )), types .NewBytesDatum ([]byte ("ab\x7f 0" ))},
596
+ {types .NewBytesDatum ([]byte ("ab\x7f 0" )), types .NewBytesDatum ([]byte ("ab\xff 0" ))},
597
+ {types .NewBytesDatum ([]byte ("ab\xff 0" )), types .NewBytesDatum ([]byte ("ac\x00 1" ))},
598
+ {types .NewBytesDatum ([]byte ("ac\x00 1" )), types .NewBytesDatum ([]byte ("ad\x0a 1" ))},
599
+ {types .NewBytesDatum ([]byte ("ad\x0a 1" )), types .NewBytesDatum ([]byte ("ad23" ))},
600
+ {types .NewBytesDatum ([]byte ("ad23" )), types .NewBytesDatum ([]byte ("ad230\xff " ))},
601
+ {types .NewBytesDatum ([]byte ("ad230\xff " )), types .NewBytesDatum ([]byte ("befh" ))},
602
+ {types .NewBytesDatum ([]byte ("befh" )), types .NewBytesDatum ([]byte ("中文" ))},
603
+ {types .NewBytesDatum ([]byte ("中文" )), types.Datum {}},
604
+ },
605
+ stringExpected : [][]types.Datum {
606
+ {types.Datum {}, types .NewStringDatum ("abc" )},
607
+ {types .NewStringDatum ("abc" ), types .NewStringDatum ("ac" )},
608
+ {types .NewStringDatum ("ac" ), types .NewStringDatum ("ad\n 1" )},
609
+ {types .NewStringDatum ("ad\n 1" ), types .NewStringDatum ("ad23" )},
610
+ {types .NewStringDatum ("ad23" ), types .NewStringDatum ("ad230" )},
611
+ {types .NewStringDatum ("ad230" ), types .NewStringDatum ("befh" )},
612
+ {types .NewStringDatum ("befh" ), types.Datum {}},
613
+ },
614
+ },
519
615
}
520
616
521
617
tikvStore := newMockTiKVStore (t )
522
618
for _ , tbl := range tbls {
523
- // test only one region
524
- tikvStore .clearRegions ()
525
- ranges , err := tbl .SplitScanRanges (context .TODO (), tikvStore , 4 )
526
- require .NoError (t , err )
527
- require .Equal (t , 1 , len (ranges ))
528
- checkRange (t , ranges [0 ], types.Datum {}, types.Datum {})
529
-
530
- // test share regions with other table
531
- tikvStore .clearRegions ()
532
- tikvStore .addRegion (
533
- tablecodec .GenTablePrefix (tbl .ID - 1 ),
534
- tablecodec .GenTablePrefix (tbl .ID + 1 ),
535
- )
536
- ranges , err = tbl .SplitScanRanges (context .TODO (), tikvStore , 4 )
537
- require .NoError (t , err )
538
- require .Equal (t , 1 , len (ranges ))
539
- checkRange (t , ranges [0 ], types.Datum {}, types.Datum {})
619
+ for _ , c := range cases {
620
+ tikvStore .clearRegions ()
621
+ require .Greater (t , len (c .regionEdges ), 0 )
622
+ for i , edge := range c .regionEdges {
623
+ if i == 0 {
624
+ tikvStore .addRegionBeginWithTablePrefix (tbl .ID , edge )
625
+ } else {
626
+ tikvStore .addRegionWithTablePrefix (tbl .ID , c .regionEdges [i - 1 ], edge )
627
+ }
628
+ }
629
+ tikvStore .addRegionEndWithTablePrefix (c .regionEdges [len (c .regionEdges )- 1 ], tbl .ID )
630
+ ranges , err := tbl .SplitScanRanges (context .TODO (), tikvStore , c .splitCnt )
631
+ require .NoError (t , err )
632
+
633
+ keyTp := tbl .KeyColumnTypes [0 ]
634
+ var expected [][]types.Datum
635
+ if keyTp .GetType () == mysql .TypeBit || mysql .HasBinaryFlag (keyTp .GetFlag ()) {
636
+ expected = c .binaryExpected
637
+ } else {
638
+ expected = c .stringExpected
639
+ }
540
640
541
- // test one table has multiple regions
542
- tikvStore .clearRegions ()
543
- tikvStore .addRegionBeginWithTablePrefix (tbl .ID , bytesHandle (t , []byte {1 , 2 , 3 }))
544
- tikvStore .addRegionWithTablePrefix (
545
- tbl .ID , bytesHandle (t , []byte {1 , 2 , 3 }), bytesHandle (t , []byte {1 , 2 , 3 , 4 }))
546
- tikvStore .addRegionWithTablePrefix (
547
- tbl .ID , bytesHandle (t , []byte {1 , 2 , 3 , 4 }), bytesHandle (t , []byte {1 , 2 , 3 , 4 , 5 }))
548
- tikvStore .addRegionWithTablePrefix (
549
- tbl .ID , bytesHandle (t , []byte {1 , 2 , 3 , 4 , 5 }), bytesHandle (t , []byte {1 , 2 , 4 }))
550
- tikvStore .addRegionWithTablePrefix (
551
- tbl .ID , bytesHandle (t , []byte {1 , 2 , 4 }), bytesHandle (t , []byte {1 , 2 , 5 }))
552
- tikvStore .addRegionEndWithTablePrefix (bytesHandle (t , []byte {1 , 2 , 5 }), tbl .ID )
553
- ranges , err = tbl .SplitScanRanges (context .TODO (), tikvStore , 4 )
554
- require .NoError (t , err )
555
- require .Equal (t , 4 , len (ranges ))
556
- checkRange (t , ranges [0 ], types.Datum {}, types .NewBytesDatum ([]byte {1 , 2 , 3 , 4 }))
557
- checkRange (t , ranges [1 ], types .NewBytesDatum ([]byte {1 , 2 , 3 , 4 }), types .NewBytesDatum ([]byte {1 , 2 , 4 }))
558
- checkRange (t , ranges [2 ], types .NewBytesDatum ([]byte {1 , 2 , 4 }), types .NewBytesDatum ([]byte {1 , 2 , 5 }))
559
- checkRange (t , ranges [3 ], types .NewBytesDatum ([]byte {1 , 2 , 5 }), types.Datum {})
641
+ require .Equal (t , len (expected ), len (ranges ), "tbl: %s, case: %s" , tbl .Name , c .name )
642
+ for i , r := range ranges {
643
+ checkRange (t , r , expected [i ][0 ], expected [i ][1 ],
644
+ "tbl: %s, case: %s, i: %d" , tbl .Name , c .name , i )
645
+ }
646
+ }
560
647
}
561
648
}
562
649
@@ -565,10 +652,10 @@ func TestNoTTLSplitSupportTables(t *testing.T) {
565
652
tk := testkit .NewTestKit (t , store )
566
653
567
654
tbls := []* cache.PhysicalTable {
568
- createTTLTable (t , tk , "t1" , "char (32) CHARACTER SET UTF8MB4 " ),
569
- createTTLTable (t , tk , "t2" , "varchar(32) CHARACTER SET UTF8MB4 " ),
570
- createTTLTable (t , tk , "t4 " , "decimal(32, 2) " ),
571
- create2PKTTLTable (t , tk , "t5 " , "char(32) CHARACTER SET UTF8MB4 " ),
655
+ createTTLTable (t , tk , "t1" , "decimal (32, 2) " ),
656
+ createTTLTable (t , tk , "t2" , "date " ),
657
+ createTTLTable (t , tk , "t3 " , "datetime " ),
658
+ createTTLTable (t , tk , "t4 " , "timestamp " ),
572
659
}
573
660
574
661
tikvStore := newMockTiKVStore (t )
@@ -827,6 +914,51 @@ func TestGetNextBytesHandleDatum(t *testing.T) {
827
914
}
828
915
}
829
916
917
+ func TestGetASCIIPrefixDatumFromBytes (t * testing.T ) {
918
+ cases := []struct {
919
+ bytes []byte
920
+ expected string
921
+ }{
922
+ {bytes : nil , expected : "" },
923
+ {bytes : []byte {}, expected : "" },
924
+ {bytes : []byte {0 }, expected : "" },
925
+ {bytes : []byte {1 }, expected : "" },
926
+ {bytes : []byte {8 }, expected : "" },
927
+ {bytes : []byte {9 }, expected : "\t " },
928
+ {bytes : []byte {10 }, expected : "\n " },
929
+ {bytes : []byte {11 }, expected : "" },
930
+ {bytes : []byte {12 }, expected : "" },
931
+ {bytes : []byte {13 }, expected : "\r " },
932
+ {bytes : []byte {14 }, expected : "" },
933
+ {bytes : []byte {0x19 }, expected : "" },
934
+ {bytes : []byte {0x20 }, expected : " " },
935
+ {bytes : []byte {0x21 }, expected : "!" },
936
+ {bytes : []byte {0x7D }, expected : "}" },
937
+ {bytes : []byte {0x7E }, expected : "~" },
938
+ {bytes : []byte {0x7F }, expected : "" },
939
+ {bytes : []byte {0xFF }, expected : "" },
940
+ {bytes : []byte {0x0 , 'a' , 'b' }, expected : "" },
941
+ {bytes : []byte {0xFF , 'a' , 'b' }, expected : "" },
942
+ {bytes : []byte {'0' , '1' , 0x0 , 'a' , 'b' }, expected : "01" },
943
+ {bytes : []byte {'0' , '1' , 0x15 , 'a' , 'b' }, expected : "01" },
944
+ {bytes : []byte {'0' , '1' , 0xFF , 'a' , 'b' }, expected : "01" },
945
+ {bytes : []byte {'a' , 'b' , 0x0 }, expected : "ab" },
946
+ {bytes : []byte {'a' , 'b' , 0x15 }, expected : "ab" },
947
+ {bytes : []byte {'a' , 'b' , 0xFF }, expected : "ab" },
948
+ {bytes : []byte ("ab\r cd\t ef\n AB!~GH()tt ;;" ), expected : "ab\r cd\t ef\n AB!~GH()tt ;;" },
949
+ {bytes : []byte ("中文" ), expected : "" },
950
+ {bytes : []byte ("cn中文" ), expected : "cn" },
951
+ {bytes : []byte ("😀" ), expected : "" },
952
+ {bytes : []byte ("emoji😀" ), expected : "emoji" },
953
+ }
954
+
955
+ for i , c := range cases {
956
+ d := cache .GetASCIIPrefixDatumFromBytes (c .bytes )
957
+ require .Equalf (t , types .KindString , d .Kind (), "i: %d" , i )
958
+ require .Equalf (t , c .expected , d .GetString (), "i: %d, bs: %v" , i , c .bytes )
959
+ }
960
+ }
961
+
830
962
func TestGetNextIntHandle (t * testing.T ) {
831
963
tblID := int64 (7 )
832
964
cases := []struct {
0 commit comments