Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop passthrough constraint #4501

Merged
merged 1 commit into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
337 changes: 0 additions & 337 deletions ydb/library/yql/ast/yql_constraint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1672,338 +1672,6 @@ template class TPartOfConstraintNode<TDistinctConstraintNode>;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

TPassthroughConstraintNode::TPassthroughConstraintNode(TExprContext& ctx, TMapType&& mapping)
: TPartOfConstraintBaseT(ctx, Name()), Mapping_(std::move(mapping))
{
YQL_ENSURE(!Mapping_.empty());
if (const auto original = Mapping_.cbegin()->first;
original && 1U == Mapping_.size() && 1U == original->Mapping_.size() && Mapping_.cbegin()->second == original->Mapping_.cbegin()->second) {
// Comeback original constraint.
Hash_ = original->Hash_;
Mapping_ = original->Mapping_;
} else {
for (const auto& part : Mapping_) {
YQL_ENSURE(!part.second.empty());
if (part.first)
Hash_ = MurmurHash<ui64>(&part.first->Hash_, sizeof(part.first->Hash_), Hash_);
for (const auto& item: part.second) {
Hash_ = std::accumulate(item.first.cbegin(), item.first.cend(), Hash_, [](ui64 hash, const std::string_view& field) { return MurmurHash<ui64>(field.data(), field.size(), hash); });
Hash_ = MurmurHash<ui64>(item.second.data(), item.second.size(), Hash_);
}
}
}
}

TPassthroughConstraintNode::TPassthroughConstraintNode(TExprContext& ctx, const TStructExprType& itemType)
: TPartOfConstraintBaseT(ctx, Name())
{
auto& mapping = Mapping_[nullptr];
for (const auto& item: itemType.GetItems()) {
const auto name = ctx.AppendString(item->GetName());
Hash_ = MurmurHash<ui64>(name.data(), name.size(), Hash_); // hash as name
Hash_ = MurmurHash<ui64>(name.data(), name.size(), Hash_); // hash as value
mapping.push_back(std::make_pair(TPathType(1U, name), name)); // Struct items are sorted
}

YQL_ENSURE(!mapping.empty());
}

TPassthroughConstraintNode::TPassthroughConstraintNode(TExprContext& ctx, const ui32 width)
: TPartOfConstraintBaseT(ctx, Name())
{
auto& mapping = Mapping_[nullptr];
for (ui32 i = 0U; i < width; ++i) {
const auto name = ctx.GetIndexAsString(i);
Hash_ = MurmurHash<ui64>(name.data(), name.size(), Hash_); // hash as name
Hash_ = MurmurHash<ui64>(name.data(), name.size(), Hash_); // hash as value
mapping.push_back(std::make_pair(TPathType(1U, name), name)); // Struct items are sorted
}

YQL_ENSURE(!mapping.empty());
}

TPassthroughConstraintNode::TPassthroughConstraintNode(TPassthroughConstraintNode&& constr) = default;

bool TPassthroughConstraintNode::Equals(const TConstraintNode& node) const {
if (this == &node) {
return true;
}
if (GetHash() != node.GetHash()) {
return false;
}
if (const auto c = dynamic_cast<const TPassthroughConstraintNode*>(&node)) {
return Mapping_ == c->Mapping_;
}
return false;
}

bool TPassthroughConstraintNode::Includes(const TConstraintNode& node) const {
if (this == &node) {
return true;
}
if (const auto c = dynamic_cast<const TPassthroughConstraintNode*>(&node)) {
for (const auto& part : c->Mapping_) {
if (const auto it = Mapping_.find(part.first == this ? nullptr : part.first); Mapping_.cend() != it) {
for (const auto& pair : part.second) {
if (const auto p = it->second.find(pair.first); it->second.cend() == p || p->second != pair.second) {
return false;
}
}
} else
return false;
}
return true;
}
return false;
}

void TPassthroughConstraintNode::Out(IOutputStream& out) const {
TConstraintNode::Out(out);
out.Write('(');

bool first = true;
for (const auto& part : Mapping_) {
for (const auto& item : part.second) {
if (first)
first = false;
else
out.Write(',');

out << item.first;
out.Write(':');
out << item.second;
}
}
out.Write(')');
}

void TPassthroughConstraintNode::ToJson(NJson::TJsonWriter& out) const {
out.OpenMap();
for (const auto& part : Mapping_) {
for (const auto& [resultColumn, originalColumn] : part.second) {
out.Write(JoinSeq(';', resultColumn), originalColumn);
}
}
out.CloseMap();
}

