diff options
author | Mikhail Surin <surinmike@gmail.com> | 2022-06-15 13:44:04 +0300 |
---|---|---|
committer | Daniil Cherednik <dan.cherednik@gmail.com> | 2022-06-15 13:44:04 +0300 |
commit | 4230edd531b7ad8794a2f0b2fbd3ff3b5cdd8f9f (patch) | |
tree | 92262046d8195cc3c421c8aff91936423ebf20f4 | |
parent | 65b5db5601fc4b0e91597f5d63979e587494bc31 (diff) | |
download | ydb-4230edd531b7ad8794a2f0b2fbd3ff3b5cdd8f9f.tar.gz |
Add column name in typecast error message
merge from trunk: r9575690
REVIEW: 2632489
x-ydb-stable-ref: 601ef863c7ff914ec5338b52ebb52ae86f780044
-rw-r--r-- | ydb/core/kqp/ut/kqp_yql_ut.cpp | 26 | ||||
-rw-r--r-- | ydb/library/yql/core/yql_expr_type_annotation.cpp | 72 | ||||
-rw-r--r-- | ydb/library/yql/public/issue/yql_issue_manager.cpp | 30 | ||||
-rw-r--r-- | ydb/library/yql/public/issue/yql_issue_manager.h | 8 | ||||
-rw-r--r-- | ydb/services/ydb/ydb_table_ut.cpp | 1 |
5 files changed, 103 insertions, 34 deletions
diff --git a/ydb/core/kqp/ut/kqp_yql_ut.cpp b/ydb/core/kqp/ut/kqp_yql_ut.cpp index 99fee295a6..0ac17d67b2 100644 --- a/ydb/core/kqp/ut/kqp_yql_ut.cpp +++ b/ydb/core/kqp/ut/kqp_yql_ut.cpp @@ -309,6 +309,32 @@ Y_UNIT_TEST_SUITE(KqpYql) { [[2u];["Two"]] ])", FormatResultSetYson(result.GetResultSet(0))); } + + Y_UNIT_TEST_NEW_ENGINE(ColumnTypeMismatch) { + TKikimrRunner kikimr; + auto db = kikimr.GetTableClient(); + auto session = db.CreateSession().GetValueSync().GetSession(); + + auto params = TParamsBuilder() + .AddParam("$key").Uint64(1).Build() + .AddParam("$value").Uint64(2).Build() + .Build(); + + TExecDataQuerySettings settings; + auto req = session.ExecuteDataQuery(Q_(R"( + DECLARE $key AS Uint64; + DECLARE $value AS Uint64; + + REPLACE INTO `KeyValue` + (Key, Value) + VALUES + ($key, $value); + )"), TTxControl::BeginTx().CommitTx(), params).ExtractValueSync(); + + req.GetIssues().PrintTo(Cerr); + UNIT_ASSERT_VALUES_EQUAL(req.GetStatus(), EStatus::GENERIC_ERROR); + UNIT_ASSERT_STRING_CONTAINS(req.GetIssues().ToString(), "Failed to convert 'Value': Uint64 to Optional<String>"); + } } } // namespace NKqp diff --git a/ydb/library/yql/core/yql_expr_type_annotation.cpp b/ydb/library/yql/core/yql_expr_type_annotation.cpp index a3c53a6633..42f35c4bd9 100644 --- a/ydb/library/yql/core/yql_expr_type_annotation.cpp +++ b/ydb/library/yql/core/yql_expr_type_annotation.cpp @@ -83,7 +83,7 @@ TExprNode::TPtr RebuildVariant(const TExprNode::TPtr& node, } IGraphTransformer::TStatus TryConvertToImpl(TExprContext& ctx, TExprNode::TPtr& node, - const TTypeAnnotationNode& sourceType, const TTypeAnnotationNode& expectedType, TConvertFlags flags) { + const TTypeAnnotationNode& sourceType, const TTypeAnnotationNode& expectedType, TConvertFlags flags, bool raiseIssues = false) { if (IsSameAnnotation(sourceType, expectedType)) { return IGraphTransformer::TStatus::Ok; @@ -105,7 +105,7 @@ IGraphTransformer::TStatus TryConvertToImpl(TExprContext& ctx, TExprNode::TPtr& if (expectedType.GetKind() == ETypeAnnotationKind::Optional) { auto nextType = expectedType.Cast<TOptionalExprType>()->GetItemType(); auto originalNode = node; - auto status1 = TryConvertToImpl(ctx, node, sourceType, *nextType, flags); + auto status1 = TryConvertToImpl(ctx, node, sourceType, *nextType, flags, raiseIssues); if (status1.Level != IGraphTransformer::TStatus::Error) { node = ctx.NewCallable(node->Pos(), "Just", { node }); return IGraphTransformer::TStatus::Repeat; @@ -115,7 +115,7 @@ IGraphTransformer::TStatus TryConvertToImpl(TExprContext& ctx, TExprNode::TPtr& if (node->IsCallable("Just")) { auto sourceItemType = sourceType.Cast<TOptionalExprType>()->GetItemType(); auto value = node->HeadRef(); - auto status = TryConvertToImpl(ctx, value, *sourceItemType, *nextType, flags); + auto status = TryConvertToImpl(ctx, value, *sourceItemType, *nextType, flags, raiseIssues); if (status.Level != IGraphTransformer::TStatus::Error) { node = ctx.NewCallable(node->Pos(), "Just", { value }); return IGraphTransformer::TStatus::Repeat; @@ -124,7 +124,7 @@ IGraphTransformer::TStatus TryConvertToImpl(TExprContext& ctx, TExprNode::TPtr& auto sourceItemType = sourceType.Cast<TOptionalExprType>()->GetItemType(); auto arg = ctx.NewArgument(node->Pos(), "item"); auto originalArg = arg; - auto status = TryConvertToImpl(ctx, arg, *sourceItemType, *nextType, flags); + auto status = TryConvertToImpl(ctx, arg, *sourceItemType, *nextType, flags, raiseIssues); if (status.Level != IGraphTransformer::TStatus::Error) { auto lambda = ctx.NewLambda(node->Pos(), ctx.NewArguments(node->Pos(), { originalArg }), @@ -376,6 +376,10 @@ IGraphTransformer::TStatus TryConvertToImpl(TExprContext& ctx, TExprNode::TPtr& TExprNode::TPtr field; if (!pos) { if (newField->GetItemType()->GetKind() != ETypeAnnotationKind::Optional) { + if (raiseIssues) { + ctx.AddError(TIssue(node->Pos(ctx), TStringBuilder() << + "Can't find '" << newField->GetName() << "': " << *newField->GetItemType() << " in " << sourceType)); + } return IGraphTransformer::TStatus::Error; } @@ -395,8 +399,12 @@ IGraphTransformer::TStatus TryConvertToImpl(TExprContext& ctx, TExprNode::TPtr& } YQL_ENSURE(field); - auto status = TryConvertToImpl(ctx, field, *oldType->GetItemType(), *newField->GetItemType(), flags); + auto status = TryConvertToImpl(ctx, field, *oldType->GetItemType(), *newField->GetItemType(), flags, raiseIssues); if (status.Level == IGraphTransformer::TStatus::Error) { + if (raiseIssues) { + ctx.AddError(TIssue(node->Pos(ctx), TStringBuilder() << + "Failed to convert '" << newField->GetName() << "': " << *oldType->GetItemType() << " to " << *newField->GetItemType())); + } return status; } } @@ -438,6 +446,10 @@ IGraphTransformer::TStatus TryConvertToImpl(TExprContext& ctx, TExprNode::TPtr& .Seal() .Build(); } else { + if (raiseIssues) { + ctx.AddError(TIssue(node->Pos(ctx), TStringBuilder() << + "Can't find '" << newField->GetName() << ": " << *newField->GetItemType() << "' in " << sourceType)); + } return IGraphTransformer::TStatus::Error; } } else { @@ -450,8 +462,12 @@ IGraphTransformer::TStatus TryConvertToImpl(TExprContext& ctx, TExprNode::TPtr& .Seal() .Build(); - auto status = TryConvertToImpl(ctx, field, *oldType->GetItemType(), *newField->GetItemType(), flags); + auto status = TryConvertToImpl(ctx, field, *oldType->GetItemType(), *newField->GetItemType(), flags, raiseIssues); if (status.Level == IGraphTransformer::TStatus::Error) { + if (raiseIssues) { + ctx.AddError(TIssue(node->Pos(ctx), TStringBuilder() << + "Failed to convert '" << newField->GetName() << "': " << *oldType->GetItemType() << " to " << *newField->GetItemType())); + } return status; } } @@ -502,7 +518,7 @@ IGraphTransformer::TStatus TryConvertToImpl(TExprContext& ctx, TExprNode::TPtr& auto status = TryConvertToImpl( ctx, targetItem, *fromUnderlying->GetItems()[*fromTargetIndex]->GetItemType(), - *toUnderlying->GetItems()[*toTargetIndex]->GetItemType(), flags); + *toUnderlying->GetItems()[*toTargetIndex]->GetItemType(), flags, raiseIssues); if (status.Level == IGraphTransformer::TStatus::Error) { return status; } @@ -519,7 +535,7 @@ IGraphTransformer::TStatus TryConvertToImpl(TExprContext& ctx, TExprNode::TPtr& auto fromElement = item->GetItemType(); auto toElement = toUnderlying->GetItems()[*toIndex]->GetItemType(); auto arg = ctx.NewArgument(TPositionHandle(), "arg"); - auto status1 = TryConvertToImpl(ctx, arg, *fromElement, *toElement, flags); + auto status1 = TryConvertToImpl(ctx, arg, *fromElement, *toElement, flags, raiseIssues); if (status1.Level == IGraphTransformer::TStatus::Error) { return status1; } @@ -549,7 +565,7 @@ IGraphTransformer::TStatus TryConvertToImpl(TExprContext& ctx, TExprNode::TPtr& auto status = TryConvertToImpl( ctx, targetItem, *fromUnderlying->GetItems()[targetIndex], - *toUnderlying->GetItems()[targetIndex], flags); + *toUnderlying->GetItems()[targetIndex], flags, raiseIssues); if (status.Level == IGraphTransformer::TStatus::Error) { return status; } @@ -560,7 +576,7 @@ IGraphTransformer::TStatus TryConvertToImpl(TExprContext& ctx, TExprNode::TPtr& } auto arg = ctx.NewArgument(TPositionHandle(), "arg"); auto status1 = TryConvertToImpl(ctx, arg, *fromUnderlying->GetItems()[i], - *toUnderlying->GetItems()[i], flags); + *toUnderlying->GetItems()[i], flags, raiseIssues); if (status1.Level == IGraphTransformer::TStatus::Error) { return status1; } @@ -615,7 +631,7 @@ IGraphTransformer::TStatus TryConvertToImpl(TExprContext& ctx, TExprNode::TPtr& auto arg = ctx.NewArgument(node->Pos(), "item"); auto originalArg = arg; - auto status = TryConvertToImpl(ctx, arg, *fromElement, *toElement, flags); + auto status = TryConvertToImpl(ctx, arg, *fromElement, *toElement, flags, raiseIssues); if (status.Level == IGraphTransformer::TStatus::Error) { return status; } @@ -650,7 +666,7 @@ IGraphTransformer::TStatus TryConvertToImpl(TExprContext& ctx, TExprNode::TPtr& auto arg = ctx.NewArgument(node->Pos(), "item"); auto originalArg = arg; - auto status = TryConvertToImpl(ctx, arg, *fromElement, *toElement, flags); + auto status = TryConvertToImpl(ctx, arg, *fromElement, *toElement, flags, raiseIssues); if (status.Level == IGraphTransformer::TStatus::Error) { return status; } @@ -686,7 +702,7 @@ IGraphTransformer::TStatus TryConvertToImpl(TExprContext& ctx, TExprNode::TPtr& const auto oldType = from->GetItems()[i]; const auto newType = to->GetItems()[i]; auto value = node->ChildPtr(i); - if (const auto status = TryConvertToImpl(ctx, value, *oldType, *newType, flags); status.Level == IGraphTransformer::TStatus::Error) { + if (const auto status = TryConvertToImpl(ctx, value, *oldType, *newType, flags, raiseIssues); status.Level == IGraphTransformer::TStatus::Error) { return status; } @@ -726,7 +742,7 @@ IGraphTransformer::TStatus TryConvertToImpl(TExprContext& ctx, TExprNode::TPtr& .Seal() .Build(); - if (const auto status = TryConvertToImpl(ctx, value, *oldType, *newType, flags); status.Level == IGraphTransformer::TStatus::Error) { + if (const auto status = TryConvertToImpl(ctx, value, *oldType, *newType, flags, raiseIssues); status.Level == IGraphTransformer::TStatus::Error) { return status; } @@ -764,7 +780,7 @@ IGraphTransformer::TStatus TryConvertToImpl(TExprContext& ctx, TExprNode::TPtr& for (ui32 i = node->IsCallable("List") ? 1 : 0; i < node->ChildrenSize(); ++i) { auto value = node->ChildPtr(i); - auto status = TryConvertToImpl(ctx, value, *oldItemType, *newItemType, flags); + auto status = TryConvertToImpl(ctx, value, *oldItemType, *newItemType, flags, raiseIssues); if (status.Level == IGraphTransformer::TStatus::Error) { return status; } @@ -782,7 +798,7 @@ IGraphTransformer::TStatus TryConvertToImpl(TExprContext& ctx, TExprNode::TPtr& auto nextType = to->GetItemType(); auto arg = ctx.NewArgument(node->Pos(), "item"); auto originalArg = arg; - auto status = TryConvertToImpl(ctx, arg, *from->GetItemType(), *nextType, flags); + auto status = TryConvertToImpl(ctx, arg, *from->GetItemType(), *nextType, flags, raiseIssues); if (status.Level != IGraphTransformer::TStatus::Error) { auto lambda = ctx.NewLambda(node->Pos(), ctx.NewArguments(node->Pos(), { originalArg }), std::move(arg)); @@ -798,7 +814,7 @@ IGraphTransformer::TStatus TryConvertToImpl(TExprContext& ctx, TExprNode::TPtr& auto nextType = to->GetItemType(); auto arg = ctx.NewArgument(node->Pos(), "item"); auto originalArg = arg; - auto status = TryConvertToImpl(ctx, arg, *from->GetItemType(), *nextType, flags); + auto status = TryConvertToImpl(ctx, arg, *from->GetItemType(), *nextType, flags, raiseIssues); if (status.Level != IGraphTransformer::TStatus::Error) { auto lambda = ctx.NewLambda(node->Pos(), ctx.NewArguments(node->Pos(), { originalArg }), std::move(arg)); @@ -824,8 +840,8 @@ IGraphTransformer::TStatus TryConvertToImpl(TExprContext& ctx, TExprNode::TPtr& for (ui32 i = node->IsCallable("Dict") ? 1 : 0; i < node->ChildrenSize(); ++i) { auto valueKey = node->Child(i)->ChildPtr(0); auto valuePayload = node->Child(i)->ChildPtr(1); - auto status = TryConvertToImpl(ctx, valueKey, *oldKeyType, *newKeyType, flags); - status = status.Combine(TryConvertToImpl(ctx, valuePayload, *oldPayloadType, *newPayloadType, flags)); + auto status = TryConvertToImpl(ctx, valueKey, *oldKeyType, *newKeyType, flags, raiseIssues); + status = status.Combine(TryConvertToImpl(ctx, valuePayload, *oldPayloadType, *newPayloadType, flags, raiseIssues)); if (status.Level == IGraphTransformer::TStatus::Error) { return status; } @@ -847,8 +863,8 @@ IGraphTransformer::TStatus TryConvertToImpl(TExprContext& ctx, TExprNode::TPtr& auto arg = ctx.NewArgument(node->Pos(), "item"); auto key = ctx.NewCallable(node->Pos(), "Nth", { arg, ctx.NewAtom(node->Pos(), "0") }); auto value = ctx.NewCallable(node->Pos(), "Nth", { arg, ctx.NewAtom(node->Pos(), "1") }); - auto status = TryConvertToImpl(ctx, key, *oldKeyType, *newKeyType, flags); - status = status.Combine(TryConvertToImpl(ctx, value, *oldPayloadType, *newPayloadType, flags)); + auto status = TryConvertToImpl(ctx, key, *oldKeyType, *newKeyType, flags, raiseIssues); + status = status.Combine(TryConvertToImpl(ctx, value, *oldPayloadType, *newPayloadType, flags, raiseIssues)); if (status.Level != IGraphTransformer::TStatus::Error) { auto body = ctx.NewList(node->Pos(), { key, value }); auto lambda = ctx.NewLambda(node->Pos(), ctx.NewArguments(node->Pos(), { arg }), std::move(body)); @@ -861,7 +877,7 @@ IGraphTransformer::TStatus TryConvertToImpl(TExprContext& ctx, TExprNode::TPtr& if (from->GetTag() == to->GetTag()) { auto nextType = to->GetBaseType(); auto arg = ctx.NewCallable(node->Pos(), "Untag", { node, ctx.NewAtom(node->Pos(), from->GetTag()) }); - auto status = TryConvertToImpl(ctx, arg, *from->GetBaseType(), *nextType, flags); + auto status = TryConvertToImpl(ctx, arg, *from->GetBaseType(), *nextType, flags, raiseIssues); if (status.Level != IGraphTransformer::TStatus::Error) { node = ctx.NewCallable(node->Pos(), "AsTagged", { arg, ctx.NewAtom(node->Pos(), from->GetTag()) }); return IGraphTransformer::TStatus::Repeat; @@ -3364,12 +3380,14 @@ IGraphTransformer::TStatus TryConvertTo(TExprNode::TPtr& node, const TTypeAnnota return IGraphTransformer::TStatus::Error; } - auto status = TryConvertToImpl(ctx, node, sourceType, expectedType, flags); - if (status.Level == IGraphTransformer::TStatus::Error) { - ctx.AddError(TIssue(ctx.GetPosition(node->Pos()), TStringBuilder() << "Failed to convert type: " << - sourceType << " to " << expectedType)); + TIssueScopeGuard guard(ctx.IssueManager, [&] { + return MakeIntrusive<TIssue>(ctx.GetPosition(node->Pos()), + TStringBuilder() << "Failed to convert type: " << sourceType << " to " << expectedType); + }); + auto status = TryConvertToImpl(ctx, node, sourceType, expectedType, flags, /* raiseIssues */ true); + if (status.Level == IGraphTransformer::TStatus::Error) { + guard.RaiseIssueForEmptyScope(); } - return status; } diff --git a/ydb/library/yql/public/issue/yql_issue_manager.cpp b/ydb/library/yql/public/issue/yql_issue_manager.cpp index 7375d2d30f..08daf0fcdd 100644 --- a/ydb/library/yql/public/issue/yql_issue_manager.cpp +++ b/ydb/library/yql/public/issue/yql_issue_manager.cpp @@ -69,29 +69,45 @@ void TIssueManager::LeaveScope() { } } +void TIssueManager::RaiseIssueForEmptyScope() { + if (RawIssues_.top().first.Empty()) { + TIssuePtr materialized = RawIssues_.top().second(); + if (auto p = CheckUniqAndLimit(materialized)) { + RawIssues_.top().first = p; + } + } +} + void TIssueManager::LeaveAllScopes() { while (!RawIssues_.empty()) { LeaveScope(); } } -TIssuePtr TIssueManager::CheckUniqAndLimit(const TIssue& issue) { - const auto severity = issue.GetSeverity(); +TIssuePtr TIssueManager::CheckUniqAndLimit(TIssuePtr issue) { + const auto severity = issue->GetSeverity(); if (OverflowIssues_[severity]) { return {}; } - TIssuePtr p = MakeIntrusive<TIssue>(issue); - if (UniqueIssues_[severity].contains(p)) { + if (UniqueIssues_[severity].contains(issue)) { return {}; } if (IssueLimit_ && UniqueIssues_[severity].size() == IssueLimit_) { OverflowIssues_[severity] = MakeIntrusive<TIssue>(TStringBuilder() - << "Too many " << SeverityToString(issue.GetSeverity()) << " issues"); + << "Too many " << SeverityToString(issue->GetSeverity()) << " issues"); OverflowIssues_[severity]->Severity = severity; return {}; } - UniqueIssues_[severity].insert(p); - return p; + UniqueIssues_[severity].insert(issue); + return issue; +} + +TIssuePtr TIssueManager::CheckUniqAndLimit(const TIssue& issue) { + const auto severity = issue.GetSeverity(); + if (OverflowIssues_[severity]) { + return {}; + } + return CheckUniqAndLimit(MakeIntrusive<TIssue>(issue)); } void TIssueManager::RaiseIssue(const TIssue& issue) { diff --git a/ydb/library/yql/public/issue/yql_issue_manager.h b/ydb/library/yql/public/issue/yql_issue_manager.h index 9ad5ac7bb4..d9ab4a2821 100644 --- a/ydb/library/yql/public/issue/yql_issue_manager.h +++ b/ydb/library/yql/public/issue/yql_issue_manager.h @@ -36,8 +36,11 @@ public: IssueLimit_ = limit; } + void RaiseIssueForEmptyScope(); + private: TIssuePtr CheckUniqAndLimit(const TIssue& issue); + TIssuePtr CheckUniqAndLimit(TIssuePtr issue); struct TIssueHash { ui64 operator()(const TIssuePtr& p) { @@ -66,6 +69,11 @@ public: { Manager_.AddScope(fn); } + + void RaiseIssueForEmptyScope() { + Manager_.RaiseIssueForEmptyScope(); + } + ~TIssueScopeGuard() { Manager_.LeaveScope(); diff --git a/ydb/services/ydb/ydb_table_ut.cpp b/ydb/services/ydb/ydb_table_ut.cpp index b066b130e0..d98800be5a 100644 --- a/ydb/services/ydb/ydb_table_ut.cpp +++ b/ydb/services/ydb/ydb_table_ut.cpp @@ -180,6 +180,7 @@ Y_UNIT_TEST_SUITE(YdbYqlClient) { auto ref = R"___(<main>: Error: Type annotation, code: 1030 <main>:2:25: Error: At function: KiWriteTable! <main>:2:43: Error: Failed to convert type: Struct<'Key':String,'Value':String> to Struct<'Key':Uint32?,'Value':String?> + <main>:2:43: Error: Failed to convert 'Key': String to Optional<Uint32> <main>:2:43: Error: Failed to convert input columns types to scheme types, code: 2031 )___"; UNIT_ASSERT_EQUAL(result.GetIssues().Size(), 1); |