| 1042 | } |
| 1043 | |
| 1044 | Result<bool> ApplyOriginalStorageMetadata(const Field& origin_field, |
| 1045 | SchemaField* inferred) { |
| 1046 | bool modified = false; |
| 1047 | |
| 1048 | auto& origin_type = origin_field.type(); |
| 1049 | auto& inferred_type = inferred->field->type(); |
| 1050 | |
| 1051 | const int num_children = inferred_type->num_fields(); |
| 1052 | |
| 1053 | if (num_children > 0 && origin_type->num_fields() == num_children) { |
| 1054 | DCHECK_EQ(static_cast<int>(inferred->children.size()), num_children); |
| 1055 | const auto factory = GetNestedFactory(*origin_type, *inferred_type); |
| 1056 | if (factory) { |
| 1057 | // The type may be modified (e.g. LargeList) while the children stay the same |
| 1058 | modified |= origin_type->id() != inferred_type->id(); |
| 1059 | |
| 1060 | // Apply original metadata recursively to children |
| 1061 | for (int i = 0; i < inferred_type->num_fields(); ++i) { |
| 1062 | ARROW_ASSIGN_OR_RAISE( |
| 1063 | const bool child_modified, |
| 1064 | ApplyOriginalMetadata(*origin_type->field(i), &inferred->children[i])); |
| 1065 | modified |= child_modified; |
| 1066 | } |
| 1067 | if (modified) { |
| 1068 | // Recreate this field using the modified child fields |
| 1069 | ::arrow::FieldVector modified_children(inferred_type->num_fields()); |
| 1070 | for (int i = 0; i < inferred_type->num_fields(); ++i) { |
| 1071 | modified_children[i] = inferred->children[i].field; |
| 1072 | } |
| 1073 | inferred->field = |
| 1074 | inferred->field->WithType(factory(std::move(modified_children))); |
| 1075 | } |
| 1076 | } |
| 1077 | } |
| 1078 | |
| 1079 | if (origin_type->id() == ::arrow::Type::TIMESTAMP && |
| 1080 | inferred_type->id() == ::arrow::Type::TIMESTAMP) { |
| 1081 | // Restore time zone, if any |
| 1082 | const auto& ts_type = checked_cast<const ::arrow::TimestampType&>(*inferred_type); |
| 1083 | const auto& ts_origin_type = |
| 1084 | checked_cast<const ::arrow::TimestampType&>(*origin_type); |
| 1085 | |
| 1086 | // If the data is tz-aware, then set the original time zone, since Parquet |
| 1087 | // has no native storage for timezones |
| 1088 | if (ts_type.timezone() == "UTC" && !ts_origin_type.timezone().empty()) { |
| 1089 | if (ts_type.unit() == ts_origin_type.unit()) { |
| 1090 | inferred->field = inferred->field->WithType(origin_type); |
| 1091 | } else { |
| 1092 | auto ts_type_new = ::arrow::timestamp(ts_type.unit(), ts_origin_type.timezone()); |
| 1093 | inferred->field = inferred->field->WithType(ts_type_new); |
| 1094 | } |
| 1095 | } |
| 1096 | modified = true; |
| 1097 | } |
| 1098 | |
| 1099 | if (origin_type->id() == ::arrow::Type::DURATION && |
| 1100 | inferred_type->id() == ::arrow::Type::INT64) { |
| 1101 | // Read back int64 arrays as duration. |
no test coverage detected