void TPassthroughConstraintNode::UniqueMerge(TMapType& output, TMapType&& input) {
output.merge(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_) {
auto it = part.second.lower_bound(TPathType(1U, field));
if (part.second.cend() == it || it->first.front() != field)
continue;

if (1U == it->first.size()) {
return ctx.MakeConstraint<TPassthroughConstraintNode>(TMapType{{part.first ? part.first : this , TPartType{{TPathType(), it->second}}}});
}

TPartType mapping;
mapping.reserve(part.second.size());
while (it < part.second.cend() && it->first.size() > 1U && field == it->first.front()) {
auto item = *it++;
item.first.pop_front();
mapping.emplace_back(std::move(item));
}

if (!mapping.empty()) {
passtrought.emplace(part.first ? part.first : this, std::move(mapping));
}
}
return passtrought.empty() ? nullptr : ctx.MakeConstraint<TPassthroughConstraintNode>(std::move(passtrought));
}

const TPartOfConstraintBase*
TPassthroughConstraintNode::DoFilterFields(TExprContext& ctx, const TPathFilter& predicate) const {
if (!predicate)
return this;

TMapType passtrought(Mapping_.size());
for (const auto& part : Mapping_) {
TPartType mapping;
mapping.reserve(part.second.size());

for (const auto& item : part.second) {
if (predicate(item.first)) {
mapping.insert_unique(std::make_pair(item.first, item.second));
}
}

if (!mapping.empty())
passtrought.emplace(part.first ? part.first : this, std::move(mapping));
}
return passtrought.empty() ? nullptr : ctx.MakeConstraint<TPassthroughConstraintNode>(std::move(passtrought));
}

const TPartOfConstraintBase*
TPassthroughConstraintNode::DoRenameFields(TExprContext& ctx, const TPathReduce& rename) const {
if (!rename)
return this;

TMapType passtrought(Mapping_.size());
for (const auto& part : Mapping_) {
TPartType mapping;
mapping.reserve(part.second.size());

for (const auto& item : part.second) {
for (auto& path : rename(item.first)) {
mapping.insert_unique(std::make_pair(std::move(path), item.second));
}
}

if (!mapping.empty())
passtrought.emplace(part.first ? part.first : this, std::move(mapping));
}
return passtrought.empty() ? nullptr : ctx.MakeConstraint<TPassthroughConstraintNode>(std::move(passtrought));
}

const TPassthroughConstraintNode* TPassthroughConstraintNode::MakeCommon(const std::vector<const TConstraintSet*>& constraints, TExprContext& ctx) {
if (constraints.empty()) {
return nullptr;
}

if (constraints.size() == 1) {
return constraints.front()->GetConstraint<TPassthroughConstraintNode>();
}

bool first = true;
TPassthroughConstraintNode::TMapType mapping;
for (size_t i = 0; i < constraints.size(); ++i) {
auto part = constraints[i]->GetConstraint<TPassthroughConstraintNode>();
if (!part) {
if (constraints[i]->GetConstraint<TEmptyConstraintNode>()) {
continue;
}
return nullptr;
}
if (first) {
mapping = part->GetColumnMapping();
if (const auto self = mapping.find(nullptr); mapping.cend() != self) {
mapping.emplace(part, std::move(mapping.extract(self).mapped()));
}
first = false;
} else {
for (const auto& nextMapping : part->GetColumnMapping()) {
if (const auto it = mapping.find(nextMapping.first ? nextMapping.first : part); mapping.cend() != it) {
TPassthroughConstraintNode::TPartType result;
std::set_intersection(
it->second.cbegin(), it->second.cend(),
nextMapping.second.cbegin(), nextMapping.second.cend(),
std::back_inserter(result),
[] (const TPassthroughConstraintNode::TPartType::value_type& c1, const TPassthroughConstraintNode::TPartType::value_type& c2) {
return c1 < c2;
}
);
if (result.empty())
mapping.erase(it);
else
it->second = std::move(result);
}
}
}
if (mapping.empty()) {
break;
}
}

return mapping.empty() ? nullptr : ctx.MakeConstraint<TPassthroughConstraintNode>(std::move(mapping));
}

