|
5 | 5 | namespace NKikimr {
|
6 | 6 | namespace NMiniKQL {
|
7 | 7 |
|
| 8 | +class TImpl : public NYql::NUdf::TBoxedValue { |
| 9 | +public: |
| 10 | + explicit TImpl(NYql::NUdf::TSourcePosition pos, |
| 11 | + const std::string_view upvalue) |
| 12 | + : Pos_(pos) |
| 13 | + , Upvalue_(upvalue) |
| 14 | + {} |
| 15 | + |
| 16 | + NYql::NUdf::TUnboxedValue Run(const NYql::NUdf::IValueBuilder* valueBuilder, |
| 17 | + const NYql::NUdf::TUnboxedValuePod* args) |
| 18 | + const override try { |
| 19 | + TStringStream concat; |
| 20 | + concat << Upvalue_ << " " << args[0].AsStringRef(); |
| 21 | + return valueBuilder->NewString(NYql::NUdf::TStringRef(concat.Data(), |
| 22 | + concat.Size())); |
| 23 | + } catch (const std::exception& e) { |
| 24 | + UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).data()); |
| 25 | + } |
| 26 | + |
| 27 | + |
| 28 | +private: |
| 29 | + const NYql::NUdf::TSourcePosition Pos_; |
| 30 | + const TString Upvalue_; |
| 31 | +}; |
| 32 | + |
8 | 33 | // Class, implementing the closure with run config.
|
9 | 34 | class TRunConfig : public NYql::NUdf::TBoxedValue {
|
10 | 35 | public:
|
@@ -35,6 +60,15 @@ class TRunConfig : public NYql::NUdf::TBoxedValue {
|
35 | 60 | return true;
|
36 | 61 | }
|
37 | 62 |
|
| 63 | + NYql::NUdf::TUnboxedValue Run(const NYql::NUdf::IValueBuilder*, |
| 64 | + const NYql::NUdf::TUnboxedValuePod* args) |
| 65 | + const final try { |
| 66 | + const std::string_view upvalue(args[0].AsStringRef()); |
| 67 | + return NYql::NUdf::TUnboxedValuePod(new TImpl(Pos_, upvalue)); |
| 68 | + } catch (const std::exception& e) { |
| 69 | + UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).data()); |
| 70 | + } |
| 71 | + |
38 | 72 | private:
|
39 | 73 | const NYql::NUdf::TSourcePosition Pos_;
|
40 | 74 | };
|
@@ -81,31 +115,6 @@ class TCurrying : public NYql::NUdf::TBoxedValue {
|
81 | 115 | }
|
82 | 116 |
|
83 | 117 | private:
|
84 |
| - class TImpl : public NYql::NUdf::TBoxedValue { |
85 |
| - public: |
86 |
| - explicit TImpl(NYql::NUdf::TSourcePosition pos, |
87 |
| - const std::string_view upvalue) |
88 |
| - : Pos_(pos) |
89 |
| - , Upvalue_(upvalue) |
90 |
| - {} |
91 |
| - |
92 |
| - NYql::NUdf::TUnboxedValue Run(const NYql::NUdf::IValueBuilder* valueBuilder, |
93 |
| - const NYql::NUdf::TUnboxedValuePod* args) |
94 |
| - const override try { |
95 |
| - TStringStream concat; |
96 |
| - concat << Upvalue_ << " " << args[0].AsStringRef(); |
97 |
| - return valueBuilder->NewString(NYql::NUdf::TStringRef(concat.Data(), |
98 |
| - concat.Size())); |
99 |
| - } catch (const std::exception& e) { |
100 |
| - UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).data()); |
101 |
| - } |
102 |
| - |
103 |
| - |
104 |
| - private: |
105 |
| - const NYql::NUdf::TSourcePosition Pos_; |
106 |
| - const TString Upvalue_; |
107 |
| - }; |
108 |
| - |
109 | 118 | const NYql::NUdf::TSourcePosition Pos_;
|
110 | 119 | };
|
111 | 120 |
|
@@ -166,6 +175,55 @@ Y_UNIT_TEST_SUITE(TMiniKQLUdfTest) {
|
166 | 175 | UNIT_ASSERT_STRINGS_EQUAL(TStringBuf(result.AsStringRef()), "Canary is alive");
|
167 | 176 | UNIT_ASSERT(!iterator.Next(result));
|
168 | 177 | }
|
| 178 | + |
| 179 | + Y_UNIT_TEST_LLVM(CurryingToRunconfig) { |
| 180 | + // Create the test setup, using TCurrying implementation |
| 181 | + // for TestModule.Test UDF. |
| 182 | + TVector<TUdfModuleInfo> compileModules; |
| 183 | + compileModules.emplace_back( |
| 184 | + TUdfModuleInfo{"", "TestModule", new TCurryingUTModule()} |
| 185 | + ); |
| 186 | + TSetup<LLVM> compileSetup(GetTestFactory(), std::move(compileModules)); |
| 187 | + TProgramBuilder& pb = *compileSetup.PgmBuilder; |
| 188 | + |
| 189 | + // Build the graph on the setup with TRunConfig implementation. |
| 190 | + const auto strType = pb.NewDataType(NUdf::TDataType<char*>::Id); |
| 191 | + const auto upvalue = pb.NewDataLiteral<NUdf::EDataSlot::String>("Canary"); |
| 192 | + const auto optional = pb.NewOptional(pb.NewDataLiteral(true)); |
| 193 | + const auto value = pb.NewDataLiteral<NUdf::EDataSlot::String>("is alive"); |
| 194 | + const auto userType = pb.NewTupleType({ |
| 195 | + pb.NewTupleType({strType}), |
| 196 | + pb.NewEmptyStructType(), |
| 197 | + pb.NewEmptyTupleType()}); |
| 198 | + const auto udf = pb.Udf("TestModule.Test", pb.NewVoid(), userType); |
| 199 | + const auto closure = pb.Apply(udf, {upvalue, optional}); |
| 200 | + |
| 201 | + const auto list = pb.NewList(strType, {value}); |
| 202 | + const auto pgmReturn = pb.Map(list, [&pb, closure](const TRuntimeNode item) { |
| 203 | + return pb.Apply(closure, {item}); |
| 204 | + }); |
| 205 | + |
| 206 | + // Create the test setup, using TRunConfig implementation |
| 207 | + // for TestModule.Test UDF. |
| 208 | + TVector<TUdfModuleInfo> runModules; |
| 209 | + runModules.emplace_back( |
| 210 | + TUdfModuleInfo{"", "TestModule", new TRunConfigUTModule()} |
| 211 | + ); |
| 212 | + TSetup<LLVM> runSetup(GetTestFactory(), std::move(runModules)); |
| 213 | + // Move the graph from the one setup to another as a |
| 214 | + // serialized bytecode sequence. |
| 215 | + const auto bytecode = SerializeRuntimeNode(pgmReturn, *compileSetup.Env); |
| 216 | + const auto root = DeserializeRuntimeNode(bytecode, *runSetup.Env); |
| 217 | + |
| 218 | + // Run the graph on the setup with TCurrying implementation. |
| 219 | + const auto graph = runSetup.BuildGraph(root); |
| 220 | + const auto iterator = graph->GetValue().GetListIterator(); |
| 221 | + |
| 222 | + NUdf::TUnboxedValue result; |
| 223 | + UNIT_ASSERT(iterator.Next(result)); |
| 224 | + UNIT_ASSERT_STRINGS_EQUAL(TStringBuf(result.AsStringRef()), "Canary is alive"); |
| 225 | + UNIT_ASSERT(!iterator.Next(result)); |
| 226 | + } |
169 | 227 | } // Y_UNIT_TEST_SUITE
|
170 | 228 |
|
171 | 229 | } // namespace NMiniKQL
|
|
0 commit comments