Skip to content

Commit

Permalink
add set rel property planning (#1136)
Browse files Browse the repository at this point in the history
  • Loading branch information
andyfengHKU committed Dec 23, 2022
1 parent 059ec91 commit f73bb9d
Show file tree
Hide file tree
Showing 28 changed files with 493 additions and 220 deletions.
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

0 comments on commit f73bb9d

Please sign in to comment.