From 833ea93b6f64a80b9b800bcfb9097d68e3db1be9 Mon Sep 17 00:00:00 2001 From: xiyang Date: Fri, 9 Dec 2022 21:04:29 +0800 Subject: [PATCH] refactor extend and scan rel properties --- src/include/planner/join_order_enumerator.h | 10 +- .../logical_operator/base_logical_operator.h | 19 +-- .../logical_operator/logical_extend.h | 55 ++----- .../logical_scan_rel_property.h | 49 ------ src/include/planner/query_planner.h | 11 -- src/include/processor/mapper/plan_mapper.h | 4 - src/include/processor/operator/base_extend.h | 32 ++++ .../processor/operator/generic_extend.h | 31 ++-- .../operator/scan_column/adj_column_extend.h | 31 ++-- .../operator/scan_column/scan_column.h | 25 +--- .../scan_column/scan_column_property.h | 50 ------- .../scan_column/scan_node_properties.h | 51 +++++++ .../operator/scan_list/adj_list_extend.h | 34 ++++- .../processor/operator/scan_list/scan_list.h | 38 ----- .../scan_list/scan_rel_property_list.h | 28 ---- src/include/processor/result/result_set.h | 15 +- src/planner/join_order_enumerator.cpp | 34 +---- src/planner/query_planner.cpp | 16 -- src/processor/mapper/CMakeLists.txt | 1 - src/processor/mapper/map_extend.cpp | 139 +++++++++++------- .../mapper/map_scan_node_property.cpp | 30 ++-- .../mapper/map_scan_rel_property.cpp | 40 ----- src/processor/mapper/plan_mapper.cpp | 7 - src/processor/operator/CMakeLists.txt | 1 + src/processor/operator/base_extend.cpp | 17 +++ src/processor/operator/generic_extend.cpp | 62 ++++---- .../operator/scan_column/CMakeLists.txt | 2 +- .../scan_column/adj_column_extend.cpp | 21 ++- .../operator/scan_column/scan_column.cpp | 9 +- .../scan_column/scan_column_property.cpp | 41 ------ .../scan_column/scan_node_properties.cpp | 43 ++++++ .../operator/scan_list/CMakeLists.txt | 2 +- .../operator/scan_list/adj_list_extend.cpp | 64 +++++--- .../scan_list/scan_rel_property_list.cpp | 22 --- test/runner/e2e_read_test.cpp | 2 +- 35 files changed, 420 insertions(+), 616 deletions(-) create mode 100644 src/include/processor/operator/base_extend.h delete mode 100644 src/include/processor/operator/scan_column/scan_column_property.h create mode 100644 src/include/processor/operator/scan_column/scan_node_properties.h delete mode 100644 src/include/processor/operator/scan_list/scan_list.h delete mode 100644 src/include/processor/operator/scan_list/scan_rel_property_list.h delete mode 100644 src/processor/mapper/map_scan_rel_property.cpp create mode 100644 src/processor/operator/base_extend.cpp delete mode 100644 src/processor/operator/scan_column/scan_column_property.cpp create mode 100644 src/processor/operator/scan_column/scan_node_properties.cpp delete mode 100644 src/processor/operator/scan_list/scan_rel_property_list.cpp diff --git a/src/include/planner/join_order_enumerator.h b/src/include/planner/join_order_enumerator.h index 36bacc1eaf..70340c2337 100644 --- a/src/include/planner/join_order_enumerator.h +++ b/src/include/planner/join_order_enumerator.h @@ -73,16 +73,8 @@ class JoinOrderEnumerator { void planRelScan(uint32_t relPos); - void planExtendFiltersAndPropertyScans(shared_ptr rel, RelDirection direction, + void planExtendAndFilters(shared_ptr rel, RelDirection direction, expression_vector& predicates, LogicalPlan& plan); - // Filter push down for rel table. - void planFiltersForRel(const expression_vector& predicates, - shared_ptr boundNode, shared_ptr nbrNode, - shared_ptr rel, RelDirection direction, LogicalPlan& plan); - // Property push down for rel table. - void planPropertyScansForRel(const expression_vector& properties, - shared_ptr boundNode, shared_ptr nbrNode, - shared_ptr rel, RelDirection direction, LogicalPlan& plan); void planLevel(uint32_t level); diff --git a/src/include/planner/logical_plan/logical_operator/base_logical_operator.h b/src/include/planner/logical_plan/logical_operator/base_logical_operator.h index 1c433c791e..d87d3c9877 100644 --- a/src/include/planner/logical_plan/logical_operator/base_logical_operator.h +++ b/src/include/planner/logical_plan/logical_operator/base_logical_operator.h @@ -12,13 +12,11 @@ enum LogicalOperatorType : uint8_t { LOGICAL_INDEX_SCAN_NODE, LOGICAL_UNWIND, LOGICAL_EXTEND, - LOGICAL_GENERIC_EXTEND, LOGICAL_FLATTEN, LOGICAL_FILTER, LOGICAL_INTERSECT, LOGICAL_PROJECTION, LOGICAL_SCAN_NODE_PROPERTY, - LOGICAL_SCAN_REL_PROPERTY, LOGICAL_CROSS_PRODUCT, LOGICAL_SEMI_MASKER, LOGICAL_HASH_JOIN, @@ -44,15 +42,14 @@ enum LogicalOperatorType : uint8_t { }; const string LogicalOperatorTypeNames[] = {"LOGICAL_SCAN_NODE", "LOGICAL_INDEX_SCAN_NODE", - "LOGICAL_UNWIND", "LOGICAL_EXTEND", "LOGICAL_GENERIC_EXTEND", "LOGICAL_FLATTEN", - "LOGICAL_FILTER", "LOGICAL_INTERSECT", "LOGICAL_PROJECTION", "LOGICAL_SCAN_NODE_PROPERTY", - "LOGICAL_SCAN_REL_PROPERTY", "LOGICAL_CROSS_PRODUCT", "LOGICAL_SEMI_MASKER", - "LOGICAL_HASH_JOIN", "LOGICAL_MULTIPLICITY_REDUCER", "LOGICAL_LIMIT", "LOGICAL_SKIP", - "LOGICAL_AGGREGATE", "LOGICAL_ORDER_BY", "LOGICAL_UNION_ALL", "LOGICAL_DISTINCT", - "LOGICAL_CREATE_NODE", "LOGICAL_CREATE_REL", "LOGICAL_SET_NODE_PROPERTY", "LOGICAL_DELETE_NODE", - "LOGICAL_DELETE_REL", "LOGICAL_ACCUMULATE", "LOGICAL_EXPRESSIONS_SCAN", "LOGICAL_FTABLE_SCAN", - "LOGICAL_CREATE_NODE_TABLE", "LOGICAL_CREATE_REL_TABLE", "LOGICAL_COPY_CSV", - "LOGICAL_DROP_TABLE"}; + "LOGICAL_UNWIND", "LOGICAL_EXTEND", "LOGICAL_FLATTEN", "LOGICAL_FILTER", "LOGICAL_INTERSECT", + "LOGICAL_PROJECTION", "LOGICAL_SCAN_NODE_PROPERTY", "LOGICAL_CROSS_PRODUCT", + "LOGICAL_SEMI_MASKER", "LOGICAL_HASH_JOIN", "LOGICAL_MULTIPLICITY_REDUCER", "LOGICAL_LIMIT", + "LOGICAL_SKIP", "LOGICAL_AGGREGATE", "LOGICAL_ORDER_BY", "LOGICAL_UNION_ALL", + "LOGICAL_DISTINCT", "LOGICAL_CREATE_NODE", "LOGICAL_CREATE_REL", "LOGICAL_SET_NODE_PROPERTY", + "LOGICAL_DELETE_NODE", "LOGICAL_DELETE_REL", "LOGICAL_ACCUMULATE", "LOGICAL_EXPRESSIONS_SCAN", + "LOGICAL_FTABLE_SCAN", "LOGICAL_CREATE_NODE_TABLE", "LOGICAL_CREATE_REL_TABLE", + "LOGICAL_COPY_CSV", "LOGICAL_DROP_TABLE"}; class LogicalOperator { public: 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 1769f5072f..7bacd722ed 100644 --- a/src/include/planner/logical_plan/logical_operator/logical_extend.h +++ b/src/include/planner/logical_plan/logical_operator/logical_extend.h @@ -10,22 +10,22 @@ using namespace kuzu::binder; class LogicalExtend : public LogicalOperator { public: LogicalExtend(shared_ptr boundNode, shared_ptr nbrNode, - shared_ptr rel, RelDirection direction, bool extendToNewGroup, - shared_ptr child) - : LogicalOperator{std::move(child)}, boundNode{std::move(boundNode)}, nbrNode{std::move( - nbrNode)}, - rel{std::move(rel)}, direction{direction}, extendToNewGroup{extendToNewGroup} {} + shared_ptr rel, RelDirection direction, expression_vector properties, + bool extendToNewGroup, shared_ptr child) + : LogicalOperator{std::move(child)}, boundNode{std::move(boundNode)}, + nbrNode{std::move(nbrNode)}, rel{std::move(rel)}, direction{direction}, + properties{std::move(properties)}, extendToNewGroup{extendToNewGroup} {} - LogicalOperatorType getLogicalOperatorType() const override { + inline LogicalOperatorType getLogicalOperatorType() const override { return LogicalOperatorType::LOGICAL_EXTEND; } - string getExpressionsForPrinting() const override { + inline string getExpressionsForPrinting() const override { return boundNode->getRawName() + (direction == RelDirection::FWD ? "->" : "<-") + nbrNode->getRawName(); } - inline virtual void computeSchema(Schema& schema) { + inline void computeSchema(Schema& schema) { auto boundGroupPos = schema.getGroupPos(boundNode->getInternalIDPropertyName()); uint32_t nbrGroupPos = 0u; if (!extendToNewGroup) { @@ -35,16 +35,20 @@ class LogicalExtend : public LogicalOperator { nbrGroupPos = schema.createGroup(); } schema.insertToGroupAndScope(nbrNode->getInternalIDProperty(), nbrGroupPos); + for (auto& property : properties) { + schema.insertToGroupAndScope(property, nbrGroupPos); + } } inline shared_ptr getBoundNode() const { return boundNode; } inline shared_ptr getNbrNode() const { return nbrNode; } inline shared_ptr getRel() const { return rel; } inline RelDirection getDirection() const { return direction; } + inline expression_vector getProperties() const { return properties; } unique_ptr copy() override { return make_unique( - boundNode, nbrNode, rel, direction, extendToNewGroup, children[0]->copy()); + boundNode, nbrNode, rel, direction, properties, extendToNewGroup, children[0]->copy()); } protected: @@ -52,41 +56,10 @@ class LogicalExtend : public LogicalOperator { shared_ptr nbrNode; shared_ptr rel; RelDirection direction; + expression_vector properties; // When extend might increase cardinality (i.e. n * m), we extend to a new factorization group. bool extendToNewGroup; }; -class LogicalGenericExtend : public LogicalExtend { -public: - LogicalGenericExtend(shared_ptr boundNode, shared_ptr nbrNode, - shared_ptr rel, RelDirection direction, bool extendToNewGroup, - expression_vector properties, shared_ptr child) - : LogicalExtend(std::move(boundNode), std::move(nbrNode), std::move(rel), direction, - extendToNewGroup, std::move(child)), - properties{std::move(properties)} {} - - inline LogicalOperatorType getLogicalOperatorType() const override { - return LogicalOperatorType::LOGICAL_GENERIC_EXTEND; - } - - inline void computeSchema(Schema& schema) override { - LogicalExtend::computeSchema(schema); - auto nbrNodePos = schema.getGroupPos(nbrNode->getInternalIDPropertyName()); - for (auto& property : properties) { - schema.insertToGroupAndScope(property, nbrNodePos); - } - } - - inline expression_vector getProperties() const { return properties; } - - unique_ptr copy() override { - return make_unique( - boundNode, nbrNode, rel, direction, extendToNewGroup, properties, children[0]->copy()); - } - -private: - expression_vector properties; -}; - } // namespace planner } // namespace kuzu diff --git a/src/include/planner/logical_plan/logical_operator/logical_scan_rel_property.h b/src/include/planner/logical_plan/logical_operator/logical_scan_rel_property.h index a9c05974b8..e69de29bb2 100644 --- a/src/include/planner/logical_plan/logical_operator/logical_scan_rel_property.h +++ b/src/include/planner/logical_plan/logical_operator/logical_scan_rel_property.h @@ -1,49 +0,0 @@ -#pragma once - -#include "base_logical_operator.h" -#include "binder/expression/rel_expression.h" - -namespace kuzu { -namespace planner { - -class LogicalScanRelProperty : public LogicalOperator { -public: - LogicalScanRelProperty(shared_ptr boundNode, shared_ptr nbrNode, - shared_ptr rel, RelDirection direction, shared_ptr property, - shared_ptr child) - : LogicalOperator{std::move(child)}, boundNode{std::move(boundNode)}, nbrNode{std::move( - nbrNode)}, - rel{std::move(rel)}, direction{direction}, property{std::move(property)} {} - - inline LogicalOperatorType getLogicalOperatorType() const override { - return LogicalOperatorType::LOGICAL_SCAN_REL_PROPERTY; - } - - inline string getExpressionsForPrinting() const override { return property->getRawName(); } - - inline void computeSchema(Schema& schema) { - auto nbrGroupPos = schema.getGroupPos(nbrNode->getInternalIDPropertyName()); - schema.insertToGroupAndScope(property, nbrGroupPos); - } - - inline shared_ptr getBoundNode() const { return boundNode; } - inline shared_ptr getNbrNode() const { return nbrNode; } - inline shared_ptr getRel() const { return rel; } - inline RelDirection getDirection() const { return direction; } - inline shared_ptr getProperty() const { return property; } - - unique_ptr copy() override { - return make_unique( - boundNode, nbrNode, rel, direction, property, children[0]->copy()); - } - -private: - shared_ptr boundNode; - shared_ptr nbrNode; - shared_ptr rel; - RelDirection direction; - shared_ptr property; -}; - -} // namespace planner -} // namespace kuzu diff --git a/src/include/planner/query_planner.h b/src/include/planner/query_planner.h index 619aeffafa..415cb31dcc 100644 --- a/src/include/planner/query_planner.h +++ b/src/include/planner/query_planner.h @@ -78,17 +78,6 @@ class QueryPlanner { void appendScanNodePropIfNecessary(const expression_vector& propertyExpressions, shared_ptr node, LogicalPlan& plan); - inline void appendScanRelPropsIfNecessary(shared_ptr boundNode, - shared_ptr nbrNode, shared_ptr rel, RelDirection direction, - const expression_vector& properties, LogicalPlan& plan) { - for (auto& property : properties) { - appendScanRelPropIfNecessary(boundNode, nbrNode, rel, direction, property, plan); - } - } - void appendScanRelPropIfNecessary(shared_ptr boundNode, - shared_ptr nbrNode, shared_ptr rel, RelDirection direction, - shared_ptr property, LogicalPlan& plan); - unique_ptr createUnionPlan( vector>& childrenPlans, bool isUnionAll); diff --git a/src/include/processor/mapper/plan_mapper.h b/src/include/processor/mapper/plan_mapper.h index cbd0dc3fa2..318c138fad 100644 --- a/src/include/processor/mapper/plan_mapper.h +++ b/src/include/processor/mapper/plan_mapper.h @@ -38,8 +38,6 @@ class PlanMapper { LogicalOperator* logicalOperator, MapperContext& mapperContext); unique_ptr mapLogicalExtendToPhysical( LogicalOperator* logicalOperator, MapperContext& mapperContext); - unique_ptr mapLogicalGenericExtendToPhysical( - LogicalOperator* logicalOperator, MapperContext& mapperContext); unique_ptr mapLogicalFlattenToPhysical( LogicalOperator* logicalOperator, MapperContext& mapperContext); unique_ptr mapLogicalFilterToPhysical( @@ -48,8 +46,6 @@ class PlanMapper { LogicalOperator* logicalOperator, MapperContext& mapperContext); unique_ptr mapLogicalScanNodePropertyToPhysical( LogicalOperator* logicalOperator, MapperContext& mapperContext); - unique_ptr mapLogicalScanRelPropertyToPhysical( - LogicalOperator* logicalOperator, MapperContext& mapperContext); unique_ptr mapLogicalSemiMaskerToPhysical( LogicalOperator* logicalOperator, MapperContext& mapperContext); unique_ptr mapLogicalHashJoinToPhysical( diff --git a/src/include/processor/operator/base_extend.h b/src/include/processor/operator/base_extend.h new file mode 100644 index 0000000000..21c2c94a6e --- /dev/null +++ b/src/include/processor/operator/base_extend.h @@ -0,0 +1,32 @@ +#pragma once + +#include "processor/operator/physical_operator.h" + +namespace kuzu { +namespace processor { + +class BaseExtendAndScanRelProperties : public PhysicalOperator { +protected: + BaseExtendAndScanRelProperties(const DataPos& inNodeIDVectorPos, + const DataPos& outNodeIDVectorPos, vector outPropertyVectorsPos, + unique_ptr child, uint32_t id, const string& paramsString) + : PhysicalOperator{std::move(child), id, paramsString}, + inNodeIDVectorPos{inNodeIDVectorPos}, outNodeIDVectorPos{outNodeIDVectorPos}, + outPropertyVectorsPos{std::move(outPropertyVectorsPos)} {} + virtual ~BaseExtendAndScanRelProperties() override = default; + + void initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) override; + +protected: + // vector positions + DataPos inNodeIDVectorPos; + DataPos outNodeIDVectorPos; + vector outPropertyVectorsPos; + // vectors + shared_ptr inNodeIDVector; + shared_ptr outNodeIDVector; + vector> outPropertyVectors; +}; + +} // namespace processor +} // namespace kuzu diff --git a/src/include/processor/operator/generic_extend.h b/src/include/processor/operator/generic_extend.h index 070e9ddf37..a1e26282f4 100644 --- a/src/include/processor/operator/generic_extend.h +++ b/src/include/processor/operator/generic_extend.h @@ -1,6 +1,6 @@ #pragma once -#include "processor/operator/physical_operator.h" +#include "processor/operator/base_extend.h" #include "storage/storage_structure/column.h" #include "storage/storage_structure/lists/lists.h" @@ -52,6 +52,8 @@ class AdjAndPropertyCollection { bool scanList(uint32_t idx, const shared_ptr& inVector, const shared_ptr& outNodeVector, const vector>& outPropertyVectors, Transaction* transaction); + void scanPropertyList(uint32_t idx, const vector>& outPropertyVectors, + Transaction* transaction); private: unique_ptr adjCollection; @@ -69,18 +71,17 @@ class AdjAndPropertyCollection { unique_ptr listSyncState = nullptr; }; -class GenericExtend : public PhysicalOperator { +class GenericExtendAndScanRelProperties : public BaseExtendAndScanRelProperties { public: - GenericExtend(const DataPos& inVectorPos, const DataPos& outNodeVectorPos, - vector outPropertyVectorsPos, + GenericExtendAndScanRelProperties(const DataPos& inNodeIDVectorPos, + const DataPos& outNodeIDVectorPos, vector outPropertyVectorsPos, unordered_map> adjAndPropertyCollectionPerNodeTable, unique_ptr child, uint32_t id, const string& paramsString) - : PhysicalOperator{std::move(child), id, paramsString}, inVectorPos{inVectorPos}, - outNodeVectorPos{outNodeVectorPos}, outPropertyVectorsPos{std::move( - outPropertyVectorsPos)}, + : BaseExtendAndScanRelProperties{inNodeIDVectorPos, outNodeIDVectorPos, + std::move(outPropertyVectorsPos), std::move(child), id, paramsString}, adjAndPropertyCollectionPerNodeTable{std::move(adjAndPropertyCollectionPerNodeTable)} {} - ~GenericExtend() override = default; + ~GenericExtendAndScanRelProperties() override = default; inline PhysicalOperatorType getOperatorType() override { return PhysicalOperatorType::GENERIC_EXTEND; @@ -95,8 +96,9 @@ class GenericExtend : public PhysicalOperator { for (auto& [tableID, adjAndPropertyCollection] : adjAndPropertyCollectionPerNodeTable) { clonedCollections.insert({tableID, adjAndPropertyCollection->clone()}); } - return make_unique(inVectorPos, outNodeVectorPos, outPropertyVectorsPos, - std::move(clonedCollections), children[0]->clone(), id, paramsString); + return make_unique(inNodeIDVectorPos, outNodeIDVectorPos, + outPropertyVectorsPos, std::move(clonedCollections), children[0]->clone(), id, + paramsString); } private: @@ -104,15 +106,6 @@ class GenericExtend : public PhysicalOperator { void initCurrentAdjAndPropertyCollection(const nodeID_t& nodeID); private: - // vector positions - DataPos inVectorPos; - DataPos outNodeVectorPos; - vector outPropertyVectorsPos; - // vectors - shared_ptr inVector; - shared_ptr outNodeVector; - vector> outPropertyVectors; - // storage structures unordered_map> adjAndPropertyCollectionPerNodeTable; AdjAndPropertyCollection* currentAdjAndPropertyCollection = nullptr; diff --git a/src/include/processor/operator/scan_column/adj_column_extend.h b/src/include/processor/operator/scan_column/adj_column_extend.h index db740657f9..b83762e618 100644 --- a/src/include/processor/operator/scan_column/adj_column_extend.h +++ b/src/include/processor/operator/scan_column/adj_column_extend.h @@ -1,33 +1,38 @@ #pragma once +#include "processor/operator/base_extend.h" #include "processor/operator/filtering_operator.h" -#include "processor/operator/scan_column/scan_column.h" #include "storage/storage_structure/column.h" namespace kuzu { namespace processor { -class AdjColumnExtend : public ScanSingleColumn, public FilteringOperator { - +class ColumnExtendAndScanRelProperties : public BaseExtendAndScanRelProperties, + public FilteringOperator { public: - AdjColumnExtend(const DataPos& inputNodeIDVectorPos, const DataPos& outputNodeIDVectorPos, - Column* nodeIDColumn, unique_ptr child, uint32_t id, + ColumnExtendAndScanRelProperties(const DataPos& inNodeIDVectorPos, + const DataPos& outNodeIDVectorPos, vector outPropertyVectorsPos, Column* adjColumn, + vector propertyColumns, unique_ptr child, uint32_t id, const string& paramsString) - : ScanSingleColumn{inputNodeIDVectorPos, outputNodeIDVectorPos, move(child), id, - paramsString}, - FilteringOperator{1 /* numStatesToSave */}, nodeIDColumn{nodeIDColumn} {} + : BaseExtendAndScanRelProperties{inNodeIDVectorPos, outNodeIDVectorPos, + std::move(outPropertyVectorsPos), std::move(child), id, paramsString}, + FilteringOperator{1 /* numStatesToSave */}, adjColumn{adjColumn}, + propertyColumns{std::move(propertyColumns)} {} + ~ColumnExtendAndScanRelProperties() override = default; - PhysicalOperatorType getOperatorType() override { return COLUMN_EXTEND; } + inline PhysicalOperatorType getOperatorType() override { return COLUMN_EXTEND; } bool getNextTuplesInternal() override; - unique_ptr clone() override { - return make_unique(inputNodeIDVectorPos, outputVectorPos, nodeIDColumn, - children[0]->clone(), id, paramsString); + inline unique_ptr clone() override { + return make_unique(inNodeIDVectorPos, outNodeIDVectorPos, + outPropertyVectorsPos, adjColumn, propertyColumns, children[0]->clone(), id, + paramsString); } private: - Column* nodeIDColumn; + Column* adjColumn; + vector propertyColumns; }; } // namespace processor diff --git a/src/include/processor/operator/scan_column/scan_column.h b/src/include/processor/operator/scan_column/scan_column.h index fa97d888b6..350a12e5bc 100644 --- a/src/include/processor/operator/scan_column/scan_column.h +++ b/src/include/processor/operator/scan_column/scan_column.h @@ -20,30 +20,15 @@ class BaseScanColumn : public PhysicalOperator { protected: DataPos inputNodeIDVectorPos; - shared_ptr inputNodeIDVector; }; -class ScanSingleColumn : public BaseScanColumn { -protected: - ScanSingleColumn(const DataPos& inputNodeIDVectorPos, const DataPos& outputVectorPos, - unique_ptr child, uint32_t id, const string& paramsString) - : BaseScanColumn{inputNodeIDVectorPos, move(child), id, paramsString}, - outputVectorPos{outputVectorPos} {} - - void initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) override; - -protected: - DataPos outputVectorPos; - shared_ptr outputVector; -}; - class ScanMultipleColumns : public BaseScanColumn { protected: - ScanMultipleColumns(const DataPos& inVectorPos, vector outVectorsPos, + ScanMultipleColumns(const DataPos& inVectorPos, vector outPropertyVectorsPos, unique_ptr child, uint32_t id, const string& paramsString) - : BaseScanColumn{inVectorPos, std::move(child), id, paramsString}, outVectorsPos{std::move( - outVectorsPos)} {} + : BaseScanColumn{inVectorPos, std::move(child), id, paramsString}, + outPropertyVectorsPos{std::move(outPropertyVectorsPos)} {} inline PhysicalOperatorType getOperatorType() override { return PhysicalOperatorType::SCAN_COLUMN_PROPERTY; @@ -52,8 +37,8 @@ class ScanMultipleColumns : public BaseScanColumn { void initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) override; protected: - vector outVectorsPos; - vector> outVectors; + vector outPropertyVectorsPos; + vector> outPropertyVectors; }; } // namespace processor diff --git a/src/include/processor/operator/scan_column/scan_column_property.h b/src/include/processor/operator/scan_column/scan_column_property.h deleted file mode 100644 index 5763510c94..0000000000 --- a/src/include/processor/operator/scan_column/scan_column_property.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include "processor/operator/scan_column/scan_column.h" -#include "storage/storage_structure/column.h" - -namespace kuzu { -namespace processor { - -class ScanSingleTableProperties : public ScanMultipleColumns { -public: - ScanSingleTableProperties(const DataPos& inVectorPos, vector outVectorsPos, - vector columns, unique_ptr prevOperator, uint32_t id, - const string& paramsString) - : ScanMultipleColumns{inVectorPos, std::move(outVectorsPos), std::move(prevOperator), id, - paramsString}, - columns{std::move(columns)} {} - - bool getNextTuplesInternal() override; - - inline unique_ptr clone() override { - return make_unique( - inputNodeIDVectorPos, outVectorsPos, columns, children[0]->clone(), id, paramsString); - } - -private: - vector columns; -}; - -class ScanMultiTableProperties : public ScanMultipleColumns { -public: - ScanMultiTableProperties(const DataPos& inVectorPos, vector outVectorsPos, - vector> tableIDToColumns, - unique_ptr prevOperator, uint32_t id, const string& paramsString) - : ScanMultipleColumns{inVectorPos, std::move(outVectorsPos), std::move(prevOperator), id, - paramsString}, - tableIDToColumns{std::move(tableIDToColumns)} {} - - bool getNextTuplesInternal() override; - - inline unique_ptr clone() override { - return make_unique(inputNodeIDVectorPos, outVectorsPos, - tableIDToColumns, children[0]->clone(), id, paramsString); - } - -private: - vector> tableIDToColumns; -}; - -} // namespace processor -} // namespace kuzu diff --git a/src/include/processor/operator/scan_column/scan_node_properties.h b/src/include/processor/operator/scan_column/scan_node_properties.h new file mode 100644 index 0000000000..896c0fbbdb --- /dev/null +++ b/src/include/processor/operator/scan_column/scan_node_properties.h @@ -0,0 +1,51 @@ +#pragma once + +#include "processor/operator/scan_column/scan_column.h" +#include "storage/storage_structure/column.h" + +namespace kuzu { +namespace processor { + +class ScanSingleNodeTableProperties : public ScanMultipleColumns { +public: + ScanSingleNodeTableProperties(const DataPos& inVectorPos, vector outVectorsPos, + vector propertyColumns, unique_ptr prevOperator, uint32_t id, + const string& paramsString) + : ScanMultipleColumns{inVectorPos, std::move(outVectorsPos), std::move(prevOperator), id, + paramsString}, + propertyColumns{std::move(propertyColumns)} {} + + bool getNextTuplesInternal() override; + + inline unique_ptr clone() override { + return make_unique(inputNodeIDVectorPos, + outPropertyVectorsPos, propertyColumns, children[0]->clone(), id, paramsString); + } + +private: + vector propertyColumns; +}; + +class ScanMultiNodeTableProperties : public ScanMultipleColumns { +public: + ScanMultiNodeTableProperties(const DataPos& inVectorPos, vector outVectorsPos, + unordered_map> tableIDToPropertyColumns, + unique_ptr prevOperator, uint32_t id, const string& paramsString) + : ScanMultipleColumns{inVectorPos, std::move(outVectorsPos), std::move(prevOperator), id, + paramsString}, + tableIDToPropertyColumns{std::move(tableIDToPropertyColumns)} {} + + bool getNextTuplesInternal() override; + + inline unique_ptr clone() override { + return make_unique(inputNodeIDVectorPos, + outPropertyVectorsPos, tableIDToPropertyColumns, children[0]->clone(), id, + paramsString); + } + +private: + unordered_map> tableIDToPropertyColumns; +}; + +} // namespace processor +} // namespace kuzu diff --git a/src/include/processor/operator/scan_list/adj_list_extend.h b/src/include/processor/operator/scan_list/adj_list_extend.h index 602651bd9a..45c6d57929 100644 --- a/src/include/processor/operator/scan_list/adj_list_extend.h +++ b/src/include/processor/operator/scan_list/adj_list_extend.h @@ -1,16 +1,21 @@ #pragma once -#include "processor/operator/scan_list/scan_list.h" +#include "processor/operator/base_extend.h" +#include "storage/storage_structure/lists/lists.h" namespace kuzu { namespace processor { -class AdjListExtend : public ScanList { - +class ListExtendAndScanRelProperties : public BaseExtendAndScanRelProperties { public: - AdjListExtend(const DataPos& inDataPos, const DataPos& outDataPos, AdjLists* adjLists, - unique_ptr child, uint32_t id, const string& paramsString) - : ScanList{inDataPos, outDataPos, adjLists, move(child), id, paramsString} {} + ListExtendAndScanRelProperties(const DataPos& inNodeIDVectorPos, + const DataPos& outNodeIDVectorPos, vector outPropertyVectorsPos, Lists* adjList, + vector propertyLists, unique_ptr child, uint32_t id, + const string& paramsString) + : BaseExtendAndScanRelProperties{inNodeIDVectorPos, outNodeIDVectorPos, + std::move(outPropertyVectorsPos), std::move(child), id, paramsString}, + adjList{adjList}, propertyLists{std::move(propertyLists)} {} + ~ListExtendAndScanRelProperties() override = default; inline PhysicalOperatorType getOperatorType() override { return LIST_EXTEND; } @@ -19,9 +24,22 @@ class AdjListExtend : public ScanList { bool getNextTuplesInternal() override; inline unique_ptr clone() override { - return make_unique( - inDataPos, outDataPos, (AdjLists*)lists, children[0]->clone(), id, paramsString); + return make_unique(inNodeIDVectorPos, outNodeIDVectorPos, + outPropertyVectorsPos, adjList, propertyLists, children[0]->clone(), id, paramsString); } + +private: + void scanPropertyLists(); + +private: + // lists + Lists* adjList; + vector propertyLists; + // list handles + shared_ptr adjListHandle; + vector> propertyListHandles; + // sync state between adj and property lists + unique_ptr syncState; }; } // namespace processor diff --git a/src/include/processor/operator/scan_list/scan_list.h b/src/include/processor/operator/scan_list/scan_list.h deleted file mode 100644 index cf3f9bf0eb..0000000000 --- a/src/include/processor/operator/scan_list/scan_list.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include "processor/operator/physical_operator.h" -#include "storage/storage_structure/lists/lists.h" - -namespace kuzu { -namespace processor { - -class ScanList : public PhysicalOperator { - -public: - ScanList(const DataPos& inDataPos, const DataPos& outDataPos, Lists* lists, - unique_ptr child, uint32_t id, const string& paramsString) - : PhysicalOperator{move(child), id, paramsString}, inDataPos{inDataPos}, - outDataPos{outDataPos}, lists{lists} {} - - ~ScanList() override{}; - - PhysicalOperatorType getOperatorType() override = 0; - - inline void initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) override { - inValueVector = resultSet->getValueVector(inDataPos); - outValueVector = resultSet->getValueVector(outDataPos); - } - -protected: - DataPos inDataPos; - DataPos outDataPos; - - shared_ptr inValueVector; - shared_ptr outValueVector; - - Lists* lists; - shared_ptr listHandle; -}; - -} // namespace processor -} // namespace kuzu diff --git a/src/include/processor/operator/scan_list/scan_rel_property_list.h b/src/include/processor/operator/scan_list/scan_rel_property_list.h deleted file mode 100644 index 92c3dbe1b7..0000000000 --- a/src/include/processor/operator/scan_list/scan_rel_property_list.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include "processor/operator/scan_list/scan_list.h" - -namespace kuzu { -namespace processor { - -class ScanRelPropertyList : public ScanList { - -public: - ScanRelPropertyList(const DataPos& inDataPos, const DataPos& outDataPos, Lists* lists, - unique_ptr child, uint32_t id, const string& paramsString) - : ScanList{inDataPos, outDataPos, lists, move(child), id, paramsString} {} - - inline PhysicalOperatorType getOperatorType() override { return SCAN_REL_PROPERTY; } - - void initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) override; - - bool getNextTuplesInternal() override; - - inline unique_ptr clone() override { - return make_unique( - inDataPos, outDataPos, lists, children[0]->clone(), id, paramsString); - } -}; - -} // namespace processor -} // namespace kuzu diff --git a/src/include/processor/result/result_set.h b/src/include/processor/result/result_set.h index 8d083f03ce..5a8aa6e9f7 100644 --- a/src/include/processor/result/result_set.h +++ b/src/include/processor/result/result_set.h @@ -15,19 +15,13 @@ namespace processor { class ResultSet { public: - explicit ResultSet(uint32_t numDataChunks) - : multiplicity{1}, dataChunks(numDataChunks), listSyncStatesPerDataChunk(numDataChunks) {} + explicit ResultSet(uint32_t numDataChunks) : multiplicity{1}, dataChunks(numDataChunks) {} inline void insert(uint32_t pos, shared_ptr dataChunk) { assert(dataChunks.size() > pos); dataChunks[pos] = std::move(dataChunk); } - inline void initListSyncState(uint32_t pos) { - assert(listSyncStatesPerDataChunk.size() > pos); - listSyncStatesPerDataChunk[pos] = make_shared(); - } - inline shared_ptr getValueVector(DataPos& dataPos) { return dataChunks[dataPos.dataChunkPos]->valueVectors[dataPos.valueVectorPos]; } @@ -40,16 +34,9 @@ class ResultSet { uint64_t getNumTuplesWithoutMultiplicity(const unordered_set& dataChunksPosInScope); - shared_ptr getListSyncState(uint64_t dataChunkPos) { - return listSyncStatesPerDataChunk[dataChunkPos]; - } - public: uint64_t multiplicity; vector> dataChunks; - -private: - vector> listSyncStatesPerDataChunk; }; } // namespace processor diff --git a/src/planner/join_order_enumerator.cpp b/src/planner/join_order_enumerator.cpp index 944e57081c..09b327c5c6 100644 --- a/src/planner/join_order_enumerator.cpp +++ b/src/planner/join_order_enumerator.cpp @@ -253,38 +253,21 @@ void JoinOrderEnumerator::planRelScan(uint32_t relPos) { auto plan = make_unique(); auto [boundNode, _] = getBoundAndNbrNodes(*rel, direction); appendScanNode(boundNode, *plan); - planExtendFiltersAndPropertyScans(rel, direction, predicates, *plan); + planExtendAndFilters(rel, direction, predicates, *plan); context->addPlan(newSubgraph, move(plan)); } } -void JoinOrderEnumerator::planExtendFiltersAndPropertyScans(shared_ptr rel, +void JoinOrderEnumerator::planExtendAndFilters(shared_ptr rel, RelDirection direction, expression_vector& predicates, LogicalPlan& plan) { auto [boundNode, dstNode] = getBoundAndNbrNodes(*rel, direction); auto properties = queryPlanner->getPropertiesForRel(*rel); appendExtend(boundNode, dstNode, rel, direction, properties, plan); - planFiltersForRel(predicates, boundNode, dstNode, rel, direction, plan); - planPropertyScansForRel(properties, boundNode, dstNode, rel, direction, plan); -} - -void JoinOrderEnumerator::planFiltersForRel(const expression_vector& predicates, - shared_ptr boundNode, shared_ptr nbrNode, - shared_ptr rel, RelDirection direction, LogicalPlan& plan) { for (auto& predicate : predicates) { - auto relPropertiesToScan = getPropertiesForVariable(*predicate, *rel); - queryPlanner->appendScanRelPropsIfNecessary( - boundNode, nbrNode, rel, direction, relPropertiesToScan, plan); queryPlanner->appendFilter(predicate, plan); } } -void JoinOrderEnumerator::planPropertyScansForRel(const expression_vector& properties, - shared_ptr boundNode, shared_ptr nbrNode, - shared_ptr rel, RelDirection direction, LogicalPlan& plan) { - queryPlanner->appendScanRelPropsIfNecessary( - boundNode, nbrNode, rel, direction, properties, plan); -} - static unordered_map>> populateIntersectRelCandidates( const QueryGraph& queryGraph, const SubqueryGraph& subgraph) { unordered_map>> intersectNodePosToRelsMap; @@ -475,7 +458,7 @@ void JoinOrderEnumerator::planInnerINLJoin(const SubqueryGraph& subgraph, if (isNodeSequential(*prevPlan, boundNode)) { auto plan = prevPlan->shallowCopy(); auto direction = boundNode->getUniqueName() == rel->getSrcNodeName() ? FWD : BWD; - planExtendFiltersAndPropertyScans(rel, direction, predicates, *plan); + planExtendAndFilters(rel, direction, predicates, *plan); context->addPlan(newSubgraph, move(plan)); } } @@ -594,15 +577,8 @@ void JoinOrderEnumerator::appendExtend(shared_ptr boundNode, if (needFlatInput(*rel, *boundNode, direction)) { QueryPlanner::appendFlattenIfNecessary(boundNode->getInternalIDProperty(), plan); } - shared_ptr extend; - // TODO(Xiyang): merge extend and generic extend on the logical level. - if (rel->getNumTableIDs() > 1 || boundNode->getNumTableIDs() > 1) { - extend = make_shared(boundNode, nbrNode, rel, direction, - extendToNewGroup, properties, plan.getLastOperator()); - } else { - extend = make_shared( - boundNode, nbrNode, rel, direction, extendToNewGroup, plan.getLastOperator()); - } + auto extend = make_shared( + boundNode, nbrNode, rel, direction, properties, extendToNewGroup, plan.getLastOperator()); extend->computeSchema(*schema); plan.setLastOperator(std::move(extend)); // update cardinality estimation info diff --git a/src/planner/query_planner.cpp b/src/planner/query_planner.cpp index 220742348e..8af7c0145b 100644 --- a/src/planner/query_planner.cpp +++ b/src/planner/query_planner.cpp @@ -8,7 +8,6 @@ #include "planner/logical_plan/logical_operator/logical_filter.h" #include "planner/logical_plan/logical_operator/logical_flatten.h" #include "planner/logical_plan/logical_operator/logical_scan_node_property.h" -#include "planner/logical_plan/logical_operator/logical_scan_rel_property.h" #include "planner/logical_plan/logical_operator/logical_union.h" #include "planner/logical_plan/logical_operator/logical_unwind.h" #include "planner/logical_plan/logical_operator/sink_util.h" @@ -395,21 +394,6 @@ void QueryPlanner::appendScanNodePropIfNecessary(const expression_vector& proper plan.setLastOperator(std::move(scanNodeProperty)); } -void QueryPlanner::appendScanRelPropIfNecessary(shared_ptr boundNode, - shared_ptr nbrNode, shared_ptr rel, RelDirection direction, - shared_ptr property, LogicalPlan& plan) { - auto schema = plan.getSchema(); - if (schema->isExpressionInScope(*property)) { - return; - } - assert( - !rel->isVariableLength() && rel->getNumTableIDs() == 1 && boundNode->getNumTableIDs() == 1); - auto scanProperty = make_shared(std::move(boundNode), - std::move(nbrNode), std::move(rel), direction, std::move(property), plan.getLastOperator()); - scanProperty->computeSchema(*schema); - plan.setLastOperator(std::move(scanProperty)); -} - unique_ptr QueryPlanner::createUnionPlan( vector>& childrenPlans, bool isUnionAll) { // If an expression to union has different flat/unflat state in different child, we diff --git a/src/processor/mapper/CMakeLists.txt b/src/processor/mapper/CMakeLists.txt index 5c0dfe19a8..34ca3bcd3c 100644 --- a/src/processor/mapper/CMakeLists.txt +++ b/src/processor/mapper/CMakeLists.txt @@ -20,7 +20,6 @@ add_library(kuzu_processor_mapper map_projection.cpp map_scan_node.cpp map_scan_node_property.cpp - map_scan_rel_property.cpp map_set.cpp map_skip.cpp map_union.cpp diff --git a/src/processor/mapper/map_extend.cpp b/src/processor/mapper/map_extend.cpp index 1893fb9fe4..0aaa5ea2fd 100644 --- a/src/processor/mapper/map_extend.cpp +++ b/src/processor/mapper/map_extend.cpp @@ -9,43 +9,28 @@ namespace kuzu { namespace processor { -unique_ptr PlanMapper::mapLogicalExtendToPhysical( - LogicalOperator* logicalOperator, MapperContext& mapperContext) { - auto extend = (LogicalExtend*)logicalOperator; - auto boundNode = extend->getBoundNode(); - auto nbrNode = extend->getNbrNode(); - auto rel = extend->getRel(); - auto direction = extend->getDirection(); - auto prevOperator = mapLogicalOperatorToPhysical(logicalOperator->getChild(0), mapperContext); - auto inDataPos = mapperContext.getDataPos(boundNode->getInternalIDPropertyName()); - auto outDataPos = mapperContext.getDataPos(nbrNode->getInternalIDPropertyName()); - mapperContext.addComputedExpressions(nbrNode->getInternalIDPropertyName()); - auto& relsStore = storageManager.getRelsStore(); - auto boundNodeTableID = boundNode->getTableID(); - assert(rel->getNumTableIDs() == 1 && boundNode->getNumTableIDs() == 1); - auto relTableID = *rel->getTableIDs().begin(); - if (relsStore.hasAdjColumn(direction, boundNodeTableID, relTableID)) { - auto column = relsStore.getAdjColumn(direction, boundNodeTableID, relTableID); - if (rel->isVariableLength()) { - return make_unique(inDataPos, outDataPos, column, - rel->getLowerBound(), rel->getUpperBound(), std::move(prevOperator), - getOperatorID(), extend->getExpressionsForPrinting()); - } else { - return make_unique(inDataPos, outDataPos, column, - std::move(prevOperator), getOperatorID(), extend->getExpressionsForPrinting()); - } - } else { - assert(relsStore.hasAdjList(direction, boundNodeTableID, relTableID)); - auto list = relsStore.getAdjLists(direction, boundNodeTableID, relTableID); - if (rel->isVariableLength()) { - return make_unique(inDataPos, outDataPos, list, - rel->getLowerBound(), rel->getUpperBound(), std::move(prevOperator), - getOperatorID(), extend->getExpressionsForPrinting()); - } else { - return make_unique(inDataPos, outDataPos, list, std::move(prevOperator), - getOperatorID(), extend->getExpressionsForPrinting()); - } +static vector populatePropertyColumns(table_id_t boundNodeTableID, table_id_t relID, + RelDirection direction, const expression_vector& properties, const RelsStore& relsStore) { + vector propertyColumns; + for (auto& expression : properties) { + auto propertyExpression = (PropertyExpression*)expression.get(); + auto column = relsStore.getRelPropertyColumn( + direction, relID, boundNodeTableID, propertyExpression->getPropertyID(relID)); + propertyColumns.push_back(column); } + return propertyColumns; +} + +static vector populatePropertyLists(table_id_t boundNodeTableID, table_id_t relID, + RelDirection direction, const expression_vector& properties, const RelsStore& relsStore) { + vector propertyLists; + for (auto& expression : properties) { + auto propertyExpression = (PropertyExpression*)expression.get(); + auto list = relsStore.getRelPropertyLists( + direction, boundNodeTableID, relID, propertyExpression->getPropertyID(relID)); + propertyLists.push_back(list); + } + return propertyLists; } static unique_ptr populateAdjCollection(table_id_t boundNodeTableID, @@ -90,16 +75,28 @@ static unique_ptr populatePropertyCollection(table_id_t std::move(propertyColumns), std::move(propertyLists)); } -unique_ptr PlanMapper::mapLogicalGenericExtendToPhysical( +static vector> populatePropertyCollections( + table_id_t boundNodeTableID, const RelExpression& rel, RelDirection direction, + const expression_vector& properties, const RelsStore& relsStore) { + vector> propertyCollections; + for (auto& expression : properties) { + auto propertyExpression = (PropertyExpression*)expression.get(); + propertyCollections.push_back(populatePropertyCollection( + boundNodeTableID, rel, direction, *propertyExpression, relsStore)); + } + return propertyCollections; +} + +unique_ptr PlanMapper::mapLogicalExtendToPhysical( LogicalOperator* logicalOperator, MapperContext& mapperContext) { - auto extend = (LogicalGenericExtend*)logicalOperator; + auto extend = (LogicalExtend*)logicalOperator; auto boundNode = extend->getBoundNode(); auto nbrNode = extend->getNbrNode(); auto rel = extend->getRel(); auto direction = extend->getDirection(); auto prevOperator = mapLogicalOperatorToPhysical(logicalOperator->getChild(0), mapperContext); - auto inDataPos = mapperContext.getDataPos(boundNode->getInternalIDPropertyName()); - auto outNodePos = mapperContext.getDataPos(nbrNode->getInternalIDPropertyName()); + auto inNodeIDVectorPos = mapperContext.getDataPos(boundNode->getInternalIDPropertyName()); + auto outNodeIDVectorPos = mapperContext.getDataPos(nbrNode->getInternalIDPropertyName()); mapperContext.addComputedExpressions(nbrNode->getInternalIDPropertyName()); vector outPropertyVectorsPos; for (auto& expression : extend->getProperties()) { @@ -107,23 +104,55 @@ unique_ptr PlanMapper::mapLogicalGenericExtendToPhysical( mapperContext.addComputedExpressions(expression->getUniqueName()); } auto& relsStore = storageManager.getRelsStore(); - unordered_map> - adjAndPropertyCollectionPerNodeTable; - for (auto boundNodeTableID : boundNode->getTableIDs()) { - auto adjCollection = populateAdjCollection(boundNodeTableID, *rel, direction, relsStore); - vector> propertyCollections; - for (auto& expression : extend->getProperties()) { - auto propertyExpression = (PropertyExpression*)expression.get(); - propertyCollections.push_back(populatePropertyCollection( - boundNodeTableID, *rel, direction, *propertyExpression, relsStore)); + if (rel->getNumTableIDs() == 1 && boundNode->getNumTableIDs() == 1) { + auto boundNodeTableID = boundNode->getTableID(); + auto relTableID = *rel->getTableIDs().begin(); + if (relsStore.hasAdjColumn(direction, boundNodeTableID, relTableID)) { + auto adjColumn = relsStore.getAdjColumn(direction, boundNodeTableID, relTableID); + if (rel->isVariableLength()) { + return make_unique(inNodeIDVectorPos, outNodeIDVectorPos, + adjColumn, rel->getLowerBound(), rel->getUpperBound(), std::move(prevOperator), + getOperatorID(), extend->getExpressionsForPrinting()); + } else { + auto propertyColumns = populatePropertyColumns( + boundNodeTableID, relTableID, direction, extend->getProperties(), relsStore); + return make_unique(inNodeIDVectorPos, + outNodeIDVectorPos, std::move(outPropertyVectorsPos), adjColumn, + std::move(propertyColumns), std::move(prevOperator), getOperatorID(), + extend->getExpressionsForPrinting()); + } + } else { + assert(relsStore.hasAdjList(direction, boundNodeTableID, relTableID)); + auto adjList = relsStore.getAdjLists(direction, boundNodeTableID, relTableID); + if (rel->isVariableLength()) { + return make_unique(inNodeIDVectorPos, outNodeIDVectorPos, + adjList, rel->getLowerBound(), rel->getUpperBound(), std::move(prevOperator), + getOperatorID(), extend->getExpressionsForPrinting()); + } else { + auto propertyLists = populatePropertyLists( + boundNodeTableID, relTableID, direction, extend->getProperties(), relsStore); + return make_unique(inNodeIDVectorPos, + outNodeIDVectorPos, std::move(outPropertyVectorsPos), adjList, + std::move(propertyLists), std::move(prevOperator), getOperatorID(), + extend->getExpressionsForPrinting()); + } + } + } else { // map to generic extend + unordered_map> + adjAndPropertyCollectionPerNodeTable; + for (auto boundNodeTableID : boundNode->getTableIDs()) { + auto adjCollection = + populateAdjCollection(boundNodeTableID, *rel, direction, relsStore); + auto propertyCollections = populatePropertyCollections( + boundNodeTableID, *rel, direction, extend->getProperties(), relsStore); + adjAndPropertyCollectionPerNodeTable.insert( + {boundNodeTableID, make_unique( + std::move(adjCollection), std::move(propertyCollections))}); } - adjAndPropertyCollectionPerNodeTable.insert( - {boundNodeTableID, make_unique( - std::move(adjCollection), std::move(propertyCollections))}); + return make_unique(inNodeIDVectorPos, outNodeIDVectorPos, + outPropertyVectorsPos, std::move(adjAndPropertyCollectionPerNodeTable), + std::move(prevOperator), getOperatorID(), extend->getExpressionsForPrinting()); } - return make_unique(inDataPos, outNodePos, outPropertyVectorsPos, - std::move(adjAndPropertyCollectionPerNodeTable), std::move(prevOperator), getOperatorID(), - extend->getExpressionsForPrinting()); } } // namespace processor diff --git a/src/processor/mapper/map_scan_node_property.cpp b/src/processor/mapper/map_scan_node_property.cpp index 56e9269658..34397783e2 100644 --- a/src/processor/mapper/map_scan_node_property.cpp +++ b/src/processor/mapper/map_scan_node_property.cpp @@ -1,6 +1,6 @@ #include "planner/logical_plan/logical_operator/logical_scan_node_property.h" #include "processor/mapper/plan_mapper.h" -#include "processor/operator/scan_column/scan_column_property.h" +#include "processor/operator/scan_column/scan_node_properties.h" namespace kuzu { namespace processor { @@ -18,23 +18,23 @@ unique_ptr PlanMapper::mapLogicalScanNodePropertyToPhysical( mapperContext.addComputedExpressions(expression->getUniqueName()); } if (node->getNumTableIDs() > 1) { - vector> tableIDToColumns; - for (auto& expression : scanProperty.getProperties()) { - auto property = static_pointer_cast(expression); - unordered_map tableIDToColumn; - for (auto tableID : node->getTableIDs()) { + unordered_map> tableIDToColumns; + for (auto& tableID : node->getTableIDs()) { + vector columns; + for (auto& expression : scanProperty.getProperties()) { + auto property = static_pointer_cast(expression); if (!property->hasPropertyID(tableID)) { - // property doesn't exist for current node table - continue; + columns.push_back(nullptr); + } else { + columns.push_back( + nodeStore.getNodePropertyColumn(tableID, property->getPropertyID(tableID))); } - tableIDToColumn.insert({tableID, - nodeStore.getNodePropertyColumn(tableID, property->getPropertyID(tableID))}); } - tableIDToColumns.push_back(std::move(tableIDToColumn)); + tableIDToColumns.insert({tableID, std::move(columns)}); } - return make_unique(inputNodeIDVectorPos, std::move(outVectorsPos), - std::move(tableIDToColumns), std::move(prevOperator), getOperatorID(), - scanProperty.getExpressionsForPrinting()); + return make_unique(inputNodeIDVectorPos, + std::move(outVectorsPos), std::move(tableIDToColumns), std::move(prevOperator), + getOperatorID(), scanProperty.getExpressionsForPrinting()); } else { auto tableID = node->getTableID(); vector columns; @@ -43,7 +43,7 @@ unique_ptr PlanMapper::mapLogicalScanNodePropertyToPhysical( columns.push_back( nodeStore.getNodePropertyColumn(tableID, property->getPropertyID(tableID))); } - return make_unique(inputNodeIDVectorPos, + return make_unique(inputNodeIDVectorPos, std::move(outVectorsPos), std::move(columns), std::move(prevOperator), getOperatorID(), scanProperty.getExpressionsForPrinting()); } diff --git a/src/processor/mapper/map_scan_rel_property.cpp b/src/processor/mapper/map_scan_rel_property.cpp deleted file mode 100644 index 16fc886301..0000000000 --- a/src/processor/mapper/map_scan_rel_property.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "planner/logical_plan/logical_operator/logical_scan_rel_property.h" -#include "processor/mapper/plan_mapper.h" -#include "processor/operator/scan_column/scan_column_property.h" -#include "processor/operator/scan_list/scan_rel_property_list.h" - -namespace kuzu { -namespace processor { - -unique_ptr PlanMapper::mapLogicalScanRelPropertyToPhysical( - LogicalOperator* logicalOperator, MapperContext& mapperContext) { - auto scanRelProperty = (LogicalScanRelProperty*)logicalOperator; - auto boundNode = scanRelProperty->getBoundNode(); - auto rel = scanRelProperty->getRel(); - assert( - !rel->isVariableLength() && rel->getNumTableIDs() == 1 && boundNode->getNumTableIDs() == 1); - auto relID = rel->getTableID(); - auto direction = scanRelProperty->getDirection(); - auto propertyExpression = (PropertyExpression*)scanRelProperty->getProperty().get(); - auto prevOperator = mapLogicalOperatorToPhysical(logicalOperator->getChild(0), mapperContext); - auto inputNodeIDVectorPos = mapperContext.getDataPos(boundNode->getInternalIDPropertyName()); - auto outputPropertyVectorPos = mapperContext.getDataPos(propertyExpression->getUniqueName()); - mapperContext.addComputedExpressions(propertyExpression->getUniqueName()); - auto& relStore = storageManager.getRelsStore(); - if (relStore.hasAdjColumn(direction, boundNode->getTableID(), relID)) { - auto column = relStore.getRelPropertyColumn( - direction, relID, boundNode->getTableID(), propertyExpression->getPropertyID(relID)); - return make_unique(inputNodeIDVectorPos, - vector{outputPropertyVectorPos}, vector{column}, move(prevOperator), - getOperatorID(), scanRelProperty->getExpressionsForPrinting()); - } else { - auto lists = relStore.getRelPropertyLists( - direction, boundNode->getTableID(), relID, propertyExpression->getPropertyID(relID)); - return make_unique(inputNodeIDVectorPos, move(outputPropertyVectorPos), - lists, move(prevOperator), getOperatorID(), - scanRelProperty->getExpressionsForPrinting()); - } -} - -} // namespace processor -} // namespace kuzu diff --git a/src/processor/mapper/plan_mapper.cpp b/src/processor/mapper/plan_mapper.cpp index 93ea10ff96..a42f2a380d 100644 --- a/src/processor/mapper/plan_mapper.cpp +++ b/src/processor/mapper/plan_mapper.cpp @@ -35,9 +35,6 @@ unique_ptr PlanMapper::mapLogicalOperatorToPhysical( case LOGICAL_EXTEND: { physicalOperator = mapLogicalExtendToPhysical(logicalOperator.get(), mapperContext); } break; - case LOGICAL_GENERIC_EXTEND: { - physicalOperator = mapLogicalGenericExtendToPhysical(logicalOperator.get(), mapperContext); - } break; case LOGICAL_FLATTEN: { physicalOperator = mapLogicalFlattenToPhysical(logicalOperator.get(), mapperContext); } break; @@ -63,10 +60,6 @@ unique_ptr PlanMapper::mapLogicalOperatorToPhysical( physicalOperator = mapLogicalScanNodePropertyToPhysical(logicalOperator.get(), mapperContext); } break; - case LOGICAL_SCAN_REL_PROPERTY: { - physicalOperator = - mapLogicalScanRelPropertyToPhysical(logicalOperator.get(), mapperContext); - } break; case LOGICAL_MULTIPLICITY_REDUCER: { physicalOperator = mapLogicalMultiplicityReducerToPhysical(logicalOperator.get(), mapperContext); diff --git a/src/processor/operator/CMakeLists.txt b/src/processor/operator/CMakeLists.txt index cb7efa52fa..c666879762 100644 --- a/src/processor/operator/CMakeLists.txt +++ b/src/processor/operator/CMakeLists.txt @@ -12,6 +12,7 @@ add_subdirectory(var_length_extend) add_library(kuzu_processor_operator OBJECT + base_extend.cpp base_table_scan.cpp cross_product.cpp filter.cpp diff --git a/src/processor/operator/base_extend.cpp b/src/processor/operator/base_extend.cpp new file mode 100644 index 0000000000..adceb3ce89 --- /dev/null +++ b/src/processor/operator/base_extend.cpp @@ -0,0 +1,17 @@ +#include "processor/operator/base_extend.h" + +namespace kuzu { +namespace processor { + +void BaseExtendAndScanRelProperties::initLocalStateInternal( + ResultSet* resultSet, ExecutionContext* context) { + inNodeIDVector = resultSet->getValueVector(inNodeIDVectorPos); + outNodeIDVector = resultSet->getValueVector(outNodeIDVectorPos); + for (auto& dataPos : outPropertyVectorsPos) { + auto vector = resultSet->getValueVector(dataPos); + outPropertyVectors.push_back(vector); + } +} + +} // namespace processor +} // namespace kuzu diff --git a/src/processor/operator/generic_extend.cpp b/src/processor/operator/generic_extend.cpp index 3e6f7d06d9..a426b50716 100644 --- a/src/processor/operator/generic_extend.cpp +++ b/src/processor/operator/generic_extend.cpp @@ -60,18 +60,7 @@ bool AdjAndPropertyCollection::scanLists(const shared_ptr& inVector if (currentAdjListHandle->listSyncState.hasMoreToRead()) { // scan current adjList currentAdjList->readValues(outNodeVector, *currentAdjListHandle); - // scan current propertyLists - for (auto i = 0u; i < propertyCollections.size(); ++i) { - auto currentPropertyList = propertyCollections[i]->lists[currentListIdx]; - auto currentPropertyListHandle = - propertyCollections[i]->listHandles[currentListIdx].get(); - if (currentPropertyList == nullptr) { - outPropertyVectors[i]->setAllNull(); - } else { - currentPropertyList->readValues( - outPropertyVectors[i], *currentPropertyListHandle); - } - } + scanPropertyList(currentListIdx, outPropertyVectors, transaction); return true; } else { // no more to scan on current list, move to next list. @@ -109,10 +98,12 @@ bool AdjAndPropertyCollection::scanColumn(uint32_t idx, const shared_ptrcolumns[idx]; + auto& propertyVector = outPropertyVectors[i]; + propertyVector->resetOverflowBuffer(); if (propertyColumn == nullptr) { - outPropertyVectors[i]->setAllNull(); + propertyVector->setAllNull(); } else { - propertyColumn->read(transaction, inVector, outPropertyVectors[i]); + propertyColumn->read(transaction, inVector, propertyVector); } } return true; @@ -134,19 +125,25 @@ bool AdjAndPropertyCollection::scanList(uint32_t idx, const shared_ptrselectedSize != 0; +} + +void AdjAndPropertyCollection::scanPropertyList(uint32_t idx, + const vector>& outPropertyVectors, Transaction* transaction) { for (auto i = 0u; i < propertyCollections.size(); ++i) { auto propertyList = propertyCollections[i]->lists[idx]; auto propertyListHandle = propertyCollections[i]->listHandles[idx].get(); + auto& propertyVector = outPropertyVectors[i]; + propertyVector->resetOverflowBuffer(); if (propertyList == nullptr) { outPropertyVectors[i]->setAllNull(); } else { - propertyList->readValues(outPropertyVectors[i], *propertyListHandle); + propertyList->readValues(propertyVector, *propertyListHandle); propertyList->setDeletedRelsIfNecessary( - transaction, propertyListHandle->listSyncState, outPropertyVectors[i]); + transaction, propertyListHandle->listSyncState, propertyVector); } } - return selVector->selectedSize != 0; } unique_ptr AdjAndPropertyCollection::clone() const { @@ -161,13 +158,9 @@ unique_ptr AdjAndPropertyCollection::clone() const { std::move(clonedAdjCollection), std::move(clonedPropertyCollections)); } -void GenericExtend::initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) { - inVector = resultSet->getValueVector(inVectorPos); - outNodeVector = resultSet->getValueVector(outNodeVectorPos); - for (auto& dataPos : outPropertyVectorsPos) { - auto vector = resultSet->getValueVector(dataPos); - outPropertyVectors.push_back(vector); - } +void GenericExtendAndScanRelProperties::initLocalStateInternal( + ResultSet* resultSet, ExecutionContext* context) { + BaseExtendAndScanRelProperties::initLocalStateInternal(resultSet, context); for (auto& [_, adjAndPropertyCollection] : adjAndPropertyCollectionPerNodeTable) { adjAndPropertyCollection->populateListHandles(); } @@ -175,34 +168,35 @@ void GenericExtend::initLocalStateInternal(ResultSet* resultSet, ExecutionContex currentAdjAndPropertyCollection = nullptr; } -bool GenericExtend::getNextTuplesInternal() { +bool GenericExtendAndScanRelProperties::getNextTuplesInternal() { while (true) { if (scanCurrentAdjAndPropertyCollection()) { - metrics->numOutputTuple.increase(outNodeVector->state->selVector->selectedSize); + metrics->numOutputTuple.increase(outNodeIDVector->state->selVector->selectedSize); return true; } if (!children[0]->getNextTuple()) { return false; } - auto currentIdx = inVector->state->selVector->selectedPositions[0]; - if (inVector->isNull(currentIdx)) { - outNodeVector->state->selVector->selectedSize = 0; + auto currentIdx = inNodeIDVector->state->selVector->selectedPositions[0]; + if (inNodeIDVector->isNull(currentIdx)) { + outNodeIDVector->state->selVector->selectedSize = 0; continue; } - auto nodeID = inVector->getValue(currentIdx); + auto nodeID = inNodeIDVector->getValue(currentIdx); initCurrentAdjAndPropertyCollection(nodeID); } } -bool GenericExtend::scanCurrentAdjAndPropertyCollection() { +bool GenericExtendAndScanRelProperties::scanCurrentAdjAndPropertyCollection() { if (currentAdjAndPropertyCollection == nullptr) { return false; } return currentAdjAndPropertyCollection->scan( - inVector, outNodeVector, outPropertyVectors, transaction); + inNodeIDVector, outNodeIDVector, outPropertyVectors, transaction); } -void GenericExtend::initCurrentAdjAndPropertyCollection(const nodeID_t& nodeID) { +void GenericExtendAndScanRelProperties::initCurrentAdjAndPropertyCollection( + const nodeID_t& nodeID) { if (adjAndPropertyCollectionPerNodeTable.contains(nodeID.tableID)) { currentAdjAndPropertyCollection = adjAndPropertyCollectionPerNodeTable.at(nodeID.tableID).get(); diff --git a/src/processor/operator/scan_column/CMakeLists.txt b/src/processor/operator/scan_column/CMakeLists.txt index 3335e1ff19..6ef286f32a 100644 --- a/src/processor/operator/scan_column/CMakeLists.txt +++ b/src/processor/operator/scan_column/CMakeLists.txt @@ -2,7 +2,7 @@ add_library(kuzu_processor_operator_scan_column OBJECT adj_column_extend.cpp scan_column.cpp - scan_column_property.cpp) + scan_node_properties.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ diff --git a/src/processor/operator/scan_column/adj_column_extend.cpp b/src/processor/operator/scan_column/adj_column_extend.cpp index 5cac11b999..57f1a6ecec 100644 --- a/src/processor/operator/scan_column/adj_column_extend.cpp +++ b/src/processor/operator/scan_column/adj_column_extend.cpp @@ -3,19 +3,26 @@ namespace kuzu { namespace processor { -bool AdjColumnExtend::getNextTuplesInternal() { +bool ColumnExtendAndScanRelProperties::getNextTuplesInternal() { bool hasAtLeastOneNonNullValue; + // join with adjColumn do { - restoreSelVector(inputNodeIDVector->state->selVector.get()); + restoreSelVector(inNodeIDVector->state->selVector.get()); if (!children[0]->getNextTuple()) { return false; } - saveSelVector(inputNodeIDVector->state->selVector.get()); - outputVector->setAllNull(); - nodeIDColumn->read(transaction, inputNodeIDVector, outputVector); - hasAtLeastOneNonNullValue = NodeIDVector::discardNull(*outputVector); + saveSelVector(inNodeIDVector->state->selVector.get()); + outNodeIDVector->setAllNull(); + adjColumn->read(transaction, inNodeIDVector, outNodeIDVector); + hasAtLeastOneNonNullValue = NodeIDVector::discardNull(*outNodeIDVector); } while (!hasAtLeastOneNonNullValue); - metrics->numOutputTuple.increase(inputNodeIDVector->state->selVector->selectedSize); + // scan column properties + for (auto i = 0u; i < propertyColumns.size(); ++i) { + auto vector = outPropertyVectors[i]; + vector->resetOverflowBuffer(); + propertyColumns[i]->read(transaction, inNodeIDVector, vector); + } + metrics->numOutputTuple.increase(inNodeIDVector->state->selVector->selectedSize); return true; } diff --git a/src/processor/operator/scan_column/scan_column.cpp b/src/processor/operator/scan_column/scan_column.cpp index 25765cf455..f1326483bd 100644 --- a/src/processor/operator/scan_column/scan_column.cpp +++ b/src/processor/operator/scan_column/scan_column.cpp @@ -7,16 +7,11 @@ void BaseScanColumn::initLocalStateInternal(ResultSet* resultSet, ExecutionConte inputNodeIDVector = resultSet->getValueVector(inputNodeIDVectorPos); } -void ScanSingleColumn::initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) { - BaseScanColumn::initLocalStateInternal(resultSet, context); - outputVector = resultSet->getValueVector(outputVectorPos); -} - void ScanMultipleColumns::initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) { BaseScanColumn::initLocalStateInternal(resultSet, context); - for (auto& dataPos : outVectorsPos) { + for (auto& dataPos : outPropertyVectorsPos) { auto vector = resultSet->getValueVector(dataPos); - outVectors.push_back(vector); + outPropertyVectors.push_back(vector); } } diff --git a/src/processor/operator/scan_column/scan_column_property.cpp b/src/processor/operator/scan_column/scan_column_property.cpp deleted file mode 100644 index da9b099ce0..0000000000 --- a/src/processor/operator/scan_column/scan_column_property.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "processor/operator/scan_column/scan_column_property.h" - -using namespace kuzu::common; - -namespace kuzu { -namespace processor { - -bool ScanSingleTableProperties::getNextTuplesInternal() { - if (!children[0]->getNextTuple()) { - return false; - } - for (auto i = 0u; i < columns.size(); ++i) { - auto vector = outVectors[i]; - vector->resetOverflowBuffer(); - columns[i]->read(transaction, inputNodeIDVector, vector); - } - return true; -} - -bool ScanMultiTableProperties::getNextTuplesInternal() { - if (!children[0]->getNextTuple()) { - return false; - } - auto state = inputNodeIDVector->state; - assert(!state->isFlat()); // Property scans should be sequential and thus on unflat vector only. - auto tableID = - inputNodeIDVector->getValue(state->selVector->selectedPositions[0]).tableID; - for (auto i = 0u; i < tableIDToColumns.size(); ++i) { - auto vector = outVectors[i]; - vector->resetOverflowBuffer(); - if (tableIDToColumns[i].contains(tableID)) { - tableIDToColumns[i].at(tableID)->read(transaction, inputNodeIDVector, vector); - } else { - vector->setAllNull(); - } - } - return true; -} - -} // namespace processor -} // namespace kuzu diff --git a/src/processor/operator/scan_column/scan_node_properties.cpp b/src/processor/operator/scan_column/scan_node_properties.cpp new file mode 100644 index 0000000000..25bd8a9a9f --- /dev/null +++ b/src/processor/operator/scan_column/scan_node_properties.cpp @@ -0,0 +1,43 @@ +#include "processor/operator/scan_column/scan_node_properties.h" + +using namespace kuzu::common; + +namespace kuzu { +namespace processor { + +bool ScanSingleNodeTableProperties::getNextTuplesInternal() { + if (!children[0]->getNextTuple()) { + return false; + } + for (auto i = 0u; i < propertyColumns.size(); ++i) { + auto vector = outPropertyVectors[i]; + // TODO(Everyone): move resetOverflowBuffer to column & list read? + vector->resetOverflowBuffer(); + propertyColumns[i]->read(transaction, inputNodeIDVector, vector); + } + return true; +} + +bool ScanMultiNodeTableProperties::getNextTuplesInternal() { + if (!children[0]->getNextTuple()) { + return false; + } + auto state = inputNodeIDVector->state; + assert(!state->isFlat()); // Property scans should be sequential and thus on unflat vector only. + auto tableID = + inputNodeIDVector->getValue(state->selVector->selectedPositions[0]).tableID; + auto& columns = tableIDToPropertyColumns.at(tableID); + for (auto i = 0u; i < outPropertyVectors.size(); ++i) { + auto vector = outPropertyVectors[i]; + vector->resetOverflowBuffer(); + if (columns[i] != nullptr) { + columns[i]->read(transaction, inputNodeIDVector, vector); + } else { + vector->setAllNull(); + } + } + return true; +} + +} // namespace processor +} // namespace kuzu diff --git a/src/processor/operator/scan_list/CMakeLists.txt b/src/processor/operator/scan_list/CMakeLists.txt index d3efec1e8f..bb703eceb2 100644 --- a/src/processor/operator/scan_list/CMakeLists.txt +++ b/src/processor/operator/scan_list/CMakeLists.txt @@ -1,7 +1,7 @@ add_library(kuzu_processor_operator_scan_list OBJECT adj_list_extend.cpp - scan_rel_property_list.cpp) + ) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ diff --git a/src/processor/operator/scan_list/adj_list_extend.cpp b/src/processor/operator/scan_list/adj_list_extend.cpp index 2d13e80d2a..73a0e3b4d6 100644 --- a/src/processor/operator/scan_list/adj_list_extend.cpp +++ b/src/processor/operator/scan_list/adj_list_extend.cpp @@ -3,35 +3,51 @@ namespace kuzu { namespace processor { -void AdjListExtend::initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) { - ScanList::initLocalStateInternal(resultSet, context); - resultSet->initListSyncState(outDataPos.dataChunkPos); - listHandle = make_shared(*resultSet->getListSyncState(outDataPos.dataChunkPos)); +void ListExtendAndScanRelProperties::initLocalStateInternal( + ResultSet* resultSet, ExecutionContext* context) { + BaseExtendAndScanRelProperties::initLocalStateInternal(resultSet, context); + syncState = make_unique(); + adjListHandle = make_shared(*syncState); + for (auto& _ : propertyLists) { + propertyListHandles.push_back(make_shared(*syncState)); + } } -bool AdjListExtend::getNextTuplesInternal() { - if (listHandle->listSyncState.hasMoreToRead()) { - lists->readValues(outValueVector, *listHandle); - metrics->numOutputTuple.increase(outValueVector->state->selVector->selectedSize); - return true; +bool ListExtendAndScanRelProperties::getNextTuplesInternal() { + if (adjListHandle->listSyncState.hasMoreToRead()) { + adjList->readValues(outNodeIDVector, *adjListHandle); + } else { + do { + if (!children[0]->getNextTuple()) { + return false; + } + auto currentIdx = inNodeIDVector->state->selVector->selectedPositions[0]; + if (inNodeIDVector->isNull(currentIdx)) { + outNodeIDVector->state->selVector->selectedSize = 0; + continue; + } + auto currentNodeOffset = inNodeIDVector->readNodeOffset(currentIdx); + ((AdjLists*)adjList) + ->initListReadingState(currentNodeOffset, *adjListHandle, transaction->getType()); + adjList->readValues(outNodeIDVector, *adjListHandle); + } while (outNodeIDVector->state->selVector->selectedSize == 0); } - do { - if (!children[0]->getNextTuple()) { - return false; - } - auto currentIdx = inValueVector->state->selVector->selectedPositions[0]; - if (inValueVector->isNull(currentIdx)) { - outValueVector->state->selVector->selectedSize = 0; - continue; - } - ((AdjLists*)lists) - ->initListReadingState( - inValueVector->readNodeOffset(currentIdx), *listHandle, transaction->getType()); - lists->readValues(outValueVector, *listHandle); - } while (outValueVector->state->selVector->selectedSize == 0); - metrics->numOutputTuple.increase(outValueVector->state->selVector->selectedSize); + // TODO(Ziyi/Guodong): this is a hidden bug found in this refactor but also exists in master. + // Our protocol is that an operator cannot output empty result. This is violated when + // introducing setDeletedRelsIfNecessary() which might set selectedSize = 0. Let me know if my + // understanding is correct about this. + scanPropertyLists(); + metrics->numOutputTuple.increase(outNodeIDVector->state->selVector->selectedSize); return true; } +void ListExtendAndScanRelProperties::scanPropertyLists() { + for (auto i = 0u; i < propertyLists.size(); ++i) { + outPropertyVectors[i]->resetOverflowBuffer(); + propertyLists[i]->readValues(outPropertyVectors[i], *propertyListHandles[i]); + propertyLists[i]->setDeletedRelsIfNecessary(transaction, *syncState, outPropertyVectors[i]); + } +} + } // namespace processor } // namespace kuzu diff --git a/src/processor/operator/scan_list/scan_rel_property_list.cpp b/src/processor/operator/scan_list/scan_rel_property_list.cpp deleted file mode 100644 index 1dce48cbb6..0000000000 --- a/src/processor/operator/scan_list/scan_rel_property_list.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "processor/operator/scan_list/scan_rel_property_list.h" - -namespace kuzu { -namespace processor { - -void ScanRelPropertyList::initLocalStateInternal(ResultSet* resultSet, ExecutionContext* context) { - ScanList::initLocalStateInternal(resultSet, context); - listHandle = make_shared(*resultSet->getListSyncState(outDataPos.dataChunkPos)); -} - -bool ScanRelPropertyList::getNextTuplesInternal() { - if (!children[0]->getNextTuple()) { - return false; - } - outValueVector->resetOverflowBuffer(); - lists->readValues(outValueVector, *listHandle); - lists->setDeletedRelsIfNecessary(transaction, listHandle->listSyncState, outValueVector); - return true; -} - -} // namespace processor -} // namespace kuzu diff --git a/test/runner/e2e_read_test.cpp b/test/runner/e2e_read_test.cpp index 04ca7210b4..233dab5c3c 100644 --- a/test/runner/e2e_read_test.cpp +++ b/test/runner/e2e_read_test.cpp @@ -18,7 +18,7 @@ TEST_F(LongStringPKTest, LongStringPKTest) { runTest(TestHelper::appendKuzuRootPath("test/test_files/long_string_pk/long_string_pk.test")); } -TEST_F(TinySnbReadTest, MatchExecute) { +TEST_F(TinySnbReadTest, Match) { runTest(TestHelper::appendKuzuRootPath("test/test_files/tinysnb/match/node.test")); runTest(TestHelper::appendKuzuRootPath("test/test_files/tinysnb/match/one_hop.test")); runTest(TestHelper::appendKuzuRootPath("test/test_files/tinysnb/match/two_hop.test"));