@@ -48,6 +48,10 @@ ::avro::LogicalType GetMapLogicalType() {
4848 return ::avro::LogicalType (std::make_shared<MapLogicalType>());
4949}
5050
51+ ::avro::LogicalType GetVariantLogicalType () {
52+ return ::avro::LogicalType (std::make_shared<VariantLogicalType>());
53+ }
54+
5155::avro::CustomAttributes GetAttributesWithFieldId (int32_t field_id) {
5256 ::avro::CustomAttributes attributes;
5357 attributes.addAttribute (std::string (kFieldIdProp ), std::to_string (field_id),
@@ -237,6 +241,22 @@ Status ToAvroNodeVisitor::Visit(const BinaryType& type, ::avro::NodePtr* node) {
237241 return {};
238242}
239243
244+ Status ToAvroNodeVisitor::Visit (const VariantType& type, ::avro::NodePtr* node) {
245+ *node = std::make_shared<::avro::NodeRecord>();
246+ if (field_ids_.empty ()) {
247+ (*node)->setName (::avro::Name (std::string (kVariantLogicalType )));
248+ } else {
249+ (*node)->setName (::avro::Name (std::format (" r{}" , field_ids_.top ())));
250+ }
251+ (*node)->setLogicalType (GetVariantLogicalType ());
252+
253+ (*node)->addName (std::string (kMetadata ));
254+ (*node)->addLeaf (std::make_shared<::avro::NodePrimitive>(::avro::AVRO_BYTES ));
255+ (*node)->addName (std::string (kValue ));
256+ (*node)->addLeaf (std::make_shared<::avro::NodePrimitive>(::avro::AVRO_BYTES ));
257+ return {};
258+ }
259+
240260Status ToAvroNodeVisitor::Visit (const StructType& type, ::avro::NodePtr* node) {
241261 *node = std::make_shared<::avro::NodeRecord>();
242262
@@ -392,6 +412,10 @@ Status HasIdVisitor::Visit(const ::avro::NodePtr& node) {
392412}
393413
394414Status HasIdVisitor::VisitRecord (const ::avro::NodePtr& node) {
415+ if (HasVariantLogicalType (node)) {
416+ return {};
417+ }
418+
395419 static const std::string kFieldIdKey {kFieldIdProp };
396420 total_fields_ += node->leaves ();
397421 for (size_t i = 0 ; i < node->leaves (); ++i) {
@@ -510,6 +534,13 @@ Result<int32_t> GetFieldId(const ::avro::NodePtr& node, size_t field_idx) {
510534 return GetId (node, kFieldIdKey , field_idx);
511535}
512536
537+ bool IsVariantAvroSchema (const ::avro::NodePtr& node) {
538+ return HasVariantLogicalType (node) && node->type () == ::avro::AVRO_RECORD &&
539+ node->leaves () == 2 && node->names () == 2 && node->nameAt (0 ) == kMetadata &&
540+ node->nameAt (1 ) == kValue && node->leafAt (0 )->type () == ::avro::AVRO_BYTES &&
541+ node->leafAt (1 )->type () == ::avro::AVRO_BYTES ;
542+ }
543+
513544Status ValidateAvroSchemaEvolution (const Type& expected_type,
514545 const ::avro::NodePtr& avro_node) {
515546 switch (expected_type.type_id ()) {
@@ -615,6 +646,11 @@ Status ValidateAvroSchemaEvolution(const Type& expected_type,
615646 return {};
616647 }
617648 break ;
649+ case TypeId::kVariant :
650+ if (IsVariantAvroSchema (avro_node)) {
651+ return {};
652+ }
653+ break ;
618654 default :
619655 break ;
620656 }
@@ -847,7 +883,13 @@ Result<FieldProjection> ProjectNested(const Type& expected_type,
847883bool HasMapLogicalType (const ::avro::NodePtr& node) {
848884 return node->logicalType ().type () == ::avro::LogicalType::CUSTOM &&
849885 node->logicalType ().customLogicalType () != nullptr &&
850- node->logicalType ().customLogicalType ()->name () == " map" ;
886+ node->logicalType ().customLogicalType ()->name () == kMapLogicalType ;
887+ }
888+
889+ bool HasVariantLogicalType (const ::avro::NodePtr& node) {
890+ return node->logicalType ().type () == ::avro::LogicalType::CUSTOM &&
891+ node->logicalType ().customLogicalType () != nullptr &&
892+ node->logicalType ().customLogicalType ()->name () == kVariantLogicalType ;
851893}
852894
853895Result<SchemaProjection> Project (const Schema& expected_schema,
@@ -1032,6 +1074,10 @@ Result<::avro::NodePtr> MakeUnionNodeWithFieldIds(const ::avro::NodePtr& origina
10321074Result<::avro::NodePtr> MakeAvroNodeWithFieldIds (const ::avro::NodePtr& original_node,
10331075 const NameMapping& mapping,
10341076 std::vector<std::string>& names) {
1077+ if (HasVariantLogicalType (original_node)) {
1078+ return original_node;
1079+ }
1080+
10351081 switch (original_node->type ()) {
10361082 case ::avro::AVRO_RECORD :
10371083 return MakeRecordNodeWithFieldIds (original_node, mapping, names);
0 commit comments