@@ -790,3 +790,112 @@ func TestSSTBatcherCloseWithoutFlush(t *testing.T) {
790790 // There should be no rows written since all the flushes were blocked and cancelled.
791791 tdb .CheckQueryResults (t , `SELECT count(*) FROM kv` , [][]string {{"0" }})
792792}
793+
794+ func TestSSTBatcherSplitBetweenColumnFamilies (t * testing.T ) {
795+ defer leaktest .AfterTest (t )()
796+ defer log .Scope (t ).Close (t )
797+ ctx := context .Background ()
798+
799+ tc := testcluster .StartTestCluster (t , 5 , base.TestClusterArgs {})
800+ defer tc .Stopper ().Stop (ctx )
801+ s := tc .ApplicationLayer (0 )
802+ db := tc .ServerConn (0 )
803+ kvDB := s .DB ()
804+
805+ tdb := sqlutils .MakeSQLRunner (db )
806+
807+ // Create a table with multiple column families and a secondary index.
808+ tdb .Exec (t , `
809+ CREATE TABLE t (
810+ pk INT PRIMARY KEY,
811+ a INT,
812+ b STRING,
813+ INDEX idx_a (a),
814+ FAMILY f0 (pk, a),
815+ FAMILY f1 (b)
816+ )
817+ ` )
818+
819+ // Insert some rows.
820+ for i := 1 ; i <= 11 ; i ++ {
821+ tdb .Exec (t , `INSERT INTO t VALUES ($1, $2, $3)` , i , i * 10 , fmt .Sprintf ("b-%d" , i ))
822+ }
823+
824+ // Get the table descriptor to construct keys.
825+ tableDesc := desctestutils .TestingGetPublicTableDescriptor (kvDB , s .Codec (), "defaultdb" , "t" )
826+ tableID := tableDesc .GetID ()
827+
828+ // The primary index has ID 1.
829+ indexPrefix := s .Codec ().IndexPrefix (uint32 (tableID ), 1 )
830+
831+ // Create unsafe split keys between family 0 and family 1 for each row.
832+ for pk := 1 ; pk <= 11 ; pk ++ {
833+ pkKey := encoding .EncodeVarintAscending (append ([]byte {}, indexPrefix ... ), int64 (pk ))
834+ family0Key := keys .MakeFamilyKey (pkKey , 0 )
835+ unsafeSplitKey := roachpb .Key (family0Key ).Next ()
836+
837+ _ , err := keys .EnsureSafeSplitKey (unsafeSplitKey )
838+ require .Error (t , err )
839+ //require.NotEqual(t, unsafeSplitKey, endRowKey)
840+
841+ splitReq := & kvpb.AdminSplitRequest {
842+ RequestHeader : kvpb.RequestHeader {
843+ Key : unsafeSplitKey ,
844+ },
845+ SplitKey : unsafeSplitKey ,
846+ }
847+
848+ _ , pErr := kv .SendWrapped (ctx , kvDB .NonTransactionalSender (), splitReq )
849+ require .Nil (t , pErr , "AdminSplit at unsafe key should succeed" )
850+ }
851+
852+ // Use the first unsafe split key for subsequent checks.
853+ //pkKey := encoding.EncodeVarintAscending(append([]byte{}, indexPrefix...), 1)
854+ //family0Key := keys.MakeFamilyKey(pkKey, 0)
855+ //unsafeSplitKey := roachpb.Key(family0Key).Next()
856+ //t.Logf("Family 0 key for pk=1: %s", roachpb.Key(family0Key))
857+ //t.Logf("Unsafe split key: %s", unsafeSplitKey)
858+
859+ tdb .Exec (t , `ALTER TABLE t SCATTER` )
860+
861+ // Clear the range cache to ensure it's updated with all the new splits.
862+ // This ensures any subsequent operations have fresh range descriptor information.
863+ s .DistSenderI ().(* kvcoord.DistSender ).RangeDescriptorCache ().Clear ()
864+
865+ // Verify the split occurred by checking range boundaries.
866+ ranges := tdb .QueryStr (t , `SELECT start_key, end_key, replicas FROM [SHOW RANGES FROM TABLE t]` )
867+ t .Logf ("Ranges after split:" )
868+ for i , r := range ranges {
869+ t .Logf (" Range %d: [%s, %s), replicas %s" , i , r [0 ], r [1 ], r [2 ])
870+ }
871+
872+ tdb .Exec (t , `SET streamer_enabled = true` )
873+
874+ // Query each value of 'a' individually in a loop
875+ for pk := 1 ; pk <= 11 ; pk ++ {
876+ aValue := pk * 10
877+ row := tdb .QueryStr (t , `SELECT * FROM t WHERE a = $1` , aValue )
878+ expectedRow := [][]string {{fmt .Sprintf ("%d" , pk ), fmt .Sprintf ("%d" , aValue ), fmt .Sprintf ("b-%d" , pk )}}
879+ require .Equal (t , expectedRow , row , "row with pk=%d should have correct values" , pk )
880+ }
881+
882+ // Scan over the table key space and verify the row is split.
883+ //tableSpan := tableDesc.TableSpan(s.Codec())
884+
885+ //kvs, err := kvDB.Scan(ctx, tableSpan.Key, unsafeSplitKey, 0 /* maxRows */)
886+ //require.NoError(t, err)
887+
888+ //for i, kv := range kvs {
889+ // t.Logf("(Before Split Key) Key %d: %s (len=%d, value len=%d)", i, kv.Key, len(kv.Key), len(kv.Value.RawBytes))
890+ //}
891+
892+ //afterKvs, err := kvDB.Scan(ctx, unsafeSplitKey, tableSpan.EndKey, 0 /* maxRows */)
893+ //require.NoError(t, err)
894+
895+ // for i, kv := range afterKvs {
896+ // t.Logf("(After Split Key) Key %d: %s (len=%d, value len=%d)", i, kv.Key, len(kv.Key), len(kv.Value.RawBytes))
897+ //}
898+
899+ //err := sqlutils.RunInspect(db, "defaultdb", "t")
900+ //require.NoError(t, err)
901+ }
0 commit comments