Basic CREATE query works (e.g. CREATE (n {age:25, name:"test"}) RETURN n)
This commit is contained in:
parent
99a0fcd8e3
commit
d77800b2f9
@ -3,6 +3,11 @@
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <dlfcn.h>
|
||||
#include <atomic>
|
||||
|
||||
#include <iostream>
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
template<typename T>
|
||||
class DynamicLib
|
||||
@ -10,26 +15,25 @@ class DynamicLib
|
||||
private:
|
||||
using produce_t = typename T::produce;
|
||||
using destruct_t = typename T::destruct;
|
||||
std::atomic<uint8_t> counter;
|
||||
|
||||
public:
|
||||
produce_t produce_method;
|
||||
destruct_t destruct_method;
|
||||
|
||||
DynamicLib(const std::string& lib_path) :
|
||||
lib_path(lib_path)
|
||||
lib_path(lib_path),
|
||||
lib_object(nullptr)
|
||||
{
|
||||
load();
|
||||
}
|
||||
|
||||
// TODO debug why this doesn't work
|
||||
typename T::lib_object* instance()
|
||||
{
|
||||
// TODO singleton, lazy, concurrency
|
||||
// ifs are uncommented -> SEGMENTATION FAULT
|
||||
// TODO debug
|
||||
// if (dynamic_lib == nullptr)
|
||||
this->load();
|
||||
// if (dynamic_lib == nullptr)
|
||||
// TODO singleton, concurrency
|
||||
if (lib_object == nullptr) {
|
||||
lib_object = this->produce_method();
|
||||
}
|
||||
return lib_object;
|
||||
}
|
||||
|
||||
@ -50,7 +54,7 @@ public:
|
||||
private:
|
||||
std::string lib_path;
|
||||
void *dynamic_lib;
|
||||
typename T::lib_object* lib_object;
|
||||
typename T::lib_object *lib_object;
|
||||
|
||||
void load_lib()
|
||||
{
|
||||
|
@ -7,15 +7,17 @@
|
||||
class CodeCompiler
|
||||
{
|
||||
public:
|
||||
|
||||
void compile(const std::string& in_file, const std::string& out_file)
|
||||
{
|
||||
auto compile_command = utils::prints(
|
||||
"clang++",
|
||||
"-std=c++1y",
|
||||
in_file,
|
||||
"-o", out_file,
|
||||
"-I../",
|
||||
"-shared -fPIC"
|
||||
// "-std=c++1y -O2 -DNDEBUG", // compile flags
|
||||
"-std=c++1y", // compile flags
|
||||
in_file, // input file
|
||||
"-o", out_file, // ouput file
|
||||
"-I../", // include paths
|
||||
"-shared -fPIC" // shared library flags
|
||||
);
|
||||
|
||||
// synchronous call
|
||||
|
@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "i_code_cpu.hpp"
|
||||
#include "database/db.hpp"
|
||||
#include "utils/log/logger.hpp"
|
||||
|
||||
// preparations before execution
|
||||
// execution
|
||||
// postprocess the results
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
class CodeExecutor
|
||||
{
|
||||
public:
|
||||
void execute(ICodeCPU *code_cpu)
|
||||
{
|
||||
auto result = code_cpu->run(db);
|
||||
cout << result->result << endl;
|
||||
}
|
||||
|
||||
private:
|
||||
Db db;
|
||||
};
|
@ -10,19 +10,6 @@ using std::string;
|
||||
class CodeGenerator
|
||||
{
|
||||
public:
|
||||
void generate_hpp(const uint64_t stripped_hash, const std::string& path)
|
||||
{
|
||||
string template_path = CONFIG(config::TEMPLATE_CPU_HPP_PATH);
|
||||
string template_file = utils::read_file(template_path.c_str());
|
||||
string generated = template_engine.render(
|
||||
template_file,
|
||||
{
|
||||
{"stripped_hash", std::to_string(stripped_hash)},
|
||||
{"data_type", "int"}
|
||||
}
|
||||
);
|
||||
utils::write_file(generated, path);
|
||||
}
|
||||
|
||||
void generate_cpp(const std::string& query,
|
||||
const uint64_t stripped_hash,
|
||||
|
@ -5,4 +5,5 @@
|
||||
# clang++ -std=c++1y create_return.cpp -o create_return.so -I../../../ -shared -fPIC
|
||||
# cd ../..
|
||||
# clang++ -std=c++1y -g -I../ -I ../lib/yaml-cpp/include main.cpp ../cypher/cypher.cpp -o engine -L ../lib/yaml-cpp/build -l yaml-cpp -l dl
|
||||
# clang++ -std=c++1y -g -O2 -I../ main.cpp ../cypher/cypher.cpp -o engine.out -l dl -pthread
|
||||
clang++ -std=c++1y -g -I../ main.cpp ../cypher/cypher.cpp -o engine.out -l dl -pthread
|
||||
|
23
query_engine/debug.hpp
Normal file
23
query_engine/debug.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "storage/model/properties/traversers/jsonwriter.hpp"
|
||||
#include "storage/model/properties/properties.hpp"
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
void print_props(const Properties& properties)
|
||||
{
|
||||
StringBuffer buffer;
|
||||
JsonWriter<StringBuffer> writer(buffer);
|
||||
properties.accept(writer);
|
||||
cout << buffer.str() << endl;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
# define PRINT_PROPS(_PROPS_) print_props(_PROPS_);
|
||||
#else
|
||||
# define PRINT_PROPS(_)
|
||||
#endif
|
@ -1,12 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "query_engine/query_result.hpp"
|
||||
#include "query_stripped.hpp"
|
||||
#include "database/db.hpp"
|
||||
|
||||
class ICodeCPU
|
||||
{
|
||||
public:
|
||||
virtual QueryResult::sptr run(Db& db) = 0;
|
||||
virtual QueryResult::sptr run(Db& db, code_args_t& args) = 0;
|
||||
virtual ~ICodeCPU() {}
|
||||
};
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "utils/command_line/arguments.hpp"
|
||||
#include "cypher/common.hpp"
|
||||
#include "query_engine.hpp"
|
||||
#include "utils/time/timer.hpp"
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
@ -17,7 +18,18 @@ int main(int argc, char** argv)
|
||||
cout << "QUERY: " << cypher_query << endl;
|
||||
|
||||
QueryEngine engine;
|
||||
engine.execute(cypher_query);
|
||||
// engine.execute(cypher_query);
|
||||
|
||||
using std::placeholders::_1;
|
||||
auto f = std::bind(&QueryEngine::execute, &engine, _1);
|
||||
|
||||
cout << std::fixed << timer(f, cypher_query) << endl;
|
||||
|
||||
// double counter = 0;
|
||||
// for (int i = 0; i < 1000000; ++i) {
|
||||
// counter += timer(f, cypher_query);
|
||||
// }
|
||||
// cout << 1000000 / (counter / 1000000000) << "create_transactions per sec" << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
33
query_engine/program_executor.hpp
Normal file
33
query_engine/program_executor.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "query_program.hpp"
|
||||
#include "database/db.hpp"
|
||||
#include "utils/log/logger.hpp"
|
||||
|
||||
// preparations before execution
|
||||
// execution
|
||||
// postprocess the results
|
||||
|
||||
#define DEBUG 1
|
||||
#include "query_engine/debug.hpp"
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
class ProgramExecutor
|
||||
{
|
||||
public:
|
||||
|
||||
auto execute(QueryProgram& program)
|
||||
{
|
||||
auto result = program.code->run(db, program.stripped.arguments);
|
||||
print_props(*result->data["n"]->data[0]);
|
||||
return result;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Db db;
|
||||
};
|
@ -4,7 +4,7 @@
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
|
||||
// #define NOT_LOG_INFO
|
||||
#define NOT_LOG_INFO
|
||||
|
||||
#include "memgraph_dynamic_lib.hpp"
|
||||
#include "query_stripper.hpp"
|
||||
@ -13,28 +13,27 @@
|
||||
#include "utils/hashing/fnv.hpp"
|
||||
#include "config/config.hpp"
|
||||
#include "utils/log/logger.hpp"
|
||||
#include "query_program.hpp"
|
||||
|
||||
using std::string;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
|
||||
class CodeLoader
|
||||
class ProgramLoader
|
||||
{
|
||||
public:
|
||||
|
||||
using sptr_code_lib = std::shared_ptr<CodeLib>;
|
||||
|
||||
CodeLoader()
|
||||
: stripper(make_query_stripper(TK_INT, TK_FLOAT, TK_STR))
|
||||
{
|
||||
}
|
||||
ProgramLoader()
|
||||
: stripper(make_query_stripper(TK_INT, TK_FLOAT, TK_STR, TK_BOOL)) {}
|
||||
|
||||
ICodeCPU* load_code_cpu(const string& query)
|
||||
auto load(const string& query)
|
||||
{
|
||||
auto stripped = stripper.strip(query);
|
||||
LOG_INFO("stripped_query=" + stripped);
|
||||
auto stripped_hash = fnv(stripped);
|
||||
LOG_INFO("stripped_query=" + stripped.query);
|
||||
|
||||
auto stripped_hash = fnv(stripped.query);
|
||||
auto hash_string = std::to_string(stripped_hash);
|
||||
LOG_INFO("query_hash=" + hash_string);
|
||||
|
||||
@ -42,9 +41,10 @@ public:
|
||||
|
||||
// code is already compiled and loaded, just return runnable
|
||||
// instance
|
||||
if (code_lib_iter != code_libs.end())
|
||||
// TODO also return extracted arguments
|
||||
return code_lib_iter->second->instance();
|
||||
if (code_lib_iter != code_libs.end()) {
|
||||
auto code = code_lib_iter->second->instance();
|
||||
return QueryProgram(code, std::move(stripped));
|
||||
}
|
||||
|
||||
// code has to be generated, compiled and loaded
|
||||
// TODO load output path from config
|
||||
@ -61,12 +61,13 @@ public:
|
||||
code_libs.insert({{stripped_hash, code_lib}});
|
||||
|
||||
// return instance of runnable code (ICodeCPU)
|
||||
return code_lib->instance();
|
||||
return QueryProgram(code_lib->instance(), std::move(stripped));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// TODO somehow remove int.. from here
|
||||
QueryStripper<int, int, int> stripper;
|
||||
QueryStripper<int, int, int, int> stripper;
|
||||
// TODO ifdef MEMGRAPH64 problem, how to use this kind
|
||||
// of ifdef functions?
|
||||
// uint64_t depends on fnv function
|
@ -1,30 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "code_loader.hpp"
|
||||
#include "code_executor.hpp"
|
||||
#include "program_loader.hpp"
|
||||
#include "program_executor.hpp"
|
||||
#include "query_result.hpp"
|
||||
|
||||
//
|
||||
// Current arhitecture:
|
||||
// query -> code_loader -> query_stripper -> [code_generator]
|
||||
// -> [code_compiler] -> code_executor
|
||||
//
|
||||
|
||||
class QueryEngine
|
||||
{
|
||||
public:
|
||||
QueryEngine()
|
||||
{
|
||||
}
|
||||
|
||||
QueryResult* execute(const std::string& query)
|
||||
auto execute(const std::string& query)
|
||||
{
|
||||
executor.execute(loader.load_code_cpu(query));
|
||||
|
||||
throw std::runtime_error("implement me");
|
||||
auto program = program_loader.load(query);
|
||||
auto result = program_executor.execute(program);
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
CodeLoader loader;
|
||||
CodeExecutor executor;
|
||||
ProgramExecutor program_executor;
|
||||
ProgramLoader program_loader;
|
||||
};
|
||||
|
17
query_engine/query_program.hpp
Normal file
17
query_engine/query_program.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "i_code_cpu.hpp"
|
||||
#include "query_stripped.hpp"
|
||||
|
||||
struct QueryProgram
|
||||
{
|
||||
QueryProgram(ICodeCPU* code, QueryStripped&& stripped) :
|
||||
code(code),
|
||||
stripped(std::forward<QueryStripped>(stripped)) {}
|
||||
|
||||
QueryProgram(QueryProgram& other) = delete;
|
||||
QueryProgram(QueryProgram&& other) = default;
|
||||
|
||||
ICodeCPU *code;
|
||||
QueryStripped stripped;
|
||||
};
|
@ -1,15 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
class QueryResult
|
||||
#include "storage/model/properties/properties.hpp"
|
||||
|
||||
struct ResultList
|
||||
{
|
||||
public:
|
||||
using sptr = std::shared_ptr<QueryResult>;
|
||||
using sptr = std::shared_ptr<ResultList>;
|
||||
using data_t = std::vector<const Properties*>;
|
||||
|
||||
QueryResult(std::string result) :
|
||||
result(result) {}
|
||||
ResultList() = delete;
|
||||
ResultList(ResultList& other) = delete;
|
||||
ResultList(ResultList&& other) = default;
|
||||
|
||||
std::string result;
|
||||
ResultList(data_t&& data) :
|
||||
data(std::forward<data_t>(data)) {}
|
||||
|
||||
std::vector<const Properties*> data;
|
||||
};
|
||||
|
||||
struct QueryResult
|
||||
{
|
||||
using sptr = std::shared_ptr<QueryResult>;
|
||||
using data_t = std::unordered_map<std::string, ResultList::sptr>;
|
||||
|
||||
QueryResult() = delete;
|
||||
QueryResult(QueryResult& other) = delete;
|
||||
QueryResult(QueryResult&& other) = default;
|
||||
|
||||
QueryResult(data_t&& data) :
|
||||
data(std::forward<data_t>(data)) {}
|
||||
|
||||
data_t data;
|
||||
};
|
||||
|
20
query_engine/query_stripped.hpp
Normal file
20
query_engine/query_stripped.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "storage/model/properties/property.hpp"
|
||||
|
||||
using code_args_t = std::vector<Property::sptr>;
|
||||
|
||||
struct QueryStripped
|
||||
{
|
||||
QueryStripped(const std::string&& query, code_args_t&& arguments) :
|
||||
query(std::forward<const std::string>(query)),
|
||||
arguments(std::forward<code_args_t>(arguments)) {}
|
||||
|
||||
QueryStripped(QueryStripped& other) = delete;
|
||||
QueryStripped(QueryStripped&& other) = default;
|
||||
|
||||
std::string query;
|
||||
code_args_t arguments;
|
||||
};
|
@ -3,13 +3,22 @@
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "cypher/cypher.h"
|
||||
#include "cypher/tokenizer/cypher_lexer.hpp"
|
||||
#include "utils/variadic/variadic.hpp"
|
||||
#include "storage/model/properties/all.hpp"
|
||||
#include "query_stripped.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
template<class T, class V>
|
||||
void store_query_param(code_args_t& arguments, V&& v)
|
||||
{
|
||||
arguments.emplace_back(std::make_shared<T>(std::forward<V>(v)));
|
||||
}
|
||||
|
||||
template<typename ...Ts>
|
||||
class QueryStripper
|
||||
{
|
||||
@ -17,32 +26,63 @@ public:
|
||||
|
||||
QueryStripper(Ts&&... strip_types) :
|
||||
lexer(std::make_unique<CypherLexer>()),
|
||||
strip_types(std::make_tuple(std::forward<Ts>(strip_types)...))
|
||||
{
|
||||
}
|
||||
strip_types(std::make_tuple(std::forward<Ts>(strip_types)...)) {}
|
||||
|
||||
QueryStripper(QueryStripper& other) = delete;
|
||||
|
||||
QueryStripper(QueryStripper&& other) :
|
||||
strip_types(std::move(other.strip_types)),
|
||||
lexer(std::move(other.lexer))
|
||||
{
|
||||
}
|
||||
lexer(std::move(other.lexer)) {}
|
||||
|
||||
decltype(auto) strip(const std::string& query)
|
||||
auto strip(const std::string& query)
|
||||
{
|
||||
// TODO return hash and arguments
|
||||
// TODO write this more optimal (resplace string
|
||||
// concatenation with something smarter)
|
||||
// TODO: in place substring replacement
|
||||
|
||||
auto tokenizer = lexer->tokenize(query);
|
||||
std::string stripped = "";
|
||||
int counter = 0;
|
||||
|
||||
// TMP size of supported token types
|
||||
constexpr auto size = std::tuple_size<decltype(strip_types)>::value;
|
||||
|
||||
int counter = 0;
|
||||
code_args_t stripped_arguments;
|
||||
std::string stripped_query;
|
||||
stripped_query.reserve(query.size());
|
||||
|
||||
while (auto token = tokenizer.lookup())
|
||||
{
|
||||
// TODO: better implementation
|
||||
if (_or(token.id, strip_types, std::make_index_sequence<size>{})) {
|
||||
stripped += "@" + std::to_string(counter++);
|
||||
auto index = counter++;
|
||||
switch (token.id) {
|
||||
case TK_INT:
|
||||
store_query_param<Int32>(stripped_arguments,
|
||||
std::stoi(token.value));
|
||||
break;
|
||||
case TK_STR:
|
||||
store_query_param<String>(stripped_arguments,
|
||||
token.value);
|
||||
break;
|
||||
case TK_BOOL: {
|
||||
bool value = token.value[0] == 'T' ||
|
||||
token.value[0] == 't';
|
||||
store_query_param<Bool>(stripped_arguments, value);
|
||||
break;
|
||||
}
|
||||
case TK_FLOAT:
|
||||
store_query_param<Float>(stripped_arguments,
|
||||
std::stof(token.value));
|
||||
break;
|
||||
}
|
||||
stripped_query += std::to_string(index);
|
||||
} else {
|
||||
stripped += token.value;
|
||||
stripped_query += token.value;
|
||||
}
|
||||
}
|
||||
return stripped;
|
||||
|
||||
return QueryStripped(std::move(stripped_query),
|
||||
std::move(stripped_arguments));
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "query_engine/i_code_cpu.hpp"
|
||||
#include "storage/model/properties/all.hpp"
|
||||
|
||||
// TODO generate with the template engine
|
||||
// #include "storage/model/properties/jsonwriter.hpp"
|
||||
@ -15,7 +16,7 @@ class {{class_name}} : public ICodeCPU
|
||||
{
|
||||
public:
|
||||
|
||||
QueryResult::sptr run(Db& db) override
|
||||
QueryResult::sptr run(Db& db, code_args_t& args) override
|
||||
{
|
||||
{{code}} }
|
||||
|
||||
|
@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "query_engine/i_code_cpu.hpp"
|
||||
|
||||
class ICodeCPUData : ICodeCPU
|
||||
{
|
||||
public:
|
||||
{{data_type}} data;
|
||||
};
|
@ -4,38 +4,52 @@
|
||||
#include <typeinfo>
|
||||
#include <map>
|
||||
|
||||
#include "storage/model/properties/properties.hpp"
|
||||
#include "storage/model/properties/jsonwriter.hpp"
|
||||
#include "cypher/visitor/traverser.hpp"
|
||||
#include "node_traverser.hpp"
|
||||
#include "query_engine/util.hpp"
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
class CreateTraverser : public Traverser
|
||||
{
|
||||
private:
|
||||
std::string key;
|
||||
uint32_t index{0};
|
||||
|
||||
public:
|
||||
std::string code;
|
||||
Properties properties;
|
||||
|
||||
void visit(ast::Create& create) override
|
||||
{
|
||||
code = "\t\tauto& t = db.tx_engine.begin();\n";
|
||||
code += "\t\tauto vertex_accessor = db.graph.vertices.insert(t);\n";
|
||||
code += line("auto& t = db.tx_engine.begin();");
|
||||
code += line("auto vertex_accessor = db.graph.vertices.insert(t);");
|
||||
|
||||
Traverser::visit(create);
|
||||
};
|
||||
|
||||
void visit(ast::Node& node) override
|
||||
void visit(ast::Property& property) override
|
||||
{
|
||||
Traverser::visit(node);
|
||||
key = property.idn->name;
|
||||
|
||||
Traverser::visit(property);
|
||||
|
||||
code += line("vertex_accessor.property(");
|
||||
code += line("\t\"" + key + "\", args[" + std::to_string(index) + "]");
|
||||
code += line(");");
|
||||
|
||||
++index;
|
||||
}
|
||||
|
||||
void visit(ast::Return& ret) override
|
||||
{
|
||||
code += "\t\tauto properties = vertex_accessor.properties();\n";
|
||||
code += "\t\tStringBuffer buffer;\n";
|
||||
code += "\t\tJsonWriter<StringBuffer> writer(buffer);\n";
|
||||
code += "\t\tproperties.accept(writer);\n";
|
||||
code += "\t\treturn std::make_shared<QueryResult>(buffer.str());\n";
|
||||
code += line("t.commit();");
|
||||
code += line("auto &properties = vertex_accessor.properties();");
|
||||
code += line("ResultList::data_t data = {&properties};");
|
||||
code += line("auto result_data = "
|
||||
"std::make_shared<ResultList>(std::move(data));");
|
||||
code += line("QueryResult::data_t query_data = {{\"" +
|
||||
ret.return_list->value->name + "\", result_data}};");
|
||||
code += line("return std::make_shared<QueryResult>"
|
||||
"(std::move(query_data));");
|
||||
}
|
||||
};
|
||||
|
@ -1,49 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "cypher/visitor/traverser.hpp"
|
||||
#include "storage/model/properties/properties.hpp"
|
||||
|
||||
struct NodeTraverser : public Traverser
|
||||
{
|
||||
Properties traverse(ast::Node& node)
|
||||
{
|
||||
Traverser::visit(node);
|
||||
return properties;
|
||||
}
|
||||
|
||||
void visit(ast::Property& property) override
|
||||
{
|
||||
key = property.idn->name;
|
||||
Traverser::visit(property);
|
||||
if (flag == Property::Flags::Int32) {
|
||||
properties.set<Int32>(key, *int_value);
|
||||
}
|
||||
if (flag == Property::Flags::String) {
|
||||
properties.set<String>(key, *string_value);
|
||||
}
|
||||
}
|
||||
|
||||
void visit(ast::String& string) override
|
||||
{
|
||||
flag = Property::Flags::String;
|
||||
string_value = std::make_shared<String>(string.value);
|
||||
}
|
||||
|
||||
void visit(ast::Integer& integer) override
|
||||
{
|
||||
flag = Property::Flags::Int32;
|
||||
int_value = std::make_shared<Int32>(integer.value);
|
||||
}
|
||||
|
||||
void visit(ast::Node& node) override
|
||||
{
|
||||
Traverser::visit(node);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string key;
|
||||
Property::Flags flag;
|
||||
std::shared_ptr<Int32> int_value;
|
||||
std::shared_ptr<String> string_value;
|
||||
Properties properties;
|
||||
};
|
8
query_engine/util.hpp
Normal file
8
query_engine/util.hpp
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
std::string line(std::string line)
|
||||
{
|
||||
return "\t\t" + line + "\n";
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include "mvcc/record.hpp"
|
||||
#include "model/edge_model.hpp"
|
||||
#include "model/properties/jsonwriter.hpp"
|
||||
#include "model/properties/traversers/jsonwriter.hpp"
|
||||
|
||||
class Edge : public mvcc::Record<Edge>
|
||||
{
|
||||
|
@ -7,9 +7,9 @@
|
||||
|
||||
class Properties
|
||||
{
|
||||
using props_t = std::map<std::string, Property::sptr>;
|
||||
|
||||
public:
|
||||
using sptr = std::shared_ptr<Properties>;
|
||||
|
||||
const Property& at(const std::string& key) const
|
||||
{
|
||||
auto it = props.find(key);
|
||||
@ -56,6 +56,8 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
using props_t = std::map<std::string, Property::sptr>;
|
||||
|
||||
props_t props;
|
||||
};
|
||||
|
||||
|
@ -60,6 +60,11 @@ public:
|
||||
record->data.props.template set<V>(key, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void property(const std::string& key, Property::sptr value)
|
||||
{
|
||||
record->data.props.set(key, std::move(value));
|
||||
}
|
||||
|
||||
Properties& properties() const
|
||||
{
|
||||
return record->data.props;
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include "mvcc/record.hpp"
|
||||
#include "model/vertex_model.hpp"
|
||||
#include "model/properties/jsonwriter.hpp"
|
||||
#include "model/properties/traversers/jsonwriter.hpp"
|
||||
|
||||
class Vertex : public mvcc::Record<Vertex>
|
||||
{
|
||||
|
19
utils/time/timer.hpp
Normal file
19
utils/time/timer.hpp
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <utility>
|
||||
#include <chrono>
|
||||
|
||||
using time_point_t = std::chrono::high_resolution_clock::time_point;
|
||||
|
||||
#define duration(a) \
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(a).count()
|
||||
|
||||
#define time_now() std::chrono::high_resolution_clock::now()
|
||||
|
||||
template<typename F, typename... Args>
|
||||
double timer(F func, Args&&... args)
|
||||
{
|
||||
time_point_t start_time = time_now();
|
||||
func(std::forward<Args>(args)...);
|
||||
return duration(time_now() - start_time);
|
||||
}
|
Loading…
Reference in New Issue
Block a user