diff options
author | Tony-Romanov <150126326+Tony-Romanov@users.noreply.github.com> | 2024-07-15 13:31:04 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-15 14:31:04 +0300 |
commit | 755aa56521d25e7d7f4b078e675b1d60b5fc5264 (patch) | |
tree | 0588b9729953404a6e3f14fc5d37c719257a5ffe | |
parent | a6eb07c046fa5e88777549a74558adc62787aaf0 (diff) | |
download | ydb-755aa56521d25e7d7f4b078e675b1d60b5fc5264.tar.gz |
Fix DqPhyJoinDict. (#6610)
9 files changed, 117 insertions, 184 deletions
diff --git a/ydb/library/yql/core/peephole_opt/yql_opt_peephole_physical.cpp b/ydb/library/yql/core/peephole_opt/yql_opt_peephole_physical.cpp index 17b1458c69..e671f434bc 100644 --- a/ydb/library/yql/core/peephole_opt/yql_opt_peephole_physical.cpp +++ b/ydb/library/yql/core/peephole_opt/yql_opt_peephole_physical.cpp @@ -670,8 +670,8 @@ TExprNode::TPtr ExpandEquiJoinImpl(const TExprNode& node, TExprContext& ctx) { const bool multi1 = payload1 && !uniqueLeft; const bool multi2 = payload2 && !uniqueRight; - list1 = PrepareListForJoin(std::move(list1), keyTypeItems, keyMembers1, payloads1, payload1, optKey, filter1, ctx); - list2 = PrepareListForJoin(std::move(list2), keyTypeItems, keyMembers2, payloads2, payload2, optKey, filter2, ctx); + list1 = PrepareListForJoin(std::move(list1), keyTypeItems, keyMembers1, std::move(payloads1), payload1, optKey, filter1, ctx); + list2 = PrepareListForJoin(std::move(list2), keyTypeItems, keyMembers2, std::move(payloads2), payload2, optKey, filter2, ctx); return ctx.Builder(node.Pos()) .Callable("Map") diff --git a/ydb/library/yql/core/yql_join.cpp b/ydb/library/yql/core/yql_join.cpp index 544cd1fadf..265a78da9a 100644 --- a/ydb/library/yql/core/yql_join.cpp +++ b/ydb/library/yql/core/yql_join.cpp @@ -1421,8 +1421,20 @@ TExprNode::TPtr RemapNonConvertibleMemberForJoin(TPositionHandle pos, const TExp return result; } -TExprNode::TPtr PrepareListForJoin(TExprNode::TPtr list, const TTypeAnnotationNode::TListType& keyTypes, TExprNode::TListType& keys, TExprNode::TListType& payloads, bool payload, bool optional, bool filter, TExprContext& ctx) { +TExprNode::TPtr PrepareListForJoin(TExprNode::TPtr list, const TTypeAnnotationNode::TListType& keyTypes, TExprNode::TListType& keys, TExprNode::TListType&& payloads, bool payload, bool optional, bool filter, TExprContext& ctx) { const auto pos = list->Pos(); + const auto filterPayloads = [&payloads](TExprNodeBuilder& parent) -> TExprNodeBuilder& { + if (payloads.empty()) + parent.Arg(1, "row"); + else + parent.Callable(1, "FilterMembers") + .Arg(0, "row") + .List(1) + .Add(std::move(payloads)) + .Seal() + .Seal(); + return parent; + }; if (keyTypes.empty() && 1U == keys.size()) { return payload ? @@ -1433,12 +1445,7 @@ TExprNode::TPtr PrepareListForJoin(TExprNode::TPtr list, const TTypeAnnotationNo .Param("row") .List() .Add(0, std::move(keys.front())) - .Callable(1, "FilterMembers") - .Arg(0, "row") - .List(1) - .Add(std::move(payloads)) - .Seal() - .Seal() + .Do(filterPayloads) .Seal() .Seal() .Seal() @@ -1470,12 +1477,7 @@ TExprNode::TPtr PrepareListForJoin(TExprNode::TPtr list, const TTypeAnnotationNo .Seal() .Add(1, ExpandType(pos, *keyType, ctx)) .Seal() - .Callable(1, "FilterMembers") - .Arg(0, "row") - .List(1) - .Add(std::move(payloads)) - .Seal() - .Seal() + .Do(filterPayloads) .Seal() .Seal() .Seal() @@ -1498,12 +1500,7 @@ TExprNode::TPtr PrepareListForJoin(TExprNode::TPtr list, const TTypeAnnotationNo .Callable("Just") .List(0) .Arg(0, "key") - .Callable(1, "FilterMembers") - .Arg(0, "row") - .List(1) - .Add(std::move(payloads)) - .Seal() - .Seal() + .Do(filterPayloads) .Seal() .Seal() .Seal() @@ -1550,12 +1547,7 @@ TExprNode::TPtr PrepareListForJoin(TExprNode::TPtr list, const TTypeAnnotationNo .Seal() .Add(1, ExpandType(pos, *keyType, ctx)) .Seal() - .Callable(1, "FilterMembers") - .Arg(0, "row") - .List(1) - .Add(std::move(payloads)) - .Seal() - .Seal() + .Do(filterPayloads) .Seal() .Seal() .Seal() @@ -1586,12 +1578,7 @@ TExprNode::TPtr PrepareListForJoin(TExprNode::TPtr list, const TTypeAnnotationNo .Callable("Just") .List(0) .Arg(0, "key") - .Callable(1, "FilterMembers") - .Arg(0, "row") - .List(1) - .Add(std::move(payloads)) - .Seal() - .Seal() + .Do(filterPayloads) .Seal() .Seal() .Seal() @@ -1634,7 +1621,7 @@ TExprNode::TPtr PrepareListForJoin(TExprNode::TPtr list, const TTypeAnnotationNo .Callable(0, "Exists") .Callable(0, "Nth") .Arg(0, "row") - .Atom(1, "0", TNodeFlags::Default) + .Atom(1, 0U) .Seal() .Seal() .Seal() @@ -1666,14 +1653,14 @@ TExprNode::TPtr MakeDictForJoin(TExprNode::TPtr&& list, bool payload, bool multi .Param("row") .Callable("Nth") .Arg(0, "row") - .Atom(1, "0", TNodeFlags::Default) + .Atom(1, 0U) .Seal() .Seal() .Lambda(2) .Param("row") .Callable("Nth") .Arg(0, "row") - .Atom(1, "1", TNodeFlags::Default) + .Atom(1, 1U) .Seal() .Seal() .List(3) diff --git a/ydb/library/yql/core/yql_join.h b/ydb/library/yql/core/yql_join.h index fbed1f9383..40150764e4 100644 --- a/ydb/library/yql/core/yql_join.h +++ b/ydb/library/yql/core/yql_join.h @@ -154,7 +154,8 @@ TExprNode::TPtr BuildEquiJoinLinkSettings(const TEquiJoinLinkSettings& linkSetti TExprNode::TPtr RemapNonConvertibleMemberForJoin(TPositionHandle pos, const TExprNode::TPtr& memberValue, const TTypeAnnotationNode& memberType, const TTypeAnnotationNode& unifiedType, TExprContext& ctx); -TExprNode::TPtr PrepareListForJoin(TExprNode::TPtr list, const TTypeAnnotationNode::TListType& keyTypes, TExprNode::TListType& keys, TExprNode::TListType& payloads, bool payload, bool optional, bool filter, TExprContext& ctx); +TExprNode::TPtr PrepareListForJoin(TExprNode::TPtr list, const TTypeAnnotationNode::TListType& keyTypes, TExprNode::TListType& keys, bool payload, bool optional, bool filter, TExprContext& ctx); +TExprNode::TPtr PrepareListForJoin(TExprNode::TPtr list, const TTypeAnnotationNode::TListType& keyTypes, TExprNode::TListType& keys, TExprNode::TListType&& payloads, bool payload, bool optional, bool filter, TExprContext& ctx); template<bool Squeeze = false> TExprNode::TPtr MakeDictForJoin(TExprNode::TPtr&& list, bool payload, bool multi, TExprContext& ctx); diff --git a/ydb/library/yql/dq/opt/dq_opt_peephole.cpp b/ydb/library/yql/dq/opt/dq_opt_peephole.cpp index cd6d3138fb..1fc1e59cd1 100644 --- a/ydb/library/yql/dq/opt/dq_opt_peephole.cpp +++ b/ydb/library/yql/dq/opt/dq_opt_peephole.cpp @@ -68,60 +68,6 @@ std::pair<TExprNode::TListType, TExprNode::TListType> JoinKeysToAtoms(TExprConte return {std::move(leftNodes), std::move(rightNodes)}; } -TExprNode::TPtr BuildDictKeySelector(TExprContext& ctx, TPositionHandle pos, const TExprNode::TListType& keyAtoms, - const TTypeAnnotationNode::TListType& keyDryTypes, bool needCast) -{ - YQL_ENSURE(keyAtoms.size() == keyDryTypes.size()); - - TExprNode::TListType keysTuple; - - auto keySelectorArg = Build<TCoArgument>(ctx, pos) - .Name("keyArg") - .Done(); - - for (const auto& atom: keyAtoms) { - auto member = Build<TCoMember>(ctx, pos) - .Struct(keySelectorArg) - .Name(atom) - .Done(); - - keysTuple.emplace_back(member.Ptr()); - } - - if (keysTuple.size() == 1) { - return needCast - ? Build<TCoLambda>(ctx, pos) - .Args({keySelectorArg}) - .Body<TCoStrictCast>() - .Value(keysTuple[0]) - .Type(ExpandType(pos, *keyDryTypes[0], ctx)) - .Build() - .Done().Ptr() - : Build<TCoLambda>(ctx, pos) - .Args({keySelectorArg}) - .Body<TCoJust>() - .Input(keysTuple[0]) - .Build() - .Done().Ptr(); - } - - auto type = ctx.MakeType<TOptionalExprType>(ctx.MakeType<TTupleExprType>(keyDryTypes)); - return needCast - ? Build<TCoLambda>(ctx, pos) - .Args({keySelectorArg}) - .Body<TCoStrictCast>() - .Value(ctx.NewList(pos, std::move(keysTuple))) - .Type(ExpandType(pos, *type, ctx)) - .Build() - .Done().Ptr() - : Build<TCoLambda>(ctx, pos) - .Args({keySelectorArg}) - .Body<TCoJust>() - .Input(ctx.NewList(pos, std::move(keysTuple))) - .Build() - .Done().Ptr(); -} - TExprNode::TPtr AddConvertedKeys(TExprNode::TPtr list, TExprContext& ctx, TExprNode::TListType& leftKeyColumnNodes, const TTypeAnnotationNode::TListType& keyTypes, const TStructExprType* origItemType) { std::vector<std::pair<TString, std::pair<TString, const TTypeAnnotationNode*>>> columnsToConvert; for (auto i = 0U; i < leftKeyColumnNodes.size(); i++) { @@ -290,7 +236,7 @@ TExprBase DqPeepholeRewriteMapJoin(const TExprBase& node, TExprContext& ctx) { } const bool payloads = !rightPayloads.empty(); - rightInput = MakeDictForJoin<true>(PrepareListForJoin(std::move(rightInput), keyTypes, rightKeyColumnNodes, rightPayloads, payloads, false, true, ctx), payloads, withRightSide, ctx); + rightInput = MakeDictForJoin<true>(PrepareListForJoin(std::move(rightInput), keyTypes, rightKeyColumnNodes, std::move(rightPayloads), payloads, false, true, ctx), payloads, withRightSide, ctx); leftInput = AddConvertedKeys(std::move(leftInput), ctx, leftKeyColumnNodes, keyTypesLeft, itemTypeLeft); auto [leftKeyColumnNodesCopy, rightKeyColumnNodesCopy] = JoinKeysToAtoms(ctx, mapJoin, leftTableLabel, rightTableLabel); auto [_, rightKeyColumnNodesAnotherCopy] = JoinKeysToAtoms(ctx, mapJoin, leftTableLabel, rightTableLabel); @@ -471,97 +417,105 @@ NNodes::TExprBase DqPeepholeRewriteJoinDict(const NNodes::TExprBase& node, TExpr const auto* leftRowType = GetSeqItemType(*joinDict.LeftInput().Ref().GetTypeAnn()).Cast<TStructExprType>(); const auto* rightRowType = GetSeqItemType(*joinDict.RightInput().Ref().GetTypeAnn()).Cast<TStructExprType>(); - bool castKeyLeft = false, castKeyRight = false, badKey = false; + bool optKey = false, badKey = false; + const bool filter = joinKind == "Inner" || joinKind.ends_with("Semi"); + const bool leftKind = joinKind.starts_with("Left"); + const bool rightKind = joinKind.starts_with("Right"); TTypeAnnotationNode::TListType keyTypeItems; - keyTypeItems.reserve(leftKeys.size()); - for (auto i = 0U; i < leftKeys.size(); ++i) { - bool optKeyLeft = false, optKeyRight = false; - auto leftKeyType = leftRowType->FindItemType(leftKeys[i]->Content()); - auto rightKeyType = rightRowType->FindItemType(rightKeys[i]->Content()); - auto leftDryType = DryType(leftKeyType, optKeyLeft, ctx); - auto rightDryType = DryType(rightKeyType, optKeyRight, ctx); - auto commonType = CommonType<true>(node.Pos(), leftDryType, rightDryType, ctx); - badKey = !commonType; - if (badKey) { - YQL_CLOG(DEBUG, CoreDq) << "Join has null result in key comparison: " << leftKeys[i]->Content() - << "(" << *leftKeyType << ") and " << rightKeys[i]->Content() << "(" << *rightKeyType << ")"; - break; + keyTypeItems.reserve(rightKeys.size()); + std::vector<std::string_view> lKeys(leftKeys.size()), rKeys(rightKeys.size()); + for (auto i = 0U; i < rightKeys.size() && !badKey; ++i) { + const auto keyType1 = leftRowType->FindItemType(lKeys[i] = leftKeys[i]->Content()); + const auto keyType2 = rightRowType->FindItemType(rKeys[i] = rightKeys[i]->Content()); + if (leftKind) { + keyTypeItems.emplace_back(JoinDryKeyType(keyType1, keyType2, optKey, ctx)); + } else if (rightKind){ + keyTypeItems.emplace_back(JoinDryKeyType(keyType2, keyType1, optKey, ctx)); + } else { + keyTypeItems.emplace_back(CommonType<true>(node.Pos(), DryType(keyType1, optKey, ctx), DryType(keyType2, optKey, ctx), ctx)); + optKey = optKey && !filter; } - castKeyLeft = castKeyLeft || (!IsSameAnnotation(*leftDryType, *commonType) || optKeyLeft); - castKeyRight = castKeyRight || (!IsSameAnnotation(*rightDryType, *commonType) || optKeyRight); - keyTypeItems.emplace_back(commonType); + badKey = !keyTypeItems.back(); } - TExprNode::TPtr leftKeySelector; - TExprNode::TPtr rightKeySelector; + const bool payload1 = joinKind != "RightOnly" && joinKind != "RightSemi"; + const bool payload2 = joinKind != "LeftOnly" && joinKind != "LeftSemi"; - if (badKey) { - leftKeySelector = Build<TCoLambda>(ctx, node.Pos()) - .Args({"row"}) - .Body<TCoBool>() - .Literal().Build("true") - .Build() - .Done().Ptr(); + const bool filter1 = filter || rightKind; + const bool filter2 = filter || leftKind; - rightKeySelector = Build<TCoLambda>(ctx, node.Pos()) - .Args({"item"}) - .Body<TCoBool>() - .Literal().Build("false") - .Build() - .Done().Ptr(); - } else { - leftKeySelector = BuildDictKeySelector(ctx, joinDict.Pos(), leftKeys, keyTypeItems, castKeyLeft); - rightKeySelector = BuildDictKeySelector(ctx, joinDict.Pos(), rightKeys, keyTypeItems, castKeyRight); + auto list1 = joinDict.LeftInput().Ptr(); + auto list2 = joinDict.RightInput().Ptr(); + + if (list1->IsCallable(TCoIterator::CallableName())) + list1 = list1->HeadPtr(); + + if (list2->IsCallable(TCoIterator::CallableName())) + list2 = list2->HeadPtr(); + + const auto lUnique = list1->GetConstraint<TUniqueConstraintNode>(); + const auto rUnique = list2->GetConstraint<TUniqueConstraintNode>(); + + const bool uniqueLeft = lUnique && lUnique->ContainsCompleteSet(lKeys); + const bool uniqueRight = rUnique && rUnique->ContainsCompleteSet(rKeys); + + const bool multi1 = payload1 && !uniqueLeft; + const bool multi2 = payload2 && !uniqueRight; + + TExprNode::TListType flags; + if (uniqueLeft) + flags.emplace_back(ctx.NewAtom(node.Pos(), "LeftUnique", TNodeFlags::Default)); + if (uniqueRight) + flags.emplace_back(ctx.NewAtom(node.Pos(), "RightUnique", TNodeFlags::Default)); + + if (badKey) { + if (filter) + return TExprBase(ctx.NewCallable(node.Pos(), "EmptyIterator", {ExpandType(node.Pos(), *node.Ref().GetTypeAnn(), ctx)})); + + lKeys.clear(); + rKeys.clear(); + keyTypeItems.clear(); + leftKeys.clear(); + rightKeys.clear(); + leftKeys.emplace_back(MakeBool<true>(node.Pos(), ctx)); + rightKeys.emplace_back(MakeBool<false>(node.Pos(), ctx)); } - const auto streamToDict = [&ctx](const TExprBase& input, const TExprNode::TPtr& keySelector) { - return Build<TCoSqueezeToDict>(ctx, input.Pos()) - .Stream(TCoIterator::Match(input.Raw()) ? TExprBase(ctx.RenameNode(input.Ref(), TCoToFlow::CallableName())) : input) - .KeySelector(keySelector) - .PayloadSelector() - .Args({"item"}) - .Body("item") - .Build() - .Settings() - .Add<TCoAtom>().Build("Hashed", TNodeFlags::Default) - .Add<TCoAtom>().Build("Many", TNodeFlags::Default) - .Add<TCoAtom>().Build("Compact", TNodeFlags::Default) - .Build() - .Done(); - }; + list1 = ctx.WrapByCallableIf(ETypeAnnotationKind::Flow != list1->GetTypeAnn()->GetKind(), TCoToFlow::CallableName(), std::move(list1)); + list2 = ctx.WrapByCallableIf(ETypeAnnotationKind::Flow != list2->GetTypeAnn()->GetKind(), TCoToFlow::CallableName(), std::move(list2)); + + list1 = PrepareListForJoin(std::move(list1), keyTypeItems, leftKeys, {}, payload1, optKey, filter1, ctx); + list2 = PrepareListForJoin(std::move(list2), keyTypeItems, rightKeys, {}, payload2, optKey, filter2, ctx); + + list1 = MakeDictForJoin<true>(std::move(list1), payload1, multi1, ctx); + list2 = MakeDictForJoin<true>(std::move(list2), payload2, multi2, ctx); - auto leftDict = streamToDict(joinDict.LeftInput(), leftKeySelector); - auto rightDict = streamToDict(joinDict.RightInput(), rightKeySelector); + // Join return list of tuple of structs. I.e. if you have tables t1 and t2 with values t1.a, t1.b and t2.c, t2.d, + // you will receive List<Tuple<Struct<t1.a, t1.b>, Struct<t2.c, t2.d>>> and this data should be unpacked to + // List<Struct<t1.a, t1.b, t2.c, t2.d>> + const auto unpackData = UnpackJoinedData(leftRowType, rightRowType, leftTableLabel, rightTableLabel, joinDict.Pos(), ctx); - auto join = Build<TCoFlatMap>(ctx, joinDict.Pos()) - .Input(leftDict) // only 1 element with dict + return Build<TCoFlatMap>(ctx, joinDict.Pos()) + .Input(std::move(list1)) .Lambda() .Args({"left"}) .Body<TCoFlatMap>() - .Input(rightDict) // only 1 element with dict + .Input(std::move(list2)) .Lambda() .Args({"right"}) - .Body<TCoJoinDict>() - .LeftInput("left") - .RightInput("right") - .JoinKind(joinDict.JoinType()) + .Body<TCoMap>() + .Input<TCoJoinDict>() + .LeftInput("left") + .RightInput("right") + .JoinKind(joinDict.JoinType()) + .Flags().Add(std::move(flags)).Build() + .Build() + .Lambda(unpackData) .Build() .Build() .Build() .Build() .Done(); - - // Join return list of tuple of structs. I.e. if you have tables t1 and t2 with values t1.a, t1.b and t2.c, t2.d, - // you will receive List<Tuple<Struct<t1.a, t1.b>, Struct<t2.c, t2.d>>> and this data should be unpacked to - // List<Struct<t1.a, t1.b, t2.c, t2.d>> - auto unpackData = UnpackJoinedData(leftRowType, rightRowType, leftTableLabel, rightTableLabel, join.Pos(), ctx); - - return Build<TCoMap>(ctx, joinDict.Pos()) - .Input<TCoToFlow>() - .Input(join) - .Build() - .Lambda(unpackData) - .Done(); } NNodes::TExprBase DqPeepholeRewritePureJoin(const NNodes::TExprBase& node, TExprContext& ctx) { diff --git a/ydb/tests/functional/suite_tests/canondata/test_postgres.TestPGSQL.test_sql_suite_plan-jointest_join0.test_/query_14.plan b/ydb/tests/functional/suite_tests/canondata/test_postgres.TestPGSQL.test_sql_suite_plan-jointest_join0.test_/query_14.plan index 311ea09b1a..5083d32a5a 100644 --- a/ydb/tests/functional/suite_tests/canondata/test_postgres.TestPGSQL.test_sql_suite_plan-jointest_join0.test_/query_14.plan +++ b/ydb/tests/functional/suite_tests/canondata/test_postgres.TestPGSQL.test_sql_suite_plan-jointest_join0.test_/query_14.plan @@ -64,11 +64,20 @@ "PlanNodeType": "Connection", "Plans": [ { - "Node Type": "FullJoin (JoinDict)", + "Node Type": "Filter-FullJoin (JoinDict)", "Operators": [ { "Inputs": [ { + "InternalOperatorId": 1 + } + ], + "Name": "Filter", + "Predicate": "Exist(item.yy_1.id)" + }, + { + "Inputs": [ + { "ExternalPlanNodeId": 4 }, { diff --git a/ydb/tests/functional/suite_tests/canondata/test_postgres.TestPGSQL.test_sql_suite_plan-jointest_join0.test_/query_16.plan b/ydb/tests/functional/suite_tests/canondata/test_postgres.TestPGSQL.test_sql_suite_plan-jointest_join0.test_/query_16.plan index 069755e91d..1664f00d6f 100644 --- a/ydb/tests/functional/suite_tests/canondata/test_postgres.TestPGSQL.test_sql_suite_plan-jointest_join0.test_/query_16.plan +++ b/ydb/tests/functional/suite_tests/canondata/test_postgres.TestPGSQL.test_sql_suite_plan-jointest_join0.test_/query_16.plan @@ -50,7 +50,7 @@ } ], "Name": "Filter", - "Predicate": "Nth.unique2 == 42" + "Predicate": "item.b.unique2 == 42" }, { "Inputs": [ diff --git a/ydb/tests/functional/suite_tests/canondata/test_postgres.TestPGSQL.test_sql_suite_plan-jointest_join1.test_/query_11.plan b/ydb/tests/functional/suite_tests/canondata/test_postgres.TestPGSQL.test_sql_suite_plan-jointest_join1.test_/query_11.plan index f8325b2f07..2a8b12fc78 100644 --- a/ydb/tests/functional/suite_tests/canondata/test_postgres.TestPGSQL.test_sql_suite_plan-jointest_join1.test_/query_11.plan +++ b/ydb/tests/functional/suite_tests/canondata/test_postgres.TestPGSQL.test_sql_suite_plan-jointest_join1.test_/query_11.plan @@ -35,15 +35,6 @@ "Inputs": [ { "InternalOperatorId": 1 - }, - { - "InternalOperatorId": 1 - }, - { - "InternalOperatorId": 1 - }, - { - "InternalOperatorId": 1 } ], "Limit": "1001", diff --git a/ydb/tests/functional/suite_tests/canondata/test_postgres.TestPGSQL.test_sql_suite_plan-jointest_join1.test_/query_12.plan b/ydb/tests/functional/suite_tests/canondata/test_postgres.TestPGSQL.test_sql_suite_plan-jointest_join1.test_/query_12.plan index 750e3105a2..42aca3955b 100644 --- a/ydb/tests/functional/suite_tests/canondata/test_postgres.TestPGSQL.test_sql_suite_plan-jointest_join1.test_/query_12.plan +++ b/ydb/tests/functional/suite_tests/canondata/test_postgres.TestPGSQL.test_sql_suite_plan-jointest_join1.test_/query_12.plan @@ -35,15 +35,6 @@ "Inputs": [ { "InternalOperatorId": 1 - }, - { - "InternalOperatorId": 1 - }, - { - "InternalOperatorId": 1 - }, - { - "InternalOperatorId": 1 } ], "Limit": "1001", diff --git a/ydb/tests/functional/suite_tests/postgres/jointest/join-group-by-with-null.test b/ydb/tests/functional/suite_tests/postgres/jointest/join-group-by-with-null.test index 443f4ec64c..beea35f7bc 100644 --- a/ydb/tests/functional/suite_tests/postgres/jointest/join-group-by-with-null.test +++ b/ydb/tests/functional/suite_tests/postgres/jointest/join-group-by-with-null.test @@ -32,7 +32,7 @@ select a.x as x, count(b.q) from left join (select 2 as q, 5 as p) as b on b.q = a.y -group by a.x +group by a.x order by x desc statement query select t1.q2 as q2, count(t1.q1) as cnt |