@@ -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),
@@ -242,6 +246,22 @@ Status ToAvroNodeVisitor::Visit(const UnknownType&, ::avro::NodePtr* node) {
242246 return {};
243247}
244248
249+ Status ToAvroNodeVisitor::Visit (const VariantType& type, ::avro::NodePtr* node) {
250+ *node = std::make_shared<::avro::NodeRecord>();
251+ if (field_ids_.empty ()) {
252+ (*node)->setName (::avro::Name (std::string (kVariantLogicalType )));
253+ } else {
254+ (*node)->setName (::avro::Name (std::format (" r{}" , field_ids_.top ())));
255+ }
256+ (*node)->setLogicalType (GetVariantLogicalType ());
257+
258+ (*node)->addName (std::string (kMetadata ));
259+ (*node)->addLeaf (std::make_shared<::avro::NodePrimitive>(::avro::AVRO_BYTES ));
260+ (*node)->addName (std::string (kValue ));
261+ (*node)->addLeaf (std::make_shared<::avro::NodePrimitive>(::avro::AVRO_BYTES ));
262+ return {};
263+ }
264+
245265Status ToAvroNodeVisitor::Visit (const StructType& type, ::avro::NodePtr* node) {
246266 *node = std::make_shared<::avro::NodeRecord>();
247267
@@ -397,6 +417,10 @@ Status HasIdVisitor::Visit(const ::avro::NodePtr& node) {
397417}
398418
399419Status HasIdVisitor::VisitRecord (const ::avro::NodePtr& node) {
420+ if (HasVariantLogicalType (node)) {
421+ return {};
422+ }
423+
400424 static const std::string kFieldIdKey {kFieldIdProp };
401425 total_fields_ += node->leaves ();
402426 for (size_t i = 0 ; i < node->leaves (); ++i) {
@@ -515,6 +539,13 @@ Result<int32_t> GetFieldId(const ::avro::NodePtr& node, size_t field_idx) {
515539 return GetId (node, kFieldIdKey , field_idx);
516540}
517541
542+ bool IsVariantAvroSchema (const ::avro::NodePtr& node) {
543+ return HasVariantLogicalType (node) && node->type () == ::avro::AVRO_RECORD &&
544+ node->leaves () == 2 && node->names () == 2 && node->nameAt (0 ) == kMetadata &&
545+ node->nameAt (1 ) == kValue && node->leafAt (0 )->type () == ::avro::AVRO_BYTES &&
546+ node->leafAt (1 )->type () == ::avro::AVRO_BYTES ;
547+ }
548+
518549Status ValidateAvroSchemaEvolution (const Type& expected_type,
519550 const ::avro::NodePtr& avro_node) {
520551 if (avro_node->type () == ::avro::AVRO_NULL ) {
@@ -626,6 +657,11 @@ Status ValidateAvroSchemaEvolution(const Type& expected_type,
626657 break ;
627658 case TypeId::kUnknown :
628659 return {};
660+ case TypeId::kVariant :
661+ if (IsVariantAvroSchema (avro_node)) {
662+ return {};
663+ }
664+ break ;
629665 default :
630666 break ;
631667 }
@@ -859,7 +895,13 @@ Result<FieldProjection> ProjectNested(const Type& expected_type,
859895bool HasMapLogicalType (const ::avro::NodePtr& node) {
860896 return node->logicalType ().type () == ::avro::LogicalType::CUSTOM &&
861897 node->logicalType ().customLogicalType () != nullptr &&
862- node->logicalType ().customLogicalType ()->name () == " map" ;
898+ node->logicalType ().customLogicalType ()->name () == kMapLogicalType ;
899+ }
900+
901+ bool HasVariantLogicalType (const ::avro::NodePtr& node) {
902+ return node->logicalType ().type () == ::avro::LogicalType::CUSTOM &&
903+ node->logicalType ().customLogicalType () != nullptr &&
904+ node->logicalType ().customLogicalType ()->name () == kVariantLogicalType ;
863905}
864906
865907Result<SchemaProjection> Project (const Schema& expected_schema,
@@ -1044,6 +1086,10 @@ Result<::avro::NodePtr> MakeUnionNodeWithFieldIds(const ::avro::NodePtr& origina
10441086Result<::avro::NodePtr> MakeAvroNodeWithFieldIds (const ::avro::NodePtr& original_node,
10451087 const NameMapping& mapping,
10461088 std::vector<std::string>& names) {
1089+ if (HasVariantLogicalType (original_node)) {
1090+ return original_node;
1091+ }
1092+
10471093 switch (original_node->type ()) {
10481094 case ::avro::AVRO_RECORD :
10491095 return MakeRecordNodeWithFieldIds (original_node, mapping, names);
0 commit comments