diff options
author | vvvv <vvvv@yandex-team.com> | 2025-02-21 18:08:26 +0300 |
---|---|---|
committer | vvvv <vvvv@yandex-team.com> | 2025-02-21 19:12:56 +0300 |
commit | 807412ee4958d5903d6bb22cfb95ea126919c6f9 (patch) | |
tree | 94e95014f93ccb0e440dd0d16cb4fe4d52a8d269 | |
parent | 253d0dcf6c3fbbbf0594538d398123fc4eb9ae68 (diff) | |
download | ydb-807412ee4958d5903d6bb22cfb95ea126919c6f9.tar.gz |
YQL-19593 better error handling for Udf
commit_hash:216229b0558e1004453dedddbec8b767b2dab9c6
-rw-r--r-- | yql/essentials/minikql/comp_nodes/mkql_udf.cpp | 76 | ||||
-rw-r--r-- | yql/essentials/minikql/computation/mkql_computation_node_graph.cpp | 5 |
2 files changed, 65 insertions, 16 deletions
diff --git a/yql/essentials/minikql/comp_nodes/mkql_udf.cpp b/yql/essentials/minikql/comp_nodes/mkql_udf.cpp index 9240dad141..0834256743 100644 --- a/yql/essentials/minikql/comp_nodes/mkql_udf.cpp +++ b/yql/essentials/minikql/comp_nodes/mkql_udf.cpp @@ -15,6 +15,16 @@ namespace NMiniKQL { namespace { +constexpr size_t TypeDiffLimit = 1000; + +TString TruncateTypeDiff(const TString& s) { + if (s.size() < TypeDiffLimit) { + return s; + } + + return s.substr(0,TypeDiffLimit) + "..."; +} + template<class TValidatePolicy, class TValidateMode> class TSimpleUdfWrapper: public TMutableComputationNode<TSimpleUdfWrapper<TValidatePolicy,TValidateMode>> { using TBaseComputation = TMutableComputationNode<TSimpleUdfWrapper<TValidatePolicy,TValidateMode>>; @@ -43,8 +53,15 @@ public: ctx.TypeEnv, ctx.TypeInfoHelper, ctx.CountersProvider, FunctionName, UserType->IsVoid() ? nullptr : UserType, TypeConfig, flags, Pos, ctx.SecureParamsProvider, &funcInfo); - MKQL_ENSURE(status.IsOk(), status.GetError()); - MKQL_ENSURE(funcInfo.Implementation, "UDF implementation is not set for function " << FunctionName); + if (!status.IsOk()) { + UdfTerminate((TStringBuilder() << Pos << " Failed to find UDF function " << FunctionName << ", reason: " + << status.GetError()).c_str()); + } + + if (!funcInfo.Implementation) { + UdfTerminate((TStringBuilder() << Pos << " UDF implementation is not set for function " << FunctionName).c_str()); + } + NUdf::TUnboxedValue udf(NUdf::TUnboxedValuePod(funcInfo.Implementation.Release())); TValidate<TValidatePolicy,TValidateMode>::WrapCallable(CallableType, udf, TStringBuilder() << "FunctionWithConfig<" << FunctionName << ">"); return udf.Release(); @@ -190,13 +207,19 @@ private: ctx.TypeEnv, ctx.TypeInfoHelper, ctx.CountersProvider, FunctionName, UserType->IsVoid() ? nullptr : UserType, TypeConfig, flags, Pos, ctx.SecureParamsProvider, &funcInfo); - MKQL_ENSURE(status.IsOk(), status.GetError()); - MKQL_ENSURE(funcInfo.Implementation, "UDF implementation is not set for function " << FunctionName); + if (!status.IsOk()) { + UdfTerminate((TStringBuilder() << Pos << " Failed to find UDF function " << FunctionName << ", reason: " + << status.GetError()).c_str()); + } + + if (!funcInfo.Implementation) { + UdfTerminate((TStringBuilder() << Pos << " UDF implementation is not set for function " << FunctionName).c_str()); + } + udf = NUdf::TUnboxedValuePod(funcInfo.Implementation.Release()); } void Wrap(NUdf::TUnboxedValue& callable) const { - MKQL_ENSURE(bool(callable), "Returned empty value in function: " << FunctionName); TValidate<TValidatePolicy,TValidateMode>::WrapCallable(CallableType, callable, TStringBuilder() << "FunctionWithConfig<" << FunctionName << ">"); } @@ -270,16 +293,27 @@ IComputationNode* WrapUdf(TCallable& callable, const TComputationNodeFactoryCont ctx.Env, ctx.TypeInfoHelper, ctx.CountersProvider, funcName, userType->IsVoid() ? nullptr : userType, typeConfig, flags, pos, ctx.SecureParamsProvider, &funcInfo); - MKQL_ENSURE(status.IsOk(), status.GetError()); - MKQL_ENSURE(funcInfo.FunctionType->IsConvertableTo(*callable.GetType()->GetReturnType(), true), - "Function '" << funcName << "' type mismatch, expected return type: " << PrintNode(callable.GetType()->GetReturnType(), true) << - ", actual:" << PrintNode(funcInfo.FunctionType, true)); - MKQL_ENSURE(funcInfo.Implementation, "UDF implementation is not set for function " << funcName); + if (!status.IsOk()) { + UdfTerminate((TStringBuilder() << pos << " Failed to find UDF function " << funcName << ", reason: " + << status.GetError()).c_str()); + } + + if (!funcInfo.FunctionType->IsConvertableTo(*callable.GetType()->GetReturnType(), true)) { + TString diff = TStringBuilder() << "type mismatch, expected return type: " << PrintNode(callable.GetType()->GetReturnType(), true) << + ", actual:" << PrintNode(funcInfo.FunctionType, true); + UdfTerminate((TStringBuilder() << pos << " UDF Function '" << funcName << "' " << TruncateTypeDiff(diff)).c_str()); + } + + if (!funcInfo.Implementation) { + UdfTerminate((TStringBuilder() << pos << " UDF implementation is not set for function " << funcName).c_str()); + } const auto runConfigType = funcInfo.RunConfigType; - const bool typesMatch = runConfigType->IsSameType(*runCfgNode.GetStaticType()); - MKQL_ENSURE(typesMatch, "RunConfig '" << funcName << "' type mismatch, expected: " << PrintNode(runCfgNode.GetStaticType(), true) << - ", actual: " << PrintNode(runConfigType, true)); + if (!runConfigType->IsSameType(*runCfgNode.GetStaticType())) { + TString diff = TStringBuilder() << "run config type mismatch, expected: " << PrintNode(runCfgNode.GetStaticType(), true) << + ", actual:" << PrintNode(runConfigType, true); + UdfTerminate((TStringBuilder() << pos << " UDF Function '" << funcName << "' " << TruncateTypeDiff(diff)).c_str()); + } if (runConfigType->IsVoid()) { if (ctx.ValidateMode == NUdf::EValidateMode::None && funcInfo.ModuleIR && funcInfo.IRFunctionName) { @@ -320,10 +354,20 @@ IComputationNode* WrapScriptUdf(TCallable& callable, const TComputationNodeFacto const auto status = ctx.FunctionRegistry.FindFunctionTypeInfo( ctx.Env, ctx.TypeInfoHelper, ctx.CountersProvider, funcName, userType, typeConfig, flags, pos, ctx.SecureParamsProvider, &funcInfo); - MKQL_ENSURE(status.IsOk(), status.GetError()); - MKQL_ENSURE(funcInfo.Implementation, "UDF implementation is not set"); - MKQL_ENSURE(!funcInfo.FunctionType, "Function type info is exist for same kind script, it's better use it"); + if (!status.IsOk()) { + UdfTerminate((TStringBuilder() << pos << " Failed to find UDF function " << funcName << ", reason: " + << status.GetError()).c_str()); + } + + if (!funcInfo.Implementation) { + UdfTerminate((TStringBuilder() << pos << " UDF implementation is not set for function " << funcName).c_str()); + } + + if (funcInfo.FunctionType) { + UdfTerminate((TStringBuilder() << pos << " UDF function type exists for function " << funcName).c_str()); + } + const auto callableType = callable.GetType(); MKQL_ENSURE(callableType->GetKind() == TType::EKind::Callable, "Expected callable type in callable type info"); const auto callableResultType = callableType->GetReturnType(); diff --git a/yql/essentials/minikql/computation/mkql_computation_node_graph.cpp b/yql/essentials/minikql/computation/mkql_computation_node_graph.cpp index e1a79dff5b..75bcc4ce5c 100644 --- a/yql/essentials/minikql/computation/mkql_computation_node_graph.cpp +++ b/yql/essentials/minikql/computation/mkql_computation_node_graph.cpp @@ -164,6 +164,10 @@ public: } } + ITerminator& GetTerminator() { + return *ValueBuilder; + } + const TComputationMutables& GetMutables() const { return Mutables; } @@ -994,6 +998,7 @@ TIntrusivePtr<TComputationPatternImpl> MakeComputationPatternImpl(TExploringNode depScanner.Walk(root.GetNode(), opts.Env); auto builder = MakeHolder<TComputationGraphBuildingVisitor>(opts); + const TBindTerminator bind(&builder->GetPatternNodes()->GetTerminator()); for (const auto& node : explorer.GetNodes()) { Y_ABORT_UNLESS(node->GetCookie() <= IS_NODE_REACHABLE, "TNode graph should not be reused"); if (node->GetCookie() == IS_NODE_REACHABLE) { |