diff options
author | a-romanov <Anton.Romanov@ydb.tech> | 2023-04-04 17:10:08 +0300 |
---|---|---|
committer | a-romanov <Anton.Romanov@ydb.tech> | 2023-04-04 17:10:08 +0300 |
commit | 895f6854157845969c838a81e1902976d28f51e9 (patch) | |
tree | d2d91106b7c07445ff9b58c4a30c7d49e8472744 | |
parent | f5c065b054162f46999670b20571fb74c360b8f2 (diff) | |
download | ydb-895f6854157845969c838a81e1902976d28f51e9.tar.gz |
YQL-8971 YQL-15555 Constraints for FlattenMembers.
-rw-r--r-- | ydb/library/yql/ast/yql_constraint.cpp | 49 | ||||
-rw-r--r-- | ydb/library/yql/ast/yql_constraint.h | 7 | ||||
-rw-r--r-- | ydb/library/yql/core/yql_expr_constraint.cpp | 59 |
3 files changed, 96 insertions, 19 deletions
diff --git a/ydb/library/yql/ast/yql_constraint.cpp b/ydb/library/yql/ast/yql_constraint.cpp index fc556132c5d..4ffe62e4b6b 100644 --- a/ydb/library/yql/ast/yql_constraint.cpp +++ b/ydb/library/yql/ast/yql_constraint.cpp @@ -994,6 +994,24 @@ TPartOfConstraintNode<TOriginalConstraintNode>::GetColumnMapping(const std::stri } template<class TOriginalConstraintNode> +typename TPartOfConstraintNode<TOriginalConstraintNode>::TMapType +TPartOfConstraintNode<TOriginalConstraintNode>::GetColumnMapping(TExprContext& ctx, const std::string_view& prefix) const { + auto mapping = Mapping_; + if (!prefix.empty()) { + const TString str(prefix); + for (auto& item : mapping) { + for (auto& part : item.second) { + if (part.first.empty()) + part.first.emplace_front(prefix); + else + part.first.front() = ctx.AppendString(str + part.first.front()); + } + } + } + return mapping; +} + +template<class TOriginalConstraintNode> const TPartOfConstraintNode<TOriginalConstraintNode>* TPartOfConstraintNode<TOriginalConstraintNode>::MakeCommon(const std::vector<const TConstraintSet*>& constraints, TExprContext& ctx) { if (constraints.empty()) { @@ -1274,6 +1292,17 @@ void TPassthroughConstraintNode::ToJson(NJson::TJsonWriter& out) const { out.CloseMap(); } +void TPassthroughConstraintNode::UniqueMerge(TMapType& output, TMapType&& input) { + output.merge(std::move(input)); + while (!input.empty()) { + const auto exists = input.extract(input.cbegin()); + auto& target = output[exists.key()]; + target.reserve(target.size() + exists.mapped().size()); + for (auto& item : exists.mapped()) + target.insert_unique(std::move(item)); + } +} + const TPassthroughConstraintNode* TPassthroughConstraintNode::ExtractField(TExprContext& ctx, const std::string_view& field) const { TMapType passtrought; for (const auto& part : Mapping_) { @@ -1388,7 +1417,7 @@ const TPassthroughConstraintNode::TMapType& TPassthroughConstraintNode::GetColum return Mapping_; } -TPassthroughConstraintNode::TMapType TPassthroughConstraintNode::GetMappingForField(const std::string_view& field) const { +TPassthroughConstraintNode::TMapType TPassthroughConstraintNode::GetColumnMapping(const std::string_view& field) const { TMapType mapping(Mapping_.size()); for (const auto& map : Mapping_) { TPartType part; @@ -1402,6 +1431,24 @@ TPassthroughConstraintNode::TMapType TPassthroughConstraintNode::GetMappingForFi return mapping; } +TPassthroughConstraintNode::TMapType TPassthroughConstraintNode::GetColumnMapping(TExprContext& ctx, const std::string_view& prefix) const { + TMapType mapping(Mapping_.size()); + for (const auto& map : Mapping_) { + TPartType part; + part.reserve(map.second.size()); + const TString str(prefix); + std::transform(map.second.cbegin(), map.second.cend(), std::back_inserter(part), [&](TPartType::value_type item) { + if (item.first.empty()) + item.first.emplace_front(prefix); + else + item.first.front() = ctx.AppendString(str + item.first.front()); + return item; + }); + mapping.emplace(map.first ? map.first : this, std::move(part)); + } + return mapping; +} + TPassthroughConstraintNode::TReverseMapType TPassthroughConstraintNode::GetReverseMapping() const { if (1U == Mapping_.size() && 1U == Mapping_.cbegin()->second.size() && Mapping_.cbegin()->second.cbegin()->first.empty()) return {{Mapping_.cbegin()->second.cbegin()->second, Mapping_.cbegin()->second.cbegin()->second}}; diff --git a/ydb/library/yql/ast/yql_constraint.h b/ydb/library/yql/ast/yql_constraint.h index 947b5f6281f..743583b08d8 100644 --- a/ydb/library/yql/ast/yql_constraint.h +++ b/ydb/library/yql/ast/yql_constraint.h @@ -299,6 +299,7 @@ public: const TMapType& GetColumnMapping() const; TMapType GetColumnMapping(const std::string_view& asField) const; + TMapType GetColumnMapping(TExprContext& ctx, const std::string_view& prefix) const; bool Equals(const TConstraintNode& node) const override; bool Includes(const TConstraintNode& node) const override; @@ -360,15 +361,17 @@ public: } const TMapType& GetColumnMapping() const; - TReverseMapType GetReverseMapping() const; + TMapType GetColumnMapping(const std::string_view& asField) const; + TMapType GetColumnMapping(TExprContext& ctx, const std::string_view& prefix) const; - TMapType GetMappingForField(const std::string_view& field) const; + TReverseMapType GetReverseMapping() const; bool Equals(const TConstraintNode& node) const override; bool Includes(const TConstraintNode& node) const override; void Out(IOutputStream& out) const override; void ToJson(NJson::TJsonWriter& out) const override; + static void UniqueMerge(TMapType& output, TMapType&& input); const TPassthroughConstraintNode* ExtractField(TExprContext& ctx, const std::string_view& field) const; static const TPassthroughConstraintNode* MakeCommon(const std::vector<const TConstraintSet*>& constraints, TExprContext& ctx); diff --git a/ydb/library/yql/core/yql_expr_constraint.cpp b/ydb/library/yql/core/yql_expr_constraint.cpp index c29ef767565..d0db56f85de 100644 --- a/ydb/library/yql/core/yql_expr_constraint.cpp +++ b/ydb/library/yql/core/yql_expr_constraint.cpp @@ -112,6 +112,7 @@ public: Functions["ExtractMembers"] = &TCallableConstraintTransformer::ExtractMembersWrap; Functions["RemoveSystemMembers"] = &TCallableConstraintTransformer::RemovePrefixMembersWrap; Functions["RemovePrefixMembers"] = &TCallableConstraintTransformer::RemovePrefixMembersWrap; + Functions["FlattenMembers"] = &TCallableConstraintTransformer::FlattenMembersWrap; Functions["SelectMembers"] = &TCallableConstraintTransformer::SelectMembersWrap; Functions["FilterMembers"] = &TCallableConstraintTransformer::SelectMembersWrap; Functions["CastStruct"] = &TCallableConstraintTransformer::SelectMembersWrap; @@ -1366,13 +1367,8 @@ private: for (auto i = 0U; i < input->ChildrenSize(); ++i) { const auto child = input->Child(i); const auto& name = ctx.GetIndexAsString(i); - if (const auto pass = child->GetConstraint<TPassthroughConstraintNode>()) { - for (auto part : pass->GetColumnMapping()) { - std::transform(part.second.cbegin(), part.second.cend(), std::back_inserter(passthrough[part.first ? part.first : pass]), [&name](TPassthroughConstraintNode::TPartType::value_type item) { - item.first.emplace_front(name); - return item; - }); - } + if (const auto part = child->GetConstraint<TPassthroughConstraintNode>()) { + TPassthroughConstraintNode::UniqueMerge(passthrough, part->GetColumnMapping(name)); } if (const auto part = child->GetConstraint<TPartOfSortedConstraintNode>()) { @@ -1421,13 +1417,8 @@ private: std::vector<const TConstraintSet*> structConstraints; for (const auto& child : input->Children()) { const auto& name = child->Head().Content(); - if (const auto pass = child->Tail().GetConstraint<TPassthroughConstraintNode>()) { - for (auto part : pass->GetColumnMapping()) { - std::transform(part.second.cbegin(), part.second.cend(), std::back_inserter(passthrough[part.first ? part.first : pass]), [&name](TPassthroughConstraintNode::TPartType::value_type item) { - item.first.emplace_front(name); - return item; - }); - } + if (const auto part = child->Tail().GetConstraint<TPassthroughConstraintNode>()) { + TPassthroughConstraintNode::UniqueMerge(passthrough, part->GetColumnMapping(name)); } if (const auto part = child->Tail().GetConstraint<TPartOfSortedConstraintNode>()) { @@ -1465,6 +1456,42 @@ private: return TStatus::Ok; } + TStatus FlattenMembersWrap(const TExprNode::TPtr& input, TExprNode::TPtr& /*output*/, TExprContext& ctx) const { + TPassthroughConstraintNode::TMapType passthrough; + TPartOfSortedConstraintNode::TMapType sorted; + TPartOfUniqueConstraintNode::TMapType uniques; + TPartOfDistinctConstraintNode::TMapType distincts; + + for (const auto& child : input->Children()) { + const auto& prefix = child->Head().Content(); + if (const auto part = child->Tail().GetConstraint<TPassthroughConstraintNode>()) { + TPassthroughConstraintNode::UniqueMerge(passthrough, part->GetColumnMapping(ctx, prefix)); + } + if (const auto part = child->Tail().GetConstraint<TPartOfSortedConstraintNode>()) { + TPartOfSortedConstraintNode::UniqueMerge(sorted, part->GetColumnMapping(ctx, prefix)); + } + if (const auto part = child->Tail().GetConstraint<TPartOfUniqueConstraintNode>()) { + TPartOfUniqueConstraintNode::UniqueMerge(uniques, part->GetColumnMapping(ctx, prefix)); + } + if (const auto part = child->Tail().GetConstraint<TPartOfDistinctConstraintNode>()) { + TPartOfDistinctConstraintNode::UniqueMerge(distincts, part->GetColumnMapping(ctx, prefix)); + } + } + if (!passthrough.empty()) { + input->AddConstraint(ctx.MakeConstraint<TPassthroughConstraintNode>(std::move(passthrough))); + } + if (!sorted.empty()) { + input->AddConstraint(ctx.MakeConstraint<TPartOfSortedConstraintNode>(std::move(sorted))); + } + if (!uniques.empty()) { + input->AddConstraint(ctx.MakeConstraint<TPartOfUniqueConstraintNode>(std::move(uniques))); + } + if (!distincts.empty()) { + input->AddConstraint(ctx.MakeConstraint<TPartOfDistinctConstraintNode>(std::move(distincts))); + } + return TStatus::Ok; + } + template<class TPartOfConstraint> static void AddPartOf(const TExprNode::TPtr& input, TExprContext& ctx) { typename TPartOfConstraint::TMapType map; @@ -2636,9 +2663,9 @@ private: TPassthroughConstraintNode::TMapType passthrough; if (const auto keysPassthrough = GetConstraintFromLambda<TPassthroughConstraintNode, false>(*input->Child(1), ctx)) - passthrough.merge(keysPassthrough->GetMappingForField(ctx.GetIndexAsString(0U))); + passthrough.merge(keysPassthrough->GetColumnMapping(ctx.GetIndexAsString(0U))); if (const auto paysPassthrough = GetConstraintFromLambda<TPassthroughConstraintNode, false>(*input->Child(2), ctx)) - passthrough.merge(paysPassthrough->GetMappingForField(ctx.GetIndexAsString(1U))); + passthrough.merge(paysPassthrough->GetColumnMapping(ctx.GetIndexAsString(1U))); if (!passthrough.empty()) input->AddConstraint(ctx.MakeConstraint<TPassthroughConstraintNode>(std::move(passthrough))); |