@@ -1806,6 +1806,118 @@ Y_UNIT_TEST_SUITE(IncrementalBackup) {
18061806 false , Ydb::StatusIds::SCHEME_ERROR);
18071807 }
18081808
1809+ Y_UNIT_TEST (VerifyIncrementalBackupTableAttributes) {
1810+ TPortManager portManager;
1811+ TServer::TPtr server = new TServer (TServerSettings (portManager.GetPort (2134 ), {}, DefaultPQConfig ())
1812+ .SetUseRealThreads (false )
1813+ .SetDomainName (" Root" )
1814+ .SetEnableChangefeedInitialScan (true )
1815+ .SetEnableBackupService (true )
1816+ );
1817+
1818+ auto & runtime = *server->GetRuntime ();
1819+ const auto edgeActor = runtime.AllocateEdgeActor ();
1820+
1821+ SetupLogging (runtime);
1822+ InitRoot (server, edgeActor);
1823+ CreateShardedTable (server, edgeActor, " /Root" , " Table" , SimpleTable ());
1824+
1825+ // Insert some initial data
1826+ ExecSQL (server, edgeActor, R"(
1827+ UPSERT INTO `/Root/Table` (key, value) VALUES
1828+ (1, 10), (2, 20), (3, 30);
1829+ )" );
1830+
1831+ // Create backup collection with incremental backup enabled
1832+ ExecSQL (server, edgeActor, R"(
1833+ CREATE BACKUP COLLECTION `TestCollection`
1834+ ( TABLE `/Root/Table`
1835+ )
1836+ WITH
1837+ ( STORAGE = 'cluster'
1838+ , INCREMENTAL_BACKUP_ENABLED = 'true'
1839+ );
1840+ )" , false );
1841+
1842+ // Create full backup first
1843+ ExecSQL (server, edgeActor, R"( BACKUP `TestCollection`;)" , false );
1844+ runtime.SimulateSleep (TDuration::Seconds (5 ));
1845+
1846+ // Modify some data
1847+ ExecSQL (server, edgeActor, R"(
1848+ UPSERT INTO `/Root/Table` (key, value) VALUES (2, 200);
1849+ DELETE FROM `/Root/Table` WHERE key = 1;
1850+ )" );
1851+
1852+ // Create incremental backup - this should create the incremental backup implementation tables
1853+ ExecSQL (server, edgeActor, R"( BACKUP `TestCollection` INCREMENTAL;)" , false );
1854+ runtime.SimulateSleep (TDuration::Seconds (10 )); // More time for incremental backup to complete
1855+
1856+ // Try to find the incremental backup table by iterating through possible timestamps
1857+ TString foundIncrementalBackupPath;
1858+ bool foundIncrementalBackupTable = false ;
1859+
1860+ // Common incremental backup paths to try (timestamp-based)
1861+ TVector<TString> possiblePaths = {
1862+ " /Root/.backups/collections/TestCollection/19700101000002Z_incremental/Table" ,
1863+ " /Root/.backups/collections/TestCollection/19700101000003Z_incremental/Table" ,
1864+ " /Root/.backups/collections/TestCollection/19700101000004Z_incremental/Table" ,
1865+ " /Root/.backups/collections/TestCollection/19700101000005Z_incremental/Table" ,
1866+ " /Root/.backups/collections/TestCollection/19700101000006Z_incremental/Table" ,
1867+ " /Root/.backups/collections/TestCollection/19700101000007Z_incremental/Table" ,
1868+ " /Root/.backups/collections/TestCollection/19700101000008Z_incremental/Table" ,
1869+ " /Root/.backups/collections/TestCollection/19700101000009Z_incremental/Table" ,
1870+ " /Root/.backups/collections/TestCollection/19700101000010Z_incremental/Table" ,
1871+ };
1872+
1873+ for (const auto & path : possiblePaths) {
1874+ auto request = MakeHolder<TEvTxUserProxy::TEvNavigate>();
1875+ request->Record .MutableDescribePath ()->SetPath (path);
1876+ request->Record .MutableDescribePath ()->MutableOptions ()->SetShowPrivateTable (true );
1877+ runtime.Send (new IEventHandle (MakeTxProxyID (), edgeActor, request.Release ()));
1878+ auto reply = runtime.GrabEdgeEventRethrow <NSchemeShard::TEvSchemeShard::TEvDescribeSchemeResult>(edgeActor);
1879+
1880+ if (reply->Get ()->GetRecord ().GetStatus () == NKikimrScheme::EStatus::StatusSuccess) {
1881+ foundIncrementalBackupPath = path;
1882+ foundIncrementalBackupTable = true ;
1883+ Cerr << " Found incremental backup table at: " << path << Endl;
1884+ break ;
1885+ }
1886+ }
1887+
1888+ UNIT_ASSERT_C (foundIncrementalBackupTable, TStringBuilder () << " Could not find incremental backup table. Tried paths: " << JoinSeq (" , " , possiblePaths));
1889+
1890+ // Now check the found incremental backup table attributes
1891+ auto request = MakeHolder<TEvTxUserProxy::TEvNavigate>();
1892+ request->Record .MutableDescribePath ()->SetPath (foundIncrementalBackupPath);
1893+ request->Record .MutableDescribePath ()->MutableOptions ()->SetShowPrivateTable (true );
1894+ runtime.Send (new IEventHandle (MakeTxProxyID (), edgeActor, request.Release ()));
1895+ auto reply = runtime.GrabEdgeEventRethrow <NSchemeShard::TEvSchemeShard::TEvDescribeSchemeResult>(edgeActor);
1896+
1897+ UNIT_ASSERT_EQUAL (reply->Get ()->GetRecord ().GetStatus (), NKikimrScheme::EStatus::StatusSuccess);
1898+
1899+ const auto & pathDescription = reply->Get ()->GetRecord ().GetPathDescription ();
1900+ UNIT_ASSERT (pathDescription.HasTable ());
1901+
1902+ // Verify that incremental backup table has __incremental_backup attribute
1903+ bool hasIncrementalBackupAttr = false ;
1904+ bool hasAsyncReplicaAttr = false ;
1905+
1906+ for (const auto & attr : pathDescription.GetUserAttributes ()) {
1907+ Cerr << " Found attribute: " << attr.GetKey () << " = " << attr.GetValue () << Endl;
1908+ if (attr.GetKey () == " __incremental_backup" ) {
1909+ hasIncrementalBackupAttr = true ;
1910+ }
1911+ if (attr.GetKey () == " __async_replica" ) {
1912+ hasAsyncReplicaAttr = true ;
1913+ }
1914+ }
1915+
1916+ // Verify that we have __incremental_backup but NOT __async_replica
1917+ UNIT_ASSERT_C (hasIncrementalBackupAttr, TStringBuilder () << " Incremental backup table at " << foundIncrementalBackupPath << " must have __incremental_backup attribute" );
1918+ UNIT_ASSERT_C (!hasAsyncReplicaAttr, TStringBuilder () << " Incremental backup table at " << foundIncrementalBackupPath << " must NOT have __async_replica attribute" );
1919+ }
1920+
18091921} // Y_UNIT_TEST_SUITE(IncrementalBackup)
18101922
18111923} // NKikimr
0 commit comments