|
1 | 1 | #include "mkql_computation_node_ut.h"
|
2 | 2 | #include <yql/essentials/public/udf/udf_helpers.h>
|
3 | 3 | #include <yql/essentials/minikql/mkql_node_serialization.h>
|
| 4 | +#include <yql/essentials/minikql/mkql_node_cast.h> |
4 | 5 |
|
5 | 6 | namespace NKikimr {
|
6 | 7 | namespace NMiniKQL {
|
7 | 8 |
|
| 9 | +// XXX: Emulate type transformations similar to the one made by |
| 10 | +// type annotation and compilation phases. As a result, the name |
| 11 | +// (i.e. "UDF") of callable type is lost. Hence, the type resolved |
| 12 | +// at the type annotation phase (and, ergo, used for bytecode |
| 13 | +// compilation) differs from the type, resolved for the underline |
| 14 | +// function at runtime. |
| 15 | +template<typename TUdf> |
| 16 | +static TType* TweakUdfType(const NYql::NUdf::TStringRef& name, TType* userType, |
| 17 | + const TTypeEnvironment& env) |
| 18 | +{ |
| 19 | + TFunctionTypeInfoBuilder typeInfoBuilder(NYql::UnknownLangVersion, env, |
| 20 | + new TTypeInfoHelper(), |
| 21 | + "", nullptr, {}); |
| 22 | + |
| 23 | + // Obtain the callable type of the particular UDF. |
| 24 | + TFunctionTypeInfo funcInfo; |
| 25 | + UNIT_ASSERT(TUdf::DeclareSignature(name, userType, typeInfoBuilder, true)); |
| 26 | + typeInfoBuilder.Build(&funcInfo); |
| 27 | + |
| 28 | + // Create the new MiniKQL type to emulate two conversions: |
| 29 | + // * Convert the given MiniKQL type to the expression type. |
| 30 | + // See <NYql::NCommon::ConvertMiniKQLType>. |
| 31 | + // * Convert the expression type back to the MiniKQL one. |
| 32 | + // See <NYql::NCommon::TMkqlBuildContext::BuildType>. |
| 33 | + // The aforementioned conversions are made by the pipeline in |
| 34 | + // scope of type annotation and compilation phases. |
| 35 | + // As a result of the first conversion, the name of the |
| 36 | + // callable type is lost, so the new MiniKQL type has to be |
| 37 | + // the same as the resolved one, but the name is omitted. |
| 38 | + const auto funcType = AS_TYPE(TCallableType, funcInfo.FunctionType); |
| 39 | + TVector<TType*> argsTypes; |
| 40 | + for (size_t i = 0; i < funcType->GetArgumentsCount(); i++) { |
| 41 | + argsTypes.push_back(funcType->GetArgumentType(i)); |
| 42 | + } |
| 43 | + const auto nodeType = TCallableType::Create("", /* Name has to be empty. */ |
| 44 | + funcType->GetReturnType(), |
| 45 | + funcType->GetArgumentsCount(), |
| 46 | + argsTypes.data(), |
| 47 | + funcType->GetPayload(), |
| 48 | + env); |
| 49 | + nodeType->SetOptionalArgumentsCount(funcType->GetOptionalArgumentsCount()); |
| 50 | + return nodeType; |
| 51 | +}; |
| 52 | + |
8 | 53 | class TImpl : public NYql::NUdf::TBoxedValue {
|
9 | 54 | public:
|
10 | 55 | explicit TImpl(NYql::NUdf::TSourcePosition pos,
|
@@ -219,7 +264,9 @@ Y_UNIT_TEST_SUITE(TMiniKQLUdfTest) {
|
219 | 264 | pb.NewTupleType({strType}),
|
220 | 265 | pb.NewEmptyStructType(),
|
221 | 266 | pb.NewEmptyTupleType()});
|
222 |
| - const auto udf = pb.Udf("TestModule.Test", upvalue, userType); |
| 267 | + |
| 268 | + const auto udfType = TweakUdfType<TRunConfig>("Test", userType, *compileSetup.Env); |
| 269 | + const auto udf = pb.TypedUdf("TestModule.Test", udfType, upvalue, userType); |
223 | 270 |
|
224 | 271 | const auto list = pb.NewList(strType, {value});
|
225 | 272 | const auto pgmReturn = pb.Map(list, [&pb, udf](const TRuntimeNode item) {
|
@@ -268,7 +315,9 @@ Y_UNIT_TEST_SUITE(TMiniKQLUdfTest) {
|
268 | 315 | pb.NewTupleType({strType}),
|
269 | 316 | pb.NewEmptyStructType(),
|
270 | 317 | pb.NewEmptyTupleType()});
|
271 |
| - const auto udf = pb.Udf("TestModule.Test", pb.NewVoid(), userType); |
| 318 | + |
| 319 | + const auto udfType = TweakUdfType<TCurrying>("Test", userType, *compileSetup.Env); |
| 320 | + const auto udf = pb.TypedUdf("TestModule.Test", udfType, pb.NewVoid(), userType); |
272 | 321 | const auto closure = pb.Apply(udf, {upvalue, optional});
|
273 | 322 |
|
274 | 323 | const auto list = pb.NewList(strType, {value});
|
|
0 commit comments