Status ParsePartitionSpecs()

in src/iceberg/json_internal.cc [1015:1066]


Status ParsePartitionSpecs(const nlohmann::json& json, int8_t format_version,
                           const std::shared_ptr<Schema>& current_schema,
                           int32_t& default_spec_id,
                           std::vector<std::shared_ptr<PartitionSpec>>& partition_specs) {
  if (json.contains(kPartitionSpecs)) {
    ICEBERG_ASSIGN_OR_RAISE(auto spec_array,
                            GetJsonValue<nlohmann::json>(json, kPartitionSpecs));
    if (!spec_array.is_array()) {
      return JsonParseError("Cannot parse partition specs from non-array: {}",
                            spec_array.dump());
    }
    ICEBERG_ASSIGN_OR_RAISE(default_spec_id, GetJsonValue<int32_t>(json, kDefaultSpecId));

    for (const auto& spec_json : spec_array) {
      ICEBERG_ASSIGN_OR_RAISE(auto spec,
                              PartitionSpecFromJson(current_schema, spec_json));
      partition_specs.push_back(std::move(spec));
    }
  } else {
    if (format_version != 1) {
      return JsonParseError("{} must exist in format v{}", kPartitionSpecs,
                            format_version);
    }

    ICEBERG_ASSIGN_OR_RAISE(auto partition_spec_json,
                            GetJsonValue<nlohmann::json>(json, kPartitionSpec));
    if (!partition_spec_json.is_array()) {
      return JsonParseError("Cannot parse v1 partition spec from non-array: {}",
                            partition_spec_json.dump());
    }

    int32_t next_partition_field_id = PartitionSpec::kLegacyPartitionDataIdStart;
    std::vector<PartitionField> fields;
    for (const auto& entry_json : partition_spec_json) {
      ICEBERG_ASSIGN_OR_RAISE(auto field, PartitionFieldFromJson(entry_json));
      int32_t field_id = field->field_id();
      if (field_id == SchemaField::kInvalidFieldId) {
        // If the field ID is not set, we need to assign a new one
        field_id = next_partition_field_id++;
      }
      fields.emplace_back(field->source_id(), field_id, std::string(field->name()),
                          std::move(field->transform()));
    }

    auto spec = std::make_unique<PartitionSpec>(
        current_schema, PartitionSpec::kInitialSpecId, std::move(fields));
    default_spec_id = spec->spec_id();
    partition_specs.push_back(std::move(spec));
  }

  return {};
}