Skip to content

Commit e3ea33a

Browse files
committed
Add assertion for empty data files for append action
1 parent b4bc6dd commit e3ea33a

File tree

3 files changed

+26
-0
lines changed

3 files changed

+26
-0
lines changed

crates/iceberg/src/error.rs

+4
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ pub type Result<T> = std::result::Result<T, Error>;
2828
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2929
#[non_exhaustive]
3030
pub enum ErrorKind {
31+
/// Function receives an invalid argument, which iceberg library cannot handle.
32+
InvalidArgument,
33+
3134
/// Iceberg don't know what happened here, and no actions other than
3235
/// just returning it back. For example, iceberg returns an internal
3336
/// service error.
@@ -76,6 +79,7 @@ impl From<ErrorKind> for &'static str {
7679
ErrorKind::TableNotFound => "TableNotFound",
7780
ErrorKind::NamespaceAlreadyExists => "NamespaceAlreadyExists",
7881
ErrorKind::NamespaceNotFound => "NamespaceNotFound",
82+
ErrorKind::InvalidArgument => "InvalidArgument",
7983
}
8084
}
8185
}

crates/iceberg/src/transaction/append.rs

+8
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,14 @@ mod tests {
219219
use crate::transaction::Transaction;
220220
use crate::{TableRequirement, TableUpdate};
221221

222+
#[tokio::test]
223+
async fn test_empty_data_append_action() {
224+
let table = make_v2_minimal_table();
225+
let tx = Transaction::new(&table);
226+
let mut action = tx.fast_append(None, vec![]).unwrap();
227+
assert(action.add_data_files(vec![]).is_err());
228+
}
229+
222230
#[tokio::test]
223231
async fn test_fast_append_action() {
224232
let table = make_v2_minimal_table();

crates/iceberg/src/transaction/snapshot.rs

+14
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,13 @@ impl<'a> SnapshotProduceAction<'a> {
129129
data_files: impl IntoIterator<Item = DataFile>,
130130
) -> Result<&mut Self> {
131131
let data_files: Vec<DataFile> = data_files.into_iter().collect();
132+
if data_files.is_empty() {
133+
return Err(Error::new(
134+
ErrorKind::DataInvalid,
135+
"Doesn't add any data files when fast append",
136+
));
137+
}
138+
132139
for data_file in &data_files {
133140
if data_file.content_type() != crate::spec::DataContentType::Data {
134141
return Err(Error::new(
@@ -172,6 +179,13 @@ impl<'a> SnapshotProduceAction<'a> {
172179
// Write manifest file for added data files and return the ManifestFile for ManifestList.
173180
async fn write_added_manifest(&mut self) -> Result<ManifestFile> {
174181
let added_data_files = std::mem::take(&mut self.added_data_files);
182+
if added_data_files.is_empty() {
183+
return Err(Error::new(
184+
ErrorKind::Unexpected,
185+
"No added data files found when write a manifest file",
186+
));
187+
}
188+
175189
let snapshot_id = self.snapshot_id;
176190
let format_version = self.tx.current_table.metadata().format_version();
177191
let manifest_entries = added_data_files.into_iter().map(|data_file| {

0 commit comments

Comments
 (0)