aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorilnaz <ilnaz@ydb.tech>2023-11-15 00:06:40 +0300
committerilnaz <ilnaz@ydb.tech>2023-11-15 00:26:40 +0300
commitb154d5bf531a8d988c96d52927e75ae043b8ef98 (patch)
tree5d8dff0cac9615304115e76a0e7679ebc9f75afa
parent37e4d5ec858a3a5ea9994e9213cd742f565142ae (diff)
downloadydb-b154d5bf531a8d988c96d52927e75ae043b8ef98.tar.gz
Check uniqueness of dst paths KIKIMR-20120
-rw-r--r--ydb/core/tx/schemeshard/schemeshard_import__create.cpp13
-rw-r--r--ydb/core/tx/schemeshard/ut_restore/ut_restore.cpp33
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());