aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMikhail Surin <surinmike@gmail.com>2022-06-15 13:44:04 +0300
committerDaniil Cherednik <dan.cherednik@gmail.com>2022-06-15 13:44:04 +0300
commit4230edd531b7ad8794a2f0b2fbd3ff3b5cdd8f9f (patch)
tree92262046d8195cc3c421c8aff91936423ebf20f4
parent65b5db5601fc4b0e91597f5d63979e587494bc31 (diff)
downloadydb-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.cpp26
-rw-r--r--ydb/library/yql/core/yql_expr_type_annotation.cpp72
-rw-r--r--ydb/library/yql/public/issue/yql_issue_manager.cpp30
-rw-r--r--ydb/library/yql/public/issue/yql_issue_manager.h8
-rw-r--r--ydb/services/ydb/ydb_table_ut.cpp1
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);