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;