diff options
author | ilnaz <ilnaz@ydb.tech> | 2023-11-15 00:06:40 +0300 |
---|---|---|
committer | ilnaz <ilnaz@ydb.tech> | 2023-11-15 00:26:40 +0300 |
commit | b154d5bf531a8d988c96d52927e75ae043b8ef98 (patch) | |
tree | 5d8dff0cac9615304115e76a0e7679ebc9f75afa | |
parent | 37e4d5ec858a3a5ea9994e9213cd742f565142ae (diff) | |
download | ydb-b154d5bf531a8d988c96d52927e75ae043b8ef98.tar.gz |
Check uniqueness of dst paths KIKIMR-20120
-rw-r--r-- | ydb/core/tx/schemeshard/schemeshard_import__create.cpp | 13 | ||||
-rw-r--r-- | ydb/core/tx/schemeshard/ut_restore/ut_restore.cpp | 33 |
2 files changed, 40 insertions, 6 deletions
diff --git a/ydb/core/tx/schemeshard/schemeshard_import__create.cpp b/ydb/core/tx/schemeshard/schemeshard_import__create.cpp index bde5b6f863..c7baebfee1 100644 --- a/ydb/core/tx/schemeshard/schemeshard_import__create.cpp +++ b/ydb/core/tx/schemeshard/schemeshard_import__create.cpp @@ -172,10 +172,17 @@ private: template <typename TSettings> bool FillItems(TImportInfo::TPtr importInfo, const TSettings& settings, TString& explain) { + THashSet<TString> dstPaths; + importInfo->Items.reserve(settings.items().size()); for (ui32 itemIdx : xrange(settings.items().size())) { - const auto& item = settings.items(itemIdx); - const TPath path = TPath::Resolve(item.destination_path(), Self); + const auto& dstPath = settings.items(itemIdx).destination_path(); + if (!dstPaths.insert(dstPath).second) { + explain = TStringBuilder() << "Duplicate destination_path: " << dstPath; + return false; + } + + const TPath path = TPath::Resolve(dstPath, Self); { TPath::TChecker checks = path.Check(); checks @@ -204,7 +211,7 @@ private: } } - importInfo->Items.emplace_back(item.destination_path()); + importInfo->Items.emplace_back(dstPath); } return true; diff --git a/ydb/core/tx/schemeshard/ut_restore/ut_restore.cpp b/ydb/core/tx/schemeshard/ut_restore/ut_restore.cpp index d2c00204e2..a8d8146f30 100644 --- a/ydb/core/tx/schemeshard/ut_restore/ut_restore.cpp +++ b/ydb/core/tx/schemeshard/ut_restore/ut_restore.cpp @@ -1557,9 +1557,16 @@ Y_UNIT_TEST_SUITE(TImportTests) { runtime.SetLogPriority(NKikimrServices::DATASHARD_RESTORE, NActors::NLog::PRI_TRACE); runtime.SetLogPriority(NKikimrServices::IMPORT, NActors::NLog::PRI_TRACE); - const auto initialStatus = expectedStatus == Ydb::StatusIds::PRECONDITION_FAILED - ? expectedStatus - : Ydb::StatusIds::SUCCESS; + auto initialStatus = Ydb::StatusIds::SUCCESS; + switch (expectedStatus) { + case Ydb::StatusIds::BAD_REQUEST: + case Ydb::StatusIds::PRECONDITION_FAILED: + initialStatus = expectedStatus; + break; + default: + break; + } + TestImport(runtime, schemeshardId, ++id, dbName, Sprintf(request.data(), port), userSID, initialStatus); env.TestWaitNotification(runtime, id, schemeshardId); @@ -2236,6 +2243,26 @@ Y_UNIT_TEST_SUITE(TImportTests) { )", Ydb::StatusIds::CANCELLED); } + Y_UNIT_TEST(ShouldFailOnNonUniqDestinationPaths) { + TTestBasicRuntime runtime; + + auto unusedTestData = THashMap<TString, TString>(); + Run(runtime, std::move(unusedTestData), R"( + ImportFromS3Settings { + endpoint: "localhost:%d" + scheme: HTTP + items { + source_prefix: "a" + destination_path: "/MyRoot/Table" + } + items { + source_prefix: "b" + destination_path: "/MyRoot/Table" + } + } + )", Ydb::StatusIds::BAD_REQUEST); + } + void CancelShouldSucceed(TDelayFunc delayFunc) { TTestBasicRuntime runtime; TTestEnv env(runtime, TTestEnvOptions()); |