diff --git a/src/iceberg/schema_field.cc b/src/iceberg/schema_field.cc index 9edf0a49c..04dc35bc6 100644 --- a/src/iceberg/schema_field.cc +++ b/src/iceberg/schema_field.cc @@ -27,20 +27,21 @@ namespace iceberg { SchemaField::SchemaField(int32_t field_id, std::string name, std::shared_ptr type, - bool optional) + bool optional, std::string doc) : field_id_(field_id), name_(std::move(name)), type_(std::move(type)), - optional_(optional) {} + optional_(optional), + doc_(std::move(doc)) {} SchemaField SchemaField::MakeOptional(int32_t field_id, std::string name, - std::shared_ptr type) { - return SchemaField(field_id, std::move(name), std::move(type), true); + std::shared_ptr type, std::string doc) { + return {field_id, std::move(name), std::move(type), true, std::move(doc)}; } SchemaField SchemaField::MakeRequired(int32_t field_id, std::string name, - std::shared_ptr type) { - return SchemaField(field_id, std::move(name), std::move(type), false); + std::shared_ptr type, std::string doc) { + return {field_id, std::move(name), std::move(type), false, std::move(doc)}; } int32_t SchemaField::field_id() const { return field_id_; } @@ -51,9 +52,13 @@ const std::shared_ptr& SchemaField::type() const { return type_; } bool SchemaField::optional() const { return optional_; } +std::string_view SchemaField::doc() const { return doc_; } + std::string SchemaField::ToString() const { - return std::format("{} ({}): {} ({})", name_, field_id_, *type_, - optional_ ? "optional" : "required"); + std::string result = std::format("{} ({}): {} ({}){}", name_, field_id_, *type_, + optional_ ? "optional" : "required", + !doc_.empty() ? std::format(" - {}", doc_) : ""); + return result; } bool SchemaField::Equals(const SchemaField& other) const { diff --git a/src/iceberg/schema_field.h b/src/iceberg/schema_field.h index 7f33728f2..afef71738 100644 --- a/src/iceberg/schema_field.h +++ b/src/iceberg/schema_field.h @@ -44,15 +44,16 @@ class ICEBERG_EXPORT SchemaField : public iceberg::util::Formattable { /// \param[in] name The field name. /// \param[in] type The field type. /// \param[in] optional Whether values of this field are required or nullable. + /// \param[in] doc Optional documentation string for the field. SchemaField(int32_t field_id, std::string name, std::shared_ptr type, - bool optional); + bool optional, std::string doc = {}); /// \brief Construct an optional (nullable) field. static SchemaField MakeOptional(int32_t field_id, std::string name, - std::shared_ptr type); + std::shared_ptr type, std::string doc = {}); /// \brief Construct a required (non-null) field. static SchemaField MakeRequired(int32_t field_id, std::string name, - std::shared_ptr type); + std::shared_ptr type, std::string doc = {}); /// \brief Get the field ID. [[nodiscard]] int32_t field_id() const; @@ -66,6 +67,9 @@ class ICEBERG_EXPORT SchemaField : public iceberg::util::Formattable { /// \brief Get whether the field is optional. [[nodiscard]] bool optional() const; + /// \brief Get the field documentation. + std::string_view doc() const; + [[nodiscard]] std::string ToString() const override; friend bool operator==(const SchemaField& lhs, const SchemaField& rhs) { @@ -84,6 +88,7 @@ class ICEBERG_EXPORT SchemaField : public iceberg::util::Formattable { std::string name_; std::shared_ptr type_; bool optional_; + std::string doc_; }; } // namespace iceberg diff --git a/test/schema_field_test.cc b/test/schema_field_test.cc index 76833a965..a03cc531f 100644 --- a/test/schema_field_test.cc +++ b/test/schema_field_test.cc @@ -79,3 +79,29 @@ TEST(SchemaFieldTest, Equality) { ASSERT_EQ(field1, field6); ASSERT_EQ(field6, field1); } + +TEST(SchemaFieldTest, WithDoc) { + { + iceberg::SchemaField field(/*field_id=*/1, /*name=*/"foo", + std::make_shared(), + /*optional=*/false, /*doc=*/"Field documentation"); + EXPECT_EQ(1, field.field_id()); + EXPECT_EQ("foo", field.name()); + EXPECT_EQ(iceberg::TypeId::kInt, field.type()->type_id()); + EXPECT_FALSE(field.optional()); + EXPECT_EQ("Field documentation", field.doc()); + EXPECT_EQ("foo (1): int (required) - Field documentation", field.ToString()); + } + { + iceberg::SchemaField field = iceberg::SchemaField::MakeOptional( + /*field_id=*/2, /*name=*/"bar", + /*type=*/std::make_shared(10), + /*doc=*/"Field with 10 bytes"); + EXPECT_EQ(2, field.field_id()); + EXPECT_EQ("bar", field.name()); + EXPECT_EQ(iceberg::FixedType(10), *field.type()); + EXPECT_TRUE(field.optional()); + EXPECT_EQ("Field with 10 bytes", field.doc()); + EXPECT_EQ("bar (2): fixed(10) (optional) - Field with 10 bytes", field.ToString()); + } +}