Skip to content

Commit 75f0a72

Browse files
av8or1kou
authored andcommitted
apacheGH-38703: [C++][FS][Azure] Implement DeleteFile() (apache#39840)
### Rationale for this change `DeleteFile()` API isn't implemented yet. ### What changes are included in this PR? Implement `DeleteFile()` by the "Delete Blob" API: https://learn.microsoft.com/en-us/rest/api/storageservices/delete-blob ### Are these changes tested? I tested the modification by creating a file via the web browser on our internal ADLS, then ran a sample program that deleted the file. I added three regression tests to cover the use case scenarios of: * A valid delete attempt, where "valid" means that the file exists and is indeed a file * An intentional failure where a file delete is attempted, but the file does not exist * An intentional failure where a file delete is attempted, but the target is a container * An intentional failure where a file delete is attempted, but the target is a directory ### Are there any user-facing changes? Yes. * Closes: apache#38703 Lead-authored-by: av8or1 <fivetomins@yahoo.com> Co-authored-by: jerry.adair <Jerry.Adair@sas.com> Co-authored-by: Sutou Kouhei <kou@cozmixng.org> Signed-off-by: Sutou Kouhei <kou@clear-code.com>
1 parent c33cb3f commit 75f0a72

File tree

2 files changed

+54
-2
lines changed

2 files changed

+54
-2
lines changed

cpp/src/arrow/filesystem/azurefs.cc

+22-1
Original file line numberDiff line numberDiff line change
@@ -1690,6 +1690,26 @@ class AzureFileSystem::Impl {
16901690
}
16911691
}
16921692

1693+
Status DeleteFile(const AzureLocation& location) {
1694+
RETURN_NOT_OK(ValidateFileLocation(location));
1695+
auto file_client = datalake_service_client_->GetFileSystemClient(location.container)
1696+
.GetFileClient(location.path);
1697+
try {
1698+
auto response = file_client.Delete();
1699+
// Only the "*IfExists" functions ever set Deleted to false.
1700+
// All the others either succeed or throw an exception.
1701+
DCHECK(response.Value.Deleted);
1702+
} catch (const Storage::StorageException& exception) {
1703+
if (exception.ErrorCode == "FilesystemNotFound" ||
1704+
exception.ErrorCode == "PathNotFound") {
1705+
return PathNotFound(location);
1706+
}
1707+
return ExceptionToStatus(exception, "Failed to delete a file: ", location.path,
1708+
": ", file_client.GetUrl());
1709+
}
1710+
return Status::OK();
1711+
}
1712+
16931713
Status CopyFile(const AzureLocation& src, const AzureLocation& dest) {
16941714
RETURN_NOT_OK(ValidateFileLocation(src));
16951715
RETURN_NOT_OK(ValidateFileLocation(dest));
@@ -1875,7 +1895,8 @@ Status AzureFileSystem::DeleteRootDirContents() {
18751895
}
18761896

18771897
Status AzureFileSystem::DeleteFile(const std::string& path) {
1878-
return Status::NotImplemented("The Azure FileSystem is not fully implemented");
1898+
ARROW_ASSIGN_OR_RAISE(auto location, AzureLocation::FromString(path));
1899+
return impl_->DeleteFile(location);
18791900
}
18801901

18811902
Status AzureFileSystem::Move(const std::string& src, const std::string& dest) {

cpp/src/arrow/filesystem/azurefs_test.cc

+32-1
Original file line numberDiff line numberDiff line change
@@ -1382,6 +1382,38 @@ TEST_F(TestAzuriteFileSystem, DeleteDirContentsFailureNonexistent) {
13821382
this->TestDeleteDirContentsFailureNonexistent();
13831383
}
13841384

1385+
TEST_F(TestAzuriteFileSystem, DeleteFileSuccess) {
1386+
const auto container_name = PreexistingData::RandomContainerName(rng_);
1387+
ASSERT_OK(fs()->CreateDir(container_name));
1388+
const auto file_name = ConcatAbstractPath(container_name, "abc");
1389+
CreateFile(fs(), file_name, "data");
1390+
arrow::fs::AssertFileInfo(fs(), file_name, FileType::File);
1391+
ASSERT_OK(fs()->DeleteFile(file_name));
1392+
arrow::fs::AssertFileInfo(fs(), file_name, FileType::NotFound);
1393+
}
1394+
1395+
TEST_F(TestAzuriteFileSystem, DeleteFileFailureNonexistent) {
1396+
const auto container_name = PreexistingData::RandomContainerName(rng_);
1397+
ASSERT_OK(fs()->CreateDir(container_name));
1398+
const auto nonexistent_file_name = ConcatAbstractPath(container_name, "nonexistent");
1399+
ASSERT_RAISES(IOError, fs()->DeleteFile(nonexistent_file_name));
1400+
}
1401+
1402+
TEST_F(TestAzuriteFileSystem, DeleteFileFailureContainer) {
1403+
const auto container_name = PreexistingData::RandomContainerName(rng_);
1404+
ASSERT_OK(fs()->CreateDir(container_name));
1405+
arrow::fs::AssertFileInfo(fs(), container_name, FileType::Directory);
1406+
ASSERT_RAISES(IOError, fs()->DeleteFile(container_name));
1407+
}
1408+
1409+
TEST_F(TestAzuriteFileSystem, DeleteFileFailureDirectory) {
1410+
const auto directory_name =
1411+
ConcatAbstractPath(PreexistingData::RandomContainerName(rng_), "directory");
1412+
ASSERT_OK(fs()->CreateDir(directory_name));
1413+
arrow::fs::AssertFileInfo(fs(), directory_name, FileType::Directory);
1414+
ASSERT_RAISES(IOError, fs()->DeleteFile(directory_name));
1415+
}
1416+
13851417
TEST_F(TestAzuriteFileSystem, CopyFileSuccessDestinationNonexistent) {
13861418
auto data = SetUpPreexistingData();
13871419
const auto destination_path = data.ContainerPath("copy-destionation");
@@ -1868,6 +1900,5 @@ TEST_F(TestAzuriteFileSystem, OpenInputFileClosed) {
18681900
ASSERT_RAISES(Invalid, stream->ReadAt(1, 1));
18691901
ASSERT_RAISES(Invalid, stream->Seek(2));
18701902
}
1871-
18721903
} // namespace fs
18731904
} // namespace arrow

0 commit comments

Comments
 (0)