diff --git a/src/include/optimizer/projection_push_down_optimizer.h b/src/include/optimizer/projection_push_down_optimizer.h index 346e19653c3..a53d91a76a5 100644 --- a/src/include/optimizer/projection_push_down_optimizer.h +++ b/src/include/optimizer/projection_push_down_optimizer.h @@ -46,6 +46,7 @@ class ProjectionPushDownOptimizer : public LogicalOperatorVisitor { void visitMerge(planner::LogicalOperator* op) override; void visitCopyFrom(planner::LogicalOperator* op) override; void visitTableFunctionCall(planner::LogicalOperator*) override; + void visitScanNodeTable(planner::LogicalOperator*) override; void visitSetInfo(const binder::BoundSetPropertyInfo& info); void visitInsertInfo(const planner::LogicalInsertInfo& info); @@ -57,6 +58,8 @@ class ProjectionPushDownOptimizer : public LogicalOperatorVisitor { void preAppendProjection(planner::LogicalOperator* op, common::idx_t childIdx, binder::expression_vector expressions); + bool clearScanNodeTableProperties(planner::LogicalOperator* op) const; + private: binder::expression_set propertiesInUse; binder::expression_set variablesInUse; diff --git a/src/include/planner/operator/scan/logical_scan_node_table.h b/src/include/planner/operator/scan/logical_scan_node_table.h index 6a9006129b5..7fe1567d3b9 100644 --- a/src/include/planner/operator/scan/logical_scan_node_table.h +++ b/src/include/planner/operator/scan/logical_scan_node_table.h @@ -77,6 +77,7 @@ class LogicalScanNodeTable final : public LogicalOperator { std::shared_ptr getNodeID() const { return nodeID; } std::vector getTableIDs() const { return nodeTableIDs; } + void clearProperty() { properties.clear(); } binder::expression_vector getProperties() const { return properties; } void addProperty(std::shared_ptr expr) { properties.push_back(std::move(expr)); diff --git a/src/optimizer/projection_push_down_optimizer.cpp b/src/optimizer/projection_push_down_optimizer.cpp index 4c4d3b27e0d..9fb68c19e93 100644 --- a/src/optimizer/projection_push_down_optimizer.cpp +++ b/src/optimizer/projection_push_down_optimizer.cpp @@ -20,6 +20,7 @@ #include "planner/operator/persistent/logical_insert.h" #include "planner/operator/persistent/logical_merge.h" #include "planner/operator/persistent/logical_set.h" +#include using namespace kuzu::common; using namespace kuzu::planner; @@ -266,6 +267,28 @@ void ProjectionPushDownOptimizer::visitTableFunctionCall(LogicalOperator* op) { tableFunctionCall.setColumnSkips(std::move(columnSkips)); } +void ProjectionPushDownOptimizer::visitScanNodeTable(LogicalOperator* op) { + clearScanNodeTableProperties(op); +} + +bool ProjectionPushDownOptimizer::clearScanNodeTableProperties(planner::LogicalOperator* op) const { + auto& scanNodeTable = op->cast(); + if (scanNodeTable.getProperties().empty()) { + return false; + } + bool hasPropertiesInUse = false; + for (auto expression : scanNodeTable.getProperties()) { + if (propertiesInUse.contains(expression)) { + hasPropertiesInUse = true; + break; + } + } + if (!hasPropertiesInUse) { + scanNodeTable.clearProperty(); + } + return !hasPropertiesInUse; +} + void ProjectionPushDownOptimizer::visitSetInfo(const binder::BoundSetPropertyInfo& info) { switch (info.tableType) { case TableType::NODE: { @@ -361,8 +384,14 @@ void ProjectionPushDownOptimizer::preAppendProjection(LogicalOperator* op, idx_t // We don't have a way to handle return; } - auto projection = - std::make_shared(std::move(expressions), op->getChild(childIdx)); + auto child = op->getChild(childIdx); + // reset scan node table properties + if (child->getOperatorType() == LogicalOperatorType::SCAN_NODE_TABLE) { + if (clearScanNodeTableProperties(child.get())) { + return; + } + } + auto projection = std::make_shared(std::move(expressions), child); projection->computeFlatSchema(); op->setChild(childIdx, std::move(projection)); } diff --git a/src/processor/operator/scan/primary_key_scan_node_table.cpp b/src/processor/operator/scan/primary_key_scan_node_table.cpp index 46a9f51d696..f216d23c906 100644 --- a/src/processor/operator/scan/primary_key_scan_node_table.cpp +++ b/src/processor/operator/scan/primary_key_scan_node_table.cpp @@ -16,9 +16,10 @@ std::string PrimaryKeyScanPrintInfo::toString() const { result += ",Alias: "; result += alias; } - result += ", Expressions: "; - result += binder::ExpressionUtil::toString(expressions); - + if (!expressions.empty()) { + result += ", Expressions: "; + result += binder::ExpressionUtil::toString(expressions); + } return result; } @@ -36,8 +37,18 @@ void PrimaryKeyScanNodeTable::initLocalStateInternal(ResultSet* resultSet, for (auto& pos : info.outVectorsPos) { outVectors.push_back(resultSet->getValueVector(pos).get()); } - scanState = std::make_unique( - resultSet->getValueVector(info.nodeIDPos).get(), outVectors, outVectors[0]->state); + if (outVectors.empty()) { + + scanState = + std::make_unique(resultSet->getValueVector(info.nodeIDPos).get(), + outVectors, DataChunkState::getSingleValueDataChunkState()); + + ; + } else { + + scanState = std::make_unique( + resultSet->getValueVector(info.nodeIDPos).get(), outVectors, outVectors[0]->state); + } indexEvaluator->init(*resultSet, context->clientContext); }