This is an automated email from the ASF dual-hosted git repository.

fokko pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/avro.git


The following commit(s) were added to refs/heads/main by this push:
     new 3b0c0f40c AVRO-4120: [C++] Allow custom attributes for MAP, FIXED and 
ENUM types (#3324)
3b0c0f40c is described below

commit 3b0c0f40c9fc5596111d8aa4f3e467d0f9e92e50
Author: Gang Wu <[email protected]>
AuthorDate: Sun Mar 2 04:00:45 2025 +0800

    AVRO-4120: [C++] Allow custom attributes for MAP, FIXED and ENUM types 
(#3324)
    
    * AVRO-4120: [C++] Allow custom attributes for MAP and FIXED types
    
    * support enum
---
 lang/c++/impl/Compiler.cc         | 17 ++++++++++++++++-
 lang/c++/impl/NodeImpl.cc         | 15 ++++++++++++---
 lang/c++/include/avro/NodeImpl.hh | 12 ++++++------
 lang/c++/test/SchemaTests.cc      | 15 ++++++++-------
 4 files changed, 42 insertions(+), 17 deletions(-)

diff --git a/lang/c++/impl/Compiler.cc b/lang/c++/impl/Compiler.cc
index 0e48e06bb..ee982a36f 100644
--- a/lang/c++/impl/Compiler.cc
+++ b/lang/c++/impl/Compiler.cc
@@ -281,7 +281,7 @@ static const std::unordered_set<std::string> 
&getKnownFields() {
     // return known fields
     static const std::unordered_set<std::string> kKnownFields =
         {"name", "type", "aliases", "default", "doc", "size", "logicalType",
-         "values", "precision", "scale", "namespace", "items"};
+         "values", "precision", "scale", "namespace", "items", "symbols"};
     return kKnownFields;
 }
 
@@ -417,6 +417,11 @@ static NodePtr makeEnumNode(const Entity &e,
     if (containsField(m, "doc")) {
         node->setDoc(getDocField(e, m));
     }
+
+    CustomAttributes customAttributes;
+    getCustomAttributes(m, customAttributes);
+    node->addCustomAttributesForField(customAttributes);
+
     return node;
 }
 
@@ -431,6 +436,11 @@ static NodePtr makeFixedNode(const Entity &e,
     if (containsField(m, "doc")) {
         node->setDoc(getDocField(e, m));
     }
+
+    CustomAttributes customAttributes;
+    getCustomAttributes(m, customAttributes);
+    node->addCustomAttributesForField(customAttributes);
+
     return node;
 }
 
@@ -457,6 +467,11 @@ static NodePtr makeMapNode(const Entity &e, const Object 
&m,
     if (containsField(m, "doc")) {
         node->setDoc(getDocField(e, m));
     }
+
+    CustomAttributes customAttributes;
+    getCustomAttributes(m, customAttributes);
+    node->addCustomAttributesForField(customAttributes);
+
     return node;
 }
 
diff --git a/lang/c++/impl/NodeImpl.cc b/lang/c++/impl/NodeImpl.cc
index a17732bcc..bc6bf400a 100644
--- a/lang/c++/impl/NodeImpl.cc
+++ b/lang/c++/impl/NodeImpl.cc
@@ -541,6 +541,9 @@ void NodeEnum::printJson(std::ostream &os, size_t depth) 
const {
     }
     os << '\n';
     os << indent(--depth) << "]\n";
+    for (size_t i = 0; i != customAttributes_.size(); i++) {
+        printCustomAttributes(customAttributes_.get(i), depth, os);
+    }
     os << indent(--depth) << '}';
 }
 
@@ -554,7 +557,7 @@ void NodeArray::printJson(std::ostream &os, size_t depth) 
const {
     os << indent(depth + 1) << "\"items\": ";
     leafAttributes_.get()->printJson(os, depth + 1);
     os << '\n';
-    for (size_t i = 0; i != customAttributes_.size(); i++){
+    for (size_t i = 0; i != customAttributes_.size(); i++) {
         printCustomAttributes(customAttributes_.get(i), depth + 1, os);
     }
     os << indent(depth) << '}';
@@ -570,6 +573,9 @@ void NodeMap::printJson(std::ostream &os, size_t depth) 
const {
     os << indent(depth + 1) << "\"values\": ";
     leafAttributes_.get(1)->printJson(os, depth + 1);
     os << '\n';
+    for (size_t i = 0; i != customAttributes_.size(); i++) {
+        printCustomAttributes(customAttributes_.get(i), depth + 1, os);
+    }
     os << indent(depth) << '}';
 }
 
@@ -609,8 +615,11 @@ void NodeFixed::printJson(std::ostream &os, size_t depth) 
const {
         logicalType().printJson(os);
     }
 
-    os << "\n"
-       << indent(--depth) << '}';
+    os << "\n";
+    for (size_t i = 0; i != customAttributes_.size(); i++) {
+        printCustomAttributes(customAttributes_.get(i), depth, os);
+    }
+    os << indent(--depth) << '}';
 }
 
 } // namespace avro
diff --git a/lang/c++/include/avro/NodeImpl.hh 
b/lang/c++/include/avro/NodeImpl.hh
index b4759f70e..d8a1da3c3 100644
--- a/lang/c++/include/avro/NodeImpl.hh
+++ b/lang/c++/include/avro/NodeImpl.hh
@@ -233,11 +233,11 @@ using NodeImplPrimitive = NodeImpl<NoName, NoLeaves, 
NoLeafNames, MultiAttribute
 using NodeImplSymbolic = NodeImpl<HasName, NoLeaves, NoLeafNames, 
