Make it possible to compile v2 and v3 interpreter into a single binary
This commit is contained in:
parent
155388c0a1
commit
1bc93b64f4
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||||
@ -51,7 +51,7 @@ constexpr char kId[] = "ID";
|
|||||||
|
|
||||||
namespace MG_INJECTED_NAMESPACE_NAME {
|
namespace MG_INJECTED_NAMESPACE_NAME {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
using antlropencypher::MemgraphCypher;
|
using antlropencypher::v2::MemgraphCypher;
|
||||||
|
|
||||||
template <typename TVisitor>
|
template <typename TVisitor>
|
||||||
std::optional<std::pair<Expression *, size_t>> VisitMemoryLimit(MemgraphCypher::MemoryLimitContext *memory_limit_ctx,
|
std::optional<std::pair<Expression *, size_t>> VisitMemoryLimit(MemgraphCypher::MemoryLimitContext *memory_limit_ctx,
|
||||||
@ -211,13 +211,13 @@ inline std::string_view ToString(const PulsarConfigKey key) {
|
|||||||
}
|
}
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
using antlropencypher::MemgraphCypher;
|
using antlropencypher::v2::MemgraphCypher;
|
||||||
|
|
||||||
struct ParsingContext {
|
struct ParsingContext {
|
||||||
bool is_query_cached = false;
|
bool is_query_cached = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor {
|
class CypherMainVisitor : public antlropencypher::v2::MemgraphCypherBaseVisitor {
|
||||||
public:
|
public:
|
||||||
explicit CypherMainVisitor(ParsingContext context, AstStorage *storage) : context_(context), storage_(storage) {}
|
explicit CypherMainVisitor(ParsingContext context, AstStorage *storage) : context_(context), storage_(storage) {}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ add_custom_command(
|
|||||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${opencypher_generated}
|
COMMAND ${CMAKE_COMMAND} -E make_directory ${opencypher_generated}
|
||||||
COMMAND
|
COMMAND
|
||||||
java -jar ${CMAKE_SOURCE_DIR}/libs/antlr-4.10.1-complete.jar
|
java -jar ${CMAKE_SOURCE_DIR}/libs/antlr-4.10.1-complete.jar
|
||||||
-Dlanguage=Cpp -visitor -package antlropencypher
|
-Dlanguage=Cpp -visitor -package antlropencypher::v2
|
||||||
-o ${opencypher_generated}
|
-o ${opencypher_generated}
|
||||||
${opencypher_lexer_grammar} ${opencypher_parser_grammar}
|
${opencypher_lexer_grammar} ${opencypher_parser_grammar}
|
||||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
|
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||||
@ -14,10 +14,10 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "antlr4-runtime.h"
|
#include "antlr4-runtime.h"
|
||||||
#include "utils/exceptions.hpp"
|
|
||||||
#include "parser/opencypher/generated/MemgraphCypher.h"
|
#include "parser/opencypher/generated/MemgraphCypher.h"
|
||||||
#include "parser/opencypher/generated/MemgraphCypherLexer.h"
|
#include "parser/opencypher/generated/MemgraphCypherLexer.h"
|
||||||
#include "utils/concepts.hpp"
|
#include "utils/concepts.hpp"
|
||||||
|
#include "utils/exceptions.hpp"
|
||||||
|
|
||||||
namespace memgraph::frontend::opencypher {
|
namespace memgraph::frontend::opencypher {
|
||||||
|
|
||||||
@ -32,11 +32,9 @@ class SyntaxException : public utils::BasicException {
|
|||||||
* This thing must me a class since parser.cypher() returns pointer and there is
|
* This thing must me a class since parser.cypher() returns pointer and there is
|
||||||
* no way for us to get ownership over the object.
|
* no way for us to get ownership over the object.
|
||||||
*/
|
*/
|
||||||
enum class ParserOpTag : uint8_t {
|
enum class ParserOpTag : uint8_t { CYPHER, EXPRESSION };
|
||||||
CYPHER, EXPRESSION
|
|
||||||
};
|
|
||||||
|
|
||||||
template<ParserOpTag Tag = ParserOpTag::CYPHER>
|
template <ParserOpTag Tag = ParserOpTag::CYPHER>
|
||||||
class Parser {
|
class Parser {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@ -46,10 +44,9 @@ class Parser {
|
|||||||
Parser(const std::string query) : query_(std::move(query)) {
|
Parser(const std::string query) : query_(std::move(query)) {
|
||||||
parser_.removeErrorListeners();
|
parser_.removeErrorListeners();
|
||||||
parser_.addErrorListener(&error_listener_);
|
parser_.addErrorListener(&error_listener_);
|
||||||
if constexpr(Tag == ParserOpTag::CYPHER) {
|
if constexpr (Tag == ParserOpTag::CYPHER) {
|
||||||
tree_ = parser_.cypher();
|
tree_ = parser_.cypher();
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
tree_ = parser_.expression();
|
tree_ = parser_.expression();
|
||||||
}
|
}
|
||||||
if (parser_.getNumberOfSyntaxErrors()) {
|
if (parser_.getNumberOfSyntaxErrors()) {
|
||||||
@ -75,11 +72,11 @@ class Parser {
|
|||||||
FirstMessageErrorListener error_listener_;
|
FirstMessageErrorListener error_listener_;
|
||||||
std::string query_;
|
std::string query_;
|
||||||
antlr4::ANTLRInputStream input_{query_};
|
antlr4::ANTLRInputStream input_{query_};
|
||||||
antlropencypher::MemgraphCypherLexer lexer_{&input_};
|
antlropencypher::v2::MemgraphCypherLexer lexer_{&input_};
|
||||||
antlr4::CommonTokenStream tokens_{&lexer_};
|
antlr4::CommonTokenStream tokens_{&lexer_};
|
||||||
|
|
||||||
// generate ast
|
// generate ast
|
||||||
antlropencypher::MemgraphCypher parser_{&tokens_};
|
antlropencypher::v2::MemgraphCypher parser_{&tokens_};
|
||||||
antlr4::tree::ParseTree *tree_ = nullptr;
|
antlr4::tree::ParseTree *tree_ = nullptr;
|
||||||
};
|
};
|
||||||
} // namespace memgraph::frontend::opencypher
|
} // namespace memgraph::frontend::opencypher
|
||||||
|
@ -48,18 +48,20 @@ add_dependencies(mg-query generate_lcp_query)
|
|||||||
target_include_directories(mg-query PUBLIC ${CMAKE_SOURCE_DIR}/include)
|
target_include_directories(mg-query PUBLIC ${CMAKE_SOURCE_DIR}/include)
|
||||||
target_link_libraries(mg-query dl cppitertools Boost::headers)
|
target_link_libraries(mg-query dl cppitertools Boost::headers)
|
||||||
target_link_libraries(mg-query mg-integrations-pulsar mg-integrations-kafka mg-storage-v2 mg-license mg-utils mg-kvstore mg-memory)
|
target_link_libraries(mg-query mg-integrations-pulsar mg-integrations-kafka mg-storage-v2 mg-license mg-utils mg-kvstore mg-memory)
|
||||||
|
|
||||||
if(NOT "${MG_PYTHON_PATH}" STREQUAL "")
|
if(NOT "${MG_PYTHON_PATH}" STREQUAL "")
|
||||||
set(Python3_ROOT_DIR "${MG_PYTHON_PATH}")
|
set(Python3_ROOT_DIR "${MG_PYTHON_PATH}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if("${MG_PYTHON_VERSION}" STREQUAL "")
|
if("${MG_PYTHON_VERSION}" STREQUAL "")
|
||||||
find_package(Python3 3.5 REQUIRED COMPONENTS Development)
|
find_package(Python3 3.5 REQUIRED COMPONENTS Development)
|
||||||
else()
|
else()
|
||||||
find_package(Python3 "${MG_PYTHON_VERSION}" EXACT REQUIRED COMPONENTS Development)
|
find_package(Python3 "${MG_PYTHON_VERSION}" EXACT REQUIRED COMPONENTS Development)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(mg-query Python3::Python)
|
target_link_libraries(mg-query Python3::Python)
|
||||||
|
|
||||||
# Generate Antlr openCypher parser
|
# Generate Antlr openCypher parser
|
||||||
|
|
||||||
set(opencypher_frontend ${CMAKE_CURRENT_SOURCE_DIR}/frontend/opencypher)
|
set(opencypher_frontend ${CMAKE_CURRENT_SOURCE_DIR}/frontend/opencypher)
|
||||||
set(opencypher_generated ${opencypher_frontend}/generated)
|
set(opencypher_generated ${opencypher_frontend}/generated)
|
||||||
set(opencypher_lexer_grammar ${opencypher_frontend}/grammar/MemgraphCypherLexer.g4)
|
set(opencypher_lexer_grammar ${opencypher_frontend}/grammar/MemgraphCypherLexer.g4)
|
||||||
@ -82,15 +84,15 @@ add_custom_command(
|
|||||||
OUTPUT ${antlr_opencypher_generated_src} ${antlr_opencypher_generated_include}
|
OUTPUT ${antlr_opencypher_generated_src} ${antlr_opencypher_generated_include}
|
||||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${opencypher_generated}
|
COMMAND ${CMAKE_COMMAND} -E make_directory ${opencypher_generated}
|
||||||
COMMAND
|
COMMAND
|
||||||
java -jar ${CMAKE_SOURCE_DIR}/libs/antlr-4.10.1-complete.jar
|
java -jar ${CMAKE_SOURCE_DIR}/libs/antlr-4.10.1-complete.jar
|
||||||
-Dlanguage=Cpp -visitor -package antlropencypher
|
-Dlanguage=Cpp -visitor -package antlropencypher
|
||||||
-o ${opencypher_generated}
|
-o ${opencypher_generated}
|
||||||
${opencypher_lexer_grammar} ${opencypher_parser_grammar}
|
${opencypher_lexer_grammar} ${opencypher_parser_grammar}
|
||||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
|
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
|
||||||
DEPENDS
|
DEPENDS
|
||||||
${opencypher_lexer_grammar} ${opencypher_parser_grammar}
|
${opencypher_lexer_grammar} ${opencypher_parser_grammar}
|
||||||
${opencypher_frontend}/grammar/CypherLexer.g4
|
${opencypher_frontend}/grammar/CypherLexer.g4
|
||||||
${opencypher_frontend}/grammar/Cypher.g4)
|
${opencypher_frontend}/grammar/Cypher.g4)
|
||||||
|
|
||||||
add_custom_target(generate_opencypher_parser
|
add_custom_target(generate_opencypher_parser
|
||||||
DEPENDS ${antlr_opencypher_generated_src} ${antlr_opencypher_generated_include})
|
DEPENDS ${antlr_opencypher_generated_src} ${antlr_opencypher_generated_include})
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||||
@ -14,9 +14,9 @@
|
|||||||
#include "query/v2/request_router.hpp"
|
#include "query/v2/request_router.hpp"
|
||||||
|
|
||||||
// NOLINTNEXTLINE (cppcoreguidelines-avoid-non-const-global-variables)
|
// NOLINTNEXTLINE (cppcoreguidelines-avoid-non-const-global-variables)
|
||||||
DEFINE_HIDDEN_bool(query_cost_planner, true, "Use the cost-estimating query planner.");
|
DEFINE_HIDDEN_bool(query_v2_cost_planner, true, "Use the cost-estimating query planner.");
|
||||||
// NOLINTNEXTLINE (cppcoreguidelines-avoid-non-const-global-variables)
|
// NOLINTNEXTLINE (cppcoreguidelines-avoid-non-const-global-variables)
|
||||||
DEFINE_VALIDATED_int32(query_plan_cache_ttl, 60, "Time to live for cached query plans, in seconds.",
|
DEFINE_VALIDATED_int32(query_v2_plan_cache_ttl, 60, "Time to live for cached query plans, in seconds.",
|
||||||
FLAG_IN_RANGE(0, std::numeric_limits<int32_t>::max()));
|
FLAG_IN_RANGE(0, std::numeric_limits<int32_t>::max()));
|
||||||
|
|
||||||
namespace memgraph::query::v2 {
|
namespace memgraph::query::v2 {
|
||||||
@ -123,7 +123,7 @@ std::unique_ptr<LogicalPlan> MakeLogicalPlan(AstStorage ast_storage, CypherQuery
|
|||||||
auto vertex_counts = plan::MakeVertexCountCache(request_router);
|
auto vertex_counts = plan::MakeVertexCountCache(request_router);
|
||||||
auto symbol_table = expr::MakeSymbolTable(query, predefined_identifiers);
|
auto symbol_table = expr::MakeSymbolTable(query, predefined_identifiers);
|
||||||
auto planning_context = plan::MakePlanningContext(&ast_storage, &symbol_table, query, &vertex_counts);
|
auto planning_context = plan::MakePlanningContext(&ast_storage, &symbol_table, query, &vertex_counts);
|
||||||
auto [root, cost] = plan::MakeLogicalPlan(&planning_context, parameters, FLAGS_query_cost_planner);
|
auto [root, cost] = plan::MakeLogicalPlan(&planning_context, parameters, FLAGS_query_v2_cost_planner);
|
||||||
return std::make_unique<SingleNodeLogicalPlan>(std::move(root), cost, std::move(ast_storage),
|
return std::make_unique<SingleNodeLogicalPlan>(std::move(root), cost, std::move(ast_storage),
|
||||||
std::move(symbol_table));
|
std::move(symbol_table));
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||||
@ -22,9 +22,9 @@
|
|||||||
#include "utils/timer.hpp"
|
#include "utils/timer.hpp"
|
||||||
|
|
||||||
// NOLINTNEXTLINE (cppcoreguidelines-avoid-non-const-global-variables)
|
// NOLINTNEXTLINE (cppcoreguidelines-avoid-non-const-global-variables)
|
||||||
DECLARE_bool(query_cost_planner);
|
DECLARE_bool(query_v2_cost_planner);
|
||||||
// NOLINTNEXTLINE (cppcoreguidelines-avoid-non-const-global-variables)
|
// NOLINTNEXTLINE (cppcoreguidelines-avoid-non-const-global-variables)
|
||||||
DECLARE_int32(query_plan_cache_ttl);
|
DECLARE_int32(query_v2_plan_cache_ttl);
|
||||||
|
|
||||||
namespace memgraph::query::v2 {
|
namespace memgraph::query::v2 {
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ class CachedPlan {
|
|||||||
|
|
||||||
bool IsExpired() const {
|
bool IsExpired() const {
|
||||||
// NOLINTNEXTLINE (modernize-use-nullptr)
|
// NOLINTNEXTLINE (modernize-use-nullptr)
|
||||||
return cache_timer_.Elapsed() > std::chrono::seconds(FLAGS_query_plan_cache_ttl);
|
return cache_timer_.Elapsed() > std::chrono::seconds(FLAGS_query_v2_plan_cache_ttl);
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||||
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
#include "utils/flag_validation.hpp"
|
#include "utils/flag_validation.hpp"
|
||||||
|
|
||||||
DEFINE_VALIDATED_HIDDEN_int64(query_vertex_count_to_expand_existing, 10,
|
DEFINE_VALIDATED_HIDDEN_int64(query_v2_vertex_count_to_expand_existing, 10,
|
||||||
"Maximum count of indexed vertices which provoke "
|
"Maximum count of indexed vertices which provoke "
|
||||||
"indexed lookup and then expand to existing, instead of "
|
"indexed lookup and then expand to existing, instead of "
|
||||||
"a regular expand. Default is 10, to turn off use -1.",
|
"a regular expand. Default is 10, to turn off use -1.",
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
#include "query/v2/plan/preprocess.hpp"
|
#include "query/v2/plan/preprocess.hpp"
|
||||||
#include "storage/v3/id_types.hpp"
|
#include "storage/v3/id_types.hpp"
|
||||||
|
|
||||||
DECLARE_int64(query_vertex_count_to_expand_existing);
|
DECLARE_int64(query_v2_vertex_count_to_expand_existing);
|
||||||
|
|
||||||
namespace memgraph::query::v2::plan {
|
namespace memgraph::query::v2::plan {
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ class IndexLookupRewriter final : public HierarchicalLogicalOperatorVisitor {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
ScanAll dst_scan(expand.input(), expand.common_.node_symbol, expand.view_);
|
ScanAll dst_scan(expand.input(), expand.common_.node_symbol, expand.view_);
|
||||||
auto indexed_scan = GenScanByIndex(dst_scan, FLAGS_query_vertex_count_to_expand_existing);
|
auto indexed_scan = GenScanByIndex(dst_scan, FLAGS_query_v2_vertex_count_to_expand_existing);
|
||||||
if (indexed_scan) {
|
if (indexed_scan) {
|
||||||
expand.set_input(std::move(indexed_scan));
|
expand.set_input(std::move(indexed_scan));
|
||||||
expand.common_.existing_node = true;
|
expand.common_.existing_node = true;
|
||||||
@ -129,7 +129,7 @@ class IndexLookupRewriter final : public HierarchicalLogicalOperatorVisitor {
|
|||||||
// unconditionally creating an indexed scan.
|
// unconditionally creating an indexed scan.
|
||||||
indexed_scan = GenScanByIndex(dst_scan);
|
indexed_scan = GenScanByIndex(dst_scan);
|
||||||
} else {
|
} else {
|
||||||
indexed_scan = GenScanByIndex(dst_scan, FLAGS_query_vertex_count_to_expand_existing);
|
indexed_scan = GenScanByIndex(dst_scan, FLAGS_query_v2_vertex_count_to_expand_existing);
|
||||||
}
|
}
|
||||||
if (indexed_scan) {
|
if (indexed_scan) {
|
||||||
expand.set_input(std::move(indexed_scan));
|
expand.set_input(std::move(indexed_scan));
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||||
@ -17,7 +17,7 @@
|
|||||||
#include "utils/flag_validation.hpp"
|
#include "utils/flag_validation.hpp"
|
||||||
#include "utils/logging.hpp"
|
#include "utils/logging.hpp"
|
||||||
|
|
||||||
DEFINE_VALIDATED_HIDDEN_uint64(query_max_plans, 1000U, "Maximum number of generated plans for a query.",
|
DEFINE_VALIDATED_HIDDEN_uint64(query_v2_max_plans, 1000U, "Maximum number of generated plans for a query.",
|
||||||
FLAG_IN_RANGE(1, std::numeric_limits<std::uint64_t>::max()));
|
FLAG_IN_RANGE(1, std::numeric_limits<std::uint64_t>::max()));
|
||||||
|
|
||||||
namespace memgraph::query::v2::plan::impl {
|
namespace memgraph::query::v2::plan::impl {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||||
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
#include "query/v2/plan/rule_based_planner.hpp"
|
#include "query/v2/plan/rule_based_planner.hpp"
|
||||||
|
|
||||||
DECLARE_uint64(query_max_plans);
|
DECLARE_uint64(query_v2_max_plans);
|
||||||
|
|
||||||
namespace memgraph::query::v2::plan {
|
namespace memgraph::query::v2::plan {
|
||||||
|
|
||||||
@ -310,7 +310,7 @@ class VariableStartPlanner {
|
|||||||
for (const auto &query_part : query_parts) {
|
for (const auto &query_part : query_parts) {
|
||||||
alternative_query_parts.emplace_back(impl::VaryQueryPartMatching(query_part, symbol_table));
|
alternative_query_parts.emplace_back(impl::VaryQueryPartMatching(query_part, symbol_table));
|
||||||
}
|
}
|
||||||
return iter::slice(MakeCartesianProduct(std::move(alternative_query_parts)), 0UL, FLAGS_query_max_plans);
|
return iter::slice(MakeCartesianProduct(std::move(alternative_query_parts)), 0UL, FLAGS_query_v2_max_plans);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Loading…
Reference in New Issue
Block a user