aboutsummaryrefslogtreecommitdiffstats
path: root/yql/essentials/udfs/common/protobuf/protobuf_udf.cpp
diff options
context:
space:
mode:
authorimunkin <imunkin@yandex-team.com>2024-11-08 10:00:23 +0300
committerimunkin <imunkin@yandex-team.com>2024-11-08 10:12:13 +0300
commita784a2f943d6e15caa6241e2e96d80aac6dbf375 (patch)
tree05f1e5366c916b988a8afb75bdab8ddeee0f6e6d /yql/essentials/udfs/common/protobuf/protobuf_udf.cpp
parentd70137a7b530ccaa52834274913bbb5a3d1ca06e (diff)
downloadydb-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.cpp143
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);