zhjwpku commented on code in PR #662:
URL: https://github.com/apache/iceberg-cpp/pull/662#discussion_r3294955524
##########
src/iceberg/test/schema_json_test.cc:
##########
@@ -134,6 +135,87 @@ TEST(SchemaJsonTest, RoundTrip) {
ASSERT_EQ(dumped_json, json);
}
+TEST(SchemaJsonTest, UnknownFieldRoundTrip) {
+ constexpr std::string_view json =
+
R"({"fields":[{"id":1,"name":"mystery","required":false,"type":"unknown"}],"schema-id":1,"type":"struct"})";
+
+ ICEBERG_UNWRAP_OR_FAIL(auto schema,
SchemaFromJson(nlohmann::json::parse(json)));
+ ASSERT_EQ(schema->fields().size(), 1);
+
+ const auto& field = schema->fields()[0];
+ ASSERT_EQ(field.field_id(), 1);
+ ASSERT_EQ(field.name(), "mystery");
+ ASSERT_EQ(field.type()->type_id(), TypeId::kUnknown);
+ ASSERT_TRUE(field.optional());
+ ASSERT_EQ(ToJson(*schema).dump(), json);
+}
+
+TEST(SchemaJsonTest, NestedUnknownFieldsRoundTrip) {
+ constexpr std::string_view json =
+
R"({"fields":[{"id":1,"name":"profile","required":false,"type":{"fields":[{"id":2,"name":"mystery","required":false,"type":"unknown"}],"type":"struct"}},{"id":3,"name":"mysteries","required":false,"type":{"element":"unknown","element-id":4,"element-required":false,"type":"list"}},{"id":5,"name":"properties","required":false,"type":{"key":"string","key-id":6,"type":"map","value":"unknown","value-id":7,"value-required":false}}],"schema-id":1,"type":"struct"})";
Review Comment:
nit: It would be more readable if we made this multi-line.
##########
src/iceberg/test/schema_json_test.cc:
##########
@@ -134,6 +135,87 @@ TEST(SchemaJsonTest, RoundTrip) {
ASSERT_EQ(dumped_json, json);
}
+TEST(SchemaJsonTest, UnknownFieldRoundTrip) {
+ constexpr std::string_view json =
+
R"({"fields":[{"id":1,"name":"mystery","required":false,"type":"unknown"}],"schema-id":1,"type":"struct"})";
+
+ ICEBERG_UNWRAP_OR_FAIL(auto schema,
SchemaFromJson(nlohmann::json::parse(json)));
+ ASSERT_EQ(schema->fields().size(), 1);
+
+ const auto& field = schema->fields()[0];
+ ASSERT_EQ(field.field_id(), 1);
+ ASSERT_EQ(field.name(), "mystery");
+ ASSERT_EQ(field.type()->type_id(), TypeId::kUnknown);
+ ASSERT_TRUE(field.optional());
+ ASSERT_EQ(ToJson(*schema).dump(), json);
+}
+
+TEST(SchemaJsonTest, NestedUnknownFieldsRoundTrip) {
+ constexpr std::string_view json =
+
R"({"fields":[{"id":1,"name":"profile","required":false,"type":{"fields":[{"id":2,"name":"mystery","required":false,"type":"unknown"}],"type":"struct"}},{"id":3,"name":"mysteries","required":false,"type":{"element":"unknown","element-id":4,"element-required":false,"type":"list"}},{"id":5,"name":"properties","required":false,"type":{"key":"string","key-id":6,"type":"map","value":"unknown","value-id":7,"value-required":false}}],"schema-id":1,"type":"struct"})";
+
+ ICEBERG_UNWRAP_OR_FAIL(auto schema,
SchemaFromJson(nlohmann::json::parse(json)));
+ ASSERT_EQ(schema->fields().size(), 3);
+
+ const auto* profile = dynamic_cast<const
StructType*>(schema->fields()[0].type().get());
+ ASSERT_NE(profile, nullptr);
+ ASSERT_EQ(profile->fields().size(), 1);
+ ASSERT_EQ(profile->fields()[0].type()->type_id(), TypeId::kUnknown);
+ ASSERT_TRUE(profile->fields()[0].optional());
+
+ const auto* mysteries = dynamic_cast<const
ListType*>(schema->fields()[1].type().get());
+ ASSERT_NE(mysteries, nullptr);
+ ASSERT_EQ(mysteries->fields()[0].type()->type_id(), TypeId::kUnknown);
+ ASSERT_TRUE(mysteries->fields()[0].optional());
+
+ const auto* properties = dynamic_cast<const
MapType*>(schema->fields()[2].type().get());
+ ASSERT_NE(properties, nullptr);
+ ASSERT_EQ(properties->value().type()->type_id(), TypeId::kUnknown);
+ ASSERT_TRUE(properties->value().optional());
+
+ ASSERT_EQ(ToJson(*schema).dump(), json);
+}
+
+TEST(SchemaJsonTest, RejectRequiredUnknownField) {
+ constexpr std::string_view json =
+
R"({"fields":[{"id":1,"name":"mystery","required":true,"type":"unknown"}],"schema-id":1,"type":"struct"})";
+
+ auto schema_result = SchemaFromJson(nlohmann::json::parse(json));
+ ASSERT_THAT(schema_result, IsError(ErrorKind::kJsonParseError));
+ ASSERT_THAT(schema_result,
+ HasErrorMessage("Unknown type field 'mystery' must be
optional"));
+}
+
+TEST(SchemaJsonTest, RejectRequiredUnknownListElement) {
+ constexpr std::string_view json =
+
R"({"fields":[{"id":1,"name":"mysteries","required":false,"type":{"element":"unknown","element-id":2,"element-required":true,"type":"list"}}],"schema-id":1,"type":"struct"})";
+
+ auto schema_result = SchemaFromJson(nlohmann::json::parse(json));
+ ASSERT_THAT(schema_result, IsError(ErrorKind::kJsonParseError));
+ ASSERT_THAT(schema_result,
+ HasErrorMessage("Unknown type field 'element' must be
optional"));
+}
+
+TEST(SchemaJsonTest, RejectUnknownMapKey) {
+ constexpr std::string_view json =
+
R"({"fields":[{"id":1,"name":"mysteries","required":false,"type":{"key":"unknown","key-id":2,"type":"map","value":"string","value-id":3,"value-required":false}}],"schema-id":1,"type":"struct"})";
+
+ auto schema_result = SchemaFromJson(nlohmann::json::parse(json));
Review Comment:
From the spec: Map keys are required and map values can be either optional
or required. So I'm wondering should we report `'key' can not be unknow type`
rather than the current error msg?
##########
src/iceberg/json_serde.cc:
##########
@@ -458,6 +470,10 @@ Result<std::unique_ptr<Type>> MapTypeFromJson(const
nlohmann::json& json) {
ICEBERG_ASSIGN_OR_RAISE(auto value_id, GetJsonValue<int32_t>(json,
kValueId));
ICEBERG_ASSIGN_OR_RAISE(auto value_required, GetJsonValue<bool>(json,
kValueRequired));
+ ICEBERG_RETURN_UNEXPECTED(
Review Comment:
Maybe we can restrict `key_type` can't be `unknown` here, then we don't need
to call ValidateUnknownFieldOptional for key_type.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]