diff --git a/src/binder/bind/bind_graph_pattern.cpp b/src/binder/bind/bind_graph_pattern.cpp index 253d7168a7..e16284f9d7 100644 --- a/src/binder/bind/bind_graph_pattern.cpp +++ b/src/binder/bind/bind_graph_pattern.cpp @@ -97,6 +97,9 @@ void Binder::bindQueryRel(const RelPattern& relPattern, const shared_ptr( getUniqueExpressionName(parsedName), tableID, srcNode, dstNode, lowerBound, upperBound); + if (!queryRel->isVariableLength()) { + queryRel->setInternalIDProperty(expressionBinder.bindInternalIDExpression(queryRel)); + } queryRel->setAlias(parsedName); queryRel->setRawName(parsedName); if (!parsedName.empty()) { @@ -141,6 +144,7 @@ shared_ptr Binder::createQueryNode(const NodePattern& nodePatter auto parsedName = nodePattern.getVariableName(); auto tableIDs = bindNodeTableIDs(nodePattern.getTableNames()); auto queryNode = make_shared(getUniqueExpressionName(parsedName), tableIDs); + queryNode->setInternalIDProperty(expressionBinder.bindInternalIDExpression(queryNode)); queryNode->setAlias(parsedName); queryNode->setRawName(parsedName); if (!parsedName.empty()) { diff --git a/src/binder/expression/existential_subquery_expression.cpp b/src/binder/expression/existential_subquery_expression.cpp index 3cbb780a75..20fe6dff9e 100644 --- a/src/binder/expression/existential_subquery_expression.cpp +++ b/src/binder/expression/existential_subquery_expression.cpp @@ -17,8 +17,8 @@ unordered_set ExistentialSubqueryExpression::getDependentVariableNames() // expressions from predicates and return clause. Plus nodeID expressions from query graph. expression_vector ExistentialSubqueryExpression::getChildren() const { expression_vector result; - for (auto& nodeIDExpression : queryGraphCollection->getNodeIDExpressions()) { - result.push_back(nodeIDExpression); + for (auto& node : queryGraphCollection->getQueryNodes()) { + result.push_back(node->getInternalIDProperty()); } if (hasWhereExpression()) { result.push_back(whereExpression); diff --git a/src/binder/expression_binder.cpp b/src/binder/expression_binder.cpp index cca44fb133..95af0683e8 100644 --- a/src/binder/expression_binder.cpp +++ b/src/binder/expression_binder.cpp @@ -307,16 +307,30 @@ shared_ptr ExpressionBinder::bindInternalIDExpression( shared_ptr ExpressionBinder::bindInternalIDExpression( shared_ptr nodeOrRel) { if (nodeOrRel->dataType.typeID == NODE) { - return ((NodeExpression*)nodeOrRel.get())->getNodeIDPropertyExpression(); + return bindInternalNodeIDExpression(nodeOrRel); } else { assert(nodeOrRel->dataType.typeID == REL); - auto rel = (RelExpression*)nodeOrRel.get(); - auto relTableSchema = - binder->catalog.getReadOnlyVersion()->getRelTableSchema(rel->getTableID()); - return bindRelPropertyExpression(nodeOrRel, relTableSchema->getRelIDDefinition()); + return bindInternalRelIDExpression(nodeOrRel); } } +shared_ptr ExpressionBinder::bindInternalNodeIDExpression(shared_ptr node) { + auto nodeExpression = (NodeExpression*)node.get(); + unordered_map propertyIDPerTable; + for (auto tableID : nodeExpression->getTableIDs()) { + propertyIDPerTable.insert({tableID, INVALID_PROPERTY_ID}); + } + return make_unique( + DataType(NODE_ID), INTERNAL_ID_SUFFIX, std::move(propertyIDPerTable), node); +} + +shared_ptr ExpressionBinder::bindInternalRelIDExpression(shared_ptr rel) { + auto relExpression = (RelExpression*)rel.get(); + auto relTableSchema = + binder->catalog.getReadOnlyVersion()->getRelTableSchema(relExpression->getTableID()); + return bindRelPropertyExpression(rel, relTableSchema->getRelIDDefinition()); +} + shared_ptr ExpressionBinder::bindParameterExpression( const ParsedExpression& parsedExpression) { auto& parsedParameterExpression = (ParsedParameterExpression&)parsedExpression; diff --git a/src/binder/query/bound_delete_clause.cpp b/src/binder/query/bound_delete_clause.cpp index 3dee00873a..21dfa86fbd 100644 --- a/src/binder/query/bound_delete_clause.cpp +++ b/src/binder/query/bound_delete_clause.cpp @@ -8,6 +8,11 @@ expression_vector BoundDeleteClause::getPropertiesToRead() const { for (auto& deleteNode : deleteNodes) { result.push_back(deleteNode->getPrimaryKeyExpression()); } + for (auto& deleteRel : deleteRels) { + if (deleteRel->hasInternalIDProperty()) { + result.push_back(deleteRel->getInternalIDProperty()); + } + } return result; } diff --git a/src/binder/query/query_graph.cpp b/src/binder/query/query_graph.cpp index 13e0902ac0..8e911ac189 100644 --- a/src/binder/query/query_graph.cpp +++ b/src/binder/query/query_graph.cpp @@ -187,14 +187,6 @@ bool QueryGraph::isConnected(const QueryGraph& other) { return false; } -vector> QueryGraph::getNodeIDExpressions() const { - vector> result; - for (auto& queryNode : queryNodes) { - result.push_back(queryNode->getNodeIDPropertyExpression()); - } - return result; -} - void QueryGraphCollection::addAndMergeQueryGraphIfConnected( unique_ptr queryGraphToAdd) { bool isMerged = false; @@ -209,11 +201,21 @@ void QueryGraphCollection::addAndMergeQueryGraphIfConnected( } } -expression_vector QueryGraphCollection::getNodeIDExpressions() const { - expression_vector result; +vector> QueryGraphCollection::getQueryNodes() const { + vector> result; + for (auto& queryGraph : queryGraphs) { + for (auto& node : queryGraph->getQueryNodes()) { + result.push_back(node); + } + } + return result; +} + +vector> QueryGraphCollection::getQueryRels() const { + vector> result; for (auto& queryGraph : queryGraphs) { - for (auto& nodeID : queryGraph->getNodeIDExpressions()) { - result.push_back(nodeID); + for (auto& rel : queryGraph->getQueryRels()) { + result.push_back(rel); } } return result; diff --git a/src/include/binder/expression/node_expression.h b/src/include/binder/expression/node_expression.h index ef8dca7afa..05ec7230dd 100644 --- a/src/include/binder/expression/node_expression.h +++ b/src/include/binder/expression/node_expression.h @@ -20,19 +20,20 @@ class NodeExpression : public Expression { return *tableIDs.begin(); } - inline string getIDProperty() const { return uniqueName + "." + INTERNAL_ID_SUFFIX; } - - inline shared_ptr getNodeIDPropertyExpression() { - unordered_map propertyIDPerTable; - for (auto tableID : tableIDs) { - propertyIDPerTable.insert({tableID, INVALID_PROPERTY_ID}); - } - return make_unique(DataType(NODE_ID), INTERNAL_ID_SUFFIX, - std::move(propertyIDPerTable), shared_from_this()); + inline void setInternalIDProperty(shared_ptr expression) { + internalIDExpression = std::move(expression); + } + inline shared_ptr getInternalIDProperty() const { + assert(internalIDExpression != nullptr); + return internalIDExpression; + } + inline string getInternalIDPropertyName() const { + return internalIDExpression->getUniqueName(); } private: unordered_set tableIDs; + shared_ptr internalIDExpression; }; } // namespace binder diff --git a/src/include/binder/expression/rel_expression.h b/src/include/binder/expression/rel_expression.h index dc6141546a..413fd213c9 100644 --- a/src/include/binder/expression/rel_expression.h +++ b/src/include/binder/expression/rel_expression.h @@ -1,17 +1,17 @@ #pragma once +#include "common/exception.h" #include "node_expression.h" namespace kuzu { namespace binder { class RelExpression : public Expression { - public: RelExpression(const string& uniqueName, table_id_t tableID, shared_ptr srcNode, shared_ptr dstNode, uint64_t lowerBound, uint64_t upperBound) - : Expression{VARIABLE, REL, uniqueName}, tableID{tableID}, srcNode{move(srcNode)}, - dstNode{move(dstNode)}, lowerBound{lowerBound}, upperBound{upperBound} {} + : Expression{VARIABLE, REL, uniqueName}, tableID{tableID}, srcNode{std::move(srcNode)}, + dstNode{std::move(dstNode)}, lowerBound{lowerBound}, upperBound{upperBound} {} inline table_id_t getTableID() const { return tableID; } @@ -29,12 +29,25 @@ class RelExpression : public Expression { inline bool isVariableLength() const { return !(lowerBound == 1 && upperBound == 1); } + inline void setInternalIDProperty(shared_ptr expression) { + internalIDExpression = std::move(expression); + } + inline bool hasInternalIDProperty() const { return internalIDExpression != nullptr; } + inline shared_ptr getInternalIDProperty() const { + if (!hasInternalIDProperty()) { + throw NotImplementedException( + "Cannot read internal ID property for variable length rel " + getRawName()); + } + return internalIDExpression; + } + private: table_id_t tableID; shared_ptr srcNode; shared_ptr dstNode; uint64_t lowerBound; uint64_t upperBound; + shared_ptr internalIDExpression; }; } // namespace binder diff --git a/src/include/binder/expression_binder.h b/src/include/binder/expression_binder.h index 4f9c5d044a..d2cf3144c7 100644 --- a/src/include/binder/expression_binder.h +++ b/src/include/binder/expression_binder.h @@ -54,6 +54,8 @@ class ExpressionBinder { shared_ptr bindInternalIDExpression(const ParsedExpression& parsedExpression); shared_ptr bindInternalIDExpression(shared_ptr nodeOrRel); + shared_ptr bindInternalNodeIDExpression(shared_ptr node); + shared_ptr bindInternalRelIDExpression(shared_ptr rel); shared_ptr bindParameterExpression(const ParsedExpression& parsedExpression); diff --git a/src/include/binder/query/reading_clause/bound_match_clause.h b/src/include/binder/query/reading_clause/bound_match_clause.h index 2d027165e5..89434b9559 100644 --- a/src/include/binder/query/reading_clause/bound_match_clause.h +++ b/src/include/binder/query/reading_clause/bound_match_clause.h @@ -41,6 +41,11 @@ class BoundMatchClause : public BoundReadingClause { inline expression_vector getSubPropertyExpressions() const override { expression_vector expressions; + for (auto& rel : queryGraphCollection->getQueryRels()) { + if (rel->hasInternalIDProperty()) { + expressions.push_back(rel->getInternalIDProperty()); + } + } if (this->hasWhereExpression()) { for (auto& property : this->getWhereExpression()->getSubPropertyExpressions()) { expressions.push_back(property); diff --git a/src/include/binder/query/reading_clause/query_graph.h b/src/include/binder/query/reading_clause/query_graph.h index 1e6e1e5d6a..bdb348deaf 100644 --- a/src/include/binder/query/reading_clause/query_graph.h +++ b/src/include/binder/query/reading_clause/query_graph.h @@ -87,6 +87,7 @@ class QueryGraph { inline bool containsQueryNode(const string& queryNodeName) const { return queryNodeNameToPosMap.contains(queryNodeName); } + inline vector> getQueryNodes() const { return queryNodes; } inline shared_ptr getQueryNode(const string& queryNodeName) const { return queryNodes[getQueryNodePos(queryNodeName)]; } @@ -112,6 +113,7 @@ class QueryGraph { inline bool containsQueryRel(const string& queryRelName) const { return queryRelNameToPosMap.contains(queryRelName); } + inline vector> getQueryRels() const { return queryRels; } inline shared_ptr getQueryRel(const string& queryRelName) const { return queryRels.at(queryRelNameToPosMap.at(queryRelName)); } @@ -129,8 +131,6 @@ class QueryGraph { void merge(const QueryGraph& other); - vector> getNodeIDExpressions() const; - inline unique_ptr copy() const { return make_unique(*this); } private: @@ -150,7 +150,8 @@ class QueryGraphCollection { inline uint32_t getNumQueryGraphs() const { return queryGraphs.size(); } inline QueryGraph* getQueryGraph(uint32_t idx) const { return queryGraphs[idx].get(); } - expression_vector getNodeIDExpressions() const; + vector> getQueryNodes() const; + vector> getQueryRels() const; unique_ptr copy() const; diff --git a/src/include/planner/logical_plan/logical_operator/logical_extend.h b/src/include/planner/logical_plan/logical_operator/logical_extend.h index d4353fecb4..217cf2ec40 100644 --- a/src/include/planner/logical_plan/logical_operator/logical_extend.h +++ b/src/include/planner/logical_plan/logical_operator/logical_extend.h @@ -26,7 +26,7 @@ class LogicalExtend : public LogicalOperator { } inline void computeSchema(Schema& schema) { - auto boundGroupPos = schema.getGroupPos(boundNode->getIDProperty()); + auto boundGroupPos = schema.getGroupPos(boundNode->getInternalIDPropertyName()); uint32_t nbrGroupPos = 0u; if (isColumn) { nbrGroupPos = boundGroupPos; @@ -34,7 +34,7 @@ class LogicalExtend : public LogicalOperator { assert(schema.getGroup(boundGroupPos)->getIsFlat()); nbrGroupPos = schema.createGroup(); } - schema.insertToGroupAndScope(nbrNode->getNodeIDPropertyExpression(), nbrGroupPos); + schema.insertToGroupAndScope(nbrNode->getInternalIDProperty(), nbrGroupPos); } inline shared_ptr getBoundNodeExpression() const { return boundNode; } diff --git a/src/include/planner/logical_plan/logical_operator/logical_scan_node.h b/src/include/planner/logical_plan/logical_operator/logical_scan_node.h index 5962a4e1c3..50bd3b2a11 100644 --- a/src/include/planner/logical_plan/logical_operator/logical_scan_node.h +++ b/src/include/planner/logical_plan/logical_operator/logical_scan_node.h @@ -19,7 +19,7 @@ class LogicalScanNode : public LogicalOperator { inline virtual void computeSchema(Schema& schema) { auto groupPos = schema.createGroup(); - schema.insertToGroupAndScope(node->getNodeIDPropertyExpression(), groupPos); + schema.insertToGroupAndScope(node->getInternalIDProperty(), groupPos); } inline shared_ptr getNode() const { return node; } @@ -43,7 +43,7 @@ class LogicalIndexScanNode : public LogicalScanNode { inline void computeSchema(Schema& schema) override { LogicalScanNode::computeSchema(schema); - auto groupPos = schema.getGroupPos(node->getIDProperty()); + auto groupPos = schema.getGroupPos(node->getInternalIDPropertyName()); schema.getGroup(groupPos)->setIsFlat(true); } diff --git a/src/include/processor/operator/update/delete.h b/src/include/processor/operator/update/delete.h index 1d6e2d9031..ca1a34c27e 100644 --- a/src/include/processor/operator/update/delete.h +++ b/src/include/processor/operator/update/delete.h @@ -56,15 +56,16 @@ struct DeleteRelInfo { table_id_t srcNodeTableID; DataPos dstNodePos; table_id_t dstNodeTableID; + DataPos relIDPos; DeleteRelInfo(RelTable* table, const DataPos& srcNodePos, table_id_t srcNodeTableID, - const DataPos& dstNodePos, table_id_t dstNodeTableID) + const DataPos& dstNodePos, table_id_t dstNodeTableID, const DataPos& relIDPos) : table{table}, srcNodePos{srcNodePos}, srcNodeTableID{srcNodeTableID}, - dstNodePos{dstNodePos}, dstNodeTableID{dstNodeTableID} {} + dstNodePos{dstNodePos}, dstNodeTableID{dstNodeTableID}, relIDPos{relIDPos} {} inline unique_ptr clone() { return make_unique( - table, srcNodePos, srcNodeTableID, dstNodePos, dstNodeTableID); + table, srcNodePos, srcNodeTableID, dstNodePos, dstNodeTableID, relIDPos); } }; @@ -95,7 +96,9 @@ class DeleteRel : public PhysicalOperator { private: RelsStatistics& relsStatistics; vector> deleteRelInfos; - vector> srcDstNodeIDVectorPairs; + vector srcNodeVectors; + vector dstNodeVectors; + vector relIDVectors; }; } // namespace processor diff --git a/src/planner/join_order_enumerator.cpp b/src/planner/join_order_enumerator.cpp index d25e005eff..5474d18353 100644 --- a/src/planner/join_order_enumerator.cpp +++ b/src/planner/join_order_enumerator.cpp @@ -527,7 +527,7 @@ void JoinOrderEnumerator::appendScanNode(shared_ptr& node, Logic auto scan = make_shared(node); scan->computeSchema(*schema); // update cardinality - auto group = schema->getGroup(node->getIDProperty()); + auto group = schema->getGroup(node->getInternalIDPropertyName()); auto numNodes = 0u; for (auto& tableID : node->getTableIDs()) { numNodes += nodesStatistics.getNodeStatisticsAndDeletedIDs(tableID)->getNumTuples(); @@ -543,7 +543,7 @@ void JoinOrderEnumerator::appendIndexScanNode( auto scan = make_shared(node, std::move(indexExpression)); scan->computeSchema(*schema); // update cardinality - auto group = schema->getGroup(node->getIDProperty()); + auto group = schema->getGroup(node->getInternalIDPropertyName()); group->setMultiplier(1); plan.setLastOperator(std::move(scan)); } @@ -556,7 +556,7 @@ void JoinOrderEnumerator::appendExtend( auto isColumn = catalog.getReadOnlyVersion()->isSingleMultiplicityInDirection(rel->getTableID(), direction); if (rel->isVariableLength() || !isColumn) { - QueryPlanner::appendFlattenIfNecessary(boundNode->getNodeIDPropertyExpression(), plan); + QueryPlanner::appendFlattenIfNecessary(boundNode->getInternalIDProperty(), plan); } auto extend = make_shared(boundNode, nbrNode, rel->getTableID(), direction, isColumn, rel->getLowerBound(), rel->getUpperBound(), plan.getLastOperator()); @@ -566,7 +566,7 @@ void JoinOrderEnumerator::appendExtend( if (!isColumn) { auto extensionRate = getExtensionRate(boundNode->getTableID(), rel->getTableID(), direction); - schema->getGroup(nbrNode->getIDProperty())->setMultiplier(extensionRate); + schema->getGroup(nbrNode->getInternalIDPropertyName())->setMultiplier(extensionRate); } plan.increaseCost(plan.getCardinality()); } @@ -617,7 +617,7 @@ static bool isJoinKeyUniqueOnBuildSide(const string& joinNodeID, LogicalPlan& bu return false; } auto scanNodeID = (LogicalScanNode*)firstop; - if (scanNodeID->getNode()->getIDProperty() != joinNodeID) { + if (scanNodeID->getNode()->getInternalIDPropertyName() != joinNodeID) { return false; } return true; @@ -636,9 +636,10 @@ void JoinOrderEnumerator::appendHashJoin(const vector // TODO(Guodong): when the build side has only flat payloads, we should consider getting rid of // flattening probe key, instead duplicating keys as in vectorized processing if necessary. if (joinNodes.size() > 1 || - !isJoinKeyUniqueOnBuildSide(joinNodes[0]->getIDProperty(), buildPlan)) { + !isJoinKeyUniqueOnBuildSide(joinNodes[0]->getInternalIDPropertyName(), buildPlan)) { for (auto& joinNode : joinNodes) { - auto probeSideKeyGroupPos = probeSideSchema->getGroupPos(joinNode->getIDProperty()); + auto probeSideKeyGroupPos = + probeSideSchema->getGroupPos(joinNode->getInternalIDPropertyName()); QueryPlanner::appendFlattenIfNecessary(probeSideKeyGroupPos, probePlan); } probePlan.multiplyCardinality( @@ -648,14 +649,15 @@ void JoinOrderEnumerator::appendHashJoin(const vector // Flat all but one build side key groups. unordered_set joinNodesGroupPos; for (auto& joinNode : joinNodes) { - joinNodesGroupPos.insert(buildSideSchema.getGroupPos(joinNode->getIDProperty())); + joinNodesGroupPos.insert( + buildSideSchema.getGroupPos(joinNode->getInternalIDPropertyName())); } QueryPlanner::appendFlattensButOne(joinNodesGroupPos, buildPlan); auto numGroupsBeforeMerging = probeSideSchema->getNumGroups(); vector keys; for (auto& joinNode : joinNodes) { - keys.push_back(joinNode->getIDProperty()); + keys.push_back(joinNode->getInternalIDPropertyName()); } SinkOperatorUtil::mergeSchema(buildSideSchema, *probeSideSchema, keys); vector flatOutputGroupPositions; @@ -678,8 +680,10 @@ void JoinOrderEnumerator::appendMarkJoin(const vector // Apply flattening all but one on join nodes of both probe and build side. unordered_set joinNodeGroupsPosInProbeSide, joinNodeGroupsPosInBuildSide; for (auto& joinNode : joinNodes) { - joinNodeGroupsPosInProbeSide.insert(probeSchema->getGroupPos(joinNode->getIDProperty())); - joinNodeGroupsPosInBuildSide.insert(buildSchema->getGroupPos(joinNode->getIDProperty())); + joinNodeGroupsPosInProbeSide.insert( + probeSchema->getGroupPos(joinNode->getInternalIDPropertyName())); + joinNodeGroupsPosInBuildSide.insert( + buildSchema->getGroupPos(joinNode->getInternalIDPropertyName())); } auto markGroupPos = QueryPlanner::appendFlattensButOne(joinNodeGroupsPosInProbeSide, probePlan); QueryPlanner::appendFlattensButOne(joinNodeGroupsPosInBuildSide, buildPlan); @@ -693,28 +697,28 @@ void JoinOrderEnumerator::appendMarkJoin(const vector void JoinOrderEnumerator::appendIntersect(const shared_ptr& intersectNode, vector>& boundNodes, LogicalPlan& probePlan, vector>& buildPlans) { - auto intersectNodeID = intersectNode->getIDProperty(); + auto intersectNodeID = intersectNode->getInternalIDPropertyName(); auto probeSchema = probePlan.getSchema(); assert(boundNodes.size() == buildPlans.size()); // Write intersect node and rels into a new group regardless of whether rel is n-n. auto outGroupPos = probeSchema->createGroup(); // Write intersect node into output group. - probeSchema->insertToGroupAndScope(intersectNode->getNodeIDPropertyExpression(), outGroupPos); + probeSchema->insertToGroupAndScope(intersectNode->getInternalIDProperty(), outGroupPos); vector> buildChildren; vector> buildInfos; for (auto i = 0u; i < buildPlans.size(); ++i) { auto boundNode = boundNodes[i]; QueryPlanner::appendFlattenIfNecessary( - probeSchema->getGroupPos(boundNode->getIDProperty()), probePlan); + probeSchema->getGroupPos(boundNode->getInternalIDPropertyName()), probePlan); auto buildPlan = buildPlans[i].get(); auto buildSchema = buildPlan->getSchema(); QueryPlanner::appendFlattenIfNecessary( - buildSchema->getGroupPos(boundNode->getIDProperty()), *buildPlan); + buildSchema->getGroupPos(boundNode->getInternalIDPropertyName()), *buildPlan); auto expressions = buildSchema->getExpressionsInScope(); // Write rel properties into output group. for (auto& expression : expressions) { if (expression->getUniqueName() == intersectNodeID || - expression->getUniqueName() == boundNode->getIDProperty()) { + expression->getUniqueName() == boundNode->getInternalIDPropertyName()) { continue; } probeSchema->insertToGroupAndScope(expression, outGroupPos); diff --git a/src/planner/query_planner.cpp b/src/planner/query_planner.cpp index c4298d2daa..aa5f2b47c5 100644 --- a/src/planner/query_planner.cpp +++ b/src/planner/query_planner.cpp @@ -154,9 +154,9 @@ static expression_vector getCorrelatedExpressions( result.push_back(expression); } } - for (auto& nodeIDExpression : collection.getNodeIDExpressions()) { - if (outerSchema->isExpressionInScope(*nodeIDExpression)) { - result.push_back(nodeIDExpression); + for (auto& node : collection.getQueryNodes()) { + if (outerSchema->isExpressionInScope(*node->getInternalIDProperty())) { + result.push_back(node->getInternalIDProperty()); } } return result; @@ -191,7 +191,7 @@ void QueryPlanner::planOptionalMatch(const QueryGraphCollection& queryGraphColle auto bestInnerPlan = getBestPlan(std::move(innerPlans)); joinOrderEnumerator.exitSubquery(std::move(prevContext)); for (auto& joinNode : joinNodes) { - appendFlattenIfNecessary(joinNode->getNodeIDPropertyExpression(), outerPlan); + appendFlattenIfNecessary(joinNode->getInternalIDProperty(), outerPlan); } JoinOrderEnumerator::planLeftHashJoin(joinNodes, outerPlan, *bestInnerPlan); } else { @@ -380,7 +380,7 @@ void QueryPlanner::appendScanNodePropIfNecessary(const expression_vector& proper shared_ptr node, LogicalPlan& plan) { auto schema = plan.getSchema(); expression_vector propertyExpressionToScan; - auto groupPos = schema->getGroupPos(node->getIDProperty()); + auto groupPos = schema->getGroupPos(node->getInternalIDPropertyName()); for (auto& propertyExpression : propertyExpressions) { if (schema->isExpressionInScope(*propertyExpression)) { continue; @@ -413,7 +413,7 @@ void QueryPlanner::appendScanRelPropIfNecessary(shared_ptr& expressi auto scanProperty = make_shared(boundNode, nbrNode, relTableID, direction, property->getUniqueName(), property->getPropertyID(relTableID), isColumn, plan.getLastOperator()); - auto groupPos = schema->getGroupPos(nbrNode->getIDProperty()); + auto groupPos = schema->getGroupPos(nbrNode->getInternalIDPropertyName()); schema->insertToGroupAndScope(property, groupPos); plan.setLastOperator(move(scanProperty)); } diff --git a/src/planner/update_planner.cpp b/src/planner/update_planner.cpp index e6441e30a3..6cca4c9b31 100644 --- a/src/planner/update_planner.cpp +++ b/src/planner/update_planner.cpp @@ -47,7 +47,7 @@ void UpdatePlanner::planSetItem(expression_pair setItem, LogicalPlan& plan) { // Check LHS assert(lhs->getChild(0)->dataType.typeID == NODE); auto nodeExpression = static_pointer_cast(lhs->getChild(0)); - auto lhsGroupPos = schema->getGroupPos(nodeExpression->getIDProperty()); + auto lhsGroupPos = schema->getGroupPos(nodeExpression->getInternalIDPropertyName()); auto isLhsFlat = schema->getGroup(lhsGroupPos)->getIsFlat(); // Check RHS auto rhsDependentGroupsPos = schema->getDependentGroupsPos(rhs); @@ -83,7 +83,7 @@ void UpdatePlanner::appendCreateNode( for (auto& createNode : createNodes) { auto node = createNode->getNode(); auto groupPos = schema->createGroup(); - schema->insertToGroupAndScope(node->getNodeIDPropertyExpression(), groupPos); + schema->insertToGroupAndScope(node->getInternalIDProperty(), groupPos); schema->flattenGroup(groupPos); // create output is always flat nodeAndPrimaryKeyPairs.emplace_back(node, createNode->getPrimaryKeyExpression()); for (auto& setItem : createNode->getSetItems()) { @@ -144,9 +144,9 @@ void UpdatePlanner::appendDeleteRel( const vector>& deleteRels, LogicalPlan& plan) { // Delete one rel at a time so we flatten for each rel. for (auto& rel : deleteRels) { - auto srcNodeID = rel->getSrcNode()->getNodeIDPropertyExpression(); + auto srcNodeID = rel->getSrcNode()->getInternalIDProperty(); QueryPlanner::appendFlattenIfNecessary(srcNodeID, plan); - auto dstNodeID = rel->getDstNode()->getNodeIDPropertyExpression(); + auto dstNodeID = rel->getDstNode()->getInternalIDProperty(); QueryPlanner::appendFlattenIfNecessary(dstNodeID, plan); } auto deleteRel = make_shared(deleteRels, plan.getLastOperator()); diff --git a/src/processor/mapper/map_create.cpp b/src/processor/mapper/map_create.cpp index d943b7e86b..272d72a7d0 100644 --- a/src/processor/mapper/map_create.cpp +++ b/src/processor/mapper/map_create.cpp @@ -23,7 +23,7 @@ unique_ptr PlanMapper::mapLogicalCreateNodeToPhysical( relTablesToInit.push_back(storageManager.getRelsStore().getRelTable(relTableID)); } } - auto outDataPos = mapperContext.getDataPos(node->getIDProperty()); + auto outDataPos = mapperContext.getDataPos(node->getInternalIDPropertyName()); createNodeInfos.push_back(make_unique( table, std::move(primaryKeyEvaluator), relTablesToInit, outDataPos)); } @@ -40,9 +40,9 @@ unique_ptr PlanMapper::mapLogicalCreateRelToPhysical( for (auto i = 0u; i < logicalCreateRel->getNumRels(); ++i) { auto rel = logicalCreateRel->getRel(i); auto table = relStore.getRelTable(rel->getTableID()); - auto srcNodePos = mapperContext.getDataPos(rel->getSrcNode()->getIDProperty()); + auto srcNodePos = mapperContext.getDataPos(rel->getSrcNode()->getInternalIDPropertyName()); auto srcNodeTableID = rel->getSrcNode()->getTableID(); - auto dstNodePos = mapperContext.getDataPos(rel->getDstNode()->getIDProperty()); + auto dstNodePos = mapperContext.getDataPos(rel->getDstNode()->getInternalIDPropertyName()); auto dstNodeTableID = rel->getDstNode()->getTableID(); vector> evaluators; uint32_t relIDEvaluatorIdx = UINT32_MAX; diff --git a/src/processor/mapper/map_delete.cpp b/src/processor/mapper/map_delete.cpp index 5504aaf96c..97bba2062c 100644 --- a/src/processor/mapper/map_delete.cpp +++ b/src/processor/mapper/map_delete.cpp @@ -14,7 +14,7 @@ unique_ptr PlanMapper::mapLogicalDeleteNodeToPhysical( vector> deleteNodeInfos; for (auto& [node, primaryKey] : logicalDeleteNode->getNodeAndPrimaryKeys()) { auto nodeTable = nodesStore.getNodeTable(node->getTableID()); - auto nodeIDPos = mapperContext.getDataPos(node->getIDProperty()); + auto nodeIDPos = mapperContext.getDataPos(node->getInternalIDPropertyName()); auto primaryKeyPos = mapperContext.getDataPos(primaryKey->getUniqueName()); deleteNodeInfos.push_back(make_unique(nodeTable, nodeIDPos, primaryKeyPos)); } @@ -31,12 +31,13 @@ unique_ptr PlanMapper::mapLogicalDeleteRelToPhysical( for (auto i = 0u; i < logicalDeleteRel->getNumRels(); ++i) { auto rel = logicalDeleteRel->getRel(i); auto table = relStore.getRelTable(rel->getTableID()); - auto srcNodePos = mapperContext.getDataPos(rel->getSrcNode()->getIDProperty()); + auto srcNodePos = mapperContext.getDataPos(rel->getSrcNode()->getInternalIDPropertyName()); auto srcNodeTableID = rel->getSrcNode()->getTableID(); - auto dstNodePos = mapperContext.getDataPos(rel->getDstNode()->getIDProperty()); + auto dstNodePos = mapperContext.getDataPos(rel->getDstNode()->getInternalIDPropertyName()); auto dstNodeTableID = rel->getDstNode()->getTableID(); + auto relIDPos = mapperContext.getDataPos(rel->getInternalIDProperty()->getUniqueName()); createRelInfos.push_back(make_unique( - table, srcNodePos, srcNodeTableID, dstNodePos, dstNodeTableID)); + table, srcNodePos, srcNodeTableID, dstNodePos, dstNodeTableID, relIDPos)); } return make_unique(relStore.getRelsStatistics(), std::move(createRelInfos), std::move(prevOperator), getOperatorID(), logicalOperator->getExpressionsForPrinting()); diff --git a/src/processor/mapper/map_extend.cpp b/src/processor/mapper/map_extend.cpp index 7bfe49502a..fa5e9958a2 100644 --- a/src/processor/mapper/map_extend.cpp +++ b/src/processor/mapper/map_extend.cpp @@ -14,9 +14,9 @@ unique_ptr PlanMapper::mapLogicalExtendToPhysical( auto boundNode = extend->getBoundNodeExpression(); auto nbrNode = extend->getNbrNodeExpression(); auto prevOperator = mapLogicalOperatorToPhysical(logicalOperator->getChild(0), mapperContext); - auto inDataPos = mapperContext.getDataPos(boundNode->getIDProperty()); - auto outDataPos = mapperContext.getDataPos(nbrNode->getIDProperty()); - mapperContext.addComputedExpressions(nbrNode->getIDProperty()); + auto inDataPos = mapperContext.getDataPos(boundNode->getInternalIDPropertyName()); + auto outDataPos = mapperContext.getDataPos(nbrNode->getInternalIDPropertyName()); + mapperContext.addComputedExpressions(nbrNode->getInternalIDPropertyName()); auto& relsStore = storageManager.getRelsStore(); auto lowerBound = extend->getLowerBound(); auto upperBound = extend->getUpperBound(); diff --git a/src/processor/mapper/map_hash_join.cpp b/src/processor/mapper/map_hash_join.cpp index de2cc28455..ef2e35a720 100644 --- a/src/processor/mapper/map_hash_join.cpp +++ b/src/processor/mapper/map_hash_join.cpp @@ -99,7 +99,7 @@ BuildDataInfo PlanMapper::generateBuildDataInfo(MapperContext& mapperContext, buildSideMapperContext.getResultSetDescriptor()->getNumDataChunks(), false); unordered_set joinNodeIDs; for (auto& key : keys) { - auto nodeID = key->getIDProperty(); + auto nodeID = key->getInternalIDPropertyName(); auto buildSideKeyPos = buildSideMapperContext.getDataPos(nodeID); isBuildDataChunkContainKeys[buildSideKeyPos.dataChunkPos] = true; buildKeysDataPos.push_back(buildSideMapperContext.getDataPos(nodeID)); @@ -137,7 +137,7 @@ unique_ptr PlanMapper::mapLogicalHashJoinToPhysical( vector probeKeysDataPos, probePayloadsDataPos; vector payloadsDataTypes; for (auto& joinNode : hashJoin->getJoinNodes()) { - auto joinNodeID = joinNode->getIDProperty(); + auto joinNodeID = joinNode->getInternalIDPropertyName(); probeKeysDataPos.push_back(mapperContext.getDataPos(joinNodeID)); } for (auto& dataPos : buildDataInfo.payloadsDataPos) { @@ -177,7 +177,7 @@ unique_ptr PlanMapper::mapLogicalSemiMaskerToPhysical( auto logicalSemiMasker = (LogicalSemiMasker*)logicalOperator; auto node = logicalSemiMasker->getNode(); auto prevOperator = mapLogicalOperatorToPhysical(logicalOperator->getChild(0), mapperContext); - auto keyDataPos = mapperContext.getDataPos(node->getIDProperty()); + auto keyDataPos = mapperContext.getDataPos(node->getInternalIDPropertyName()); return make_unique(keyDataPos, std::move(prevOperator), getOperatorID(), logicalSemiMasker->getExpressionsForPrinting()); } diff --git a/src/processor/mapper/map_intersect.cpp b/src/processor/mapper/map_intersect.cpp index 4cac129203..b572bab167 100644 --- a/src/processor/mapper/map_intersect.cpp +++ b/src/processor/mapper/map_intersect.cpp @@ -19,7 +19,7 @@ unique_ptr PlanMapper::mapLogicalIntersectToPhysical( // Map build side children. for (auto i = 1u; i < logicalIntersect->getNumChildren(); i++) { auto buildInfo = logicalIntersect->getBuildInfo(i - 1); - auto buildKey = buildInfo->key->getIDProperty(); + auto buildKey = buildInfo->key->getInternalIDPropertyName(); auto buildSideSchema = buildInfo->schema.get(); auto buildSideMapperContext = MapperContext(make_unique(*buildSideSchema)); @@ -33,7 +33,7 @@ unique_ptr PlanMapper::mapLogicalIntersectToPhysical( auto expression = buildSideSchema->getGroup(dataPos.dataChunkPos) ->getExpressions()[dataPos.valueVectorPos]; if (expression->getUniqueName() == - logicalIntersect->getIntersectNode()->getIDProperty()) { + logicalIntersect->getIntersectNode()->getInternalIDPropertyName()) { continue; } payloadsDataPos.push_back(mapperContext.getDataPos(expression->getUniqueName())); @@ -49,7 +49,7 @@ unique_ptr PlanMapper::mapLogicalIntersectToPhysical( } // Map intersect. auto outputDataPos = - mapperContext.getDataPos(logicalIntersect->getIntersectNode()->getIDProperty()); + mapperContext.getDataPos(logicalIntersect->getIntersectNode()->getInternalIDPropertyName()); return make_unique(outputDataPos, intersectDataInfos, sharedStates, move(children), getOperatorID(), logicalIntersect->getExpressionsForPrinting()); } diff --git a/src/processor/mapper/map_scan_node.cpp b/src/processor/mapper/map_scan_node.cpp index 489dd42b97..4be25dde56 100644 --- a/src/processor/mapper/map_scan_node.cpp +++ b/src/processor/mapper/map_scan_node.cpp @@ -13,8 +13,8 @@ unique_ptr PlanMapper::mapLogicalScanNodeToPhysical( auto node = logicalScan->getNode(); auto& nodesStore = storageManager.getNodesStore(); - auto dataPos = mapperContext.getDataPos(node->getIDProperty()); - mapperContext.addComputedExpressions(node->getIDProperty()); + auto dataPos = mapperContext.getDataPos(node->getInternalIDPropertyName()); + mapperContext.addComputedExpressions(node->getInternalIDPropertyName()); auto sharedState = make_shared(); for (auto& tableID : node->getTableIDs()) { auto nodeTable = nodesStore.getNodeTable(tableID); @@ -30,10 +30,10 @@ unique_ptr PlanMapper::mapLogicalIndexScanNodeToPhysical( auto logicalIndexScan = (LogicalIndexScanNode*)logicalOperator; auto node = logicalIndexScan->getNode(); auto nodeTable = storageManager.getNodesStore().getNodeTable(node->getTableID()); - auto dataPos = mapperContext.getDataPos(node->getIDProperty()); + auto dataPos = mapperContext.getDataPos(node->getInternalIDPropertyName()); auto evaluator = expressionMapper.mapExpression(logicalIndexScan->getIndexExpression(), mapperContext); - mapperContext.addComputedExpressions(node->getIDProperty()); + mapperContext.addComputedExpressions(node->getInternalIDPropertyName()); return make_unique(mapperContext.getResultSetDescriptor()->copy(), nodeTable->getTableID(), nodeTable->getPKIndex(), std::move(evaluator), dataPos, getOperatorID(), logicalIndexScan->getExpressionsForPrinting()); diff --git a/src/processor/mapper/map_scan_node_property.cpp b/src/processor/mapper/map_scan_node_property.cpp index 1fdda5b33f..b12f92c50c 100644 --- a/src/processor/mapper/map_scan_node_property.cpp +++ b/src/processor/mapper/map_scan_node_property.cpp @@ -10,7 +10,7 @@ unique_ptr PlanMapper::mapLogicalScanNodePropertyToPhysical( auto& scanProperty = (const LogicalScanNodeProperty&)*logicalOperator; auto prevOperator = mapLogicalOperatorToPhysical(logicalOperator->getChild(0), mapperContext); auto node = scanProperty.getNode(); - auto inputNodeIDVectorPos = mapperContext.getDataPos(node->getIDProperty()); + auto inputNodeIDVectorPos = mapperContext.getDataPos(node->getInternalIDPropertyName()); auto& nodeStore = storageManager.getNodesStore(); vector outVectorsPos; vector outDataTypes; diff --git a/src/processor/mapper/map_scan_rel_property.cpp b/src/processor/mapper/map_scan_rel_property.cpp index 3c981af043..aa04b4c459 100644 --- a/src/processor/mapper/map_scan_rel_property.cpp +++ b/src/processor/mapper/map_scan_rel_property.cpp @@ -11,7 +11,7 @@ unique_ptr PlanMapper::mapLogicalScanRelPropertyToPhysical( auto scanRelProperty = (LogicalScanRelProperty*)logicalOperator; auto boundNode = scanRelProperty->getBoundNodeExpression(); auto prevOperator = mapLogicalOperatorToPhysical(logicalOperator->getChild(0), mapperContext); - auto inputNodeIDVectorPos = mapperContext.getDataPos(boundNode->getIDProperty()); + auto inputNodeIDVectorPos = mapperContext.getDataPos(boundNode->getInternalIDPropertyName()); auto propertyName = scanRelProperty->getPropertyName(); auto propertyID = scanRelProperty->getPropertyID(); auto outputPropertyVectorPos = mapperContext.getDataPos(propertyName); diff --git a/src/processor/mapper/map_set.cpp b/src/processor/mapper/map_set.cpp index ddc7100ebf..992c51df44 100644 --- a/src/processor/mapper/map_set.cpp +++ b/src/processor/mapper/map_set.cpp @@ -24,7 +24,8 @@ unique_ptr PlanMapper::mapLogicalSetToPhysical( for (auto& [expr, _] : setItems) { auto property = static_pointer_cast(expr); auto node = static_pointer_cast(property->getChild(0)); - nodeIDVectorPositions.push_back(mapperContext.getDataPos(node->getIDProperty())); + nodeIDVectorPositions.push_back( + mapperContext.getDataPos(node->getInternalIDPropertyName())); propertyColumns.push_back(nodeStore.getNodePropertyColumn( node->getTableID(), property->getPropertyID(node->getTableID()))); } diff --git a/src/processor/operator/update/delete.cpp b/src/processor/operator/update/delete.cpp index 99bb09b33f..676d99ba9b 100644 --- a/src/processor/operator/update/delete.cpp +++ b/src/processor/operator/update/delete.cpp @@ -35,10 +35,15 @@ shared_ptr DeleteRel::init(ExecutionContext* context) { auto srcNodePos = deleteRelInfo->srcNodePos; auto srcNodeIDVector = resultSet->dataChunks[srcNodePos.dataChunkPos]->valueVectors[srcNodePos.valueVectorPos]; + srcNodeVectors.push_back(srcNodeIDVector.get()); auto dstNodePos = deleteRelInfo->dstNodePos; auto dstNodeIDVector = resultSet->dataChunks[dstNodePos.dataChunkPos]->valueVectors[dstNodePos.valueVectorPos]; - srcDstNodeIDVectorPairs.emplace_back(srcNodeIDVector.get(), dstNodeIDVector.get()); + dstNodeVectors.push_back(dstNodeIDVector.get()); + auto relIDPos = deleteRelInfo->relIDPos; + auto relIDVector = + resultSet->dataChunks[relIDPos.dataChunkPos]->valueVectors[relIDPos.valueVectorPos]; + relIDVectors.push_back(relIDVector.get()); } return resultSet; } @@ -49,11 +54,13 @@ bool DeleteRel::getNextTuplesInternal() { } for (auto i = 0u; i < deleteRelInfos.size(); ++i) { auto createRelInfo = deleteRelInfos[i].get(); - auto [srcNodeIDVector, dstNodeIDVector] = srcDstNodeIDVectorPairs[i]; + auto srcNodeVector = srcNodeVectors[i]; + auto dstNodeVector = dstNodeVectors[i]; + auto relIDVector = relIDVectors[i]; // TODO(Ziyi): you need to update rel statistics here. Though I don't think this is best // design, statistics update should be hidden inside deleteRel(). See how node create/delete // works. You can discuss this with Semih and if you decide to change, change createRel too. - createRelInfo->table->deleteRel(srcNodeIDVector, dstNodeIDVector); + createRelInfo->table->deleteRel(srcNodeVector, dstNodeVector); } return true; } diff --git a/test/include/mock_catalog/mock_catalog.h b/test/include/mock_catalog/mock_catalog.h index 223d995e65..c3b4ce2d6a 100644 --- a/test/include/mock_catalog/mock_catalog.h +++ b/test/include/mock_catalog/mock_catalog.h @@ -111,6 +111,8 @@ class TinySnbCatalogContent : public MockCatalogContent { .WillByDefault(Return(true)); ON_CALL(*this, containRelProperty(KNOWS_TABLE_ID, KNOWSDATE_PROPERTY_KEY_STR)) .WillByDefault(Return(true)); + ON_CALL(*this, containRelProperty(KNOWS_TABLE_ID, KNOWSDATE_PROPERTY_KEY_STR)) + .WillByDefault(Return(true)); ON_CALL(*this, containRelProperty(1, _)).WillByDefault(Return(false)); } @@ -219,12 +221,16 @@ class TinySnbCatalogContent : public MockCatalogContent { } void setRelTableSchemas() { - knowsTableSchema = - make_unique("knows", KNOWS_TABLE_ID, MANY_MANY, vector{}, - vector>{{PERSON_TABLE_ID, PERSON_TABLE_ID}}); - workAtTableSchema = - make_unique("workAt", WORKAT_TABLE_ID, MANY_ONE, vector{}, - vector>{{PERSON_TABLE_ID, ORGANISATION_TABLE_ID}}); + auto knowsID = Property::constructRelProperty( + PropertyNameDataType(INTERNAL_ID_SUFFIX, INT64), 0, KNOWS_TABLE_ID); + knowsTableSchema = make_unique("knows", KNOWS_TABLE_ID, MANY_MANY, + vector{knowsID}, + vector>{{PERSON_TABLE_ID, PERSON_TABLE_ID}}); + auto workAtID = Property::constructRelProperty( + PropertyNameDataType(INTERNAL_ID_SUFFIX, INT64), 0, WORKAT_TABLE_ID); + workAtTableSchema = make_unique("workAt", WORKAT_TABLE_ID, MANY_ONE, + vector{workAtID}, + vector>{{PERSON_TABLE_ID, ORGANISATION_TABLE_ID}}); } vector> srcNodeIDToRelIDs, dstNodeIDToRelIDs;