@@ -57,6 +57,16 @@ namespace {
5757 return InvalidArgument (" Required field '{}' is null at row {}" , field_name, row_idx);
5858}
5959
60+ [[nodiscard]] Status ValidateStructLength (const ArrowArrayView* view,
61+ std::string_view field_name) {
62+ for (int64_t i = 0 ; i < view->n_children ; ++i) {
63+ ICEBERG_CHECK (view->children [i]->length == view->length ,
64+ " Field '{}' child {} should have length {} matching its parent, got {}" ,
65+ field_name, i, view->length , view->children [i]->length );
66+ }
67+ return {};
68+ }
69+
6070[[nodiscard]] Status AssertViewType (const ArrowArrayView* view, ArrowType expected_type,
6171 std::string_view field_name) {
6272 if (view->storage_type != expected_type) {
@@ -318,6 +328,7 @@ Result<std::vector<ManifestFile>> ParseManifestList(ArrowSchema* arrow_schema,
318328
319329 ICEBERG_RETURN_UNEXPECTED (AssertViewTypeAndChildren (
320330 &view, ArrowType::NANOARROW_TYPE_STRUCT , schema.fields ().size (), " manifest_list" ));
331+ ICEBERG_RETURN_UNEXPECTED (ValidateStructLength (&view, " manifest_list" ));
321332
322333 std::vector<ManifestFile> manifest_files;
323334 manifest_files.resize (array->length );
@@ -476,6 +487,7 @@ Status ParseDataFile(const std::shared_ptr<StructType>& data_file_schema,
476487 ICEBERG_RETURN_UNEXPECTED (
477488 AssertViewTypeAndChildren (view, ArrowType::NANOARROW_TYPE_STRUCT ,
478489 data_file_schema->fields ().size (), " data_file" ));
490+ ICEBERG_RETURN_UNEXPECTED (ValidateStructLength (view, " data_file" ));
479491
480492 for (int64_t col_idx = 0 ; col_idx < view->n_children ; ++col_idx) {
481493 ICEBERG_ASSIGN_OR_RAISE (auto field, data_file_schema->GetFieldByIndex (col_idx));
@@ -515,6 +527,7 @@ Status ParseDataFile(const std::shared_ptr<StructType>& data_file_schema,
515527 case DataFile::kPartitionFieldId : {
516528 ICEBERG_RETURN_UNEXPECTED (
517529 AssertViewType (field_view, ArrowType::NANOARROW_TYPE_STRUCT , field_name));
530+ ICEBERG_RETURN_UNEXPECTED (ValidateStructLength (field_view, field_name));
518531 const auto & partition_type =
519532 internal::checked_cast<const StructType&>(*field->get ().type ());
520533 for (int64_t part_idx = 0 ; part_idx < field_view->n_children ; part_idx++) {
@@ -647,6 +660,7 @@ Result<std::vector<ManifestEntry>> ParseManifestEntry(
647660
648661 ICEBERG_RETURN_UNEXPECTED (AssertViewTypeAndChildren (
649662 &view, ArrowType::NANOARROW_TYPE_STRUCT , schema.fields ().size (), " manifest_entry" ));
663+ ICEBERG_RETURN_UNEXPECTED (ValidateStructLength (&view, " manifest_entry" ));
650664
651665 std::vector<ManifestEntry> manifest_entries;
652666 manifest_entries.resize (array->length );
0 commit comments