implement ReferenceExpressionEvaluator with Visitor to Identifier to retrieve pointer to object from frame
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
// Copyright 2023 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -31,6 +31,78 @@
|
||||
|
||||
namespace memgraph::query {
|
||||
|
||||
static std::chrono::duration<double> total2;
|
||||
static std::chrono::duration<double> new_print2;
|
||||
|
||||
class ReferenceExpressionEvaluator : public ExpressionVisitor<TypedValue *> {
|
||||
public:
|
||||
ReferenceExpressionEvaluator(Frame *frame, const SymbolTable *symbol_table, const EvaluationContext *ctx,
|
||||
DbAccessor *dba, storage::View view)
|
||||
: frame_(frame), symbol_table_(symbol_table), ctx_(ctx), dba_(dba), view_(view) {}
|
||||
|
||||
using ExpressionVisitor<TypedValue *>::Visit;
|
||||
|
||||
utils::MemoryResource *GetMemoryResource() const { return ctx_->memory; }
|
||||
|
||||
#define UNSUCCESFUL_VISIT(expr_name) \
|
||||
TypedValue *Visit(expr_name &expr) override { return nullptr; }
|
||||
|
||||
TypedValue *Visit(Identifier &ident) override { return &frame_->at(symbol_table_->at(ident)); }
|
||||
|
||||
UNSUCCESFUL_VISIT(NamedExpression);
|
||||
UNSUCCESFUL_VISIT(OrOperator);
|
||||
UNSUCCESFUL_VISIT(XorOperator);
|
||||
UNSUCCESFUL_VISIT(AdditionOperator);
|
||||
UNSUCCESFUL_VISIT(SubtractionOperator);
|
||||
UNSUCCESFUL_VISIT(MultiplicationOperator);
|
||||
UNSUCCESFUL_VISIT(DivisionOperator);
|
||||
UNSUCCESFUL_VISIT(ModOperator);
|
||||
UNSUCCESFUL_VISIT(NotEqualOperator);
|
||||
UNSUCCESFUL_VISIT(EqualOperator);
|
||||
UNSUCCESFUL_VISIT(LessOperator);
|
||||
UNSUCCESFUL_VISIT(GreaterOperator);
|
||||
UNSUCCESFUL_VISIT(LessEqualOperator);
|
||||
UNSUCCESFUL_VISIT(GreaterEqualOperator);
|
||||
|
||||
UNSUCCESFUL_VISIT(NotOperator);
|
||||
UNSUCCESFUL_VISIT(UnaryPlusOperator);
|
||||
UNSUCCESFUL_VISIT(UnaryMinusOperator);
|
||||
|
||||
UNSUCCESFUL_VISIT(AndOperator);
|
||||
UNSUCCESFUL_VISIT(IfOperator);
|
||||
UNSUCCESFUL_VISIT(InListOperator);
|
||||
|
||||
UNSUCCESFUL_VISIT(SubscriptOperator);
|
||||
|
||||
UNSUCCESFUL_VISIT(ListSlicingOperator);
|
||||
UNSUCCESFUL_VISIT(IsNullOperator);
|
||||
UNSUCCESFUL_VISIT(PropertyLookup);
|
||||
UNSUCCESFUL_VISIT(LabelsTest);
|
||||
|
||||
UNSUCCESFUL_VISIT(PrimitiveLiteral);
|
||||
UNSUCCESFUL_VISIT(ListLiteral);
|
||||
UNSUCCESFUL_VISIT(MapLiteral);
|
||||
UNSUCCESFUL_VISIT(Aggregation);
|
||||
UNSUCCESFUL_VISIT(Coalesce);
|
||||
UNSUCCESFUL_VISIT(Function);
|
||||
UNSUCCESFUL_VISIT(Reduce);
|
||||
UNSUCCESFUL_VISIT(Extract);
|
||||
UNSUCCESFUL_VISIT(All);
|
||||
UNSUCCESFUL_VISIT(Single);
|
||||
UNSUCCESFUL_VISIT(Any);
|
||||
UNSUCCESFUL_VISIT(None);
|
||||
UNSUCCESFUL_VISIT(ParameterLookup);
|
||||
UNSUCCESFUL_VISIT(RegexMatch);
|
||||
|
||||
private:
|
||||
Frame *frame_;
|
||||
const SymbolTable *symbol_table_;
|
||||
const EvaluationContext *ctx_;
|
||||
DbAccessor *dba_;
|
||||
// which switching approach should be used when evaluating
|
||||
storage::View view_;
|
||||
};
|
||||
|
||||
class ExpressionEvaluator : public ExpressionVisitor<TypedValue> {
|
||||
public:
|
||||
ExpressionEvaluator(Frame *frame, const SymbolTable &symbol_table, const EvaluationContext &ctx, DbAccessor *dba,
|
||||
@@ -159,49 +231,61 @@ class ExpressionEvaluator : public ExpressionVisitor<TypedValue> {
|
||||
}
|
||||
|
||||
TypedValue Visit(SubscriptOperator &list_indexing) override {
|
||||
auto lhs = list_indexing.expression1_->Accept(*this);
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
|
||||
ReferenceExpressionEvaluator referenceExpressionEvaluator(frame_, symbol_table_, ctx_, dba_, view_);
|
||||
|
||||
auto *lhs = list_indexing.expression1_->Accept(referenceExpressionEvaluator);
|
||||
auto index = list_indexing.expression2_->Accept(*this);
|
||||
if (!lhs.IsList() && !lhs.IsMap() && !lhs.IsVertex() && !lhs.IsEdge() && !lhs.IsNull())
|
||||
if (!lhs->IsList() && !lhs->IsMap() && !lhs->IsVertex() && !lhs->IsEdge() && !lhs->IsNull())
|
||||
throw QueryRuntimeException(
|
||||
"Expected a list, a map, a node or an edge to index with '[]', got "
|
||||
"{}.",
|
||||
lhs.type());
|
||||
if (lhs.IsNull() || index.IsNull()) return TypedValue(ctx_->memory);
|
||||
if (lhs.IsList()) {
|
||||
lhs->type());
|
||||
if (lhs->IsNull() || index.IsNull()) return TypedValue(ctx_->memory);
|
||||
if (lhs->IsList()) {
|
||||
if (!index.IsInt()) throw QueryRuntimeException("Expected an integer as a list index, got {}.", index.type());
|
||||
auto index_int = index.ValueInt();
|
||||
// NOTE: Take non-const reference to list, so that we can move out the
|
||||
// indexed element as the result.
|
||||
auto &list = lhs.ValueList();
|
||||
const auto &list = lhs->ValueList();
|
||||
if (index_int < 0) {
|
||||
index_int += static_cast<int64_t>(list.size());
|
||||
}
|
||||
if (index_int >= static_cast<int64_t>(list.size()) || index_int < 0) return TypedValue(ctx_->memory);
|
||||
// NOTE: Explicit move is needed, so that we return the move constructed
|
||||
// value and preserve the correct MemoryResource.
|
||||
return std::move(list[index_int]);
|
||||
auto end = std::chrono::steady_clock::now();
|
||||
std::chrono::duration<double> dif = end - start;
|
||||
total2 += dif;
|
||||
|
||||
if (total2 > new_print2) {
|
||||
std::cout << "Time difference visit = " << total2.count() << "[s]" << std::endl;
|
||||
new_print2 += static_cast<std::chrono::duration<double>>(1.0);
|
||||
}
|
||||
return TypedValue(list[index_int]);
|
||||
}
|
||||
|
||||
if (lhs.IsMap()) {
|
||||
if (lhs->IsMap()) {
|
||||
if (!index.IsString()) throw QueryRuntimeException("Expected a string as a map index, got {}.", index.type());
|
||||
// NOTE: Take non-const reference to map, so that we can move out the
|
||||
// looked-up element as the result.
|
||||
auto &map = lhs.ValueMap();
|
||||
const auto &map = lhs->ValueMap();
|
||||
auto found = map.find(index.ValueString());
|
||||
if (found == map.end()) return TypedValue(ctx_->memory);
|
||||
// NOTE: Explicit move is needed, so that we return the move constructed
|
||||
// value and preserve the correct MemoryResource.
|
||||
return std::move(found->second);
|
||||
return TypedValue(found->second);
|
||||
}
|
||||
|
||||
if (lhs.IsVertex()) {
|
||||
if (lhs->IsVertex()) {
|
||||
if (!index.IsString()) throw QueryRuntimeException("Expected a string as a property name, got {}.", index.type());
|
||||
return TypedValue(GetProperty(lhs.ValueVertex(), index.ValueString()), ctx_->memory);
|
||||
return TypedValue(GetProperty(lhs->ValueVertex(), index.ValueString()), ctx_->memory);
|
||||
}
|
||||
|
||||
if (lhs.IsEdge()) {
|
||||
if (lhs->IsEdge()) {
|
||||
if (!index.IsString()) throw QueryRuntimeException("Expected a string as a property name, got {}.", index.type());
|
||||
return TypedValue(GetProperty(lhs.ValueEdge(), index.ValueString()), ctx_->memory);
|
||||
return TypedValue(GetProperty(lhs->ValueEdge(), index.ValueString()), ctx_->memory);
|
||||
}
|
||||
|
||||
// lhs is Null
|
||||
|
||||
@@ -155,6 +155,9 @@ uint64_t ComputeProfilingKey(const T *obj) {
|
||||
|
||||
#define SCOPED_PROFILE_OP(name) ScopedProfile profile{ComputeProfilingKey(this), name, &context};
|
||||
|
||||
std::chrono::duration<double> total;
|
||||
std::chrono::duration<double> new_print;
|
||||
|
||||
bool Once::OnceCursor::Pull(Frame &, ExecutionContext &context) {
|
||||
SCOPED_PROFILE_OP("Once");
|
||||
|
||||
@@ -208,6 +211,8 @@ VertexAccessor &CreateLocalVertex(const NodeCreationInfo &node_info, Frame *fram
|
||||
storage::View::NEW);
|
||||
// TODO: PropsSetChecked allocates a PropertyValue, make it use context.memory
|
||||
// when we update PropertyValue with custom allocator.
|
||||
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
if (const auto *node_info_properties = std::get_if<PropertiesMapList>(&node_info.properties)) {
|
||||
for (const auto &[key, value_expression] : *node_info_properties) {
|
||||
PropsSetChecked(&new_node, key, value_expression->Accept(evaluator));
|
||||
@@ -219,6 +224,14 @@ VertexAccessor &CreateLocalVertex(const NodeCreationInfo &node_info, Frame *fram
|
||||
PropsSetChecked(&new_node, property_id, value);
|
||||
}
|
||||
}
|
||||
auto end = std::chrono::steady_clock::now();
|
||||
std::chrono::duration<double> dif = end - start;
|
||||
total += dif;
|
||||
|
||||
if (total > new_print) {
|
||||
std::cout << "Time difference props set checked = " << total.count() << "[s]" << std::endl;
|
||||
new_print += static_cast<std::chrono::duration<double>>(10.0);
|
||||
}
|
||||
|
||||
(*frame)[node_info.symbol] = new_node;
|
||||
return (*frame)[node_info.symbol].ValueVertex();
|
||||
@@ -4580,19 +4593,17 @@ class LoadCsvCursor : public Cursor {
|
||||
// pulling MATCH).
|
||||
if (!input_is_once_ && !input_pulled) return false;
|
||||
|
||||
bool read_something = false;
|
||||
// read and parse each row
|
||||
while (auto row = reader_->GetNextRow(context.evaluation_context.memory)) {
|
||||
if (!reader_->HasHeader()) {
|
||||
frame[self_->row_var_] = CsvRowToTypedList(*row);
|
||||
} else {
|
||||
frame[self_->row_var_] =
|
||||
CsvRowToTypedMap(*row, csv::Reader::Header(reader_->GetHeader(), context.evaluation_context.memory));
|
||||
}
|
||||
read_something = true;
|
||||
auto row = reader_->GetNextRow(context.evaluation_context.memory);
|
||||
if (!row) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return read_something;
|
||||
if (!reader_->HasHeader()) {
|
||||
frame[self_->row_var_] = CsvRowToTypedList(*row);
|
||||
} else {
|
||||
frame[self_->row_var_] =
|
||||
CsvRowToTypedMap(*row, csv::Reader::Header(reader_->GetHeader(), context.evaluation_context.memory));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Reset() override { input_cursor_->Reset(); }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
// Copyright 2023 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -26,6 +26,9 @@
|
||||
|
||||
namespace memgraph::query {
|
||||
|
||||
std::chrono::duration<double> total;
|
||||
std::chrono::duration<double> new_print;
|
||||
|
||||
TypedValue::TypedValue(const storage::PropertyValue &value)
|
||||
// TODO: MemoryResource in storage::PropertyValue
|
||||
: TypedValue(value, utils::NewDeleteResource()) {}
|
||||
@@ -289,8 +292,18 @@ TypedValue::operator storage::PropertyValue() const {
|
||||
return storage::PropertyValue(int_v);
|
||||
case TypedValue::Type::Double:
|
||||
return storage::PropertyValue(double_v);
|
||||
case TypedValue::Type::String:
|
||||
return storage::PropertyValue(std::string(string_v));
|
||||
case TypedValue::Type::String: {
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
auto value = storage::PropertyValue(std::string(string_v));
|
||||
auto end = std::chrono::steady_clock::now();
|
||||
std::chrono::duration<double> dif = end - start;
|
||||
total += dif;
|
||||
if (total > new_print) {
|
||||
std::cout << "Time typed value difference = " << total.count() << "[s]" << std::endl;
|
||||
new_print += static_cast<std::chrono::duration<double>>(10.0);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
case TypedValue::Type::List:
|
||||
return storage::PropertyValue(std::vector<storage::PropertyValue>(list_v.begin(), list_v.end()));
|
||||
case TypedValue::Type::Map: {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
// Copyright 2023 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <chrono>
|
||||
#include "storage/v2/edge_accessor.hpp"
|
||||
#include "storage/v2/id_types.hpp"
|
||||
#include "storage/v2/indices.hpp"
|
||||
@@ -60,6 +61,9 @@ std::pair<bool, bool> IsVisible(Vertex *vertex, Transaction *transaction, View v
|
||||
} // namespace
|
||||
} // namespace detail
|
||||
|
||||
std::chrono::duration<double> total;
|
||||
std::chrono::duration<double> new_print;
|
||||
|
||||
std::optional<VertexAccessor> VertexAccessor::Create(Vertex *vertex, Transaction *transaction, Indices *indices,
|
||||
Constraints *constraints, Config::Items config, View view) {
|
||||
if (const auto [exists, deleted] = detail::IsVisible(vertex, transaction, view); !exists || deleted) {
|
||||
@@ -208,6 +212,8 @@ Result<std::vector<LabelId>> VertexAccessor::Labels(View view) const {
|
||||
}
|
||||
|
||||
Result<PropertyValue> VertexAccessor::SetProperty(PropertyId property, const PropertyValue &value) {
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
|
||||
utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception;
|
||||
std::lock_guard<utils::SpinLock> guard(vertex_->lock);
|
||||
|
||||
@@ -227,6 +233,15 @@ Result<PropertyValue> VertexAccessor::SetProperty(PropertyId property, const Pro
|
||||
|
||||
UpdateOnSetProperty(indices_, property, value, vertex_, *transaction_);
|
||||
|
||||
auto end = std::chrono::steady_clock::now();
|
||||
std::chrono::duration<double> dif = end - start;
|
||||
total += dif;
|
||||
|
||||
if (total > new_print) {
|
||||
std::cout << "Time difference = " << total.count() << "[s]" << std::endl;
|
||||
new_print += static_cast<std::chrono::duration<double>>(2.0);
|
||||
}
|
||||
|
||||
return std::move(current_value);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
// Copyright 2023 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
|
||||
Reference in New Issue
Block a user