aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorimunkin <imunkin@yandex-team.com>2025-05-30 17:59:27 +0300
committerimunkin <imunkin@yandex-team.com>2025-05-30 18:18:54 +0300
commitfcc18ade321e3471411a93114f83ca8c339b876e (patch)
treee7f5de9f6831c2e42ac5705fde3f347c45785ab6
parentdb8ab61ea2bd34376d503f7f13ac77ce2732952c (diff)
downloadydb-fcc18ade321e3471411a93114f83ca8c339b876e.tar.gz
YQL-19967: Relax closure type comparison
commit_hash:6425e8ea846ad5be20c46282f4fde40f5e83f81d
-rw-r--r--yql/essentials/minikql/comp_nodes/mkql_udf.cpp2
-rw-r--r--yql/essentials/minikql/comp_nodes/ut/mkql_udf_ut.cpp53
2 files changed, 52 insertions, 3 deletions
diff --git a/yql/essentials/minikql/comp_nodes/mkql_udf.cpp b/yql/essentials/minikql/comp_nodes/mkql_udf.cpp
index 3c619a8e16e..44c45888c0a 100644
--- a/yql/essentials/minikql/comp_nodes/mkql_udf.cpp
+++ b/yql/essentials/minikql/comp_nodes/mkql_udf.cpp
@@ -421,7 +421,7 @@ IComputationNode* WrapUdf(TCallable& callable, const TComputationNodeFactoryCont
const auto closureNodeType = runConfigNodeType->IsVoid()
? AS_TYPE(TCallableType, callableNodeType)->GetReturnType()
: callableNodeType;
- if (!closureNodeType->IsSameType(*closureFuncType)) {
+ if (!closureNodeType->IsConvertableTo(*closureFuncType)) {
TString diff = TStringBuilder()
<< "type mismatch, expected return type: "
<< PrintNode(closureNodeType, true)
diff --git a/yql/essentials/minikql/comp_nodes/ut/mkql_udf_ut.cpp b/yql/essentials/minikql/comp_nodes/ut/mkql_udf_ut.cpp
index 265ad3bd059..fe7e32e189d 100644
--- a/yql/essentials/minikql/comp_nodes/ut/mkql_udf_ut.cpp
+++ b/yql/essentials/minikql/comp_nodes/ut/mkql_udf_ut.cpp
@@ -1,10 +1,55 @@
#include "mkql_computation_node_ut.h"
#include <yql/essentials/public/udf/udf_helpers.h>
#include <yql/essentials/minikql/mkql_node_serialization.h>
+#include <yql/essentials/minikql/mkql_node_cast.h>
namespace NKikimr {
namespace NMiniKQL {
+// XXX: Emulate type transformations similar to the one made by
+// type annotation and compilation phases. As a result, the name
+// (i.e. "UDF") of callable type is lost. Hence, the type resolved
+// at the type annotation phase (and, ergo, used for bytecode
+// compilation) differs from the type, resolved for the underline
+// function at runtime.
+template<typename TUdf>
+static TType* TweakUdfType(const NYql::NUdf::TStringRef& name, TType* userType,
+ const TTypeEnvironment& env)
+{
+ TFunctionTypeInfoBuilder typeInfoBuilder(NYql::UnknownLangVersion, env,
+ new TTypeInfoHelper(),
+ "", nullptr, {});
+
+ // Obtain the callable type of the particular UDF.
+ TFunctionTypeInfo funcInfo;
+ UNIT_ASSERT(TUdf::DeclareSignature(name, userType, typeInfoBuilder, true));
+ typeInfoBuilder.Build(&funcInfo);
+
+ // Create the new MiniKQL type to emulate two conversions:
+ // * Convert the given MiniKQL type to the expression type.
+ // See <NYql::NCommon::ConvertMiniKQLType>.
+ // * Convert the expression type back to the MiniKQL one.
+ // See <NYql::NCommon::TMkqlBuildContext::BuildType>.
+ // The aforementioned conversions are made by the pipeline in
+ // scope of type annotation and compilation phases.
+ // As a result of the first conversion, the name of the
+ // callable type is lost, so the new MiniKQL type has to be
+ // the same as the resolved one, but the name is omitted.
+ const auto funcType = AS_TYPE(TCallableType, funcInfo.FunctionType);
+ TVector<TType*> argsTypes;
+ for (size_t i = 0; i < funcType->GetArgumentsCount(); i++) {
+ argsTypes.push_back(funcType->GetArgumentType(i));
+ }
+ const auto nodeType = TCallableType::Create("", /* Name has to be empty. */
+ funcType->GetReturnType(),
+ funcType->GetArgumentsCount(),
+ argsTypes.data(),
+ funcType->GetPayload(),
+ env);
+ nodeType->SetOptionalArgumentsCount(funcType->GetOptionalArgumentsCount());
+ return nodeType;
+};
+
class TImpl : public NYql::NUdf::TBoxedValue {
public:
explicit TImpl(NYql::NUdf::TSourcePosition pos,
@@ -219,7 +264,9 @@ Y_UNIT_TEST_SUITE(TMiniKQLUdfTest) {
pb.NewTupleType({strType}),
pb.NewEmptyStructType(),
pb.NewEmptyTupleType()});
- const auto udf = pb.Udf("TestModule.Test", upvalue, userType);
+
+ const auto udfType = TweakUdfType<TRunConfig>("Test", userType, *compileSetup.Env);
+ const auto udf = pb.TypedUdf("TestModule.Test", udfType, upvalue, userType);
const auto list = pb.NewList(strType, {value});
const auto pgmReturn = pb.Map(list, [&pb, udf](const TRuntimeNode item) {
@@ -268,7 +315,9 @@ Y_UNIT_TEST_SUITE(TMiniKQLUdfTest) {
pb.NewTupleType({strType}),
pb.NewEmptyStructType(),
pb.NewEmptyTupleType()});
- const auto udf = pb.Udf("TestModule.Test", pb.NewVoid(), userType);
+
+ const auto udfType = TweakUdfType<TCurrying>("Test", userType, *compileSetup.Env);
+ const auto udf = pb.TypedUdf("TestModule.Test", udfType, pb.NewVoid(), userType);
const auto closure = pb.Apply(udf, {upvalue, optional});
const auto list = pb.NewList(strType, {value});