diff --git a/src/cypher/execution_plan/ops/op_all_node_scan.h b/src/cypher/execution_plan/ops/op_all_node_scan.h index ef0983426d..8d37a3b72c 100644 --- a/src/cypher/execution_plan/ops/op_all_node_scan.h +++ b/src/cypher/execution_plan/ops/op_all_node_scan.h @@ -54,10 +54,9 @@ class AllNodeScan : public OpBase { OpResult Initialize(RTContext *ctx) override { // allocate a new record - record = std::make_shared(rec_length_, sym_tab_); + record = std::make_shared(rec_length_, sym_tab_, ctx->param_tab_); record->values[node_rec_idx_].type = Entry::NODE; record->values[node_rec_idx_].node = node_; - record->SetParameter(ctx->param_tab_); // transaction allocated before in plan:execute // TODO(anyone) remove patternGraph's state (ctx) node_->ItRef()->Initialize(ctx->txn_->GetTxn().get(), lgraph::VIter::VERTEX_ITER); diff --git a/src/cypher/execution_plan/ops/op_argument.cpp b/src/cypher/execution_plan/ops/op_argument.cpp index 99b9c04ed8..1565d8d9ef 100644 --- a/src/cypher/execution_plan/ops/op_argument.cpp +++ b/src/cypher/execution_plan/ops/op_argument.cpp @@ -43,8 +43,7 @@ void Argument::Receive(std::shared_ptr *input_record, PatternGraph *patt OpBase::OpResult Argument::Initialize(RTContext *ctx) { // allocate a new record - record = std::make_shared(sym_tab_->symbols.size(), sym_tab_); - record->SetParameter(ctx->param_tab_); + record = std::make_shared(sym_tab_->symbols.size(), sym_tab_, ctx->param_tab_); for (auto &arg : args_) { if (arg.type == SymbolNode::NODE) { auto &node = pattern_graph_->GetNode(arg.alias); diff --git a/src/cypher/execution_plan/ops/op_cartesian_product.h b/src/cypher/execution_plan/ops/op_cartesian_product.h index 91a7ae9202..f75cec073e 100644 --- a/src/cypher/execution_plan/ops/op_cartesian_product.h +++ b/src/cypher/execution_plan/ops/op_cartesian_product.h @@ -73,7 +73,7 @@ class CartesianProduct : public OpBase { } } if (!sym_tab) throw lgraph::CypherException("CartesianProduct initialize failed"); - record = std::make_shared(sym_tab->symbols.size(), sym_tab); + record = std::make_shared(sym_tab->symbols.size(), sym_tab, ctx->param_tab_); return OP_OK; } diff --git a/src/cypher/execution_plan/ops/op_create.h b/src/cypher/execution_plan/ops/op_create.h index fb94b0e87e..dc045a8692 100644 --- a/src/cypher/execution_plan/ops/op_create.h +++ b/src/cypher/execution_plan/ops/op_create.h @@ -208,7 +208,8 @@ class OpCreate : public OpBase { for (auto child : children) { child->Initialize(ctx); } - record = children.empty() ? std::make_shared(sym_tab_.symbols.size(), &sym_tab_) + record = children.empty() ? + std::make_shared(sym_tab_.symbols.size(), &sym_tab_, ctx->param_tab_) : children[0]->record; return OP_OK; } diff --git a/src/cypher/execution_plan/ops/op_immediate_argument.h b/src/cypher/execution_plan/ops/op_immediate_argument.h index 1b9c57bd89..f0d9bec99d 100644 --- a/src/cypher/execution_plan/ops/op_immediate_argument.h +++ b/src/cypher/execution_plan/ops/op_immediate_argument.h @@ -28,7 +28,7 @@ class ImmediateArgument : public OpBase { std::vector args_; public: - ImmediateArgument(RTContext *ctx, PatternGraph *pattern) + explicit ImmediateArgument(PatternGraph *pattern) : OpBase(OpType::ARGUMENT, "Immediate Argument"), pattern_graph_(pattern) { auto sym_tab = &pattern_graph_->symbol_table; for (auto &s : sym_tab->symbols) { @@ -37,13 +37,14 @@ class ImmediateArgument : public OpBase { args_.emplace_back(s.first, s.second.id, s.second.type); } } - // allocate a new record - record = std::make_shared(sym_tab->symbols.size(), sym_tab); } void Receive(const Record *input_record) { input_record_ = input_record; } OpResult Initialize(RTContext *ctx) override { + auto sym_tab = &pattern_graph_->symbol_table; + // allocate a new record + record = std::make_shared(sym_tab->symbols.size(), sym_tab, ctx->param_tab_); for (auto &arg : args_) { if (arg.type == SymbolNode::NODE) { auto &node = pattern_graph_->GetNode(arg.alias); diff --git a/src/cypher/execution_plan/ops/op_inquery_call.h b/src/cypher/execution_plan/ops/op_inquery_call.h index 3463a53f55..6023571e1d 100644 --- a/src/cypher/execution_plan/ops/op_inquery_call.h +++ b/src/cypher/execution_plan/ops/op_inquery_call.h @@ -85,7 +85,7 @@ class InQueryCall : public OpBase { OpResult Initialize(RTContext *ctx) override { auto &sym_tab = pattern_->symbol_table; if (children.empty()) { - record = std::make_shared(sym_tab.symbols.size(), &sym_tab); + record = std::make_shared(sym_tab.symbols.size(), &sym_tab, ctx->param_tab_); } else { CYPHER_THROW_ASSERT(children.size() == 1); if (children[0]->Initialize(ctx) != OP_OK) return OP_ERR; diff --git a/src/cypher/execution_plan/ops/op_merge.h b/src/cypher/execution_plan/ops/op_merge.h index 4401660d85..5305ee3541 100644 --- a/src/cypher/execution_plan/ops/op_merge.h +++ b/src/cypher/execution_plan/ops/op_merge.h @@ -499,7 +499,8 @@ class OpMerge : public OpBase { for (auto child : children) { child->Initialize(ctx); } - record = children.empty() ? std::make_shared(sym_tab_.symbols.size(), &sym_tab_) + record = children.empty() ? + std::make_shared(sym_tab_.symbols.size(), &sym_tab_, ctx->param_tab_) : children[0]->record; return OP_OK; } diff --git a/src/cypher/execution_plan/ops/op_node_by_id_seek.h b/src/cypher/execution_plan/ops/op_node_by_id_seek.h index a0a657e5e4..87d8f4fec4 100644 --- a/src/cypher/execution_plan/ops/op_node_by_id_seek.h +++ b/src/cypher/execution_plan/ops/op_node_by_id_seek.h @@ -57,7 +57,7 @@ class NodeByIdSeek : public OpBase { } OpResult Initialize(RTContext *ctx) override { - record = std::make_shared(rec_length_, sym_tab_); + record = std::make_shared(rec_length_, sym_tab_, ctx->param_tab_); record->values[node_rec_idx_].type = Entry::NODE; record->values[node_rec_idx_].node = node_; record->SetParameter(ctx->param_tab_); diff --git a/src/cypher/execution_plan/ops/op_node_by_label_scan.h b/src/cypher/execution_plan/ops/op_node_by_label_scan.h index fbf92505bf..58b4d3e085 100644 --- a/src/cypher/execution_plan/ops/op_node_by_label_scan.h +++ b/src/cypher/execution_plan/ops/op_node_by_label_scan.h @@ -53,10 +53,9 @@ class NodeByLabelScan : public OpBase { OpResult Initialize(RTContext *ctx) override { // allocate a new record - record = std::make_shared(rec_length_, sym_tab_); + record = std::make_shared(rec_length_, sym_tab_, ctx->param_tab_); record->values[node_rec_idx_].type = Entry::NODE; record->values[node_rec_idx_].node = node_; - record->SetParameter(ctx->param_tab_); // transaction allocated before in plan:execute // TODO(anyone) remove patternGraph's state (ctx) auto primary_filed = ctx->txn_->GetVertexPrimaryField(node_->Label()); diff --git a/src/cypher/execution_plan/ops/op_node_index_seek.h b/src/cypher/execution_plan/ops/op_node_index_seek.h index 5a4261c5ab..44a2c5df43 100644 --- a/src/cypher/execution_plan/ops/op_node_index_seek.h +++ b/src/cypher/execution_plan/ops/op_node_index_seek.h @@ -64,10 +64,9 @@ class NodeIndexSeek : public OpBase { OpResult Initialize(RTContext *ctx) override { // allocate a new record - record = std::make_shared(rec_length_, sym_tab_); + record = std::make_shared(rec_length_, sym_tab_, ctx->param_tab_); record->values[node_rec_idx_].type = Entry::NODE; record->values[node_rec_idx_].node = node_; - record->SetParameter(ctx->param_tab_); auto &pf = node_->Prop(); field_ = pf.type != Property::NUL ? pf.field : field_; // use pf.field if applicable diff --git a/src/cypher/execution_plan/ops/op_unwind.h b/src/cypher/execution_plan/ops/op_unwind.h index fa5c5407b6..85e5d15954 100644 --- a/src/cypher/execution_plan/ops/op_unwind.h +++ b/src/cypher/execution_plan/ops/op_unwind.h @@ -53,7 +53,7 @@ class Unwind : public OpBase { if (children.size() > 1) CYPHER_TODO(); if (children.empty()) { // No child operation, list must be static. - record = std::make_shared(sym_tab_->symbols.size(), sym_tab_); + record = std::make_shared(sym_tab_->symbols.size(), sym_tab_, ctx->param_tab_); // Set parameter, use uniform runtime context for (auto &p : ctx->param_tab_) { auto it = record->symbol_table->symbols.find(p.first); diff --git a/src/cypher/filter/filter.cpp b/src/cypher/filter/filter.cpp index d21bc7f59e..4cb1cb45a6 100644 --- a/src/cypher/filter/filter.cpp +++ b/src/cypher/filter/filter.cpp @@ -87,8 +87,7 @@ void TestExists::BuildNestedExecutionPlan() { if (expand_streams.size() > 1) CYPHER_TODO(); CYPHER_THROW_ASSERT(!expand_streams.empty() && !expand_streams[0].empty()); std::vector expand_ops; - // TODO(anyone) use dummy RTContext here. - auto *ia = new cypher::ImmediateArgument(nullptr, nested_pattern_.get()); + auto *ia = new cypher::ImmediateArgument(nested_pattern_.get()); expand_ops.emplace_back(ia); for (auto &step : expand_streams[0]) { auto &start = nested_pattern_->GetNode(std::get<0>(step)); diff --git a/src/cypher/resultset/record.cpp b/src/cypher/resultset/record.cpp index badbf92638..6b06fe68b8 100644 --- a/src/cypher/resultset/record.cpp +++ b/src/cypher/resultset/record.cpp @@ -48,7 +48,7 @@ lgraph::FieldData Entry::GetEntityField(RTContext *ctx, const std::string &fd) c } void Record::SetParameter(const PARAM_TAB &ptab) { - if (!symbol_table) return; + if (!symbol_table || ptab.empty()) return; for (auto ¶m : ptab) { auto it = symbol_table->symbols.find(param.first); if (it != symbol_table->symbols.end()) { diff --git a/src/cypher/resultset/record.h b/src/cypher/resultset/record.h index 3e8e86c04b..7c61c9cc39 100644 --- a/src/cypher/resultset/record.h +++ b/src/cypher/resultset/record.h @@ -235,7 +235,11 @@ struct Record { explicit Record(size_t size) { values.resize(size); } - Record(size_t size, const SymbolTable *sym_tab) : symbol_table(sym_tab) { values.resize(size); } + Record(size_t size, const SymbolTable *sym_tab, const PARAM_TAB &ptab) + : symbol_table(sym_tab) { + values.resize(size); + SetParameter(ptab); + } Record(const Record &rhs) { values = rhs.values; diff --git a/test/test_cypher.cpp b/test/test_cypher.cpp index bf01f69f2b..5aa85bc1a2 100644 --- a/test/test_cypher.cpp +++ b/test/test_cypher.cpp @@ -40,6 +40,7 @@ using namespace antlr4; static const cypher::PARAM_TAB g_param_tab = { {"$name", cypher::FieldData(lgraph::FieldData("Lindsay Lohan"))}, + {"$new_name", cypher::FieldData(lgraph::FieldData("new name"))}, {"$personId", cypher::FieldData(lgraph::FieldData(1))}, {"$personIds", cypher::FieldData(std::vector{ lgraph::FieldData("Liam Neeson"), lgraph::FieldData("Dennis Quaid"), @@ -501,6 +502,8 @@ int test_parameter(cypher::RTContext *ctx) { static const std::vector> script_check = { {"MATCH (n:Person) WHERE n.name = $name RETURN n", 1}, {"MATCH (n:Person {name:$name}) RETURN n", 1}, + {"CREATE (n:Person {name:$new_name}) RETURN n", 1}, + {"MATCH (n:Person {name:$new_name}) DELETE n", 1}, }; std::vector scripts; std::vector check;