@@ -249,6 +249,44 @@ void TestTableSplitBoundariesArePreserved(
249
249
UNIT_ASSERT_EQUAL (restoredTableDescription.GetKeyRanges (), originalKeyRanges);
250
250
}
251
251
252
+ void TestIndexTableSplitBoundariesArePreserved (
253
+ const char * table, const char * index, ui64 indexPartitions, TSession& session, TTableBuilder& tableBuilder,
254
+ TBackupFunction&& backup, TRestoreFunction&& restore
255
+ ) {
256
+ {
257
+ const auto result = session.CreateTable (table, tableBuilder.Build ()).ExtractValueSync ();
258
+ UNIT_ASSERT_C (result.IsSuccess (), result.GetIssues ().ToString ());
259
+ }
260
+
261
+ const TString indexTablePath = JoinFsPaths (table, index , " indexImplTable" );
262
+ const auto describeSettings = TDescribeTableSettings ()
263
+ .WithTableStatistics (true )
264
+ .WithKeyShardBoundary (true );
265
+
266
+ const auto originalDescription = GetTableDescription (
267
+ session, indexTablePath, describeSettings
268
+ );
269
+ UNIT_ASSERT_VALUES_EQUAL (originalDescription.GetPartitionsCount (), indexPartitions);
270
+ const auto & originalKeyRanges = originalDescription.GetKeyRanges ();
271
+ UNIT_ASSERT_VALUES_EQUAL (originalKeyRanges.size (), indexPartitions);
272
+
273
+ backup (table);
274
+
275
+ ExecuteDataDefinitionQuery (session, Sprintf (R"(
276
+ DROP TABLE `%s`;
277
+ )" , table
278
+ ));
279
+
280
+ restore (table);
281
+ const auto restoredDescription = GetTableDescription (
282
+ session, indexTablePath, describeSettings
283
+ );
284
+ UNIT_ASSERT_VALUES_EQUAL (restoredDescription.GetPartitionsCount (), indexPartitions);
285
+ const auto & restoredKeyRanges = restoredDescription.GetKeyRanges ();
286
+ UNIT_ASSERT_VALUES_EQUAL (restoredKeyRanges.size (), indexPartitions);
287
+ UNIT_ASSERT_EQUAL (restoredKeyRanges, originalKeyRanges);
288
+ }
289
+
252
290
}
253
291
254
292
Y_UNIT_TEST_SUITE (BackupRestore) {
@@ -545,4 +583,97 @@ Y_UNIT_TEST_SUITE(BackupRestoreS3) {
545
583
);
546
584
}
547
585
586
+ Y_UNIT_TEST (RestoreIndexTableSplitBoundaries) {
587
+ TS3TestEnv testEnv;
588
+ constexpr const char * table = " /Root/table" ;
589
+ constexpr const char * index = " byValue" ;
590
+ constexpr ui64 indexPartitions = 10 ;
591
+
592
+ TExplicitPartitions indexPartitionBoundaries;
593
+ for (ui32 i = 1 ; i < indexPartitions; ++i) {
594
+ indexPartitionBoundaries.AppendSplitPoints (
595
+ // split boundary is technically always a tuple
596
+ TValueBuilder ().BeginTuple ().AddElement ().OptionalUint32 (i * 10 ).EndTuple ().Build ()
597
+ );
598
+ }
599
+ // By default indexImplTables have auto partitioning by size enabled.
600
+ // If you don't want the partitions to merge immediately after the indexImplTable is built,
601
+ // you must set the min partition count for the table.
602
+ TPartitioningSettingsBuilder partitioningSettingsBuilder;
603
+ partitioningSettingsBuilder
604
+ .SetMinPartitionsCount (indexPartitions)
605
+ .SetMaxPartitionsCount (indexPartitions);
606
+
607
+ const auto indexSettings = TGlobalIndexSettings{
608
+ .PartitioningSettings = partitioningSettingsBuilder.Build (),
609
+ .Partitions = std::move (indexPartitionBoundaries)
610
+ };
611
+
612
+ auto tableBuilder = TTableBuilder ()
613
+ .AddNullableColumn (" Key" , EPrimitiveType::Uint32)
614
+ .AddNullableColumn (" Value" , EPrimitiveType::Uint32)
615
+ .SetPrimaryKeyColumn (" Key" )
616
+ .AddSecondaryIndex (TIndexDescription (index , EIndexType::GlobalSync, { " Value" }, {}, { indexSettings }));
617
+
618
+ TestIndexTableSplitBoundariesArePreserved (
619
+ table,
620
+ index ,
621
+ indexPartitions,
622
+ testEnv.GetSession (),
623
+ tableBuilder,
624
+ CreateBackupLambda (testEnv.GetDriver (), testEnv.GetS3Port ()),
625
+ CreateRestoreLambda (testEnv.GetDriver (), testEnv.GetS3Port ())
626
+ );
627
+ }
628
+
629
+ Y_UNIT_TEST (RestoreIndexTableDecimalSplitBoundaries) {
630
+ TS3TestEnv testEnv;
631
+ constexpr const char * table = " /Root/table" ;
632
+ constexpr const char * index = " byValue" ;
633
+ constexpr ui64 indexPartitions = 10 ;
634
+
635
+ constexpr ui8 decimalPrecision = 22 ;
636
+ constexpr ui8 decimalScale = 9 ;
637
+
638
+ TExplicitPartitions indexPartitionBoundaries;
639
+ for (ui32 i = 1 ; i < indexPartitions; ++i) {
640
+ TDecimalValue boundary (ToString (i * 10 ), decimalPrecision, decimalScale);
641
+ indexPartitionBoundaries.AppendSplitPoints (
642
+ // split boundary is technically always a tuple
643
+ TValueBuilder ()
644
+ .BeginTuple ().AddElement ()
645
+ .BeginOptional ().Decimal (boundary).EndOptional ()
646
+ .EndTuple ().Build ()
647
+ );
648
+ }
649
+ // By default indexImplTables have auto partitioning by size enabled.
650
+ // If you don't want the partitions to merge immediately after the indexImplTable is built,
651
+ // you must set the min partition count for the table.
652
+ TPartitioningSettingsBuilder partitioningSettingsBuilder;
653
+ partitioningSettingsBuilder
654
+ .SetMinPartitionsCount (indexPartitions)
655
+ .SetMaxPartitionsCount (indexPartitions);
656
+
657
+ const auto indexSettings = TGlobalIndexSettings{
658
+ .PartitioningSettings = partitioningSettingsBuilder.Build (),
659
+ .Partitions = std::move (indexPartitionBoundaries)
660
+ };
661
+
662
+ auto tableBuilder = TTableBuilder ()
663
+ .AddNullableColumn (" Key" , EPrimitiveType::Uint32)
664
+ .AddNullableColumn (" Value" , TDecimalType (decimalPrecision, decimalScale))
665
+ .SetPrimaryKeyColumn (" Key" )
666
+ .AddSecondaryIndex (TIndexDescription (index , EIndexType::GlobalSync, { " Value" }, {}, { indexSettings }));
667
+
668
+ TestIndexTableSplitBoundariesArePreserved (
669
+ table,
670
+ index ,
671
+ indexPartitions,
672
+ testEnv.GetSession (),
673
+ tableBuilder,
674
+ CreateBackupLambda (testEnv.GetDriver (), testEnv.GetS3Port ()),
675
+ CreateRestoreLambda (testEnv.GetDriver (), testEnv.GetS3Port ())
676
+ );
677
+ }
678
+
548
679
}
0 commit comments