#pragma once #include #include #include #include #include #include "cypher/cypher.h" #include "cypher/tokenizer/cypher_lexer.hpp" #include "query_stripped.hpp" #include "storage/model/properties/all.hpp" #include "utils/hashing/fnv.hpp" #include "utils/string/transform.hpp" #include "utils/variadic/variadic.hpp" template void store_query_param(code_args_t &arguments, V &&v) { arguments.emplace_back(std::make_shared(std::forward(v))); } template class QueryStripper { public: QueryStripper(Ts &&... strip_types) : strip_types(std::make_tuple(std::forward(strip_types)...)), lexer(std::make_unique()) { } QueryStripper(QueryStripper &other) = delete; QueryStripper(QueryStripper &&other) : strip_types(std::move(other.strip_types)), lexer(std::move(other.lexer)) { } auto strip_space(const std::string &query) { auto stripped = strip(query, " "); return QueryStripped(std::move(stripped.query), stripped.hash, std::move(stripped.arguments)); } auto strip(const std::string &query, const std::string &separator = "") { // TODO write this more optimal (resplace string // concatenation with something smarter) // TODO: in place substring replacement auto tokenizer = lexer->tokenize(query); // TMP size of supported token types constexpr auto size = std::tuple_size::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{})) { auto index = counter++; switch (token.id) { case TK_LONG: store_query_param(stripped_arguments, std::stol(token.value)); break; case TK_STR: store_query_param(stripped_arguments, token.value); break; case TK_BOOL: { bool value = token.value[0] == 'T' || token.value[0] == 't'; store_query_param(stripped_arguments, value); break; } case TK_FLOAT: store_query_param(stripped_arguments, std::stof(token.value)); break; } stripped_query += std::to_string(index) + separator; } else { // TODO: lowercase only keywords like (MATCH, CREATE, ...) stripped_query += token.value + separator; } } return QueryStripped(std::move(stripped_query), fnv(stripped_query), std::move(stripped_arguments)); } private: std::tuple strip_types; CypherLexer::uptr lexer; template bool _or(Value &&value, Tuple &&tuple, std::index_sequence) { return or_vargs(std::forward(value), std::get(std::forward(tuple))...); } }; template decltype(auto) make_query_stripper(Ts &&... ts) { return QueryStripper(std::forward(ts)...); }