const TPassthroughConstraintNode* TPassthroughConstraintNode::MakeCommon(const TPassthroughConstraintNode* other, TExprContext& ctx) const {
if (!other) {
return nullptr;
} else if (this == other) {
return this;
}

auto mapping = GetColumnMapping();
if (const auto self = mapping.find(nullptr); mapping.cend() != self)
mapping.emplace(this, std::move(mapping.extract(self).mapped()));

for (const auto& nextMapping : other->GetColumnMapping()) {
if (const auto it = mapping.find(nextMapping.first ? nextMapping.first : other); mapping.cend() != it) {
TPassthroughConstraintNode::TPartType result;
std::set_intersection(
it->second.cbegin(), it->second.cend(),
nextMapping.second.cbegin(), nextMapping.second.cend(),
std::back_inserter(result),
[] (const TPassthroughConstraintNode::TPartType::value_type& c1, const TPassthroughConstraintNode::TPartType::value_type& c2) {
return c1 < c2;
}
);
if (result.empty())
mapping.erase(it);
else
it->second = std::move(result);
}
}

return mapping.empty() ? nullptr : ctx.MakeConstraint<TPassthroughConstraintNode>(std::move(mapping));
}

const TPassthroughConstraintNode::TMapType& TPassthroughConstraintNode::GetColumnMapping() const {
return Mapping_;
}

TPassthroughConstraintNode::TMapType TPassthroughConstraintNode::GetColumnMapping(const std::string_view& field) const {
TMapType mapping(Mapping_.size());
for (const auto& map : Mapping_) {
TPartType part;
part.reserve(map.second.size());
std::transform(map.second.cbegin(), map.second.cend(), std::back_inserter(part), [&field](TPartType::value_type item) {
item.first.emplace_front(field);
return item;
});
mapping.emplace(map.first ? map.first : this, std::move(part));
}
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 {
TReverseMapType reverseMapping;
for (const auto& part : Mapping_) {
for (const auto& item : part.second) {
if (item.first.empty())
reverseMapping.emplace_back(item.second, std::string_view());
else if (1U == item.first.size())
reverseMapping.emplace_back(item.second, item.first.front());
}
}
::Sort(reverseMapping);
return reverseMapping;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

TEmptyConstraintNode::TEmptyConstraintNode(TExprContext& ctx)
: TConstraintNode(ctx, Name())
{
Expand Down Expand Up @@ -2482,11 +2150,6 @@ void Out<NYql::TPartOfDistinctConstraintNode>(IOutputStream& out, const NYql::TP
c.Out(out);
}

template<>
void Out<NYql::TPassthroughConstraintNode>(IOutputStream& out, const NYql::TPassthroughConstraintNode& c) {
c.Out(out);
}

template<>
void Out<NYql::TEmptyConstraintNode>(IOutputStream& out, const NYql::TEmptyConstraintNode& c) {
c.Out(out);
Expand Down
40 changes: 0 additions & 40 deletions ydb/library/yql/ast/yql_constraint.h
Original file line number Diff line number Diff line change
Expand Up @@ -436,46 +436,6 @@ constexpr std::string_view TPartOfDistinctConstraintNode::Name() {
return "PartOfDistinct";
}

class TPassthroughConstraintNode final: public TPartOfConstraintBaseT<TPassthroughConstraintNode> {
public:
using TPartType = NSorted::TSimpleMap<TPartOfConstraintBase::TPathType, std::string_view>;
using TMapType = std::unordered_map<const TPassthroughConstraintNode*, TPartType>;
using TReverseMapType = NSorted::TSimpleMap<std::string_view, std::string_view>;
private:
friend struct TExprContext;

TPassthroughConstraintNode(TExprContext& ctx, const TStructExprType& itemType);
TPassthroughConstraintNode(TExprContext& ctx, const ui32 width);
TPassthroughConstraintNode(TPassthroughConstraintNode&& constr);
TPassthroughConstraintNode(TExprContext& ctx, TMapType&& mapping);
public:
static constexpr std::string_view Name() {
return "Passthrough";
}

const TMapType& GetColumnMapping() const;
TMapType GetColumnMapping(const std::string_view& asField) const;
TMapType GetColumnMapping(TExprContext& ctx, const std::string_view& prefix) 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);
const TPassthroughConstraintNode* MakeCommon(const TPassthroughConstraintNode* other, TExprContext& ctx) const;
private:
const TPartOfConstraintBase* DoFilterFields(TExprContext& ctx, const TPathFilter& predicate) const final;
const TPartOfConstraintBase* DoRenameFields(TExprContext& ctx, const TPathReduce& reduce) const final;

TMapType Mapping_;
};

class TEmptyConstraintNode final: public TConstraintNode {
protected:
friend struct TExprContext;
Expand Down
Loading
Loading