Skip to content

Commit 724c275

Browse files
authored
[OLAP Projection pushdown] Do not push projection if kqp expects a full json document from CS (#28026)
2 parents 8caa906 + 8765a5b commit 724c275

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

ydb/core/kqp/opt/physical/kqp_opt_phy_olap_filter.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -807,17 +807,20 @@ bool IsSuitableToCollectProjection(TExprBase node) {
807807
// Collects all operations for projections and returns a vector of pair - [columName, olap operation].
808808
TVector<std::pair<TString, TExprNode::TPtr>> CollectOlapOperationsForProjections(const TExprNode::TPtr& node, const TExprNode& arg,
809809
TNodeOnNodeOwnedMap& replaces,
810-
const THashSet<TString>& predicateMembers, TExprContext& ctx) {
810+
const THashSet<TString>& predicateMembers,
811+
TExprContext& ctx) {
811812
auto asStructPred = [](const TExprNode::TPtr& node) -> bool { return !!TMaybeNode<TCoAsStruct>(node); };
812813
auto memberPred = [](const TExprNode::TPtr& node) { return !!TMaybeNode<TCoMember>(node); };
813814
THashSet<TString> projectionMembers;
815+
THashSet<TString> notSuitableToPushMembers;
814816
ui32 nextMemberId = 0;
815817

816818
TVector<std::pair<TString, TExprNode::TPtr>> olapOperationsForProjections;
817819
// Expressions for projections are placed in `AsStruct` callable.
818820
if (auto asStruct = FindNode(node, asStructPred)) {
819821
// Process each child for `AsStruct` callable.
820822
for (auto child : TExprBase(asStruct).Cast<TCoAsStruct>()) {
823+
bool memberCollected = false;
821824
if (IsSuitableToCollectProjection(child.Item(1))) {
822825
// Search for the `TCoMember` in expression, we need expression with only one `TCoMember`.
823826
if (auto originalMembers = FindNodes(child.Item(1).Ptr(), memberPred); originalMembers.size() == 1) {
@@ -834,24 +837,39 @@ TVector<std::pair<TString, TExprNode::TPtr>> CollectOlapOperationsForProjections
834837
projectionMembers.insert(originalMemberName);
835838
}
836839

840+
// clang-format off
837841
auto newMember = Build<TCoMember>(ctx, node->Pos())
838842
.Struct(originalMember.Struct())
839843
.Name<TCoAtom>()
840844
.Value(originalMemberName)
841845
.Build()
842846
.Done();
847+
// clang-format on
843848

844849
auto olapOperation = olapOperations.front();
845850
// Replace full expression with only member.
846851
replaces[child.Item(1).Raw()] = newMember.Ptr();
847852
olapOperationsForProjections.emplace_back(TString(newMember.Name()), olapOperation.Ptr());
853+
memberCollected = true;
848854

849855
YQL_CLOG(TRACE, ProviderKqp)
850856
<< "[OLAP PROJECTION] Operation in olap dialect: " << KqpExprToPrettyString(olapOperation, ctx);
851857
}
852858
}
853859
}
854860
}
861+
if (!memberCollected) {
862+
auto members = FindNodes(child.Item(1).Ptr(), memberPred);
863+
for (const auto& member : members) {
864+
notSuitableToPushMembers.insert(TString(TExprBase(member).Cast<TCoMember>().Name()));
865+
}
866+
}
867+
}
868+
}
869+
870+
for (const auto& [colName, expr] : olapOperationsForProjections) {
871+
if (notSuitableToPushMembers.count(colName)) {
872+
return {};
855873
}
856874
}
857875

ydb/core/kqp/ut/olap/kqp_olap_ut.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1861,6 +1861,29 @@ Y_UNIT_TEST_SUITE(KqpOlap) {
18611861
TString output = FormatResultSetYson(result.GetResultSet(0));
18621862
CompareYson(output, results[i]);
18631863
}
1864+
1865+
std::vector<TString> notPushedQueries = {
1866+
R"(
1867+
PRAGMA Kikimr.OptEnableOlapPushdownProjections = "true";
1868+
1869+
SELECT jsonDoc, JSON_VALUE(jsonDoc, "$.\"a.b.c\"")
1870+
FROM `/Root/foo`
1871+
where b == 1;
1872+
)"
1873+
};
1874+
1875+
for (ui32 i = 0; i < notPushedQueries.size(); ++i) {
1876+
const auto query = notPushedQueries[i];
1877+
auto result =
1878+
session2
1879+
.ExecuteQuery(query, NYdb::NQuery::TTxControl::NoTx(), NYdb::NQuery::TExecuteQuerySettings().ExecMode(NQuery::EExecMode::Explain))
1880+
.ExtractValueSync();
1881+
UNIT_ASSERT_VALUES_EQUAL(result.GetStatus(), EStatus::SUCCESS);
1882+
1883+
auto ast = *result.GetStats()->GetAst();
1884+
UNIT_ASSERT_C(ast.find("KqpOlapProjections") == std::string::npos, TStringBuilder() << "Projections pushed down. Query: " << query);
1885+
UNIT_ASSERT_C(ast.find("KqpOlapProjection") == std::string::npos, TStringBuilder() << "Projection pushed down. Query: " << query);
1886+
}
18641887
}
18651888

18661889
// Unit tests for datetime pushdowns in query service

0 commit comments

Comments
 (0)