NoAttributes, NoSize>;
 
 using NodeImplRecord = NodeImpl<HasName, MultiLeaves, LeafNames, 
MultiAttributes, NoSize>;
-using NodeImplEnum = NodeImpl<HasName, NoLeaves, LeafNames, NoAttributes, 
NoSize>;
+using NodeImplEnum = NodeImpl<HasName, NoLeaves, LeafNames, MultiAttributes, 
NoSize>;
 using NodeImplArray = NodeImpl<NoName, SingleLeaf, NoLeafNames, 
MultiAttributes, NoSize>;
-using NodeImplMap = NodeImpl<NoName, MultiLeaves, NoLeafNames, NoAttributes, 
NoSize>;
+using NodeImplMap = NodeImpl<NoName, MultiLeaves, NoLeafNames, 
MultiAttributes, NoSize>;
 using NodeImplUnion = NodeImpl<NoName, MultiLeaves, NoLeafNames, NoAttributes, 
NoSize>;
-using NodeImplFixed = NodeImpl<HasName, NoLeaves, NoLeafNames, NoAttributes, 
HasSize>;
+using NodeImplFixed = NodeImpl<HasName, NoLeaves, NoLeafNames, 
MultiAttributes, HasSize>;
 
 class AVRO_DECL NodePrimitive : public NodeImplPrimitive {
 public:
@@ -339,7 +339,7 @@ class AVRO_DECL NodeEnum : public NodeImplEnum {
 public:
     NodeEnum() : NodeImplEnum(AVRO_ENUM) {}
 
-    NodeEnum(const HasName &name, const LeafNames &symbols) : 
NodeImplEnum(AVRO_ENUM, name, NoLeaves(), symbols, NoAttributes(), NoSize()) {
+    NodeEnum(const HasName &name, const LeafNames &symbols) : 
NodeImplEnum(AVRO_ENUM, name, NoLeaves(), symbols, {}, NoSize()) {
         for (size_t i = 0; i < leafNameAttributes_.size(); ++i) {
             if (!nameIndex_.add(leafNameAttributes_.get(i), i)) {
                 throw Exception("Cannot add duplicate enum: {}", 
leafNameAttributes_.get(i));
@@ -380,7 +380,7 @@ class AVRO_DECL NodeMap : public NodeImplMap {
 public:
     NodeMap();
 
-    explicit NodeMap(const SingleLeaf &values) : NodeImplMap(AVRO_MAP, 
NoName(), MultiLeaves(values), NoLeafNames(), NoAttributes(), NoSize()) {
+    explicit NodeMap(const SingleLeaf &values) : NodeImplMap(AVRO_MAP, 
NoName(), MultiLeaves(values), NoLeafNames(), {}, NoSize()) {
         // need to add the key for the map too
         NodePtr key(new NodePrimitive(AVRO_STRING));
         doAddLeaf(key);
@@ -473,7 +473,7 @@ class AVRO_DECL NodeFixed : public NodeImplFixed {
 public:
     NodeFixed() : NodeImplFixed(AVRO_FIXED) {}
 
-    NodeFixed(const HasName &name, const HasSize &size) : 
NodeImplFixed(AVRO_FIXED, name, NoLeaves(), NoLeafNames(), NoAttributes(), 
size) {}
+    NodeFixed(const HasName &name, const HasSize &size) : 
NodeImplFixed(AVRO_FIXED, name, NoLeaves(), NoLeafNames(), {}, size) {}
 
     SchemaResolution resolve(const Node &reader) const override;
 
diff --git a/lang/c++/test/SchemaTests.cc b/lang/c++/test/SchemaTests.cc
index 857beadf9..24e827e3f 100644
--- a/lang/c++/test/SchemaTests.cc
+++ b/lang/c++/test/SchemaTests.cc
@@ -181,8 +181,7 @@ const char *basicSchemas[] = {
         "fields":[
             {"name": "f1","type": "long","extra field1": "1","extra field2": 
"2"}
         ]
-    })"
-};
+    })"};
 
 const char *basicSchemaErrors[] = {
     // Record
@@ -361,7 +360,10 @@ const char *roundTripSchemas[] = {
             {"name":"f2","type":"int","extra_field1":"21","extra_field2":"22"}
         ]
     })",
-    R"({"type":"array","items":"long","extra":"1"})"
+    R"({"type":"array","items":"long","extra":"1"})",
+    R"({"type":"map","values":"long","extra":"1"})",
+    R"({"type":"fixed","name":"Test","size":1,"extra":"1"})",
+    R"({"type":"enum","name":"Test","symbols":["A","B"],"extra":"1"})",
 };
 
 const char *malformedLogicalTypes[] = {
@@ -416,14 +418,13 @@ const char *compactSchemas[] = {
     "\"fields\":["
     "{\"name\":\"re1\",\"type\":\"long\",\"doc\":\"A \\\"quoted doc\\\"\"},"
     "{\"name\":\"re2\",\"type\":\"long\",\"doc\":\"extra slashes\\\\\\\\\"}"
-    "]}"
-};
+    "]}"};
 
 static const std::vector<char> whitespaces = {' ', '\f', '\n', '\r', '\t', 
'\v'};
 
-static std::string removeWhitespaceFromSchema(const std::string& schema){
+static std::string removeWhitespaceFromSchema(const std::string &schema) {
     std::string trimmedSchema = schema;
-    for (char toReplace : whitespaces){
+    for (char toReplace : whitespaces) {
         boost::algorithm::replace_all(trimmedSchema, std::string{toReplace}, 
"");
     }
     return trimmedSchema;

Reply via email to