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

Allow usage of aliases defined in previous matches. #5021

Merged
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
9 changes: 6 additions & 3 deletions src/graph/validator/MatchValidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ Status MatchValidator::buildColumnsForAllNamedAliases(const std::vector<QueryPar
switch (boundary->kind) {
case CypherClauseKind::kUnwind: {
auto unwindCtx = static_cast<const UnwindClauseContext *>(boundary.get());
columns->addColumn(makeColumn(unwindCtx->alias));
columns->addColumn(makeColumn(unwindCtx->alias), true);
break;
}
case CypherClauseKind::kWith: {
Expand All @@ -390,7 +390,7 @@ Status MatchValidator::buildColumnsForAllNamedAliases(const std::vector<QueryPar
}
for (auto &col : yieldColumns->columns()) {
if (!col->alias().empty()) {
columns->addColumn(makeColumn(col->alias()));
columns->addColumn(makeColumn(col->alias()), true);
}
}
break;
Expand Down Expand Up @@ -584,7 +584,10 @@ Status MatchValidator::validateWith(const WithClause *with,
auto found = withClauseCtx.yield->aliasesAvailable.find(label);
DCHECK(found != withClauseCtx.yield->aliasesAvailable.end());
if (!withClauseCtx.aliasesGenerated.emplace(col->alias(), found->second).second) {
return Status::SemanticError("`%s': Redefined alias", col->alias().c_str());
auto columnFound = withClauseCtx.yield->yieldColumns->find(col->alias());
if (!(columnFound != nullptr && columnFound->isMatched())) {
return Status::SemanticError("`%s': Redefined alias", col->alias().c_str());
}
}
} else {
if (!withClauseCtx.aliasesGenerated.emplace(col->alias(), aliasType).second) {
Expand Down
22 changes: 21 additions & 1 deletion src/parser/Clauses.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ class YieldColumn final {
explicit YieldColumn(Expression *expr, const std::string &alias = "") {
expr_ = expr;
alias_ = alias;
isMatched_ = false;
}

std::unique_ptr<YieldColumn> clone() const {
Expand Down Expand Up @@ -285,9 +286,18 @@ class YieldColumn final {

std::string toString() const;

void setMatched(bool isMatched) {
isMatched_ = isMatched;
}

bool isMatched() const {
return isMatched_;
}

private:
Expression *expr_{nullptr};
std::string alias_;
bool isMatched_;
};

bool operator==(const YieldColumn &l, const YieldColumn &r);
Expand All @@ -297,8 +307,9 @@ inline bool operator!=(const YieldColumn &l, const YieldColumn &r) {

class YieldColumns final {
public:
void addColumn(YieldColumn *field) {
void addColumn(YieldColumn *field, bool isMatched = false) {
columns_.emplace_back(field);
field->setMatched(isMatched);
}

std::vector<YieldColumn *> columns() const {
Expand Down Expand Up @@ -346,6 +357,15 @@ class YieldColumns final {

bool hasAgg() const;

YieldColumn *find(const std::string &name) const {
for (auto &col : columns_) {
if (name.compare(col->name()) == 0) {
return col.get();
}
}
return nullptr;
}

private:
std::vector<std::unique_ptr<YieldColumn>> columns_;
};
Expand Down
28 changes: 27 additions & 1 deletion tests/tck/features/match/With.feature
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ Feature: With clause
Scenario: with wildcard after unwind
When executing query:
"""
match p = (v0)-[e0]->(v1) where id(v0) in ["Tim Duncan"] unwind v0 as uv0 with * return e0 limit 5;
match p = (v0)-[e0]->(v1) where id(v0) in ["Tim Duncan"] unwind v0 as uv0 with * return e0;
"""
Then the result should be, in any order:
| e0 |
Expand All @@ -387,3 +387,29 @@ Feature: With clause
| [:teammate "Tim Duncan"->"Tony Parker" @0 {end_year: 2016, start_year: 2001}] |
| [:like "Tim Duncan"->"Tony Parker" @0 {likeness: 95}] |
| [:teammate "Tim Duncan"->"Danny Green" @0 {end_year: 2016, start_year: 2010}] |
| [:teammate "Tim Duncan"->"Manu Ginobili" @0 {end_year: 2016, start_year: 2002}] |
| [:like "Tim Duncan"->"Manu Ginobili" @0 {likeness: 95}] |

Scenario: with wildcard after multiple matches
When executing query:
"""
match (v0:player)--(v1:team) where v1.team.name == "Spurs" and v0.player.name == "Tim Duncan"
match (v:player) where v.player.name != "Tim Duncan" with v0 where v0.player.age > 0
match (v0:player)
with *
return count(v0)
xtcyclist marked this conversation as resolved.
Show resolved Hide resolved
"""
Then the result should be, in order:
| count(v0) |
| 51 |
When executing query:
"""
match (v:player)
with v AS p
match (p)
with p AS v
match (v)
with *
return count (p)
"""
Then a SemanticError should be raised at runtime: Alias used but not defined: `p'