diff options
author | imunkin <imunkin@yandex-team.com> | 2024-11-08 10:00:23 +0300 |
---|---|---|
committer | imunkin <imunkin@yandex-team.com> | 2024-11-08 10:12:13 +0300 |
commit | a784a2f943d6e15caa6241e2e96d80aac6dbf375 (patch) | |
tree | 05f1e5366c916b988a8afb75bdab8ddeee0f6e6d /yql/essentials/udfs/common/protobuf/protobuf_udf.cpp | |
parent | d70137a7b530ccaa52834274913bbb5a3d1ca06e (diff) | |
download | ydb-a784a2f943d6e15caa6241e2e96d80aac6dbf375.tar.gz |
Move yql/udfs/common/ to /yql/essentials YQL-19206
Except the following directories:
* clickhouse/client
* datetime
* knn
* roaring
commit_hash:c7da95636144d28db109d6b17ddc762e9bacb59f
Diffstat (limited to 'yql/essentials/udfs/common/protobuf/protobuf_udf.cpp')
-rw-r--r-- | yql/essentials/udfs/common/protobuf/protobuf_udf.cpp | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/yql/essentials/udfs/common/protobuf/protobuf_udf.cpp b/yql/essentials/udfs/common/protobuf/protobuf_udf.cpp new file mode 100644 index 0000000000..4b7df61c28 --- /dev/null +++ b/yql/essentials/udfs/common/protobuf/protobuf_udf.cpp @@ -0,0 +1,143 @@ +#include <yql/essentials/minikql/protobuf_udf/type_builder.h> +#include <yql/essentials/minikql/protobuf_udf/value_builder.h> +#include <yql/essentials/public/udf/udf_value.h> +#include <yql/essentials/public/udf/udf_registrator.h> + +#include <library/cpp/protobuf/yql/descriptor.h> + +using namespace NKikimr::NUdf; +using namespace NProtoBuf; + +namespace { + class TDynamicProtoValue: public TProtobufValue { + public: + TDynamicProtoValue(const TProtoInfo& info, TDynamicInfoRef dyn) + : TProtobufValue(info) + , Dynamic_(dyn) + { + Y_ASSERT(Dynamic_ != nullptr); + } + + TAutoPtr<Message> Parse(const TStringBuf& data) const override { + return Dynamic_->Parse(data); + } + + private: + TDynamicInfoRef Dynamic_; + }; + + class TDynamicProtoSerialize: public TProtobufSerialize { + public: + TDynamicProtoSerialize(const TProtoInfo& info, TDynamicInfoRef dyn) + : TProtobufSerialize(info) + , Dynamic_(dyn) + { + Y_ASSERT(Dynamic_ != nullptr); + } + + TMaybe<TString> Serialize(const Message& proto) const override { + return Dynamic_->Serialize(proto); + } + + TAutoPtr<Message> MakeProto() const override { + return Dynamic_->MakeProto(); + } + private: + TDynamicInfoRef Dynamic_; + }; + + class TDynamicProtoValueSafe: public TDynamicProtoValue { + public: + TDynamicProtoValueSafe(const TProtoInfo& info, TDynamicInfoRef dyn) + : TDynamicProtoValue(info, dyn) {} + + TAutoPtr<Message> Parse(const TStringBuf& data) const override { + try { + return TDynamicProtoValue::Parse(data); + } catch (const std::exception& e) { + return nullptr; + } + } + }; + + class TProtobufModule: public IUdfModule { + public: + TStringRef Name() const { + return TStringRef("Protobuf"); + } + + void CleanupOnTerminate() const final { + } + + void GetAllFunctions(IFunctionsSink& sink) const final { + sink.Add(TStringRef::Of("Parse"))->SetTypeAwareness(); + sink.Add(TStringRef::Of("TryParse"))->SetTypeAwareness(); + sink.Add(TStringRef::Of("Serialize"))->SetTypeAwareness(); + } + + void BuildFunctionTypeInfo( + const TStringRef& name, + TType* userType, + const TStringRef& typeConfig, + ui32 flags, + IFunctionTypeInfoBuilder& builder) const final { + Y_UNUSED(userType); + + try { + auto dyn = TDynamicInfo::Create(TStringBuf(typeConfig.Data(), typeConfig.Size())); + + TProtoInfo typeInfo; + ProtoTypeBuild(dyn->Descriptor(), + dyn->GetEnumFormat(), + dyn->GetRecursionTraits(), + dyn->GetOptionalLists(), + builder, &typeInfo, + EProtoStringYqlType::Bytes, + dyn->GetSyntaxAware(), + false, + dyn->GetYtMode()); + + auto stringType = builder.SimpleType<char*>(); + auto structType = typeInfo.StructType; + auto optionalStructType = builder.Optional()->Item(structType).Build(); + + if (TStringRef::Of("Serialize") == name) { + // function signature: + // String Serialize(Protobuf value) + builder.Returns(stringType) + .Args() + ->Add(structType) + .Flags(ICallablePayload::TArgumentFlags::AutoMap) + .Done(); + if ((flags & TFlags::TypesOnly) == 0) { + builder.Implementation(new TDynamicProtoSerialize(typeInfo, dyn)); + } + } else { + // function signature: + // Protobuf Parse(String value) + builder.Returns((TStringRef::Of("TryParse") == name) ? optionalStructType : structType) + .Args() + ->Add(stringType) + .Flags(ICallablePayload::TArgumentFlags::AutoMap) + .Done(); + + if (TStringRef::Of("Parse") == name) { + if ((flags & TFlags::TypesOnly) == 0) { + builder.Implementation(new TDynamicProtoValue(typeInfo, dyn)); + } + } else if (TStringRef::Of("TryParse") == name) { + if ((flags & TFlags::TypesOnly) == 0) { + builder.Implementation(new TDynamicProtoValueSafe(typeInfo, dyn)); + } + } + } + + } catch (const std::exception& e) { + builder.SetError(CurrentExceptionMessage()); + } + } + }; + +} + +REGISTER_MODULES(TProtobufModule); |