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

Plan rel property update #1136

Merged
merged 1 commit into from
Dec 23, 2022
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
1 change: 1 addition & 0 deletions src/binder/bind/bind_ddl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "binder/bind/bound_drop_table.h"
#include "binder/binder.h"
#include "parser/ddl/create_node_clause.h"
#include "parser/ddl/create_rel_clause.h"
#include "parser/ddl/drop_table.h"

namespace kuzu {
Expand Down
68 changes: 48 additions & 20 deletions src/binder/bind/bind_updating_clause.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,38 +108,66 @@ unique_ptr<BoundUpdatingClause> Binder::bindSetClause(const UpdatingClause& upda
auto boundSetClause = make_unique<BoundSetClause>();
for (auto i = 0u; i < setClause.getNumSetItems(); ++i) {
auto setItem = setClause.getSetItem(i);
auto boundLhs = expressionBinder.bindExpression(*setItem->origin);
auto boundNodeOrRel = boundLhs->getChild(0);
if (boundNodeOrRel->dataType.typeID != NODE) {
throw BinderException("Set " + Types::dataTypeToString(boundNodeOrRel->dataType) +
auto nodeOrRel = expressionBinder.bindExpression(*setItem.first->getChild(0));
switch (nodeOrRel->dataType.typeID) {
case DataTypeID::NODE: {
auto node = static_pointer_cast<NodeExpression>(nodeOrRel);
boundSetClause->addSetNodeProperty(bindSetNodeProperty(node, setItem));
} break;
case DataTypeID::REL: {
auto rel = static_pointer_cast<RelExpression>(nodeOrRel);
boundSetClause->addSetRelProperty(bindSetRelProperty(rel, setItem));
} break;
default:
throw BinderException("Set " + expressionTypeToString(nodeOrRel->expressionType) +
" property is supported.");
}
auto boundNode = static_pointer_cast<NodeExpression>(boundNodeOrRel);
if (boundNode->isMultiLabeled()) {
throw BinderException("Set property of node " + boundNode->getRawName() +
" with multiple node labels is not supported.");
}
auto boundRhs = expressionBinder.bindExpression(*setItem->target);
boundRhs = ExpressionBinder::implicitCastIfNecessary(boundRhs, boundLhs->dataType);
boundSetClause->addSetItem(make_pair(boundLhs, boundRhs));
}
return boundSetClause;
}

unique_ptr<BoundSetNodeProperty> Binder::bindSetNodeProperty(
shared_ptr<NodeExpression> node, pair<ParsedExpression*, ParsedExpression*> setItem) {
if (node->isMultiLabeled()) {
throw BinderException("Set property of node " + node->getRawName() +
" with multiple node labels is not supported.");
}
return make_unique<BoundSetNodeProperty>(std::move(node), bindSetItem(setItem));
}

unique_ptr<BoundSetRelProperty> Binder::bindSetRelProperty(
shared_ptr<RelExpression> rel, pair<ParsedExpression*, ParsedExpression*> setItem) {
if (rel->isMultiLabeled() || rel->isBoundByMultiLabeledNode()) {
throw BinderException("Set property of rel " + rel->getRawName() +
" with multiple rel labels or bound by multiple node labels "
"is not supported.");
}
return make_unique<BoundSetRelProperty>(std::move(rel), bindSetItem(setItem));
}

expression_pair Binder::bindSetItem(pair<ParsedExpression*, ParsedExpression*> setItem) {
auto boundLhs = expressionBinder.bindExpression(*setItem.first);
auto boundRhs = expressionBinder.bindExpression(*setItem.second);
boundRhs = ExpressionBinder::implicitCastIfNecessary(boundRhs, boundLhs->dataType);
return make_pair(std::move(boundLhs), std::move(boundRhs));
}

unique_ptr<BoundUpdatingClause> Binder::bindDeleteClause(const UpdatingClause& updatingClause) {
auto& deleteClause = (DeleteClause&)updatingClause;
auto boundDeleteClause = make_unique<BoundDeleteClause>();
for (auto i = 0u; i < deleteClause.getNumExpressions(); ++i) {
auto boundExpression = expressionBinder.bindExpression(*deleteClause.getExpression(i));
if (boundExpression->dataType.typeID == NODE) {
auto deleteNode = bindDeleteNode(static_pointer_cast<NodeExpression>(boundExpression));
auto nodeOrRel = expressionBinder.bindExpression(*deleteClause.getExpression(i));
switch (nodeOrRel->dataType.typeID) {
case DataTypeID::NODE: {
auto deleteNode = bindDeleteNode(static_pointer_cast<NodeExpression>(nodeOrRel));
boundDeleteClause->addDeleteNode(std::move(deleteNode));
} else if (boundExpression->dataType.typeID == REL) {
auto deleteRel = bindDeleteRel(static_pointer_cast<RelExpression>(boundExpression));
} break;
case DataTypeID::REL: {
auto deleteRel = bindDeleteRel(static_pointer_cast<RelExpression>(nodeOrRel));
boundDeleteClause->addDeleteRel(std::move(deleteRel));
} else {
throw BinderException("Delete " +
expressionTypeToString(boundExpression->expressionType) +
} break;
default:
throw BinderException("Delete " + expressionTypeToString(nodeOrRel->expressionType) +
" is not supported.");
}
}
Expand Down
1 change: 1 addition & 0 deletions src/binder/query/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ add_library(
bound_create_clause.cpp
bound_delete_clause.cpp
bound_projection_body.cpp
bound_set_clause.cpp
normalized_query_part.cpp
normalized_single_query.cpp
query_graph.cpp)
Expand Down
33 changes: 33 additions & 0 deletions src/binder/query/bound_set_clause.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include "binder/query/updating_clause/bound_set_clause.h"

namespace kuzu {
namespace binder {

expression_vector BoundSetClause::getPropertiesToRead() const {
expression_vector result;
for (auto& setNodeProperty : setNodeProperties) {
for (auto& property : setNodeProperty->getSetItem().second->getSubPropertyExpressions()) {
result.push_back(property);
}
}
for (auto& setRelProperty : setRelProperties) {
for (auto& property : setRelProperty->getSetItem().second->getSubPropertyExpressions()) {
result.push_back(property);
}
}
return result;
}

unique_ptr<BoundUpdatingClause> BoundSetClause::copy() {
auto result = make_unique<BoundSetClause>();
for (auto& setNodeProperty : setNodeProperties) {
result->addSetNodeProperty(setNodeProperty->copy());
}
for (auto& setRelProperty : setRelProperties) {
result->addSetRelProperty(setRelProperty->copy());
}
return result;
}

} // namespace binder
} // namespace kuzu
9 changes: 8 additions & 1 deletion src/include/binder/binder.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#include "binder/query/bound_regular_query.h"
#include "common/csv_reader/csv_reader.h"
#include "expression_binder.h"
#include "parser/ddl/create_rel_clause.h"
#include "parser/query/regular_query.h"
#include "query_normalizer.h"

Expand All @@ -15,7 +14,10 @@ namespace binder {

class BoundCreateNode;
class BoundCreateRel;
class BoundSetNodeProperty;
class BoundSetRelProperty;
class BoundDeleteNode;
class SetItem;

class Binder {
friend class ExpressionBinder;
Expand Down Expand Up @@ -76,6 +78,11 @@ class Binder {
shared_ptr<NodeExpression> node, const PropertyKeyValCollection& collection);
unique_ptr<BoundCreateRel> bindCreateRel(
shared_ptr<RelExpression> rel, const PropertyKeyValCollection& collection);
unique_ptr<BoundSetNodeProperty> bindSetNodeProperty(
shared_ptr<NodeExpression> node, pair<ParsedExpression*, ParsedExpression*> setItem);
unique_ptr<BoundSetRelProperty> bindSetRelProperty(
shared_ptr<RelExpression> rel, pair<ParsedExpression*, ParsedExpression*> setItem);
expression_pair bindSetItem(pair<ParsedExpression*, ParsedExpression*> setItem);
unique_ptr<BoundDeleteNode> bindDeleteNode(shared_ptr<NodeExpression> node);
shared_ptr<RelExpression> bindDeleteRel(shared_ptr<RelExpression> rel);

Expand Down
71 changes: 52 additions & 19 deletions src/include/binder/query/updating_clause/bound_set_clause.h
Original file line number Diff line number Diff line change
@@ -1,39 +1,72 @@
#pragma once

#include "binder/expression/rel_expression.h"
#include "bound_updating_clause.h"

namespace kuzu {
namespace binder {

class BoundSetClause : public BoundUpdatingClause {
class BoundSetNodeProperty {
public:
BoundSetNodeProperty(shared_ptr<NodeExpression> node, expression_pair setItem)
: node{std::move(node)}, setItem{std::move(setItem)} {}

inline shared_ptr<NodeExpression> getNode() const { return node; }
inline expression_pair getSetItem() const { return setItem; }

inline unique_ptr<BoundSetNodeProperty> copy() const {
return make_unique<BoundSetNodeProperty>(node, setItem);
}

private:
shared_ptr<NodeExpression> node;
expression_pair setItem;
};

class BoundSetRelProperty {
public:
BoundSetClause() : BoundUpdatingClause{ClauseType::SET} {};
BoundSetRelProperty(shared_ptr<RelExpression> rel, expression_pair setItem)
: rel{std::move(rel)}, setItem{std::move(setItem)} {}

inline void addSetItem(expression_pair setItem) { setItems.push_back(std::move(setItem)); }
inline shared_ptr<RelExpression> getRel() const { return rel; }
inline expression_pair getSetItem() const { return setItem; }

inline expression_vector getPropertiesToRead() const override {
expression_vector result;
for (auto& setItem : setItems) {
for (auto& property : setItem.second->getSubPropertyExpressions()) {
result.push_back(property);
}
}
return result;
inline unique_ptr<BoundSetRelProperty> copy() const {
return make_unique<BoundSetRelProperty>(rel, setItem);
}

inline vector<expression_pair> getSetItems() const { return setItems; }
private:
shared_ptr<RelExpression> rel;
expression_pair setItem;
};

inline unique_ptr<BoundUpdatingClause> copy() override {
auto result = make_unique<BoundSetClause>();
for (auto& setItem : setItems) {
result->addSetItem(setItem);
}
return result;
class BoundSetClause : public BoundUpdatingClause {
public:
BoundSetClause() : BoundUpdatingClause{ClauseType::SET} {};

inline void addSetNodeProperty(unique_ptr<BoundSetNodeProperty> setNodeProperty) {
setNodeProperties.push_back(std::move(setNodeProperty));
}
inline bool hasSetNodeProperty() const { return !setNodeProperties.empty(); }
inline const vector<unique_ptr<BoundSetNodeProperty>>& getSetNodeProperties() const {
return setNodeProperties;
}

inline void addSetRelProperty(unique_ptr<BoundSetRelProperty> setRelProperty) {
setRelProperties.push_back(std::move(setRelProperty));
}
inline bool hasSetRelProperty() const { return !setRelProperties.empty(); }
inline const vector<unique_ptr<BoundSetRelProperty>>& getSetRelProperties() const {
return setRelProperties;
}

expression_vector getPropertiesToRead() const override;

unique_ptr<BoundUpdatingClause> copy() override;

private:
vector<expression_pair> setItems;
vector<unique_ptr<BoundSetNodeProperty>> setNodeProperties;
vector<unique_ptr<BoundSetRelProperty>> setRelProperties;
};

} // namespace binder
Expand Down
21 changes: 8 additions & 13 deletions src/include/parser/query/updating_clause/set_clause.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,22 @@
namespace kuzu {
namespace parser {

struct SetItem {

SetItem(unique_ptr<ParsedExpression> origin, unique_ptr<ParsedExpression> target)
: origin{move(origin)}, target{move(target)} {}

unique_ptr<ParsedExpression> origin;
unique_ptr<ParsedExpression> target;
};

class SetClause : public UpdatingClause {

public:
SetClause() : UpdatingClause{ClauseType::SET} {};
~SetClause() override = default;

inline void addSetItem(unique_ptr<SetItem> setItem) { setItems.push_back(move(setItem)); }
inline void addSetItem(
pair<unique_ptr<ParsedExpression>, unique_ptr<ParsedExpression>> setItem) {
setItems.push_back(std::move(setItem));
}
inline uint32_t getNumSetItems() const { return setItems.size(); }
inline SetItem* getSetItem(uint32_t idx) const { return setItems[idx].get(); }
inline pair<ParsedExpression*, ParsedExpression*> getSetItem(uint32_t idx) const {
return make_pair(setItems[idx].first.get(), setItems[idx].second.get());
}

private:
vector<unique_ptr<SetItem>> setItems;
vector<pair<unique_ptr<ParsedExpression>, unique_ptr<ParsedExpression>>> setItems;
};

} // namespace parser
Expand Down
3 changes: 2 additions & 1 deletion src/include/parser/transformer.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ class Transformer {

unique_ptr<UpdatingClause> transformSet(CypherParser::OC_SetContext& ctx);

unique_ptr<SetItem> transformSetItem(CypherParser::OC_SetItemContext& ctx);
pair<unique_ptr<ParsedExpression>, unique_ptr<ParsedExpression>> transformSetItem(
CypherParser::OC_SetItemContext& ctx);

unique_ptr<UpdatingClause> transformDelete(CypherParser::OC_DeleteContext& ctx);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ enum class LogicalOperatorType : uint8_t {
SCAN_NODE_PROPERTY,
SEMI_MASKER,
SET_NODE_PROPERTY,
SET_REL_PROPERTY,
SKIP,
UNION_ALL,
UNWIND,
Expand Down
25 changes: 15 additions & 10 deletions src/include/planner/logical_plan/logical_operator/logical_create.h
Original file line number Diff line number Diff line change
@@ -1,32 +1,37 @@
#pragma once

#include "logical_create_delete.h"
#include "logical_update.h"

namespace kuzu {
namespace planner {

class LogicalCreateNode : public LogicalCreateOrDeleteNode {
class LogicalCreateNode : public LogicalUpdateNode {
public:
LogicalCreateNode(
vector<pair<shared_ptr<NodeExpression>, shared_ptr<Expression>>> nodeAndPrimaryKeys,
LogicalCreateNode(vector<shared_ptr<NodeExpression>> nodes, expression_vector primaryKeys,
shared_ptr<LogicalOperator> child)
: LogicalCreateOrDeleteNode{
LogicalOperatorType::CREATE_NODE, std::move(nodeAndPrimaryKeys), std::move(child)} {}
: LogicalUpdateNode{LogicalOperatorType::CREATE_NODE, std::move(nodes), std::move(child)},
primaryKeys{std::move(primaryKeys)} {}
~LogicalCreateNode() override = default;

void computeSchema() override;

inline shared_ptr<Expression> getPrimaryKey(size_t idx) const { return primaryKeys[idx]; }

inline unique_ptr<LogicalOperator> copy() override {
return make_unique<LogicalCreateNode>(nodeAndPrimaryKeys, children[0]->copy());
return make_unique<LogicalCreateNode>(nodes, primaryKeys, children[0]->copy());
}

private:
expression_vector primaryKeys;
};

class LogicalCreateRel : public LogicalCreateOrDeleteRel {
class LogicalCreateRel : public LogicalUpdateRel {
public:
LogicalCreateRel(vector<shared_ptr<RelExpression>> rels,
vector<vector<expression_pair>> setItemsPerRel, shared_ptr<LogicalOperator> child)
: LogicalCreateOrDeleteRel{LogicalOperatorType::CREATE_REL, std::move(rels),
std::move(child)},
: LogicalUpdateRel{LogicalOperatorType::CREATE_REL, std::move(rels), std::move(child)},
setItemsPerRel{std::move(setItemsPerRel)} {}
~LogicalCreateRel() override = default;

inline vector<expression_pair> getSetItems(uint32_t idx) const { return setItemsPerRel[idx]; }

Expand Down
Loading