Convert symbol.hpp to LCP
Summary: With quite frequent changes of serialization backend, it's getting really painful updating the C++ implementation. This diff defines the Symbol class via LCP, so that the C++ serialization is generated instead of written by hand. Reviewers: mtomic, llugovic Reviewed By: mtomic Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D1741
This commit is contained in:
parent
dd6fe013dc
commit
14c9044909
3
.gitignore
vendored
3
.gitignore
vendored
@ -82,6 +82,9 @@ src/durability/distributed/state_delta.capnp
|
||||
src/durability/distributed/state_delta.hpp
|
||||
src/durability/single_node/state_delta.hpp
|
||||
src/durability/single_node_ha/state_delta.hpp
|
||||
src/query/frontend/semantic/symbol.hpp
|
||||
src/query/frontend/semantic/symbol_serialization.capnp
|
||||
src/query/frontend/semantic/symbol_serialization.hpp
|
||||
src/query/plan/distributed_ops.capnp
|
||||
src/query/plan/distributed_ops.hpp
|
||||
src/query/plan/operator.hpp
|
||||
|
@ -56,6 +56,7 @@ define_add_lcp(add_lcp_single_node mg_single_node_sources generated_lcp_single_n
|
||||
|
||||
add_lcp_single_node(durability/single_node/state_delta.lcp)
|
||||
add_lcp_single_node(query/frontend/ast/ast.lcp)
|
||||
add_lcp_single_node(query/frontend/semantic/symbol.lcp)
|
||||
add_lcp_single_node(query/plan/operator.lcp)
|
||||
|
||||
add_custom_target(generate_lcp_single_node DEPENDS ${generated_lcp_single_node_files})
|
||||
@ -201,6 +202,9 @@ add_lcp_distributed(query/frontend/ast/ast.lcp)
|
||||
add_lcp_distributed(query/frontend/ast/ast_serialization.lcp CAPNP_SCHEMA @0xb107d3d6b4b1600b
|
||||
DEPENDS query/frontend/ast/ast.lcp)
|
||||
add_capnp_distributed(query/frontend/ast/ast_serialization.capnp)
|
||||
add_lcp_distributed(query/frontend/semantic/symbol.lcp)
|
||||
add_lcp_distributed(query/frontend/semantic/symbol_serialization.lcp CAPNP_SCHEMA @0x93c1dcee84e93b76
|
||||
DEPENDS query/frontend/semantic/symbol.lcp)
|
||||
add_lcp_distributed(query/plan/operator.lcp)
|
||||
add_lcp_distributed(query/plan/distributed_ops.lcp CAPNP_SCHEMA @0xe5cae8d045d30c42
|
||||
DEPENDS query/plan/operator.lcp)
|
||||
@ -218,7 +222,7 @@ add_custom_target(generate_lcp_distributed DEPENDS ${generated_lcp_distributed_f
|
||||
|
||||
add_capnp_distributed(communication/rpc/messages.capnp)
|
||||
add_capnp_distributed(durability/distributed/serialization.capnp)
|
||||
add_capnp_distributed(query/frontend/semantic/symbol.capnp)
|
||||
add_capnp_distributed(query/frontend/semantic/symbol_serialization.capnp)
|
||||
add_capnp_distributed(query/serialization.capnp)
|
||||
add_capnp_distributed(storage/distributed/rpc/serialization.capnp)
|
||||
|
||||
@ -292,6 +296,7 @@ add_lcp_single_node_ha(database/single_node_ha/serialization.lcp CAPNP_SCHEMA @0
|
||||
DEPENDS durability/single_node_ha/state_delta.lcp)
|
||||
add_capnp_single_node_ha(database/single_node_ha/serialization.capnp)
|
||||
add_lcp_single_node_ha(query/frontend/ast/ast.lcp)
|
||||
add_lcp_single_node_ha(query/frontend/semantic/symbol.lcp)
|
||||
add_lcp_single_node_ha(query/plan/operator.lcp)
|
||||
add_lcp_single_node_ha(raft/raft_rpc_messages.lcp CAPNP_SCHEMA @0xa6c29b4287233b66)
|
||||
add_capnp_single_node_ha(raft/raft_rpc_messages.capnp)
|
||||
|
@ -22,7 +22,6 @@ cpp<#
|
||||
(lcp:capnp-import 'dist-ops "/query/plan/distributed_ops.capnp")
|
||||
(lcp:capnp-import 'query "/query/serialization.capnp")
|
||||
(lcp:capnp-import 'storage "/storage/distributed/rpc/serialization.capnp")
|
||||
(lcp:capnp-import 'symbol "/query/frontend/semantic/symbol.capnp")
|
||||
(lcp:capnp-import 'utils "/utils/serialization.capnp")
|
||||
|
||||
(lcp:capnp-type-conversion "storage::EdgeAddress" "Storage.Address")
|
||||
@ -57,8 +56,7 @@ cpp<#
|
||||
std::vector<int> loaded_ast_uids;
|
||||
Load(&${member}, ${reader}, ast_storage, &loaded_ast_uids);
|
||||
cpp<#))
|
||||
(symbol-table "query::SymbolTable"
|
||||
:capnp-type "Symbol.SymbolTable")
|
||||
(symbol-table "query::SymbolTable" :capnp-type "Query.SymbolTable")
|
||||
(evaluation-context "query::EvaluationContext"
|
||||
:capnp-type "Query.EvaluationContext"
|
||||
:capnp-save (lambda (builder member capnp-name)
|
||||
|
@ -15,7 +15,7 @@ cpp<#
|
||||
|
||||
(lcp:capnp-import 'utils "/utils/serialization.capnp")
|
||||
(lcp:capnp-import 'plan "/query/plan/distributed_ops.capnp")
|
||||
(lcp:capnp-import 'sem "/query/frontend/semantic/symbol.capnp")
|
||||
(lcp:capnp-import 'query "/query/serialization.capnp")
|
||||
|
||||
(defun load-plan (reader member capnp-name)
|
||||
(declare (ignore capnp-name))
|
||||
@ -47,7 +47,7 @@ cpp<#
|
||||
(plan "std::shared_ptr<query::plan::LogicalOperator>"
|
||||
:capnp-type "Utils.SharedPtr(Plan.LogicalOperator)"
|
||||
:capnp-save #'save-plan :capnp-load #'load-plan)
|
||||
(symbol-table "query::SymbolTable" :capnp-type "Sem.SymbolTable")
|
||||
(symbol-table "query::SymbolTable" :capnp-type "Query.SymbolTable")
|
||||
(storage "query::AstStorage" :initarg nil :capnp-save :dont-save)))
|
||||
(:response ()))
|
||||
|
||||
|
@ -31,7 +31,7 @@ cpp<#
|
||||
|
||||
(lcp:capnp-import 'storage "/storage/distributed/rpc/serialization.capnp")
|
||||
(lcp:capnp-import 'query "/query/serialization.capnp")
|
||||
(lcp:capnp-import 'sem "/query/frontend/semantic/symbol.capnp")
|
||||
(lcp:capnp-import 'sem "/query/frontend/semantic/symbol_serialization.capnp")
|
||||
(lcp:capnp-import 'utils "/utils/serialization.capnp")
|
||||
|
||||
(lcp:capnp-type-conversion "tx::CommandId" "UInt32")
|
||||
|
@ -38,7 +38,7 @@ cpp<#
|
||||
(lcp:capnp-namespace "query")
|
||||
|
||||
(lcp:capnp-import 'storage "/storage/distributed/rpc/serialization.capnp")
|
||||
(lcp:capnp-import 'symbol "/query/frontend/semantic/symbol.capnp")
|
||||
(lcp:capnp-import 'symbol "/query/frontend/semantic/symbol_serialization.capnp")
|
||||
(lcp:capnp-import 'utils "/utils/serialization.capnp")
|
||||
|
||||
(lcp:capnp-type-conversion "PropertyValue" "Storage.PropertyValue")
|
||||
|
@ -1,31 +0,0 @@
|
||||
@0x93c1dcee84e93b76;
|
||||
|
||||
using Cxx = import "/capnp/c++.capnp";
|
||||
$Cxx.namespace("query::capnp");
|
||||
|
||||
struct Symbol {
|
||||
enum Type {
|
||||
any @0;
|
||||
vertex @1;
|
||||
edge @2;
|
||||
path @3;
|
||||
number @4;
|
||||
edgeList @5;
|
||||
}
|
||||
|
||||
name @0 :Text;
|
||||
position @1 :Int32;
|
||||
type @2 :Type;
|
||||
userDeclared @3 :Bool;
|
||||
tokenPosition @4 :Int32;
|
||||
}
|
||||
|
||||
struct SymbolTable {
|
||||
position @0 :Int32;
|
||||
table @1 :List(Entry);
|
||||
|
||||
struct Entry {
|
||||
key @0 :Int32;
|
||||
val @1 :Symbol;
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace query {
|
||||
|
||||
class Symbol {
|
||||
public:
|
||||
// This is similar to TypedValue::Type, but this has `Any` type.
|
||||
// TODO: Make a better Type structure which can store a generic List.
|
||||
enum class Type { Any, Vertex, Edge, Path, Number, EdgeList };
|
||||
|
||||
static std::string TypeToString(Type type) {
|
||||
const char *enum_string[] = {"Any", "Vertex", "Edge",
|
||||
"Path", "Number", "EdgeList"};
|
||||
return enum_string[static_cast<int>(type)];
|
||||
}
|
||||
|
||||
Symbol() {}
|
||||
Symbol(const std::string &name, int position, bool user_declared,
|
||||
Type type = Type::Any, int token_position = -1)
|
||||
: name_(name),
|
||||
position_(position),
|
||||
user_declared_(user_declared),
|
||||
type_(type),
|
||||
token_position_(token_position) {}
|
||||
|
||||
bool operator==(const Symbol &other) const {
|
||||
return position_ == other.position_ && name_ == other.name_ &&
|
||||
type_ == other.type_;
|
||||
}
|
||||
bool operator!=(const Symbol &other) const { return !operator==(other); }
|
||||
|
||||
// TODO: Remove these since members are public
|
||||
const auto &name() const { return name_; }
|
||||
int position() const { return position_; }
|
||||
Type type() const { return type_; }
|
||||
bool user_declared() const { return user_declared_; }
|
||||
int token_position() const { return token_position_; }
|
||||
|
||||
std::string name_;
|
||||
int position_;
|
||||
bool user_declared_ = true;
|
||||
Type type_ = Type::Any;
|
||||
int token_position_ = -1;
|
||||
};
|
||||
|
||||
} // namespace query
|
||||
|
||||
namespace std {
|
||||
|
||||
template <>
|
||||
struct hash<query::Symbol> {
|
||||
size_t operator()(const query::Symbol &symbol) const {
|
||||
size_t prime = 265443599u;
|
||||
size_t hash = std::hash<int>{}(symbol.position());
|
||||
hash ^= prime * std::hash<std::string>{}(symbol.name());
|
||||
hash ^= prime * std::hash<bool>{}(symbol.user_declared());
|
||||
hash ^= prime * std::hash<int>{}(static_cast<int>(symbol.type()));
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
77
src/query/frontend/semantic/symbol.lcp
Normal file
77
src/query/frontend/semantic/symbol.lcp
Normal file
@ -0,0 +1,77 @@
|
||||
#>cpp
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "utils/typeinfo.hpp"
|
||||
cpp<#
|
||||
|
||||
(lcp:namespace query)
|
||||
|
||||
(lcp:capnp-namespace "query")
|
||||
|
||||
(lcp:define-class symbol ()
|
||||
((name "std::string" :scope :public)
|
||||
(position :int64_t :scope :public)
|
||||
(user-declared :bool :initval "true" :scope :public)
|
||||
(type "Type" :initval "Type::ANY" :scope :public)
|
||||
(token-position :int64_t :initval "-1" :scope :public))
|
||||
(:public
|
||||
;; This is similar to TypedValue::Type, but this has `Any` type.
|
||||
;; TODO: Make a better Type structure which can store a generic List.
|
||||
(lcp:define-enum type (any vertex edge path number edge-list)
|
||||
(:serialize :capnp))
|
||||
#>cpp
|
||||
// TODO: Generate enum to string conversion from LCP. Note, that this is
|
||||
// displayed to the end user, so we may want to have a pretty name of each
|
||||
// value.
|
||||
static std::string TypeToString(Type type) {
|
||||
const char *enum_string[] = {"Any", "Vertex", "Edge",
|
||||
"Path", "Number", "EdgeList"};
|
||||
return enum_string[static_cast<int>(type)];
|
||||
}
|
||||
|
||||
Symbol() {}
|
||||
Symbol(const std::string &name, int position, bool user_declared,
|
||||
Type type = Type::ANY, int token_position = -1)
|
||||
: name_(name),
|
||||
position_(position),
|
||||
user_declared_(user_declared),
|
||||
type_(type),
|
||||
token_position_(token_position) {}
|
||||
|
||||
bool operator==(const Symbol &other) const {
|
||||
return position_ == other.position_ && name_ == other.name_ &&
|
||||
type_ == other.type_;
|
||||
}
|
||||
bool operator!=(const Symbol &other) const { return !operator==(other); }
|
||||
|
||||
// TODO: Remove these since members are public
|
||||
const auto &name() const { return name_; }
|
||||
int position() const { return position_; }
|
||||
Type type() const { return type_; }
|
||||
bool user_declared() const { return user_declared_; }
|
||||
int token_position() const { return token_position_; }
|
||||
cpp<#)
|
||||
(:serialize :capnp))
|
||||
|
||||
(lcp:pop-namespace) ;; query
|
||||
|
||||
#>cpp
|
||||
namespace std {
|
||||
|
||||
template <>
|
||||
struct hash<query::Symbol> {
|
||||
size_t operator()(const query::Symbol &symbol) const {
|
||||
size_t prime = 265443599u;
|
||||
size_t hash = std::hash<int>{}(symbol.position());
|
||||
hash ^= prime * std::hash<std::string>{}(symbol.name());
|
||||
hash ^= prime * std::hash<bool>{}(symbol.user_declared());
|
||||
hash ^= prime * std::hash<int>{}(static_cast<int>(symbol.type()));
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
cpp<#
|
@ -26,8 +26,8 @@ auto SymbolGenerator::GetOrCreateSymbol(const std::string &name,
|
||||
auto search = scope_.symbols.find(name);
|
||||
if (search != scope_.symbols.end()) {
|
||||
auto symbol = search->second;
|
||||
// Unless we have `Any` type, check that types match.
|
||||
if (type != Symbol::Type::Any && symbol.type() != Symbol::Type::Any &&
|
||||
// Unless we have `ANY` type, check that types match.
|
||||
if (type != Symbol::Type::ANY && symbol.type() != Symbol::Type::ANY &&
|
||||
type != symbol.type()) {
|
||||
throw TypeMismatchError(name, Symbol::TypeToString(symbol.type()),
|
||||
Symbol::TypeToString(type));
|
||||
@ -79,7 +79,7 @@ void SymbolGenerator::VisitReturnBody(ReturnBody &body, Where *where) {
|
||||
}
|
||||
// An improvement would be to infer the type of the expression, so that the
|
||||
// new symbol would have a more specific type.
|
||||
symbol_table_[*named_expr] = CreateSymbol(name, true, Symbol::Type::Any,
|
||||
symbol_table_[*named_expr] = CreateSymbol(name, true, Symbol::Type::ANY,
|
||||
named_expr->token_position_);
|
||||
}
|
||||
scope_.in_order_by = true;
|
||||
@ -230,7 +230,7 @@ SymbolGenerator::ReturnType SymbolGenerator::Visit(Identifier &ident) {
|
||||
// If we are in the pattern, and outside of a node or an edge, the
|
||||
// identifier is the pattern name.
|
||||
symbol = GetOrCreateSymbol(ident.name_, ident.user_declared_,
|
||||
Symbol::Type::Path);
|
||||
Symbol::Type::PATH);
|
||||
} else if (scope_.in_pattern && scope_.in_pattern_atom_identifier) {
|
||||
// Patterns used to create nodes and edges cannot redeclare already
|
||||
// established bindings. Declaration only happens in single node
|
||||
@ -242,15 +242,15 @@ SymbolGenerator::ReturnType SymbolGenerator::Visit(Identifier &ident) {
|
||||
HasSymbol(ident.name_)) {
|
||||
throw RedeclareVariableError(ident.name_);
|
||||
}
|
||||
auto type = Symbol::Type::Vertex;
|
||||
auto type = Symbol::Type::VERTEX;
|
||||
if (scope_.visiting_edge) {
|
||||
// Edge referencing is not allowed (like in Neo4j):
|
||||
// `MATCH (n) - [r] -> (n) - [r] -> (n) RETURN r` is not allowed.
|
||||
if (HasSymbol(ident.name_)) {
|
||||
throw RedeclareVariableError(ident.name_);
|
||||
}
|
||||
type = scope_.visiting_edge->IsVariable() ? Symbol::Type::EdgeList
|
||||
: Symbol::Type::Edge;
|
||||
type = scope_.visiting_edge->IsVariable() ? Symbol::Type::EDGE_LIST
|
||||
: Symbol::Type::EDGE;
|
||||
}
|
||||
symbol = GetOrCreateSymbol(ident.name_, ident.user_declared_, type);
|
||||
} else if (scope_.in_pattern && !scope_.in_pattern_atom_identifier &&
|
||||
@ -304,7 +304,7 @@ bool SymbolGenerator::PreVisit(Aggregation &aggr) {
|
||||
auto aggr_name =
|
||||
Aggregation::OpToString(aggr.op_) + std::to_string(aggr.uid_);
|
||||
symbol_table_[aggr] =
|
||||
symbol_table_.CreateSymbol(aggr_name, false, Symbol::Type::Number);
|
||||
symbol_table_.CreateSymbol(aggr_name, false, Symbol::Type::NUMBER);
|
||||
scope_.in_aggregation = true;
|
||||
scope_.has_aggregation = true;
|
||||
return true;
|
||||
@ -437,10 +437,10 @@ bool SymbolGenerator::PreVisit(EdgeAtom &edge_atom) {
|
||||
// be used in the missing filter expression.
|
||||
const auto *inner_edge = edge_atom.filter_lambda_.inner_edge;
|
||||
symbol_table_[*inner_edge] = symbol_table_.CreateSymbol(
|
||||
inner_edge->name_, inner_edge->user_declared_, Symbol::Type::Edge);
|
||||
inner_edge->name_, inner_edge->user_declared_, Symbol::Type::EDGE);
|
||||
const auto *inner_node = edge_atom.filter_lambda_.inner_node;
|
||||
symbol_table_[*inner_node] = symbol_table_.CreateSymbol(
|
||||
inner_node->name_, inner_node->user_declared_, Symbol::Type::Vertex);
|
||||
inner_node->name_, inner_node->user_declared_, Symbol::Type::VERTEX);
|
||||
}
|
||||
if (edge_atom.weight_lambda_.expression) {
|
||||
VisitWithIdentifiers(edge_atom.weight_lambda_.expression,
|
||||
@ -458,7 +458,7 @@ bool SymbolGenerator::PreVisit(EdgeAtom &edge_atom) {
|
||||
}
|
||||
symbol_table_[*edge_atom.total_weight_] = GetOrCreateSymbol(
|
||||
edge_atom.total_weight_->name_, edge_atom.total_weight_->user_declared_,
|
||||
Symbol::Type::Number);
|
||||
Symbol::Type::NUMBER);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -114,13 +114,13 @@ class SymbolGenerator : public HierarchicalTreeVisitor {
|
||||
// Returns a freshly generated symbol. Previous mapping of the same name to a
|
||||
// different symbol is replaced with the new one.
|
||||
auto CreateSymbol(const std::string &name, bool user_declared,
|
||||
Symbol::Type type = Symbol::Type::Any,
|
||||
Symbol::Type type = Symbol::Type::ANY,
|
||||
int token_position = -1);
|
||||
|
||||
// Returns the symbol by name. If the mapping already exists, checks if the
|
||||
// types match. Otherwise, returns a new symbol.
|
||||
auto GetOrCreateSymbol(const std::string &name, bool user_declared,
|
||||
Symbol::Type type = Symbol::Type::Any);
|
||||
Symbol::Type type = Symbol::Type::ANY);
|
||||
|
||||
void VisitReturnBody(ReturnBody &body, Where *where = nullptr);
|
||||
|
||||
|
11
src/query/frontend/semantic/symbol_serialization.lcp
Normal file
11
src/query/frontend/semantic/symbol_serialization.lcp
Normal file
@ -0,0 +1,11 @@
|
||||
#>cpp
|
||||
#pragma once
|
||||
|
||||
#include "query/frontend/semantic/symbol.hpp"
|
||||
#include "query/frontend/semantic/symbol_serialization.capnp.h"
|
||||
cpp<#
|
||||
|
||||
;; Generate serialization code
|
||||
;; TODO: This should be merged with query/serialization
|
||||
(load "query/frontend/semantic/symbol.lcp")
|
||||
|
@ -12,7 +12,7 @@ class SymbolTable final {
|
||||
public:
|
||||
SymbolTable() {}
|
||||
Symbol CreateSymbol(const std::string &name, bool user_declared,
|
||||
Symbol::Type type = Symbol::Type::Any,
|
||||
Symbol::Type type = Symbol::Type::ANY,
|
||||
int token_position = -1) {
|
||||
int position = position_++;
|
||||
return Symbol(name, position, user_declared, type, token_position);
|
||||
|
@ -1279,7 +1279,7 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor {
|
||||
std::to_string(worker_ident->uid_) + "<-" +
|
||||
worker_sym.name();
|
||||
auto merge_sym = distributed_plan_.symbol_table.CreateSymbol(
|
||||
merge_name, false, Symbol::Type::Number);
|
||||
merge_name, false, Symbol::Type::NUMBER);
|
||||
return Aggregate::Element{worker_ident, nullptr, op, merge_sym};
|
||||
};
|
||||
// Aggregate uses associative operation(s), so split the work across master
|
||||
@ -1320,12 +1320,12 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor {
|
||||
// * master: SUM(worker_sum) / toFloat(SUM(worker_count)) AS avg
|
||||
case Aggregation::Op::AVG: {
|
||||
auto worker_sum_sym = distributed_plan_.symbol_table.CreateSymbol(
|
||||
aggr.output_sym.name() + "_SUM", false, Symbol::Type::Number);
|
||||
aggr.output_sym.name() + "_SUM", false, Symbol::Type::NUMBER);
|
||||
Aggregate::Element worker_sum{aggr.value, aggr.key,
|
||||
Aggregation::Op::SUM, worker_sum_sym};
|
||||
worker_aggrs.emplace_back(worker_sum);
|
||||
auto worker_count_sym = distributed_plan_.symbol_table.CreateSymbol(
|
||||
aggr.output_sym.name() + "_COUNT", false, Symbol::Type::Number);
|
||||
aggr.output_sym.name() + "_COUNT", false, Symbol::Type::NUMBER);
|
||||
Aggregate::Element worker_count{
|
||||
aggr.value, aggr.key, Aggregation::Op::COUNT, worker_count_sym};
|
||||
worker_aggrs.emplace_back(worker_count);
|
||||
|
@ -126,7 +126,7 @@ cpp<#
|
||||
(lcp:capnp-import 'utils "/utils/serialization.capnp")
|
||||
(lcp:capnp-import 'storage "/storage/distributed/rpc/serialization.capnp")
|
||||
(lcp:capnp-import 'ast "/query/frontend/ast/ast_serialization.capnp")
|
||||
(lcp:capnp-import 'semantic "/query/frontend/semantic/symbol.capnp")
|
||||
(lcp:capnp-import 'semantic "/query/frontend/semantic/symbol_serialization.capnp")
|
||||
(lcp:capnp-import 'query "/query/serialization.capnp")
|
||||
|
||||
(lcp:capnp-type-conversion "Symbol" "Semantic.Symbol")
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
using Ast = import "/query/frontend/ast/ast_serialization.capnp";
|
||||
using Cxx = import "/capnp/c++.capnp";
|
||||
using Sem = import "/query/frontend/semantic/symbol_serialization.capnp";
|
||||
using Storage = import "/storage/distributed/rpc/serialization.capnp";
|
||||
using Utils = import "/utils/serialization.capnp";
|
||||
|
||||
@ -45,3 +46,13 @@ struct TypedValue {
|
||||
edges @1 :List(Storage.EdgeAccessor);
|
||||
}
|
||||
}
|
||||
|
||||
struct SymbolTable {
|
||||
position @0 :Int32;
|
||||
table @1 :List(Entry);
|
||||
|
||||
struct Entry {
|
||||
key @0 :Int32;
|
||||
val @1 :Sem.Symbol;
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,7 @@
|
||||
|
||||
#include "query/common.hpp"
|
||||
#include "query/context.hpp"
|
||||
#include "query/frontend/semantic/symbol.capnp.h"
|
||||
#include "query/frontend/semantic/symbol.hpp"
|
||||
#include "query/frontend/semantic/symbol_serialization.hpp"
|
||||
#include "query/frontend/semantic/symbol_table.hpp"
|
||||
#include "query/serialization.capnp.h"
|
||||
#include "query/typed_value.hpp"
|
||||
@ -36,60 +35,6 @@ void Save(const TypedValueVectorCompare &comparator,
|
||||
void Load(TypedValueVectorCompare *comparator,
|
||||
const capnp::TypedValueVectorCompare::Reader &reader);
|
||||
|
||||
inline void Save(const Symbol &symbol, capnp::Symbol::Builder *builder) {
|
||||
builder->setName(symbol.name());
|
||||
builder->setPosition(symbol.position());
|
||||
builder->setUserDeclared(symbol.user_declared());
|
||||
builder->setTokenPosition(symbol.token_position());
|
||||
switch (symbol.type()) {
|
||||
case Symbol::Type::Any:
|
||||
builder->setType(capnp::Symbol::Type::ANY);
|
||||
break;
|
||||
case Symbol::Type::Edge:
|
||||
builder->setType(capnp::Symbol::Type::EDGE);
|
||||
break;
|
||||
case Symbol::Type::EdgeList:
|
||||
builder->setType(capnp::Symbol::Type::EDGE_LIST);
|
||||
break;
|
||||
case Symbol::Type::Number:
|
||||
builder->setType(capnp::Symbol::Type::NUMBER);
|
||||
break;
|
||||
case Symbol::Type::Path:
|
||||
builder->setType(capnp::Symbol::Type::PATH);
|
||||
break;
|
||||
case Symbol::Type::Vertex:
|
||||
builder->setType(capnp::Symbol::Type::VERTEX);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline void Load(Symbol *symbol, const capnp::Symbol::Reader &reader) {
|
||||
symbol->name_ = reader.getName();
|
||||
symbol->position_ = reader.getPosition();
|
||||
symbol->user_declared_ = reader.getUserDeclared();
|
||||
symbol->token_position_ = reader.getTokenPosition();
|
||||
switch (reader.getType()) {
|
||||
case capnp::Symbol::Type::ANY:
|
||||
symbol->type_ = Symbol::Type::Any;
|
||||
break;
|
||||
case capnp::Symbol::Type::EDGE:
|
||||
symbol->type_ = Symbol::Type::Edge;
|
||||
break;
|
||||
case capnp::Symbol::Type::EDGE_LIST:
|
||||
symbol->type_ = Symbol::Type::EdgeList;
|
||||
break;
|
||||
case capnp::Symbol::Type::NUMBER:
|
||||
symbol->type_ = Symbol::Type::Number;
|
||||
break;
|
||||
case capnp::Symbol::Type::PATH:
|
||||
symbol->type_ = Symbol::Type::Path;
|
||||
break;
|
||||
case capnp::Symbol::Type::VERTEX:
|
||||
symbol->type_ = Symbol::Type::Vertex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline void Save(const SymbolTable &symbol_table,
|
||||
capnp::SymbolTable::Builder *builder) {
|
||||
builder->setPosition(symbol_table.max_position());
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <capnp/serialize.h>
|
||||
#include <kj/std/iostream.h>
|
||||
|
||||
#include "query/frontend/semantic/symbol.capnp.h"
|
||||
#include "query/frontend/semantic/symbol_serialization.capnp.h"
|
||||
#include "query/frontend/semantic/symbol.hpp"
|
||||
|
||||
#include "communication/rpc/serialization.hpp"
|
||||
@ -17,8 +17,8 @@ class SymbolVectorFixture : public benchmark::Fixture {
|
||||
|
||||
void SetUp(const benchmark::State &state) override {
|
||||
using Type = ::query::Symbol::Type;
|
||||
std::vector<Type> types{Type::Any, Type::Vertex, Type::Edge,
|
||||
Type::Path, Type::Number, Type::EdgeList};
|
||||
std::vector<Type> types{Type::ANY, Type::VERTEX, Type::EDGE,
|
||||
Type::PATH, Type::NUMBER, Type::EDGE_LIST};
|
||||
symbols_.reserve(state.range(0));
|
||||
for (int i = 0; i < state.range(0); ++i) {
|
||||
std::string name = "Symbol " + std::to_string(i);
|
||||
@ -80,7 +80,7 @@ BENCHMARK_DEFINE_F(SymbolVectorFixture, CapnpDeserial)
|
||||
symbols.reserve(symbols_reader.size());
|
||||
for (const auto &sym : symbols_reader) {
|
||||
symbols.emplace_back(sym.getName().cStr(), sym.getPosition(),
|
||||
sym.getUserDeclared(), query::Symbol::Type::Any,
|
||||
sym.getUserDeclared(), query::Symbol::Type::ANY,
|
||||
sym.getTokenPosition());
|
||||
}
|
||||
}
|
||||
@ -99,17 +99,17 @@ BENCHMARK_REGISTER_F(SymbolVectorFixture, CapnpDeserial)
|
||||
|
||||
uint8_t Type2Int(query::Symbol::Type type) {
|
||||
switch (type) {
|
||||
case query::Symbol::Type::Any:
|
||||
case query::Symbol::Type::ANY:
|
||||
return 1;
|
||||
case query::Symbol::Type::Vertex:
|
||||
case query::Symbol::Type::VERTEX:
|
||||
return 2;
|
||||
case query::Symbol::Type::Edge:
|
||||
case query::Symbol::Type::EDGE:
|
||||
return 3;
|
||||
case query::Symbol::Type::Path:
|
||||
case query::Symbol::Type::PATH:
|
||||
return 4;
|
||||
case query::Symbol::Type::Number:
|
||||
case query::Symbol::Type::NUMBER:
|
||||
return 5;
|
||||
case query::Symbol::Type::EdgeList:
|
||||
case query::Symbol::Type::EDGE_LIST:
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
@ -117,17 +117,17 @@ uint8_t Type2Int(query::Symbol::Type type) {
|
||||
query::Symbol::Type Int2Type(uint8_t value) {
|
||||
switch (value) {
|
||||
case 1:
|
||||
return query::Symbol::Type::Any;
|
||||
return query::Symbol::Type::ANY;
|
||||
case 2:
|
||||
return query::Symbol::Type::Vertex;
|
||||
return query::Symbol::Type::VERTEX;
|
||||
case 3:
|
||||
return query::Symbol::Type::Edge;
|
||||
return query::Symbol::Type::EDGE;
|
||||
case 4:
|
||||
return query::Symbol::Type::Path;
|
||||
return query::Symbol::Type::PATH;
|
||||
case 5:
|
||||
return query::Symbol::Type::Number;
|
||||
return query::Symbol::Type::NUMBER;
|
||||
case 6:
|
||||
return query::Symbol::Type::EdgeList;
|
||||
return query::Symbol::Type::EDGE_LIST;
|
||||
}
|
||||
CHECK(false);
|
||||
}
|
||||
|
@ -1996,9 +1996,9 @@ TYPED_TEST(TestPlanner, DistributedOptionalScanExpandExisting) {
|
||||
|
||||
TEST(CapnpSerial, Union) {
|
||||
std::vector<Symbol> left_symbols{
|
||||
Symbol("symbol", 1, true, Symbol::Type::Edge)};
|
||||
Symbol("symbol", 1, true, Symbol::Type::EDGE)};
|
||||
std::vector<Symbol> right_symbols{
|
||||
Symbol("symbol", 3, true, Symbol::Type::Any)};
|
||||
Symbol("symbol", 3, true, Symbol::Type::ANY)};
|
||||
auto union_symbols = right_symbols;
|
||||
auto union_op = std::make_unique<Union>(nullptr, nullptr, union_symbols,
|
||||
left_symbols, right_symbols);
|
||||
@ -2020,9 +2020,9 @@ TEST(CapnpSerial, Union) {
|
||||
|
||||
TEST(CapnpSerial, Cartesian) {
|
||||
std::vector<Symbol> left_symbols{
|
||||
Symbol("left_symbol", 1, true, Symbol::Type::Edge)};
|
||||
Symbol("left_symbol", 1, true, Symbol::Type::EDGE)};
|
||||
std::vector<Symbol> right_symbols{
|
||||
Symbol("right_symbol", 3, true, Symbol::Type::Any)};
|
||||
Symbol("right_symbol", 3, true, Symbol::Type::ANY)};
|
||||
auto cartesian = std::make_unique<Cartesian>(nullptr, left_symbols, nullptr,
|
||||
right_symbols);
|
||||
std::unique_ptr<LogicalOperator> loaded_plan;
|
||||
@ -2057,7 +2057,7 @@ TEST(CapnpSerial, Synchronize) {
|
||||
}
|
||||
|
||||
TEST(CapnpSerial, PullRemote) {
|
||||
std::vector<Symbol> symbols{Symbol("symbol", 1, true, Symbol::Type::Edge)};
|
||||
std::vector<Symbol> symbols{Symbol("symbol", 1, true, Symbol::Type::EDGE)};
|
||||
auto pull_remote = std::make_unique<PullRemote>(nullptr, 42, symbols);
|
||||
std::unique_ptr<LogicalOperator> loaded_plan;
|
||||
::capnp::MallocMessageBuilder message;
|
||||
@ -2077,7 +2077,7 @@ TEST(CapnpSerial, PullRemoteOrderBy) {
|
||||
auto once = std::make_shared<Once>();
|
||||
AstStorage storage;
|
||||
std::vector<Symbol> symbols{
|
||||
Symbol("my_symbol", 2, true, Symbol::Type::Vertex, 3)};
|
||||
Symbol("my_symbol", 2, true, Symbol::Type::VERTEX, 3)};
|
||||
std::vector<query::SortItem> order_by{
|
||||
{query::Ordering::ASC, IDENT("my_symbol")}};
|
||||
auto pull_remote_order_by =
|
||||
|
@ -799,7 +799,7 @@ TEST_F(QueryPlanExpandVariable, NamedPath) {
|
||||
};
|
||||
|
||||
auto path_symbol =
|
||||
symbol_table.CreateSymbol("path", true, Symbol::Type::Path);
|
||||
symbol_table.CreateSymbol("path", true, Symbol::Type::PATH);
|
||||
auto create_path = std::make_shared<ConstructNamedPath>(
|
||||
expand, path_symbol,
|
||||
std::vector<Symbol>{find_symbol("n"), e, find_symbol("m")});
|
||||
|
@ -31,12 +31,12 @@ TEST_F(TestSymbolGenerator, MatchNodeReturn) {
|
||||
auto match = dynamic_cast<Match *>(query_ast->single_query_->clauses_[0]);
|
||||
auto pattern = match->patterns_[0];
|
||||
auto pattern_sym = symbol_table[*pattern->identifier_];
|
||||
EXPECT_EQ(pattern_sym.type(), Symbol::Type::Path);
|
||||
EXPECT_EQ(pattern_sym.type(), Symbol::Type::PATH);
|
||||
EXPECT_FALSE(pattern_sym.user_declared());
|
||||
auto node_atom = dynamic_cast<NodeAtom *>(pattern->atoms_[0]);
|
||||
auto node_sym = symbol_table[*node_atom->identifier_];
|
||||
EXPECT_EQ(node_sym.name(), "node_atom_1");
|
||||
EXPECT_EQ(node_sym.type(), Symbol::Type::Vertex);
|
||||
EXPECT_EQ(node_sym.type(), Symbol::Type::VERTEX);
|
||||
auto ret = dynamic_cast<Return *>(query_ast->single_query_->clauses_[1]);
|
||||
auto named_expr = ret->body_.named_expressions[0];
|
||||
auto column_sym = symbol_table[*named_expr];
|
||||
@ -56,7 +56,7 @@ TEST_F(TestSymbolGenerator, MatchNamedPattern) {
|
||||
auto match = dynamic_cast<Match *>(query_ast->single_query_->clauses_[0]);
|
||||
auto pattern = match->patterns_[0];
|
||||
auto pattern_sym = symbol_table[*pattern->identifier_];
|
||||
EXPECT_EQ(pattern_sym.type(), Symbol::Type::Path);
|
||||
EXPECT_EQ(pattern_sym.type(), Symbol::Type::PATH);
|
||||
EXPECT_EQ(pattern_sym.name(), "p");
|
||||
EXPECT_TRUE(pattern_sym.user_declared());
|
||||
}
|
||||
@ -95,7 +95,7 @@ TEST_F(TestSymbolGenerator, CreateNodeReturn) {
|
||||
auto node_atom = dynamic_cast<NodeAtom *>(pattern->atoms_[0]);
|
||||
auto node_sym = symbol_table[*node_atom->identifier_];
|
||||
EXPECT_EQ(node_sym.name(), "n");
|
||||
EXPECT_EQ(node_sym.type(), Symbol::Type::Vertex);
|
||||
EXPECT_EQ(node_sym.type(), Symbol::Type::VERTEX);
|
||||
auto ret = dynamic_cast<Return *>(query_ast->single_query_->clauses_[1]);
|
||||
auto named_expr = ret->body_.named_expressions[0];
|
||||
auto column_sym = symbol_table[*named_expr];
|
||||
@ -195,7 +195,7 @@ TEST_F(TestSymbolGenerator, CreateDelete) {
|
||||
EXPECT_EQ(symbol_table.max_position(), 2);
|
||||
auto node_symbol = symbol_table.at(*node->identifier_);
|
||||
auto ident_symbol = symbol_table.at(*ident);
|
||||
EXPECT_EQ(node_symbol.type(), Symbol::Type::Vertex);
|
||||
EXPECT_EQ(node_symbol.type(), Symbol::Type::VERTEX);
|
||||
EXPECT_EQ(node_symbol, ident_symbol);
|
||||
}
|
||||
|
||||
@ -286,18 +286,18 @@ TEST_F(TestSymbolGenerator, CreateMultiExpand) {
|
||||
auto n1 = symbol_table.at(*node_n1->identifier_);
|
||||
auto n2 = symbol_table.at(*node_n2->identifier_);
|
||||
EXPECT_EQ(n1, n2);
|
||||
EXPECT_EQ(n1.type(), Symbol::Type::Vertex);
|
||||
EXPECT_EQ(n1.type(), Symbol::Type::VERTEX);
|
||||
auto m = symbol_table.at(*node_m->identifier_);
|
||||
EXPECT_EQ(m.type(), Symbol::Type::Vertex);
|
||||
EXPECT_EQ(m.type(), Symbol::Type::VERTEX);
|
||||
EXPECT_NE(m, n1);
|
||||
auto l = symbol_table.at(*node_l->identifier_);
|
||||
EXPECT_EQ(l.type(), Symbol::Type::Vertex);
|
||||
EXPECT_EQ(l.type(), Symbol::Type::VERTEX);
|
||||
EXPECT_NE(l, n1);
|
||||
EXPECT_NE(l, m);
|
||||
auto r = symbol_table.at(*edge_r->identifier_);
|
||||
auto p = symbol_table.at(*edge_p->identifier_);
|
||||
EXPECT_EQ(r.type(), Symbol::Type::Edge);
|
||||
EXPECT_EQ(p.type(), Symbol::Type::Edge);
|
||||
EXPECT_EQ(r.type(), Symbol::Type::EDGE);
|
||||
EXPECT_EQ(p.type(), Symbol::Type::EDGE);
|
||||
EXPECT_NE(r, p);
|
||||
}
|
||||
|
||||
@ -408,11 +408,11 @@ TEST_F(TestSymbolGenerator, MatchWithCreate) {
|
||||
// symbols: pattern * 2, `n`, `m`, `r`
|
||||
EXPECT_EQ(symbol_table.max_position(), 5);
|
||||
auto n = symbol_table.at(*node_1->identifier_);
|
||||
EXPECT_EQ(n.type(), Symbol::Type::Vertex);
|
||||
EXPECT_EQ(n.type(), Symbol::Type::VERTEX);
|
||||
auto m = symbol_table.at(*node_2->identifier_);
|
||||
EXPECT_NE(n, m);
|
||||
// Currently we don't infer expression types, so we lost true type of 'm'.
|
||||
EXPECT_EQ(m.type(), Symbol::Type::Any);
|
||||
EXPECT_EQ(m.type(), Symbol::Type::ANY);
|
||||
EXPECT_EQ(m, symbol_table.at(*node_3->identifier_));
|
||||
}
|
||||
|
||||
@ -703,7 +703,7 @@ TEST_F(TestSymbolGenerator, MatchVariablePathUsingIdentifier) {
|
||||
auto l = symbol_table.at(*node_l->identifier_);
|
||||
EXPECT_EQ(l, symbol_table.at(*l_prop->expression_));
|
||||
auto r = symbol_table.at(*edge->identifier_);
|
||||
EXPECT_EQ(r.type(), Symbol::Type::EdgeList);
|
||||
EXPECT_EQ(r.type(), Symbol::Type::EDGE_LIST);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MatchVariablePathUsingUnboundIdentifier) {
|
||||
|
Loading…
Reference in New Issue
Block a user