@@ -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,134 @@ 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 COLLATE utf8mb4_bin" ),
521
+ createTTLTable (t , tk , "t7" , "char(32) CHARACTER SET utf8 COLLATE utf8_bin" ),
522
+ create2PKTTLTable (t , tk , "t8" , "char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_bin" ),
523
+ }
524
+
525
+ cases := []struct {
526
+ name string
527
+ regionEdges []kv.Handle
528
+ splitCnt int
529
+ binaryExpected [][]types.Datum
530
+ stringExpected [][]types.Datum
531
+ }{
532
+ {
533
+ name : "2 regions with binary split" ,
534
+ regionEdges : []kv.Handle {
535
+ bytesHandle (t , []byte {1 , 2 , 3 }),
536
+ },
537
+ splitCnt : 4 ,
538
+ binaryExpected : [][]types.Datum {
539
+ {types.Datum {}, types .NewBytesDatum ([]byte {1 , 2 , 3 })},
540
+ {types .NewBytesDatum ([]byte {1 , 2 , 3 }), types.Datum {}},
541
+ },
542
+ stringExpected : [][]types.Datum {
543
+ {types.Datum {}, types.Datum {}},
544
+ },
545
+ },
546
+ {
547
+ name : "6 regions with binary split" ,
548
+ regionEdges : []kv.Handle {
549
+ bytesHandle (t , []byte {1 , 2 , 3 }),
550
+ bytesHandle (t , []byte {1 , 2 , 3 , 4 }),
551
+ bytesHandle (t , []byte {1 , 2 , 3 , 4 , 5 }),
552
+ bytesHandle (t , []byte {1 , 2 , 4 }),
553
+ bytesHandle (t , []byte {1 , 2 , 5 }),
554
+ },
555
+ splitCnt : 4 ,
556
+ binaryExpected : [][]types.Datum {
557
+ {types.Datum {}, types .NewBytesDatum ([]byte {1 , 2 , 3 , 4 })},
558
+ {types .NewBytesDatum ([]byte {1 , 2 , 3 , 4 }), types .NewBytesDatum ([]byte {1 , 2 , 4 })},
559
+ {types .NewBytesDatum ([]byte {1 , 2 , 4 }), types .NewBytesDatum ([]byte {1 , 2 , 5 })},
560
+ {types .NewBytesDatum ([]byte {1 , 2 , 5 }), types.Datum {}},
561
+ },
562
+ stringExpected : [][]types.Datum {
563
+ {types.Datum {}, types.Datum {}},
564
+ },
565
+ },
566
+ {
567
+ name : "2 regions with utf8 split" ,
568
+ regionEdges : []kv.Handle {
569
+ bytesHandle (t , []byte ("中文" )),
570
+ },
571
+ splitCnt : 4 ,
572
+ binaryExpected : [][]types.Datum {
573
+ {types.Datum {}, types .NewBytesDatum ([]byte ("中文" ))},
574
+ {types .NewBytesDatum ([]byte ("中文" )), types.Datum {}},
575
+ },
576
+ stringExpected : [][]types.Datum {
577
+ {types.Datum {}, types.Datum {}},
578
+ },
579
+ },
580
+ {
581
+ name : "several regions with mixed split" ,
582
+ regionEdges : []kv.Handle {
583
+ bytesHandle (t , []byte ("abc" )),
584
+ bytesHandle (t , []byte ("ab\x7f 0" )),
585
+ bytesHandle (t , []byte ("ab\xff 0" )),
586
+ bytesHandle (t , []byte ("ac\x00 1" )),
587
+ bytesHandle (t , []byte ("ad\x0a 1" )),
588
+ bytesHandle (t , []byte ("ad23" )),
589
+ bytesHandle (t , []byte ("ad230\xff " )),
590
+ bytesHandle (t , []byte ("befh" )),
591
+ bytesHandle (t , []byte ("中文" )),
592
+ },
593
+ splitCnt : 10 ,
594
+ binaryExpected : [][]types.Datum {
595
+ {types.Datum {}, types .NewBytesDatum ([]byte ("abc" ))},
596
+ {types .NewBytesDatum ([]byte ("abc" )), types .NewBytesDatum ([]byte ("ab\x7f 0" ))},
597
+ {types .NewBytesDatum ([]byte ("ab\x7f 0" )), types .NewBytesDatum ([]byte ("ab\xff 0" ))},
598
+ {types .NewBytesDatum ([]byte ("ab\xff 0" )), types .NewBytesDatum ([]byte ("ac\x00 1" ))},
599
+ {types .NewBytesDatum ([]byte ("ac\x00 1" )), types .NewBytesDatum ([]byte ("ad\x0a 1" ))},
600
+ {types .NewBytesDatum ([]byte ("ad\x0a 1" )), types .NewBytesDatum ([]byte ("ad23" ))},
601
+ {types .NewBytesDatum ([]byte ("ad23" )), types .NewBytesDatum ([]byte ("ad230\xff " ))},
602
+ {types .NewBytesDatum ([]byte ("ad230\xff " )), types .NewBytesDatum ([]byte ("befh" ))},
603
+ {types .NewBytesDatum ([]byte ("befh" )), types .NewBytesDatum ([]byte ("中文" ))},
604
+ {types .NewBytesDatum ([]byte ("中文" )), types.Datum {}},
605
+ },
606
+ stringExpected : [][]types.Datum {
607
+ {types.Datum {}, types .NewStringDatum ("abc" )},
608
+ {types .NewStringDatum ("abc" ), types .NewStringDatum ("ac" )},
609
+ {types .NewStringDatum ("ac" ), types .NewStringDatum ("ad\n 1" )},
610
+ {types .NewStringDatum ("ad\n 1" ), types .NewStringDatum ("ad23" )},
611
+ {types .NewStringDatum ("ad23" ), types .NewStringDatum ("ad230" )},
612
+ {types .NewStringDatum ("ad230" ), types .NewStringDatum ("befh" )},
613
+ {types .NewStringDatum ("befh" ), types.Datum {}},
614
+ },
615
+ },
519
616
}
520
617
521
618
tikvStore := newMockTiKVStore (t )
522
619
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 {})
620
+ for _ , c := range cases {
621
+ tikvStore .clearRegions ()
622
+ require .Greater (t , len (c .regionEdges ), 0 )
623
+ for i , edge := range c .regionEdges {
624
+ if i == 0 {
625
+ tikvStore .addRegionBeginWithTablePrefix (tbl .ID , edge )
626
+ } else {
627
+ tikvStore .addRegionWithTablePrefix (tbl .ID , c .regionEdges [i - 1 ], edge )
628
+ }
629
+ }
630
+ tikvStore .addRegionEndWithTablePrefix (c .regionEdges [len (c .regionEdges )- 1 ], tbl .ID )
631
+ ranges , err := tbl .SplitScanRanges (context .TODO (), tikvStore , c .splitCnt )
632
+ require .NoError (t , err )
633
+
634
+ keyTp := tbl .KeyColumnTypes [0 ]
635
+ var expected [][]types.Datum
636
+ if keyTp .GetType () == mysql .TypeBit || mysql .HasBinaryFlag (keyTp .GetFlag ()) {
637
+ expected = c .binaryExpected
638
+ } else {
639
+ expected = c .stringExpected
640
+ }
540
641
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 {})
642
+ require .Equal (t , len (expected ), len (ranges ), "tbl: %s, case: %s" , tbl .Name , c .name )
643
+ for i , r := range ranges {
644
+ checkRange (t , r , expected [i ][0 ], expected [i ][1 ],
645
+ "tbl: %s, case: %s, i: %d" , tbl .Name , c .name , i )
646
+ }
647
+ }
560
648
}
561
649
}
562
650
@@ -565,10 +653,12 @@ func TestNoTTLSplitSupportTables(t *testing.T) {
565
653
tk := testkit .NewTestKit (t , store )
566
654
567
655
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" ),
656
+ createTTLTable (t , tk , "t1" , "decimal(32, 2)" ),
657
+ createTTLTable (t , tk , "t2" , "date" ),
658
+ createTTLTable (t , tk , "t3" , "datetime" ),
659
+ createTTLTable (t , tk , "t4" , "timestamp" ),
660
+ createTTLTable (t , tk , "t5" , "varchar(32) character set utf8mb4 collate utf8mb4_general_ci" ),
661
+ createTTLTable (t , tk , "t6" , "varchar(32) character set utf8mb4 collate utf8mb4_0900_ai_ci" ),
572
662
}
573
663
574
664
tikvStore := newMockTiKVStore (t )
@@ -827,6 +917,51 @@ func TestGetNextBytesHandleDatum(t *testing.T) {
827
917
}
828
918
}
829
919
920
+ func TestGetASCIIPrefixDatumFromBytes (t * testing.T ) {
921
+ cases := []struct {
922
+ bytes []byte
923
+ expected string
924
+ }{
925
+ {bytes : nil , expected : "" },
926
+ {bytes : []byte {}, expected : "" },
927
+ {bytes : []byte {0 }, expected : "" },
928
+ {bytes : []byte {1 }, expected : "" },
929
+ {bytes : []byte {8 }, expected : "" },
930
+ {bytes : []byte {9 }, expected : "\t " },
931
+ {bytes : []byte {10 }, expected : "\n " },
932
+ {bytes : []byte {11 }, expected : "" },
933
+ {bytes : []byte {12 }, expected : "" },
934
+ {bytes : []byte {13 }, expected : "\r " },
935
+ {bytes : []byte {14 }, expected : "" },
936
+ {bytes : []byte {0x19 }, expected : "" },
937
+ {bytes : []byte {0x20 }, expected : " " },
938
+ {bytes : []byte {0x21 }, expected : "!" },
939
+ {bytes : []byte {0x7D }, expected : "}" },
940
+ {bytes : []byte {0x7E }, expected : "~" },
941
+ {bytes : []byte {0x7F }, expected : "" },
942
+ {bytes : []byte {0xFF }, expected : "" },
943
+ {bytes : []byte {0x0 , 'a' , 'b' }, expected : "" },
944
+ {bytes : []byte {0xFF , 'a' , 'b' }, expected : "" },
945
+ {bytes : []byte {'0' , '1' , 0x0 , 'a' , 'b' }, expected : "01" },
946
+ {bytes : []byte {'0' , '1' , 0x15 , 'a' , 'b' }, expected : "01" },
947
+ {bytes : []byte {'0' , '1' , 0xFF , 'a' , 'b' }, expected : "01" },
948
+ {bytes : []byte {'a' , 'b' , 0x0 }, expected : "ab" },
949
+ {bytes : []byte {'a' , 'b' , 0x15 }, expected : "ab" },
950
+ {bytes : []byte {'a' , 'b' , 0xFF }, expected : "ab" },
951
+ {bytes : []byte ("ab\r cd\t ef\n AB!~GH()tt ;;" ), expected : "ab\r cd\t ef\n AB!~GH()tt ;;" },
952
+ {bytes : []byte ("中文" ), expected : "" },
953
+ {bytes : []byte ("cn中文" ), expected : "cn" },
954
+ {bytes : []byte ("😀" ), expected : "" },
955
+ {bytes : []byte ("emoji😀" ), expected : "emoji" },
956
+ }
957
+
958
+ for i , c := range cases {
959
+ d := cache .GetASCIIPrefixDatumFromBytes (c .bytes )
960
+ require .Equalf (t , types .KindString , d .Kind (), "i: %d" , i )
961
+ require .Equalf (t , c .expected , d .GetString (), "i: %d, bs: %v" , i , c .bytes )
962
+ }
963
+ }
964
+
830
965
func TestGetNextIntHandle (t * testing.T ) {
831
966
tblID := int64 (7 )
832
967
cases := []struct {
0 commit comments