| 704 | } |
| 705 | |
| 706 | Status ResolveList(const GroupNode& group, LevelInfo current_levels, |
| 707 | SchemaTreeContext* ctx, SchemaField* out) { |
| 708 | auto check_two_level_list_repetition = [](const GroupNode& group) -> Status { |
| 709 | // When it is repeated, the LIST-annotated 2-level structure can only serve as an |
| 710 | // element within another LIST-annotated 2-level structure. |
| 711 | if (group.is_repeated() && |
| 712 | (group.parent() == nullptr || !group.parent()->logical_type()->is_list())) { |
| 713 | return Status::Invalid("LIST-annotated groups must not be repeated."); |
| 714 | } |
| 715 | return {}; |
| 716 | }; |
| 717 | |
| 718 | SchemaField* child_field = &out->children[0]; |
| 719 | const Node& list_node = *group.field(0); |
| 720 | if (!list_node.is_repeated()) { |
| 721 | return Status::Invalid( |
| 722 | "Non-repeated nodes in a LIST-annotated group are not supported."); |
| 723 | } |
| 724 | |
| 725 | if (list_node.is_group()) { |
| 726 | const auto& list_group = static_cast<const GroupNode&>(list_node); |
| 727 | if (list_group.field_count() > 1) { |
| 728 | // The inner type of the list should be a struct when there are multiple fields |
| 729 | // in the repeated group |
| 730 | RETURN_NOT_OK(check_two_level_list_repetition(group)); |
| 731 | return GroupToStruct(list_group, current_levels, ctx, out, child_field); |
| 732 | } |
| 733 | if (list_group.field_count() == 0) { |
| 734 | return Status::Invalid("Group must have at least one child."); |
| 735 | } |
| 736 | |
| 737 | if (list_group.logical_type()->is_none() && HasListElementName(list_group, group)) { |
| 738 | // Rule 4 at |
| 739 | // https://github.com/apache/parquet-format/blob/master/LogicalTypes.md#backward-compatibility-rules |
| 740 | // |
| 741 | // required/optional group name=SOMETHING { |
| 742 | // repeated group name=array or $SOMETHING_tuple { |
| 743 | // required/optional TYPE item; |
| 744 | // } |
| 745 | // } |
| 746 | // |
| 747 | // The inner type of the list should be a struct rather than a primitive value |
| 748 | // |
| 749 | // yields list<item: struct<item: TYPE ?nullable> not null> ?nullable |
| 750 | RETURN_NOT_OK(check_two_level_list_repetition(group)); |
| 751 | return GroupToStruct(list_group, current_levels, ctx, out, child_field); |
| 752 | } |
| 753 | |
| 754 | const auto& repeated_field = list_group.field(0); |
| 755 | if (!list_group.logical_type()->is_none() || repeated_field->is_repeated()) { |
| 756 | RETURN_NOT_OK(check_two_level_list_repetition(group)); |
| 757 | if (list_group.logical_type()->is_list()) { |
| 758 | // Special case where the inner type might be a list with two-level encoding |
| 759 | // like below: |
| 760 | // |
| 761 | // required/optional group name=SOMETHING (LIST) { |
| 762 | // repeated group array (LIST) { |
| 763 | // repeated TYPE item; |
no test coverage detected