mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 07:01:59 +00:00
ANTLR4 Grammar for ClickHouse and new parser (#11298)
This commit is contained in:
parent
6a48d25b74
commit
315ff4f0d9
11
.gitignore
vendored
11
.gitignore
vendored
@ -125,4 +125,15 @@ website/package-lock.json
|
||||
# Toolchains
|
||||
/cmake/toolchain/*
|
||||
|
||||
# ANTLR extension cache
|
||||
.antlr
|
||||
|
||||
# ANTLR generated files
|
||||
/src/Parsers/New/*.interp
|
||||
/src/Parsers/New/*.tokens
|
||||
/src/Parsers/New/ClickHouseParserBaseVisitor.*
|
||||
|
||||
# pytest-profiling
|
||||
/prof
|
||||
|
||||
*.iml
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -172,6 +172,9 @@
|
||||
[submodule "contrib/fmtlib"]
|
||||
path = contrib/fmtlib
|
||||
url = https://github.com/fmtlib/fmt.git
|
||||
[submodule "contrib/antlr4-runtime"]
|
||||
path = contrib/antlr4-runtime
|
||||
url = https://github.com/ClickHouse-Extras/antlr4-runtime.git
|
||||
[submodule "contrib/sentry-native"]
|
||||
path = contrib/sentry-native
|
||||
url = https://github.com/ClickHouse-Extras/sentry-native.git
|
||||
|
@ -257,6 +257,8 @@ if (WITH_COVERAGE AND COMPILER_GCC)
|
||||
set(WITHOUT_COVERAGE "-fno-profile-arcs -fno-test-coverage")
|
||||
endif()
|
||||
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS}")
|
||||
|
||||
set (CMAKE_BUILD_COLOR_MAKEFILE ON)
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMPILER_FLAGS} ${PLATFORM_EXTRA_CXX_FLAG} ${COMMON_WARNING_FLAGS} ${CXX_WARNING_FLAGS}")
|
||||
set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3 ${CMAKE_CXX_FLAGS_ADD}")
|
||||
|
@ -76,12 +76,6 @@
|
||||
# define NO_SANITIZE_THREAD
|
||||
#endif
|
||||
|
||||
#if defined __GNUC__ && !defined __clang__
|
||||
# define OPTIMIZE(x) __attribute__((__optimize__(x)))
|
||||
#else
|
||||
# define OPTIMIZE(x)
|
||||
#endif
|
||||
|
||||
/// A macro for suppressing warnings about unused variables or function results.
|
||||
/// Useful for structured bindings which have no standard way to declare this.
|
||||
#define UNUSED(...) (void)(__VA_ARGS__)
|
||||
|
@ -24,7 +24,7 @@ option (WEVERYTHING "Enable -Weverything option with some exceptions." ON)
|
||||
# Control maximum size of stack frames. It can be important if the code is run in fibers with small stack size.
|
||||
# Only in release build because debug has too large stack frames.
|
||||
if ((NOT CMAKE_BUILD_TYPE_UC STREQUAL "DEBUG") AND (NOT SANITIZE) AND (NOT CMAKE_CXX_COMPILER_ID MATCHES "AppleClang"))
|
||||
add_warning(frame-larger-than=32768)
|
||||
add_warning(frame-larger-than=65536)
|
||||
endif ()
|
||||
|
||||
if (COMPILER_CLANG)
|
||||
|
1
contrib/CMakeLists.txt
vendored
1
contrib/CMakeLists.txt
vendored
@ -21,6 +21,7 @@ endif()
|
||||
|
||||
set_property(DIRECTORY PROPERTY EXCLUDE_FROM_ALL 1)
|
||||
|
||||
add_subdirectory (antlr4-runtime-cmake)
|
||||
add_subdirectory (boost-cmake)
|
||||
add_subdirectory (cctz-cmake)
|
||||
add_subdirectory (consistent-hashing-sumbur)
|
||||
|
1
contrib/antlr4-runtime
vendored
Submodule
1
contrib/antlr4-runtime
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit a2fa7b76e2ee16d2ad955e9214a90bbf79da66fc
|
156
contrib/antlr4-runtime-cmake/CMakeLists.txt
Normal file
156
contrib/antlr4-runtime-cmake/CMakeLists.txt
Normal file
@ -0,0 +1,156 @@
|
||||
set (LIBRARY_DIR ${ClickHouse_SOURCE_DIR}/contrib/antlr4-runtime)
|
||||
|
||||
set (SRCS
|
||||
${LIBRARY_DIR}/ANTLRErrorListener.cpp
|
||||
${LIBRARY_DIR}/ANTLRErrorStrategy.cpp
|
||||
${LIBRARY_DIR}/ANTLRFileStream.cpp
|
||||
${LIBRARY_DIR}/ANTLRInputStream.cpp
|
||||
${LIBRARY_DIR}/atn/AbstractPredicateTransition.cpp
|
||||
${LIBRARY_DIR}/atn/ActionTransition.cpp
|
||||
${LIBRARY_DIR}/atn/AmbiguityInfo.cpp
|
||||
${LIBRARY_DIR}/atn/ArrayPredictionContext.cpp
|
||||
${LIBRARY_DIR}/atn/ATN.cpp
|
||||
${LIBRARY_DIR}/atn/ATNConfig.cpp
|
||||
${LIBRARY_DIR}/atn/ATNConfigSet.cpp
|
||||
${LIBRARY_DIR}/atn/ATNDeserializationOptions.cpp
|
||||
${LIBRARY_DIR}/atn/ATNDeserializer.cpp
|
||||
${LIBRARY_DIR}/atn/ATNSerializer.cpp
|
||||
${LIBRARY_DIR}/atn/ATNSimulator.cpp
|
||||
${LIBRARY_DIR}/atn/ATNState.cpp
|
||||
${LIBRARY_DIR}/atn/AtomTransition.cpp
|
||||
${LIBRARY_DIR}/atn/BasicBlockStartState.cpp
|
||||
${LIBRARY_DIR}/atn/BasicState.cpp
|
||||
${LIBRARY_DIR}/atn/BlockEndState.cpp
|
||||
${LIBRARY_DIR}/atn/BlockStartState.cpp
|
||||
${LIBRARY_DIR}/atn/ContextSensitivityInfo.cpp
|
||||
${LIBRARY_DIR}/atn/DecisionEventInfo.cpp
|
||||
${LIBRARY_DIR}/atn/DecisionInfo.cpp
|
||||
${LIBRARY_DIR}/atn/DecisionState.cpp
|
||||
${LIBRARY_DIR}/atn/EmptyPredictionContext.cpp
|
||||
${LIBRARY_DIR}/atn/EpsilonTransition.cpp
|
||||
${LIBRARY_DIR}/atn/ErrorInfo.cpp
|
||||
${LIBRARY_DIR}/atn/LexerAction.cpp
|
||||
${LIBRARY_DIR}/atn/LexerActionExecutor.cpp
|
||||
${LIBRARY_DIR}/atn/LexerATNConfig.cpp
|
||||
${LIBRARY_DIR}/atn/LexerATNSimulator.cpp
|
||||
${LIBRARY_DIR}/atn/LexerChannelAction.cpp
|
||||
${LIBRARY_DIR}/atn/LexerCustomAction.cpp
|
||||
${LIBRARY_DIR}/atn/LexerIndexedCustomAction.cpp
|
||||
${LIBRARY_DIR}/atn/LexerModeAction.cpp
|
||||
${LIBRARY_DIR}/atn/LexerMoreAction.cpp
|
||||
${LIBRARY_DIR}/atn/LexerPopModeAction.cpp
|
||||
${LIBRARY_DIR}/atn/LexerPushModeAction.cpp
|
||||
${LIBRARY_DIR}/atn/LexerSkipAction.cpp
|
||||
${LIBRARY_DIR}/atn/LexerTypeAction.cpp
|
||||
${LIBRARY_DIR}/atn/LL1Analyzer.cpp
|
||||
${LIBRARY_DIR}/atn/LookaheadEventInfo.cpp
|
||||
${LIBRARY_DIR}/atn/LoopEndState.cpp
|
||||
${LIBRARY_DIR}/atn/NotSetTransition.cpp
|
||||
${LIBRARY_DIR}/atn/OrderedATNConfigSet.cpp
|
||||
${LIBRARY_DIR}/atn/ParseInfo.cpp
|
||||
${LIBRARY_DIR}/atn/ParserATNSimulator.cpp
|
||||
${LIBRARY_DIR}/atn/PlusBlockStartState.cpp
|
||||
${LIBRARY_DIR}/atn/PlusLoopbackState.cpp
|
||||
${LIBRARY_DIR}/atn/PrecedencePredicateTransition.cpp
|
||||
${LIBRARY_DIR}/atn/PredicateEvalInfo.cpp
|
||||
${LIBRARY_DIR}/atn/PredicateTransition.cpp
|
||||
${LIBRARY_DIR}/atn/PredictionContext.cpp
|
||||
${LIBRARY_DIR}/atn/PredictionMode.cpp
|
||||
${LIBRARY_DIR}/atn/ProfilingATNSimulator.cpp
|
||||
${LIBRARY_DIR}/atn/RangeTransition.cpp
|
||||
${LIBRARY_DIR}/atn/RuleStartState.cpp
|
||||
${LIBRARY_DIR}/atn/RuleStopState.cpp
|
||||
${LIBRARY_DIR}/atn/RuleTransition.cpp
|
||||
${LIBRARY_DIR}/atn/SemanticContext.cpp
|
||||
${LIBRARY_DIR}/atn/SetTransition.cpp
|
||||
${LIBRARY_DIR}/atn/SingletonPredictionContext.cpp
|
||||
${LIBRARY_DIR}/atn/StarBlockStartState.cpp
|
||||
${LIBRARY_DIR}/atn/StarLoopbackState.cpp
|
||||
${LIBRARY_DIR}/atn/StarLoopEntryState.cpp
|
||||
${LIBRARY_DIR}/atn/TokensStartState.cpp
|
||||
${LIBRARY_DIR}/atn/Transition.cpp
|
||||
${LIBRARY_DIR}/atn/WildcardTransition.cpp
|
||||
${LIBRARY_DIR}/BailErrorStrategy.cpp
|
||||
${LIBRARY_DIR}/BaseErrorListener.cpp
|
||||
${LIBRARY_DIR}/BufferedTokenStream.cpp
|
||||
${LIBRARY_DIR}/CharStream.cpp
|
||||
${LIBRARY_DIR}/CommonToken.cpp
|
||||
${LIBRARY_DIR}/CommonTokenFactory.cpp
|
||||
${LIBRARY_DIR}/CommonTokenStream.cpp
|
||||
${LIBRARY_DIR}/ConsoleErrorListener.cpp
|
||||
${LIBRARY_DIR}/DefaultErrorStrategy.cpp
|
||||
${LIBRARY_DIR}/dfa/DFA.cpp
|
||||
${LIBRARY_DIR}/dfa/DFASerializer.cpp
|
||||
${LIBRARY_DIR}/dfa/DFAState.cpp
|
||||
${LIBRARY_DIR}/dfa/LexerDFASerializer.cpp
|
||||
${LIBRARY_DIR}/DiagnosticErrorListener.cpp
|
||||
${LIBRARY_DIR}/Exceptions.cpp
|
||||
${LIBRARY_DIR}/FailedPredicateException.cpp
|
||||
${LIBRARY_DIR}/InputMismatchException.cpp
|
||||
${LIBRARY_DIR}/InterpreterRuleContext.cpp
|
||||
${LIBRARY_DIR}/IntStream.cpp
|
||||
${LIBRARY_DIR}/Lexer.cpp
|
||||
${LIBRARY_DIR}/LexerInterpreter.cpp
|
||||
${LIBRARY_DIR}/LexerNoViableAltException.cpp
|
||||
${LIBRARY_DIR}/ListTokenSource.cpp
|
||||
${LIBRARY_DIR}/misc/InterpreterDataReader.cpp
|
||||
${LIBRARY_DIR}/misc/Interval.cpp
|
||||
${LIBRARY_DIR}/misc/IntervalSet.cpp
|
||||
${LIBRARY_DIR}/misc/MurmurHash.cpp
|
||||
${LIBRARY_DIR}/misc/Predicate.cpp
|
||||
${LIBRARY_DIR}/NoViableAltException.cpp
|
||||
${LIBRARY_DIR}/Parser.cpp
|
||||
${LIBRARY_DIR}/ParserInterpreter.cpp
|
||||
${LIBRARY_DIR}/ParserRuleContext.cpp
|
||||
${LIBRARY_DIR}/ProxyErrorListener.cpp
|
||||
${LIBRARY_DIR}/RecognitionException.cpp
|
||||
${LIBRARY_DIR}/Recognizer.cpp
|
||||
${LIBRARY_DIR}/RuleContext.cpp
|
||||
${LIBRARY_DIR}/RuleContextWithAltNum.cpp
|
||||
${LIBRARY_DIR}/RuntimeMetaData.cpp
|
||||
${LIBRARY_DIR}/support/Any.cpp
|
||||
${LIBRARY_DIR}/support/Arrays.cpp
|
||||
${LIBRARY_DIR}/support/CPPUtils.cpp
|
||||
${LIBRARY_DIR}/support/guid.cpp
|
||||
${LIBRARY_DIR}/support/StringUtils.cpp
|
||||
${LIBRARY_DIR}/Token.cpp
|
||||
${LIBRARY_DIR}/TokenSource.cpp
|
||||
${LIBRARY_DIR}/TokenStream.cpp
|
||||
${LIBRARY_DIR}/TokenStreamRewriter.cpp
|
||||
${LIBRARY_DIR}/tree/ErrorNode.cpp
|
||||
${LIBRARY_DIR}/tree/ErrorNodeImpl.cpp
|
||||
${LIBRARY_DIR}/tree/IterativeParseTreeWalker.cpp
|
||||
${LIBRARY_DIR}/tree/ParseTree.cpp
|
||||
${LIBRARY_DIR}/tree/ParseTreeListener.cpp
|
||||
${LIBRARY_DIR}/tree/ParseTreeVisitor.cpp
|
||||
${LIBRARY_DIR}/tree/ParseTreeWalker.cpp
|
||||
${LIBRARY_DIR}/tree/pattern/Chunk.cpp
|
||||
${LIBRARY_DIR}/tree/pattern/ParseTreeMatch.cpp
|
||||
${LIBRARY_DIR}/tree/pattern/ParseTreePattern.cpp
|
||||
${LIBRARY_DIR}/tree/pattern/ParseTreePatternMatcher.cpp
|
||||
${LIBRARY_DIR}/tree/pattern/RuleTagToken.cpp
|
||||
${LIBRARY_DIR}/tree/pattern/TagChunk.cpp
|
||||
${LIBRARY_DIR}/tree/pattern/TextChunk.cpp
|
||||
${LIBRARY_DIR}/tree/pattern/TokenTagToken.cpp
|
||||
${LIBRARY_DIR}/tree/TerminalNode.cpp
|
||||
${LIBRARY_DIR}/tree/TerminalNodeImpl.cpp
|
||||
${LIBRARY_DIR}/tree/Trees.cpp
|
||||
${LIBRARY_DIR}/tree/xpath/XPath.cpp
|
||||
${LIBRARY_DIR}/tree/xpath/XPathElement.cpp
|
||||
${LIBRARY_DIR}/tree/xpath/XPathLexer.cpp
|
||||
${LIBRARY_DIR}/tree/xpath/XPathLexerErrorListener.cpp
|
||||
${LIBRARY_DIR}/tree/xpath/XPathRuleAnywhereElement.cpp
|
||||
${LIBRARY_DIR}/tree/xpath/XPathRuleElement.cpp
|
||||
${LIBRARY_DIR}/tree/xpath/XPathTokenAnywhereElement.cpp
|
||||
${LIBRARY_DIR}/tree/xpath/XPathTokenElement.cpp
|
||||
${LIBRARY_DIR}/tree/xpath/XPathWildcardAnywhereElement.cpp
|
||||
${LIBRARY_DIR}/tree/xpath/XPathWildcardElement.cpp
|
||||
${LIBRARY_DIR}/UnbufferedCharStream.cpp
|
||||
${LIBRARY_DIR}/UnbufferedTokenStream.cpp
|
||||
${LIBRARY_DIR}/Vocabulary.cpp
|
||||
${LIBRARY_DIR}/WritableToken.cpp
|
||||
)
|
||||
|
||||
add_library (antlr4-runtime ${SRCS})
|
||||
|
||||
target_include_directories (antlr4-runtime SYSTEM PUBLIC ${LIBRARY_DIR})
|
@ -131,6 +131,7 @@ function clone_submodules
|
||||
cd "$FASTTEST_SOURCE"
|
||||
|
||||
SUBMODULES_TO_UPDATE=(
|
||||
contrib/antlr4-runtime
|
||||
contrib/boost
|
||||
contrib/zlib-ng
|
||||
contrib/libxml2
|
||||
|
@ -1,8 +1,8 @@
|
||||
#include <AggregateFunctions/parseAggregateFunctionParameters.h>
|
||||
|
||||
#include <Parsers/ASTFunction.h>
|
||||
#include <Parsers/ExpressionListParsers.h>
|
||||
#include <Parsers/parseQuery.h>
|
||||
#include <Common/typeid_cast.h>
|
||||
#include <Core/Defines.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -25,6 +25,13 @@ Array getAggregateFunctionParametersArray(const ASTPtr & expression_list, const
|
||||
for (size_t i = 0; i < parameters.size(); ++i)
|
||||
{
|
||||
const auto * literal = parameters[i]->as<ASTLiteral>();
|
||||
|
||||
ASTPtr func_literal;
|
||||
if (!literal)
|
||||
if (const auto * func = parameters[i]->as<ASTFunction>())
|
||||
if ((func_literal = func->toLiteral()))
|
||||
literal = func_literal->as<ASTLiteral>();
|
||||
|
||||
if (!literal)
|
||||
{
|
||||
throw Exception(
|
||||
|
@ -6,18 +6,6 @@ if (USE_CLANG_TIDY)
|
||||
set (CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_PATH}")
|
||||
endif ()
|
||||
|
||||
if(COMPILER_PIPE)
|
||||
set(MAX_COMPILER_MEMORY 2500)
|
||||
else()
|
||||
set(MAX_COMPILER_MEMORY 1500)
|
||||
endif()
|
||||
if(MAKE_STATIC_LIBRARIES)
|
||||
set(MAX_LINKER_MEMORY 3500)
|
||||
else()
|
||||
set(MAX_LINKER_MEMORY 2500)
|
||||
endif()
|
||||
include(../cmake/limit_jobs.cmake)
|
||||
|
||||
set (CONFIG_VERSION ${CMAKE_CURRENT_BINARY_DIR}/Common/config_version.h)
|
||||
set (CONFIG_COMMON ${CMAKE_CURRENT_BINARY_DIR}/Common/config.h)
|
||||
|
||||
@ -49,6 +37,7 @@ add_subdirectory (Dictionaries)
|
||||
add_subdirectory (Disks)
|
||||
add_subdirectory (Storages)
|
||||
add_subdirectory (Parsers)
|
||||
add_subdirectory (Parsers/New)
|
||||
add_subdirectory (IO)
|
||||
add_subdirectory (Functions)
|
||||
add_subdirectory (Interpreters)
|
||||
@ -186,12 +175,12 @@ endif()
|
||||
|
||||
if (MAKE_STATIC_LIBRARIES OR NOT SPLIT_SHARED_LIBRARIES)
|
||||
add_library (dbms STATIC ${dbms_headers} ${dbms_sources})
|
||||
target_link_libraries (dbms PRIVATE jemalloc libdivide ${DBMS_COMMON_LIBRARIES})
|
||||
target_link_libraries (dbms PRIVATE clickhouse_parsers_new jemalloc libdivide ${DBMS_COMMON_LIBRARIES})
|
||||
set (all_modules dbms)
|
||||
else()
|
||||
add_library (dbms SHARED ${dbms_headers} ${dbms_sources})
|
||||
target_link_libraries (dbms PUBLIC ${all_modules} ${DBMS_COMMON_LIBRARIES})
|
||||
target_link_libraries (clickhouse_interpreters PRIVATE jemalloc libdivide)
|
||||
target_link_libraries (clickhouse_interpreters PRIVATE clickhouse_parsers_new jemalloc libdivide)
|
||||
list (APPEND all_modules dbms)
|
||||
# force all split libs to be linked
|
||||
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-as-needed")
|
||||
|
@ -799,9 +799,8 @@ namespace MySQLReplication
|
||||
break;
|
||||
}
|
||||
case WRITE_ROWS_EVENT_V1:
|
||||
case WRITE_ROWS_EVENT_V2:
|
||||
{
|
||||
if (do_replicate())
|
||||
case WRITE_ROWS_EVENT_V2: {
|
||||
if (doReplicate())
|
||||
event = std::make_shared<WriteRowsEvent>(table_map, std::move(event_header));
|
||||
else
|
||||
event = std::make_shared<DryRunEvent>(std::move(event_header));
|
||||
@ -810,9 +809,8 @@ namespace MySQLReplication
|
||||
break;
|
||||
}
|
||||
case DELETE_ROWS_EVENT_V1:
|
||||
case DELETE_ROWS_EVENT_V2:
|
||||
{
|
||||
if (do_replicate())
|
||||
case DELETE_ROWS_EVENT_V2: {
|
||||
if (doReplicate())
|
||||
event = std::make_shared<DeleteRowsEvent>(table_map, std::move(event_header));
|
||||
else
|
||||
event = std::make_shared<DryRunEvent>(std::move(event_header));
|
||||
@ -821,9 +819,8 @@ namespace MySQLReplication
|
||||
break;
|
||||
}
|
||||
case UPDATE_ROWS_EVENT_V1:
|
||||
case UPDATE_ROWS_EVENT_V2:
|
||||
{
|
||||
if (do_replicate())
|
||||
case UPDATE_ROWS_EVENT_V2: {
|
||||
if (doReplicate())
|
||||
event = std::make_shared<UpdateRowsEvent>(table_map, std::move(event_header));
|
||||
else
|
||||
event = std::make_shared<DryRunEvent>(std::move(event_header));
|
||||
|
@ -549,7 +549,7 @@ namespace MySQLReplication
|
||||
std::shared_ptr<TableMapEvent> table_map;
|
||||
size_t checksum_signature_length = 4;
|
||||
|
||||
inline bool do_replicate() { return (replicate_do_db.empty() || table_map->schema == replicate_do_db); }
|
||||
inline bool doReplicate() { return (replicate_do_db.empty() || table_map->schema == replicate_do_db); }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -399,6 +399,8 @@ class IColumn;
|
||||
M(Bool, enable_global_with_statement, false, "Propagate WITH statements to UNION queries and all subqueries", 0) \
|
||||
M(Bool, aggregate_functions_null_for_empty, false, "Rewrite all aggregate functions in a query, adding -OrNull suffix to them", 0) \
|
||||
\
|
||||
M(Bool, use_antlr_parser, false, "Parse incoming queries using ANTLR-generated parser", 0) \
|
||||
\
|
||||
/** Obsolete settings that do nothing but left for compatibility reasons. Remove each one after half a year of obsolescence. */ \
|
||||
\
|
||||
M(UInt64, max_memory_usage_for_all_queries, 0, "Obsolete. Will be removed after 2020-10-20", 0) \
|
||||
|
@ -357,20 +357,23 @@ static DataTypePtr create(const ASTPtr & arguments)
|
||||
throw Exception("Unexpected level of parameters to aggregate function", ErrorCodes::SYNTAX_ERROR);
|
||||
function_name = parametric->name;
|
||||
|
||||
const ASTs & parameters = parametric->arguments->children;
|
||||
params_row.resize(parameters.size());
|
||||
|
||||
for (size_t i = 0; i < parameters.size(); ++i)
|
||||
if (parametric->arguments)
|
||||
{
|
||||
const auto * literal = parameters[i]->as<ASTLiteral>();
|
||||
if (!literal)
|
||||
throw Exception(
|
||||
ErrorCodes::PARAMETERS_TO_AGGREGATE_FUNCTIONS_MUST_BE_LITERALS,
|
||||
"Parameters to aggregate functions must be literals. "
|
||||
"Got parameter '{}' for function '{}'",
|
||||
parameters[i]->formatForErrorMessage(), function_name);
|
||||
const ASTs & parameters = parametric->arguments->children;
|
||||
params_row.resize(parameters.size());
|
||||
|
||||
params_row[i] = literal->value;
|
||||
for (size_t i = 0; i < parameters.size(); ++i)
|
||||
{
|
||||
const auto * literal = parameters[i]->as<ASTLiteral>();
|
||||
if (!literal)
|
||||
throw Exception(
|
||||
ErrorCodes::PARAMETERS_TO_AGGREGATE_FUNCTIONS_MUST_BE_LITERALS,
|
||||
"Parameters to aggregate functions must be literals. "
|
||||
"Got parameter '{}' for function '{}'",
|
||||
parameters[i]->formatForErrorMessage(), function_name);
|
||||
|
||||
params_row[i] = literal->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (auto opt_name = tryGetIdentifierName(arguments->children[0]))
|
||||
|
@ -72,20 +72,24 @@ static std::pair<DataTypePtr, DataTypeCustomDescPtr> create(const ASTPtr & argum
|
||||
throw Exception("Unexpected level of parameters to aggregate function", ErrorCodes::SYNTAX_ERROR);
|
||||
function_name = parametric->name;
|
||||
|
||||
const ASTs & parameters = parametric->arguments->as<ASTExpressionList &>().children;
|
||||
params_row.resize(parameters.size());
|
||||
|
||||
for (size_t i = 0; i < parameters.size(); ++i)
|
||||
if (parametric->arguments)
|
||||
{
|
||||
const ASTLiteral * lit = parameters[i]->as<ASTLiteral>();
|
||||
if (!lit)
|
||||
throw Exception(
|
||||
ErrorCodes::PARAMETERS_TO_AGGREGATE_FUNCTIONS_MUST_BE_LITERALS,
|
||||
"Parameters to aggregate functions must be literals. "
|
||||
"Got parameter '{}' for function '{}'",
|
||||
parameters[i]->formatForErrorMessage(), function_name);
|
||||
const ASTs & parameters = parametric->arguments->as<ASTExpressionList &>().children;
|
||||
params_row.resize(parameters.size());
|
||||
|
||||
params_row[i] = lit->value;
|
||||
for (size_t i = 0; i < parameters.size(); ++i)
|
||||
{
|
||||
const ASTLiteral * lit = parameters[i]->as<ASTLiteral>();
|
||||
if (!lit)
|
||||
throw Exception(
|
||||
ErrorCodes::PARAMETERS_TO_AGGREGATE_FUNCTIONS_MUST_BE_LITERALS,
|
||||
"Parameters to aggregate functions must be literals. "
|
||||
"Got parameter '{}' for function '{}'",
|
||||
parameters[i]->formatForErrorMessage(),
|
||||
function_name);
|
||||
|
||||
params_row[i] = lit->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (auto opt_name = tryGetIdentifierName(arguments->children[0]))
|
||||
|
@ -99,38 +99,40 @@ void buildLayoutConfiguration(
|
||||
root->appendChild(layout_element);
|
||||
AutoPtr<Element> layout_type_element(doc->createElement(layout->layout_type));
|
||||
layout_element->appendChild(layout_type_element);
|
||||
for (const auto & param : layout->parameters->children)
|
||||
{
|
||||
const ASTPair * pair = param->as<ASTPair>();
|
||||
if (!pair)
|
||||
|
||||
if (layout->parameters)
|
||||
for (const auto & param : layout->parameters->children)
|
||||
{
|
||||
throw DB::Exception(ErrorCodes::BAD_ARGUMENTS, "Dictionary layout parameters must be key/value pairs, got '{}' instead",
|
||||
param->formatForErrorMessage());
|
||||
const ASTPair * pair = param->as<ASTPair>();
|
||||
if (!pair)
|
||||
{
|
||||
throw DB::Exception(ErrorCodes::BAD_ARGUMENTS, "Dictionary layout parameters must be key/value pairs, got '{}' instead",
|
||||
param->formatForErrorMessage());
|
||||
}
|
||||
|
||||
const ASTLiteral * value_literal = pair->second->as<ASTLiteral>();
|
||||
if (!value_literal)
|
||||
{
|
||||
throw DB::Exception(ErrorCodes::BAD_ARGUMENTS,
|
||||
"Dictionary layout parameter value must be a literal, got '{}' instead",
|
||||
pair->second->formatForErrorMessage());
|
||||
}
|
||||
|
||||
const auto value_field = value_literal->value;
|
||||
|
||||
if (value_field.getType() != Field::Types::UInt64
|
||||
&& value_field.getType() != Field::Types::String)
|
||||
{
|
||||
throw DB::Exception(ErrorCodes::BAD_ARGUMENTS,
|
||||
"Dictionary layout parameter value must be an UInt64 or String, got '{}' instead",
|
||||
value_field.getTypeName());
|
||||
}
|
||||
|
||||
AutoPtr<Element> layout_type_parameter_element(doc->createElement(pair->first));
|
||||
AutoPtr<Text> value_to_append(doc->createTextNode(toString(value_field)));
|
||||
layout_type_parameter_element->appendChild(value_to_append);
|
||||
layout_type_element->appendChild(layout_type_parameter_element);
|
||||
}
|
||||
|
||||
const ASTLiteral * value_literal = pair->second->as<ASTLiteral>();
|
||||
if (!value_literal)
|
||||
{
|
||||
throw DB::Exception(ErrorCodes::BAD_ARGUMENTS,
|
||||
"Dictionary layout parameter value must be a literal, got '{}' instead",
|
||||
pair->second->formatForErrorMessage());
|
||||
}
|
||||
|
||||
const auto value_field = value_literal->value;
|
||||
|
||||
if (value_field.getType() != Field::Types::UInt64
|
||||
&& value_field.getType() != Field::Types::String)
|
||||
{
|
||||
throw DB::Exception(ErrorCodes::BAD_ARGUMENTS,
|
||||
"Dictionary layout parameter value must be an UInt64 or String, got '{}' instead",
|
||||
value_field.getTypeName());
|
||||
}
|
||||
|
||||
AutoPtr<Element> layout_type_parameter_element(doc->createElement(pair->first));
|
||||
AutoPtr<Text> value_to_append(doc->createTextNode(toString(value_field)));
|
||||
layout_type_parameter_element->appendChild(value_to_append);
|
||||
layout_type_element->appendChild(layout_type_parameter_element);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -141,16 +141,16 @@ struct NumericArraySource : public ArraySourceImpl<NumericArraySource<T>>
|
||||
|
||||
/// The methods can be virtual or not depending on the template parameter. See IStringSource.
|
||||
#if !__clang__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wsuggest-override"
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wsuggest-override"
|
||||
#elif __clang_major__ >= 11
|
||||
#pragma GCC diagnostic push
|
||||
#ifdef HAS_SUGGEST_OVERRIDE
|
||||
#pragma GCC diagnostic ignored "-Wsuggest-override"
|
||||
#endif
|
||||
#ifdef HAS_SUGGEST_DESTRUCTOR_OVERRIDE
|
||||
#pragma GCC diagnostic ignored "-Wsuggest-destructor-override"
|
||||
#endif
|
||||
# pragma GCC diagnostic push
|
||||
# ifdef HAS_SUGGEST_OVERRIDE
|
||||
# pragma GCC diagnostic ignored "-Wsuggest-override"
|
||||
# endif
|
||||
# ifdef HAS_SUGGEST_DESTRUCTOR_OVERRIDE
|
||||
# pragma GCC diagnostic ignored "-Wsuggest-destructor-override"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
template <typename Base>
|
||||
@ -234,7 +234,7 @@ struct ConstSource : public Base
|
||||
};
|
||||
|
||||
#if !__clang__ || __clang_major__ >= 11
|
||||
#pragma GCC diagnostic pop
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
struct StringSource
|
||||
@ -355,9 +355,9 @@ struct UTF8StringSource : public StringSource
|
||||
|
||||
Slice getSliceFromLeft(size_t offset) const
|
||||
{
|
||||
auto begin = &elements[prev_offset];
|
||||
auto end = elements.data() + offsets[row_num] - 1;
|
||||
auto res_begin = skipCodePointsForward(begin, offset, end);
|
||||
const auto * begin = &elements[prev_offset];
|
||||
const auto * end = elements.data() + offsets[row_num] - 1;
|
||||
const auto * res_begin = skipCodePointsForward(begin, offset, end);
|
||||
|
||||
if (res_begin >= end)
|
||||
return {begin, 0};
|
||||
@ -367,14 +367,14 @@ struct UTF8StringSource : public StringSource
|
||||
|
||||
Slice getSliceFromLeft(size_t offset, size_t length) const
|
||||
{
|
||||
auto begin = &elements[prev_offset];
|
||||
auto end = elements.data() + offsets[row_num] - 1;
|
||||
auto res_begin = skipCodePointsForward(begin, offset, end);
|
||||
const auto * begin = &elements[prev_offset];
|
||||
const auto * end = elements.data() + offsets[row_num] - 1;
|
||||
const auto * res_begin = skipCodePointsForward(begin, offset, end);
|
||||
|
||||
if (res_begin >= end)
|
||||
return {begin, 0};
|
||||
|
||||
auto res_end = skipCodePointsForward(res_begin, length, end);
|
||||
const auto * res_end = skipCodePointsForward(res_begin, length, end);
|
||||
|
||||
if (res_end >= end)
|
||||
return {res_begin, size_t(end - res_begin)};
|
||||
@ -384,19 +384,19 @@ struct UTF8StringSource : public StringSource
|
||||
|
||||
Slice getSliceFromRight(size_t offset) const
|
||||
{
|
||||
auto begin = &elements[prev_offset];
|
||||
auto end = elements.data() + offsets[row_num] - 1;
|
||||
auto res_begin = skipCodePointsBackward(end, offset, begin);
|
||||
const auto * begin = &elements[prev_offset];
|
||||
const auto * end = elements.data() + offsets[row_num] - 1;
|
||||
const auto * res_begin = skipCodePointsBackward(end, offset, begin);
|
||||
|
||||
return {res_begin, size_t(end - res_begin)};
|
||||
}
|
||||
|
||||
Slice getSliceFromRight(size_t offset, size_t length) const
|
||||
{
|
||||
auto begin = &elements[prev_offset];
|
||||
auto end = elements.data() + offsets[row_num] - 1;
|
||||
auto res_begin = skipCodePointsBackward(end, offset, begin);
|
||||
auto res_end = skipCodePointsForward(res_begin, length, end);
|
||||
const auto * begin = &elements[prev_offset];
|
||||
const auto * end = elements.data() + offsets[row_num] - 1;
|
||||
const auto * res_begin = skipCodePointsBackward(end, offset, begin);
|
||||
const auto * res_end = skipCodePointsForward(res_begin, length, end);
|
||||
|
||||
if (res_end >= end)
|
||||
return {res_begin, size_t(end - res_begin)};
|
||||
@ -495,7 +495,7 @@ struct IStringSource
|
||||
virtual bool isEnd() const = 0;
|
||||
virtual size_t getSizeForReserve() const = 0;
|
||||
virtual Slice getWhole() const = 0;
|
||||
virtual ~IStringSource() {}
|
||||
virtual ~IStringSource() = default;
|
||||
};
|
||||
|
||||
|
||||
|
@ -757,39 +757,102 @@ void ActionsMatcher::visit(const ASTFunction & node, const ASTPtr & ast, Data &
|
||||
|
||||
/// If the function has an argument-lambda expression, you need to determine its type before the recursive call.
|
||||
bool has_lambda_arguments = false;
|
||||
size_t num_arguments = node.arguments->children.size();
|
||||
for (size_t arg = 0; arg < num_arguments; ++arg)
|
||||
|
||||
if (node.arguments)
|
||||
{
|
||||
auto & child = node.arguments->children[arg];
|
||||
|
||||
const auto * function = child->as<ASTFunction>();
|
||||
const auto * identifier = child->as<ASTIdentifier>();
|
||||
if (function && function->name == "lambda")
|
||||
size_t num_arguments = node.arguments->children.size();
|
||||
for (size_t arg = 0; arg < num_arguments; ++arg)
|
||||
{
|
||||
/// If the argument is a lambda expression, just remember its approximate type.
|
||||
if (function->arguments->children.size() != 2)
|
||||
throw Exception("lambda requires two arguments", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||
auto & child = node.arguments->children[arg];
|
||||
|
||||
const auto * lambda_args_tuple = function->arguments->children.at(0)->as<ASTFunction>();
|
||||
|
||||
if (!lambda_args_tuple || lambda_args_tuple->name != "tuple")
|
||||
throw Exception("First argument of lambda must be a tuple", ErrorCodes::TYPE_MISMATCH);
|
||||
|
||||
has_lambda_arguments = true;
|
||||
argument_types.emplace_back(std::make_shared<DataTypeFunction>(DataTypes(lambda_args_tuple->arguments->children.size())));
|
||||
/// Select the name in the next cycle.
|
||||
argument_names.emplace_back();
|
||||
}
|
||||
else if (function && function->name == "untuple")
|
||||
{
|
||||
auto columns = doUntuple(function, data);
|
||||
|
||||
if (columns.empty())
|
||||
continue;
|
||||
|
||||
for (const auto & column : columns)
|
||||
const auto * function = child->as<ASTFunction>();
|
||||
const auto * identifier = child->as<ASTIdentifier>();
|
||||
if (function && function->name == "lambda")
|
||||
{
|
||||
if (auto name_type = getNameAndTypeFromAST(column, data))
|
||||
/// If the argument is a lambda expression, just remember its approximate type.
|
||||
if (function->arguments->children.size() != 2)
|
||||
throw Exception("lambda requires two arguments", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||
|
||||
const auto * lambda_args_tuple = function->arguments->children.at(0)->as<ASTFunction>();
|
||||
|
||||
if (!lambda_args_tuple || lambda_args_tuple->name != "tuple")
|
||||
throw Exception("First argument of lambda must be a tuple", ErrorCodes::TYPE_MISMATCH);
|
||||
|
||||
has_lambda_arguments = true;
|
||||
argument_types.emplace_back(std::make_shared<DataTypeFunction>(DataTypes(lambda_args_tuple->arguments->children.size())));
|
||||
/// Select the name in the next cycle.
|
||||
argument_names.emplace_back();
|
||||
}
|
||||
else if (function && function->name == "untuple")
|
||||
{
|
||||
auto columns = doUntuple(function, data);
|
||||
|
||||
if (columns.empty())
|
||||
continue;
|
||||
|
||||
for (const auto & column : columns)
|
||||
{
|
||||
if (auto name_type = getNameAndTypeFromAST(column, data))
|
||||
{
|
||||
argument_types.push_back(name_type->type);
|
||||
argument_names.push_back(name_type->name);
|
||||
}
|
||||
else
|
||||
arguments_present = false;
|
||||
}
|
||||
|
||||
node.arguments->children.erase(node.arguments->children.begin() + arg);
|
||||
node.arguments->children.insert(node.arguments->children.begin() + arg, columns.begin(), columns.end());
|
||||
num_arguments += columns.size() - 1;
|
||||
arg += columns.size() - 1;
|
||||
}
|
||||
else if (checkFunctionIsInOrGlobalInOperator(node) && arg == 1 && prepared_set)
|
||||
{
|
||||
ColumnWithTypeAndName column;
|
||||
column.type = std::make_shared<DataTypeSet>();
|
||||
|
||||
/// If the argument is a set given by an enumeration of values (so, the set was already built), give it a unique name,
|
||||
/// so that sets with the same literal representation do not fuse together (they can have different types).
|
||||
if (!prepared_set->empty())
|
||||
column.name = data.getUniqueName("__set");
|
||||
else
|
||||
column.name = child->getColumnName();
|
||||
|
||||
if (!data.hasColumn(column.name))
|
||||
{
|
||||
auto column_set = ColumnSet::create(1, prepared_set);
|
||||
/// If prepared_set is not empty, we have a set made with literals.
|
||||
/// Create a const ColumnSet to make constant folding work
|
||||
if (!prepared_set->empty())
|
||||
column.column = ColumnConst::create(std::move(column_set), 1);
|
||||
else
|
||||
column.column = std::move(column_set);
|
||||
data.addColumn(column);
|
||||
}
|
||||
|
||||
argument_types.push_back(column.type);
|
||||
argument_names.push_back(column.name);
|
||||
}
|
||||
else if (identifier && (functionIsJoinGet(node.name) || functionIsDictGet(node.name)) && arg == 0)
|
||||
{
|
||||
auto table_id = IdentifierSemantic::extractDatabaseAndTable(*identifier);
|
||||
table_id = data.context.resolveStorageID(table_id, Context::ResolveOrdinary);
|
||||
auto column_string = ColumnString::create();
|
||||
column_string->insert(table_id.getDatabaseName() + "." + table_id.getTableName());
|
||||
ColumnWithTypeAndName column(
|
||||
ColumnConst::create(std::move(column_string), 1),
|
||||
std::make_shared<DataTypeString>(),
|
||||
data.getUniqueName("__" + node.name));
|
||||
data.addColumn(column);
|
||||
argument_types.push_back(column.type);
|
||||
argument_names.push_back(column.name);
|
||||
}
|
||||
else
|
||||
{
|
||||
/// If the argument is not a lambda expression, call it recursively and find out its type.
|
||||
visit(child, data);
|
||||
|
||||
if (auto name_type = getNameAndTypeFromAST(child, data))
|
||||
{
|
||||
argument_types.push_back(name_type->type);
|
||||
argument_names.push_back(name_type->name);
|
||||
@ -797,125 +860,66 @@ void ActionsMatcher::visit(const ASTFunction & node, const ASTPtr & ast, Data &
|
||||
else
|
||||
arguments_present = false;
|
||||
}
|
||||
|
||||
node.arguments->children.erase(node.arguments->children.begin() + arg);
|
||||
node.arguments->children.insert(node.arguments->children.begin() + arg, columns.begin(), columns.end());
|
||||
num_arguments += columns.size() - 1;
|
||||
arg += columns.size() - 1;
|
||||
}
|
||||
else if (checkFunctionIsInOrGlobalInOperator(node) && arg == 1 && prepared_set)
|
||||
|
||||
if (data.only_consts && !arguments_present)
|
||||
return;
|
||||
|
||||
if (has_lambda_arguments && !data.only_consts)
|
||||
{
|
||||
ColumnWithTypeAndName column;
|
||||
column.type = std::make_shared<DataTypeSet>();
|
||||
function_builder->getLambdaArgumentTypes(argument_types);
|
||||
|
||||
/// If the argument is a set given by an enumeration of values (so, the set was already built), give it a unique name,
|
||||
/// so that sets with the same literal representation do not fuse together (they can have different types).
|
||||
if (!prepared_set->empty())
|
||||
column.name = data.getUniqueName("__set");
|
||||
else
|
||||
column.name = child->getColumnName();
|
||||
|
||||
if (!data.hasColumn(column.name))
|
||||
/// Call recursively for lambda expressions.
|
||||
for (size_t i = 0; i < node.arguments->children.size(); ++i)
|
||||
{
|
||||
auto column_set = ColumnSet::create(1, prepared_set);
|
||||
/// If prepared_set is not empty, we have a set made with literals.
|
||||
/// Create a const ColumnSet to make constant folding work
|
||||
if (!prepared_set->empty())
|
||||
column.column = ColumnConst::create(std::move(column_set), 1);
|
||||
else
|
||||
column.column = std::move(column_set);
|
||||
data.addColumn(column);
|
||||
}
|
||||
ASTPtr child = node.arguments->children[i];
|
||||
|
||||
argument_types.push_back(column.type);
|
||||
argument_names.push_back(column.name);
|
||||
}
|
||||
else if (identifier && (functionIsJoinGet(node.name) || functionIsDictGet(node.name)) && arg == 0)
|
||||
{
|
||||
auto table_id = IdentifierSemantic::extractDatabaseAndTable(*identifier);
|
||||
table_id = data.context.resolveStorageID(table_id, Context::ResolveOrdinary);
|
||||
auto column_string = ColumnString::create();
|
||||
column_string->insert(table_id.getDatabaseName() + "." + table_id.getTableName());
|
||||
ColumnWithTypeAndName column(
|
||||
ColumnConst::create(std::move(column_string), 1),
|
||||
std::make_shared<DataTypeString>(),
|
||||
data.getUniqueName("__" + node.name));
|
||||
data.addColumn(column);
|
||||
argument_types.push_back(column.type);
|
||||
argument_names.push_back(column.name);
|
||||
}
|
||||
else
|
||||
{
|
||||
/// If the argument is not a lambda expression, call it recursively and find out its type.
|
||||
visit(child, data);
|
||||
|
||||
if (auto name_type = getNameAndTypeFromAST(child, data))
|
||||
{
|
||||
argument_types.push_back(name_type->type);
|
||||
argument_names.push_back(name_type->name);
|
||||
}
|
||||
else
|
||||
arguments_present = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (data.only_consts && !arguments_present)
|
||||
return;
|
||||
|
||||
if (has_lambda_arguments && !data.only_consts)
|
||||
{
|
||||
function_builder->getLambdaArgumentTypes(argument_types);
|
||||
|
||||
/// Call recursively for lambda expressions.
|
||||
for (size_t i = 0; i < node.arguments->children.size(); ++i)
|
||||
{
|
||||
ASTPtr child = node.arguments->children[i];
|
||||
|
||||
const auto * lambda = child->as<ASTFunction>();
|
||||
if (lambda && lambda->name == "lambda")
|
||||
{
|
||||
const DataTypeFunction * lambda_type = typeid_cast<const DataTypeFunction *>(argument_types[i].get());
|
||||
const auto * lambda_args_tuple = lambda->arguments->children.at(0)->as<ASTFunction>();
|
||||
const ASTs & lambda_arg_asts = lambda_args_tuple->arguments->children;
|
||||
NamesAndTypesList lambda_arguments;
|
||||
|
||||
for (size_t j = 0; j < lambda_arg_asts.size(); ++j)
|
||||
const auto * lambda = child->as<ASTFunction>();
|
||||
if (lambda && lambda->name == "lambda")
|
||||
{
|
||||
auto opt_arg_name = tryGetIdentifierName(lambda_arg_asts[j]);
|
||||
if (!opt_arg_name)
|
||||
throw Exception("lambda argument declarations must be identifiers", ErrorCodes::TYPE_MISMATCH);
|
||||
const DataTypeFunction * lambda_type = typeid_cast<const DataTypeFunction *>(argument_types[i].get());
|
||||
const auto * lambda_args_tuple = lambda->arguments->children.at(0)->as<ASTFunction>();
|
||||
const ASTs & lambda_arg_asts = lambda_args_tuple->arguments->children;
|
||||
NamesAndTypesList lambda_arguments;
|
||||
|
||||
lambda_arguments.emplace_back(*opt_arg_name, lambda_type->getArgumentTypes()[j]);
|
||||
for (size_t j = 0; j < lambda_arg_asts.size(); ++j)
|
||||
{
|
||||
auto opt_arg_name = tryGetIdentifierName(lambda_arg_asts[j]);
|
||||
if (!opt_arg_name)
|
||||
throw Exception("lambda argument declarations must be identifiers", ErrorCodes::TYPE_MISMATCH);
|
||||
|
||||
lambda_arguments.emplace_back(*opt_arg_name, lambda_type->getArgumentTypes()[j]);
|
||||
}
|
||||
|
||||
data.actions_stack.pushLevel(lambda_arguments);
|
||||
visit(lambda->arguments->children.at(1), data);
|
||||
auto lambda_dag = data.actions_stack.popLevel();
|
||||
|
||||
String result_name = lambda->arguments->children.at(1)->getColumnName();
|
||||
lambda_dag->removeUnusedActions(Names(1, result_name));
|
||||
|
||||
auto lambda_actions = std::make_shared<ExpressionActions>(lambda_dag);
|
||||
|
||||
DataTypePtr result_type = lambda_actions->getSampleBlock().getByName(result_name).type;
|
||||
|
||||
Names captured;
|
||||
Names required = lambda_actions->getRequiredColumns();
|
||||
for (const auto & required_arg : required)
|
||||
if (findColumn(required_arg, lambda_arguments) == lambda_arguments.end())
|
||||
captured.push_back(required_arg);
|
||||
|
||||
/// We can not name `getColumnName()`,
|
||||
/// because it does not uniquely define the expression (the types of arguments can be different).
|
||||
String lambda_name = data.getUniqueName("__lambda");
|
||||
|
||||
auto function_capture = std::make_unique<FunctionCaptureOverloadResolver>(
|
||||
lambda_actions, captured, lambda_arguments, result_type, result_name);
|
||||
auto function_capture_adapter = std::make_shared<FunctionOverloadResolverAdaptor>(std::move(function_capture));
|
||||
data.addFunction(function_capture_adapter, captured, lambda_name);
|
||||
|
||||
argument_types[i] = std::make_shared<DataTypeFunction>(lambda_type->getArgumentTypes(), result_type);
|
||||
argument_names[i] = lambda_name;
|
||||
}
|
||||
|
||||
data.actions_stack.pushLevel(lambda_arguments);
|
||||
visit(lambda->arguments->children.at(1), data);
|
||||
auto lambda_dag = data.actions_stack.popLevel();
|
||||
|
||||
String result_name = lambda->arguments->children.at(1)->getColumnName();
|
||||
lambda_dag->removeUnusedActions(Names(1, result_name));
|
||||
|
||||
auto lambda_actions = std::make_shared<ExpressionActions>(lambda_dag);
|
||||
|
||||
DataTypePtr result_type = lambda_actions->getSampleBlock().getByName(result_name).type;
|
||||
|
||||
Names captured;
|
||||
Names required = lambda_actions->getRequiredColumns();
|
||||
for (const auto & required_arg : required)
|
||||
if (findColumn(required_arg, lambda_arguments) == lambda_arguments.end())
|
||||
captured.push_back(required_arg);
|
||||
|
||||
/// We can not name `getColumnName()`,
|
||||
/// because it does not uniquely define the expression (the types of arguments can be different).
|
||||
String lambda_name = data.getUniqueName("__lambda");
|
||||
|
||||
auto function_capture = std::make_unique<FunctionCaptureOverloadResolver>(
|
||||
lambda_actions, captured, lambda_arguments, result_type, result_name);
|
||||
auto function_capture_adapter = std::make_shared<FunctionOverloadResolverAdaptor>(std::move(function_capture));
|
||||
data.addFunction(function_capture_adapter, captured, lambda_name);
|
||||
|
||||
argument_types[i] = std::make_shared<DataTypeFunction>(lambda_type->getArgumentTypes(), result_type);
|
||||
argument_names[i] = lambda_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,10 +97,10 @@ public:
|
||||
function_node->name == "any" || function_node->name == "anyLast"))
|
||||
{
|
||||
KeepAggregateFunctionVisitor::Data keep_data{data.group_by_keys, false};
|
||||
KeepAggregateFunctionVisitor(keep_data).visit(function_node->arguments);
|
||||
if (function_node->arguments) KeepAggregateFunctionVisitor(keep_data).visit(function_node->arguments);
|
||||
|
||||
/// Place argument of an aggregate function instead of function
|
||||
if (!keep_data.keep_aggregator && !function_node->arguments->children.empty())
|
||||
if (!keep_data.keep_aggregator && function_node->arguments && !function_node->arguments->children.empty())
|
||||
{
|
||||
String alias = function_node->alias;
|
||||
ast = (function_node->arguments->children[0])->clone();
|
||||
|
@ -20,7 +20,7 @@ namespace
|
||||
|
||||
const ASTFunction * getInternalFunction(const ASTFunction & func)
|
||||
{
|
||||
if (func.arguments->children.size() == 1)
|
||||
if (func.arguments && func.arguments->children.size() == 1)
|
||||
return func.arguments->children[0]->as<ASTFunction>();
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1412,9 +1412,9 @@ BlockIO executeDDLQueryOnCluster(const ASTPtr & query_ptr_, const Context & cont
|
||||
|
||||
if (const auto * query_alter = query_ptr->as<ASTAlterQuery>())
|
||||
{
|
||||
for (const auto & command : query_alter->command_list->commands)
|
||||
for (const auto & command : query_alter->command_list->children)
|
||||
{
|
||||
if (!isSupportedAlterType(command->type))
|
||||
if (!isSupportedAlterType(command->as<ASTAlterCommand&>().type))
|
||||
throw Exception("Unsupported type of ALTER query", ErrorCodes::NOT_IMPLEMENTED);
|
||||
}
|
||||
}
|
||||
|
@ -423,11 +423,11 @@ bool ExpressionAnalyzer::makeAggregateDescriptions(ActionsDAGPtr & actions)
|
||||
for (const ASTFunction * node : aggregates())
|
||||
{
|
||||
AggregateDescription aggregate;
|
||||
getRootActionsNoMakeSet(node->arguments, true, actions);
|
||||
if (node->arguments) getRootActionsNoMakeSet(node->arguments, true, actions);
|
||||
|
||||
aggregate.column_name = node->getColumnName();
|
||||
|
||||
const ASTs & arguments = node->arguments->children;
|
||||
const ASTs & arguments = node->arguments ? node->arguments->children : ASTs();
|
||||
aggregate.argument_names.resize(arguments.size());
|
||||
DataTypes types(arguments.size());
|
||||
|
||||
@ -820,8 +820,9 @@ void SelectQueryExpressionAnalyzer::appendAggregateFunctionsArguments(Expression
|
||||
|
||||
/// TODO: data.aggregates -> aggregates()
|
||||
for (const ASTFunction * node : data.aggregates)
|
||||
for (auto & argument : node->arguments->children)
|
||||
getRootActions(argument, only_types, step.actions());
|
||||
if (node->arguments)
|
||||
for (auto & argument : node->arguments->children)
|
||||
getRootActions(argument, only_types, step.actions());
|
||||
}
|
||||
|
||||
bool SelectQueryExpressionAnalyzer::appendHaving(ExpressionActionsChain & chain, bool only_types)
|
||||
|
@ -105,7 +105,7 @@ public:
|
||||
{
|
||||
if (auto * function_node = ast->as<ASTFunction>())
|
||||
{
|
||||
if (!(function_node->arguments->children.empty()))
|
||||
if (function_node->arguments && !function_node->arguments->children.empty())
|
||||
visit(function_node, data);
|
||||
}
|
||||
}
|
||||
|
@ -56,8 +56,9 @@ BlockIO InterpreterAlterQuery::execute()
|
||||
PartitionCommands partition_commands;
|
||||
MutationCommands mutation_commands;
|
||||
LiveViewCommands live_view_commands;
|
||||
for (ASTAlterCommand * command_ast : alter.command_list->commands)
|
||||
for (const auto & child : alter.command_list->children)
|
||||
{
|
||||
auto * command_ast = child->as<ASTAlterCommand>();
|
||||
if (auto alter_command = AlterCommand::parse(command_ast))
|
||||
alter_commands.emplace_back(std::move(*alter_command));
|
||||
else if (auto partition_command = PartitionCommand::parse(command_ast))
|
||||
@ -124,8 +125,8 @@ AccessRightsElements InterpreterAlterQuery::getRequiredAccess() const
|
||||
{
|
||||
AccessRightsElements required_access;
|
||||
const auto & alter = query_ptr->as<ASTAlterQuery &>();
|
||||
for (ASTAlterCommand * command : alter.command_list->commands)
|
||||
boost::range::push_back(required_access, getRequiredAccessForCommand(*command, alter.database, alter.table));
|
||||
for (const auto & child : alter.command_list->children)
|
||||
boost::range::push_back(required_access, getRequiredAccessForCommand(child->as<ASTAlterCommand&>(), alter.database, alter.table));
|
||||
return required_access;
|
||||
}
|
||||
|
||||
|
@ -130,6 +130,7 @@ BlockIO InterpreterCreateQuery::createDatabase(ASTCreateQuery & create)
|
||||
auto engine = std::make_shared<ASTFunction>();
|
||||
auto storage = std::make_shared<ASTStorage>();
|
||||
engine->name = old_style_database ? "Ordinary" : "Atomic";
|
||||
engine->no_empty_args = true;
|
||||
storage->set(storage->engine, engine);
|
||||
create.set(create.storage, storage);
|
||||
}
|
||||
@ -600,6 +601,7 @@ void InterpreterCreateQuery::setEngine(ASTCreateQuery & create) const
|
||||
{
|
||||
auto engine_ast = std::make_shared<ASTFunction>();
|
||||
engine_ast->name = "Memory";
|
||||
engine_ast->no_empty_args = true;
|
||||
auto storage_ast = std::make_shared<ASTStorage>();
|
||||
storage_ast->set(storage_ast->engine, engine_ast);
|
||||
create.set(create.storage, storage_ast);
|
||||
|
@ -87,8 +87,7 @@ public:
|
||||
return;
|
||||
|
||||
/// TODO: monotonicity for functions of several arguments
|
||||
auto arguments = ast_function.arguments;
|
||||
if (arguments->children.size() != 1)
|
||||
if (!ast_function.arguments || ast_function.arguments->children.size() != 1)
|
||||
{
|
||||
data.reject();
|
||||
return;
|
||||
|
@ -442,10 +442,10 @@ ASTPtr MutationsInterpreter::prepare(bool dry_run)
|
||||
auto type_literal = std::make_shared<ASTLiteral>(columns_desc.getPhysical(column).type->getName());
|
||||
|
||||
const auto & update_expr = kv.second;
|
||||
auto updated_column = makeASTFunction("CAST",
|
||||
auto updated_column = makeASTFunction("cast",
|
||||
makeASTFunction("if",
|
||||
getPartitionAndPredicateExpressionForMutationCommand(command),
|
||||
makeASTFunction("CAST",
|
||||
makeASTFunction("cast",
|
||||
update_expr->clone(),
|
||||
type_literal),
|
||||
std::make_shared<ASTIdentifier>(column)),
|
||||
|
@ -478,7 +478,7 @@ ASTs InterpreterAlterImpl::getRewrittenQueries(
|
||||
auto rewritten_rename_query = std::make_shared<ASTRenameQuery>();
|
||||
rewritten_alter_query->database = mapped_to_database;
|
||||
rewritten_alter_query->table = alter_query.table;
|
||||
rewritten_alter_query->set(rewritten_alter_query->command_list, std::make_shared<ASTAlterCommandList>());
|
||||
rewritten_alter_query->set(rewritten_alter_query->command_list, std::make_shared<ASTExpressionList>());
|
||||
|
||||
String default_after_column;
|
||||
for (const auto & command_query : alter_query.command_list->children)
|
||||
@ -542,7 +542,7 @@ ASTs InterpreterAlterImpl::getRewrittenQueries(
|
||||
}
|
||||
|
||||
rewritten_command->children.push_back(rewritten_command->col_decl);
|
||||
rewritten_alter_query->command_list->add(rewritten_command);
|
||||
rewritten_alter_query->command_list->children.push_back(rewritten_command);
|
||||
}
|
||||
}
|
||||
else if (alter_command->type == MySQLParser::ASTAlterCommand::DROP_COLUMN)
|
||||
@ -550,7 +550,7 @@ ASTs InterpreterAlterImpl::getRewrittenQueries(
|
||||
auto rewritten_command = std::make_shared<ASTAlterCommand>();
|
||||
rewritten_command->type = ASTAlterCommand::DROP_COLUMN;
|
||||
rewritten_command->column = std::make_shared<ASTIdentifier>(alter_command->column_name);
|
||||
rewritten_alter_query->command_list->add(rewritten_command);
|
||||
rewritten_alter_query->command_list->children.push_back(rewritten_command);
|
||||
}
|
||||
else if (alter_command->type == MySQLParser::ASTAlterCommand::RENAME_COLUMN)
|
||||
{
|
||||
@ -561,7 +561,7 @@ ASTs InterpreterAlterImpl::getRewrittenQueries(
|
||||
rewritten_command->type = ASTAlterCommand::RENAME_COLUMN;
|
||||
rewritten_command->column = std::make_shared<ASTIdentifier>(alter_command->old_name);
|
||||
rewritten_command->rename_to = std::make_shared<ASTIdentifier>(alter_command->column_name);
|
||||
rewritten_alter_query->command_list->add(rewritten_command);
|
||||
rewritten_alter_query->command_list->children.push_back(rewritten_command);
|
||||
}
|
||||
}
|
||||
else if (alter_command->type == MySQLParser::ASTAlterCommand::MODIFY_COLUMN)
|
||||
@ -590,7 +590,7 @@ ASTs InterpreterAlterImpl::getRewrittenQueries(
|
||||
rewritten_command->children.push_back(rewritten_command->column);
|
||||
}
|
||||
|
||||
rewritten_alter_query->command_list->add(rewritten_command);
|
||||
rewritten_alter_query->command_list->children.push_back(rewritten_command);
|
||||
}
|
||||
|
||||
if (!alter_command->old_name.empty() && alter_command->old_name != new_column_name)
|
||||
@ -599,7 +599,7 @@ ASTs InterpreterAlterImpl::getRewrittenQueries(
|
||||
rewritten_command->type = ASTAlterCommand::RENAME_COLUMN;
|
||||
rewritten_command->column = std::make_shared<ASTIdentifier>(alter_command->old_name);
|
||||
rewritten_command->rename_to = std::make_shared<ASTIdentifier>(new_column_name);
|
||||
rewritten_alter_query->command_list->add(rewritten_command);
|
||||
rewritten_alter_query->command_list->children.push_back(rewritten_command);
|
||||
}
|
||||
}
|
||||
else if (alter_command->type == MySQLParser::ASTAlterCommand::RENAME_TABLE)
|
||||
@ -624,7 +624,7 @@ ASTs InterpreterAlterImpl::getRewrittenQueries(
|
||||
ASTs rewritten_queries;
|
||||
|
||||
/// Order is very important. We always execute alter first and then execute rename
|
||||
if (!rewritten_alter_query->command_list->commands.empty())
|
||||
if (!rewritten_alter_query->command_list->children.empty())
|
||||
rewritten_queries.push_back(rewritten_alter_query);
|
||||
|
||||
if (!rewritten_rename_query->elements.empty())
|
||||
|
@ -29,7 +29,7 @@ static bool tryExtractConstValueFromCondition(const ASTPtr & condition, bool & v
|
||||
/// cast of numeric constant in condition to UInt8
|
||||
if (const auto * function = condition->as<ASTFunction>())
|
||||
{
|
||||
if (function->name == "CAST")
|
||||
if (function->name == "cast")
|
||||
{
|
||||
if (const auto * expr_list = function->arguments->as<ASTExpressionList>())
|
||||
{
|
||||
@ -64,13 +64,17 @@ void OptimizeIfWithConstantConditionVisitor::visit(ASTPtr & current_ast)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!function_node->arguments)
|
||||
throw Exception("Wrong number of arguments for function 'if' (0 instead of 3)", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||
|
||||
if (function_node->arguments->children.size() != 3)
|
||||
throw Exception(
|
||||
"Wrong number of arguments for function 'if' (" + toString(function_node->arguments->children.size()) + " instead of 3)",
|
||||
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||
|
||||
visit(function_node->arguments);
|
||||
const auto * args = function_node->arguments->as<ASTExpressionList>();
|
||||
|
||||
if (args->children.size() != 3)
|
||||
throw Exception("Wrong number of arguments for function 'if' (" + toString(args->children.size()) + " instead of 3)",
|
||||
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||
|
||||
ASTPtr condition_expr = args->children[0];
|
||||
ASTPtr then_expr = args->children[1];
|
||||
ASTPtr else_expr = args->children[2];
|
||||
|
@ -164,14 +164,17 @@ void QueryNormalizer::visitChildren(const ASTPtr & node, Data & data)
|
||||
if (func_node->name == "lambda")
|
||||
first_pos = 1;
|
||||
|
||||
auto & func_children = func_node->arguments->children;
|
||||
|
||||
for (size_t i = first_pos; i < func_children.size(); ++i)
|
||||
if (func_node->arguments)
|
||||
{
|
||||
auto & child = func_children[i];
|
||||
auto & func_children = func_node->arguments->children;
|
||||
|
||||
if (needVisitChild(child))
|
||||
visit(child, data);
|
||||
for (size_t i = first_pos; i < func_children.size(); ++i)
|
||||
{
|
||||
auto & child = func_children[i];
|
||||
|
||||
if (needVisitChild(child))
|
||||
visit(child, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!node->as<ASTSelectQuery>())
|
||||
|
@ -22,7 +22,7 @@ static bool removeInjectiveFunction(ASTPtr & ast, const Context & context, const
|
||||
if (!func)
|
||||
return false;
|
||||
|
||||
if (func->arguments->children.size() != 1)
|
||||
if (!func->arguments || func->arguments->children.size() != 1)
|
||||
return false;
|
||||
|
||||
if (!function_factory.get(func->name, context)->isInjective({}))
|
||||
|
@ -62,7 +62,7 @@ void RewriteAnyFunctionMatcher::visit(ASTPtr & ast, Data & data)
|
||||
|
||||
void RewriteAnyFunctionMatcher::visit(const ASTFunction & func, ASTPtr & ast, Data & data)
|
||||
{
|
||||
if (func.arguments->children.empty() || !func.arguments->children[0])
|
||||
if (!func.arguments || func.arguments->children.empty() || !func.arguments->children[0])
|
||||
return;
|
||||
|
||||
if (func.name != "any" && func.name != "anyLast")
|
||||
|
@ -28,6 +28,7 @@ class ASTQueryWithTableAndOutput;
|
||||
class ASTIdentifier;
|
||||
class Context;
|
||||
|
||||
// TODO(ilezhankin): refactor and merge |ASTTableIdentifier|
|
||||
struct StorageID
|
||||
{
|
||||
String database_name;
|
||||
|
@ -126,6 +126,8 @@ void TranslateQualifiedNamesMatcher::visit(ASTFunction & node, const ASTPtr &, D
|
||||
{
|
||||
ASTPtr & func_arguments = node.arguments;
|
||||
|
||||
if (!func_arguments) return;
|
||||
|
||||
String func_name_lowercase = Poco::toLower(node.name);
|
||||
if (func_name_lowercase == "count" &&
|
||||
func_arguments->children.size() == 1 &&
|
||||
|
@ -380,8 +380,9 @@ std::vector<const ASTFunction *> getAggregates(ASTPtr & query, const ASTSelectQu
|
||||
|
||||
/// There can not be other aggregate functions within the aggregate functions.
|
||||
for (const ASTFunction * node : data.aggregates)
|
||||
for (auto & arg : node->arguments->children)
|
||||
assertNoAggregates(arg, "inside another aggregate function");
|
||||
if (node->arguments)
|
||||
for (auto & arg : node->arguments->children)
|
||||
assertNoAggregates(arg, "inside another aggregate function");
|
||||
return data.aggregates;
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ namespace DB
|
||||
|
||||
ASTPtr addTypeConversionToAST(ASTPtr && ast, const String & type_name)
|
||||
{
|
||||
auto func = makeASTFunction("CAST", ast, std::make_shared<ASTLiteral>(type_name));
|
||||
auto func = makeASTFunction("cast", ast, std::make_shared<ASTLiteral>(type_name));
|
||||
|
||||
if (ASTWithAlias * ast_with_alias = dynamic_cast<ASTWithAlias *>(ast.get()))
|
||||
{
|
||||
|
@ -15,18 +15,23 @@
|
||||
#include <DataStreams/InputStreamFromASTInsertQuery.h>
|
||||
#include <DataStreams/CountingBlockOutputStream.h>
|
||||
|
||||
#include <Parsers/ASTIdentifier.h>
|
||||
#include <Parsers/ASTInsertQuery.h>
|
||||
#include <Parsers/ASTLiteral.h>
|
||||
#include <Parsers/ASTSelectQuery.h>
|
||||
#include <Parsers/ASTSelectWithUnionQuery.h>
|
||||
#include <Parsers/ASTShowProcesslistQuery.h>
|
||||
#include <Parsers/ASTIdentifier.h>
|
||||
#include <Parsers/ASTLiteral.h>
|
||||
#include <Parsers/ParserQuery.h>
|
||||
#include <Parsers/parseQuery.h>
|
||||
#include <Parsers/queryToString.h>
|
||||
#include <Parsers/ASTWatchQuery.h>
|
||||
#include <Parsers/Lexer.h>
|
||||
|
||||
#if !defined(ARCADIA_BUILD)
|
||||
# include <Parsers/New/parseQuery.h> // Y_IGNORE
|
||||
#endif
|
||||
|
||||
#include <Parsers/parseQuery.h>
|
||||
#include <Parsers/ParserQuery.h>
|
||||
#include <Parsers/queryToString.h>
|
||||
|
||||
#include <Storages/StorageInput.h>
|
||||
|
||||
#include <Access/EnabledQuota.h>
|
||||
@ -147,10 +152,11 @@ static void logQuery(const String & query, const Context & context, bool interna
|
||||
const auto & initial_query_id = client_info.initial_query_id;
|
||||
const auto & current_user = client_info.current_user;
|
||||
|
||||
LOG_DEBUG(&Poco::Logger::get("executeQuery"), "(from {}{}{}) {}",
|
||||
LOG_DEBUG(&Poco::Logger::get("executeQuery"), "(from {}{}{}, using {} parser) {}",
|
||||
client_info.current_address.toString(),
|
||||
(current_user != "default" ? ", user: " + current_user : ""),
|
||||
(!initial_query_id.empty() && current_query_id != initial_query_id ? ", initial_query_id: " + initial_query_id : std::string()),
|
||||
(context.getSettingsRef().use_antlr_parser ? "new" : "old"),
|
||||
joinLines(query));
|
||||
|
||||
if (client_info.client_trace_context.trace_id)
|
||||
@ -321,19 +327,33 @@ static std::tuple<ASTPtr, BlockIO> executeQueryImpl(
|
||||
|
||||
const Settings & settings = context.getSettingsRef();
|
||||
|
||||
ParserQuery parser(end);
|
||||
ASTPtr ast;
|
||||
const char * query_end;
|
||||
|
||||
/// Don't limit the size of internal queries.
|
||||
size_t max_query_size = 0;
|
||||
if (!internal)
|
||||
max_query_size = settings.max_query_size;
|
||||
if (!internal) max_query_size = settings.max_query_size;
|
||||
|
||||
try
|
||||
{
|
||||
/// TODO Parser should fail early when max_query_size limit is reached.
|
||||
#if !defined(ARCADIA_BUILD)
|
||||
if (settings.use_antlr_parser)
|
||||
{
|
||||
ast = parseQuery(begin, end, max_query_size, settings.max_parser_depth);
|
||||
}
|
||||
else
|
||||
{
|
||||
ParserQuery parser(end);
|
||||
|
||||
/// TODO: parser should fail early when max_query_size limit is reached.
|
||||
ast = parseQuery(parser, begin, end, "", max_query_size, settings.max_parser_depth);
|
||||
}
|
||||
#else
|
||||
ParserQuery parser(end);
|
||||
|
||||
/// TODO: parser should fail early when max_query_size limit is reached.
|
||||
ast = parseQuery(parser, begin, end, "", max_query_size, settings.max_parser_depth);
|
||||
#endif
|
||||
|
||||
/// Interpret SETTINGS clauses as early as possible (before invoking the corresponding interpreter),
|
||||
/// to allow settings to take effect.
|
||||
@ -874,7 +894,7 @@ void executeQuery(
|
||||
end = istr.buffer().end();
|
||||
istr.position() += end - begin;
|
||||
/// Actually we don't know will query has additional data or not.
|
||||
/// But we can't check istr.eof(), because begin and end pointers will became invalid
|
||||
/// But we can't check istr.eof(), because begin and end pointers will become invalid
|
||||
may_have_tail = true;
|
||||
}
|
||||
else
|
||||
|
@ -43,7 +43,7 @@ void addDefaultRequiredExpressionsRecursively(Block & block, const String & requ
|
||||
RequiredSourceColumnsVisitor(columns_context).visit(column_default_expr);
|
||||
NameSet required_columns_names = columns_context.requiredColumns();
|
||||
|
||||
auto cast_func = makeASTFunction("CAST", column_default_expr, std::make_shared<ASTLiteral>(columns.get(required_column).type->getName()));
|
||||
auto cast_func = makeASTFunction("cast", column_default_expr, std::make_shared<ASTLiteral>(columns.get(required_column).type->getName()));
|
||||
default_expr_list_accum->children.emplace_back(setAlias(cast_func, required_column));
|
||||
added_columns.emplace(required_column);
|
||||
|
||||
@ -79,7 +79,7 @@ ASTPtr convertRequiredExpressions(Block & block, const NamesAndTypesList & requi
|
||||
continue;
|
||||
|
||||
auto cast_func = makeASTFunction(
|
||||
"CAST", std::make_shared<ASTIdentifier>(required_column.name), std::make_shared<ASTLiteral>(required_column.type->getName()));
|
||||
"cast", std::make_shared<ASTIdentifier>(required_column.name), std::make_shared<ASTLiteral>(required_column.type->getName()));
|
||||
|
||||
conversion_expr_list->children.emplace_back(setAlias(cast_func, required_column.name));
|
||||
|
||||
|
@ -345,30 +345,6 @@ void ASTAlterCommand::formatImpl(
|
||||
}
|
||||
|
||||
|
||||
ASTPtr ASTAlterCommandList::clone() const
|
||||
{
|
||||
auto res = std::make_shared<ASTAlterCommandList>();
|
||||
for (ASTAlterCommand * command : commands)
|
||||
res->add(command->clone());
|
||||
return res;
|
||||
}
|
||||
|
||||
void ASTAlterCommandList::formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const
|
||||
{
|
||||
std::string indent_str = settings.one_line ? "" : std::string(4 * frame.indent, ' ');
|
||||
|
||||
for (size_t i = 0; i < commands.size(); ++i)
|
||||
{
|
||||
static_cast<IAST *>(commands[i])->formatImpl(settings, state, frame);
|
||||
|
||||
std::string comma = (i < (commands.size() - 1)) ? "," : "";
|
||||
settings.ostr << (settings.hilite ? hilite_keyword : "") << comma << (settings.hilite ? hilite_none : "");
|
||||
|
||||
settings.ostr << settings.nl_or_ws;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Get the text that identifies this element. */
|
||||
String ASTAlterQuery::getID(char delim) const
|
||||
{
|
||||
|
@ -1,9 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/IAST.h>
|
||||
#include <Parsers/ASTQueryWithTableAndOutput.h>
|
||||
#include <Parsers/ASTExpressionList.h>
|
||||
#include <Parsers/ASTQueryWithOnCluster.h>
|
||||
#include <Parsers/ASTQueryWithTableAndOutput.h>
|
||||
#include <Parsers/ASTTTLElement.h>
|
||||
#include <Parsers/IAST.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -179,31 +180,12 @@ protected:
|
||||
void formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override;
|
||||
};
|
||||
|
||||
class ASTAlterCommandList : public IAST
|
||||
{
|
||||
public:
|
||||
std::vector<ASTAlterCommand *> commands;
|
||||
|
||||
void add(const ASTPtr & command)
|
||||
{
|
||||
commands.push_back(command->as<ASTAlterCommand>());
|
||||
children.push_back(command);
|
||||
}
|
||||
|
||||
String getID(char) const override { return "AlterCommandList"; }
|
||||
|
||||
ASTPtr clone() const override;
|
||||
|
||||
protected:
|
||||
void formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override;
|
||||
};
|
||||
|
||||
class ASTAlterQuery : public ASTQueryWithTableAndOutput, public ASTQueryWithOnCluster
|
||||
{
|
||||
public:
|
||||
bool is_live_view{false}; /// true for ALTER LIVE VIEW
|
||||
|
||||
ASTAlterCommandList * command_list = nullptr;
|
||||
ASTExpressionList * command_list = nullptr;
|
||||
|
||||
String getID(char) const override;
|
||||
|
||||
|
@ -4,10 +4,10 @@
|
||||
#include <Parsers/ASTQueryWithOnCluster.h>
|
||||
#include <Parsers/ASTDictionary.h>
|
||||
#include <Parsers/ASTDictionaryAttributeDeclaration.h>
|
||||
#include <Parsers/ASTIdentifier.h>
|
||||
#include <Parsers/ASTSelectWithUnionQuery.h>
|
||||
#include <Interpreters/StorageID.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
|
@ -65,7 +65,7 @@ ASTPtr ASTDictionaryLayout::clone() const
|
||||
{
|
||||
auto res = std::make_shared<ASTDictionaryLayout>();
|
||||
res->layout_type = layout_type;
|
||||
res->set(res->parameters, parameters->clone());
|
||||
if (parameters) res->set(res->parameters, parameters->clone());
|
||||
res->has_brackets = has_brackets;
|
||||
return res;
|
||||
}
|
||||
@ -86,7 +86,7 @@ void ASTDictionaryLayout::formatImpl(const FormatSettings & settings,
|
||||
if (has_brackets)
|
||||
settings.ostr << "(";
|
||||
|
||||
parameters->formatImpl(settings, state, frame);
|
||||
if (parameters) parameters->formatImpl(settings, state, frame);
|
||||
|
||||
if (has_brackets)
|
||||
settings.ostr << ")";
|
||||
|
@ -29,12 +29,13 @@ void ASTFunction::appendColumnNameImpl(WriteBuffer & ostr) const
|
||||
}
|
||||
|
||||
writeChar('(', ostr);
|
||||
for (auto it = arguments->children.begin(); it != arguments->children.end(); ++it)
|
||||
{
|
||||
if (it != arguments->children.begin())
|
||||
writeCString(", ", ostr);
|
||||
(*it)->appendColumnName(ostr);
|
||||
}
|
||||
if (arguments)
|
||||
for (auto it = arguments->children.begin(); it != arguments->children.end(); ++it)
|
||||
{
|
||||
if (it != arguments->children.begin())
|
||||
writeCString(", ", ostr);
|
||||
(*it)->appendColumnName(ostr);
|
||||
}
|
||||
writeChar(')', ostr);
|
||||
}
|
||||
|
||||
@ -64,6 +65,35 @@ void ASTFunction::updateTreeHashImpl(SipHash & hash_state) const
|
||||
}
|
||||
|
||||
|
||||
ASTPtr ASTFunction::toLiteral() const
|
||||
{
|
||||
if (!arguments) return {};
|
||||
|
||||
if (name == "array")
|
||||
{
|
||||
Array array;
|
||||
|
||||
for (const auto & arg : arguments->children)
|
||||
{
|
||||
if (auto * literal = arg->as<ASTLiteral>())
|
||||
array.push_back(literal->value);
|
||||
else if (auto * func = arg->as<ASTFunction>())
|
||||
{
|
||||
if (auto func_literal = func->toLiteral())
|
||||
array.push_back(func_literal->as<ASTLiteral>()->value);
|
||||
}
|
||||
else
|
||||
/// Some of the Array arguments is not literal
|
||||
return {};
|
||||
}
|
||||
|
||||
return std::make_shared<ASTLiteral>(array);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
/** A special hack. If it's [I]LIKE or NOT [I]LIKE expression and the right hand side is a string literal,
|
||||
* we will highlight unescaped metacharacters % and _ in string literal for convenience.
|
||||
* Motivation: most people are unaware that _ is a metacharacter and forgot to properly escape it with two backslashes.
|
||||
@ -378,12 +408,14 @@ void ASTFunction::formatImplWithoutAlias(const FormatSettings & settings, Format
|
||||
settings.ostr << (settings.hilite ? hilite_function : "") << ')';
|
||||
}
|
||||
|
||||
if (arguments)
|
||||
{
|
||||
if ((arguments && !arguments->children.empty()) || !no_empty_args)
|
||||
settings.ostr << '(' << (settings.hilite ? hilite_none : "");
|
||||
|
||||
if (arguments)
|
||||
{
|
||||
bool special_hilite_regexp = settings.hilite
|
||||
&& (name == "match" || name == "extract" || name == "extractAll" || name == "replaceRegexpOne" || name == "replaceRegexpAll");
|
||||
&& (name == "match" || name == "extract" || name == "extractAll" || name == "replaceRegexpOne"
|
||||
|| name == "replaceRegexpAll");
|
||||
|
||||
for (size_t i = 0, size = arguments->children.size(); i < size; ++i)
|
||||
{
|
||||
@ -397,10 +429,11 @@ void ASTFunction::formatImplWithoutAlias(const FormatSettings & settings, Format
|
||||
if (!special_hilite)
|
||||
arguments->children[i]->formatImpl(settings, state, nested_dont_need_parens);
|
||||
}
|
||||
|
||||
settings.ostr << (settings.hilite ? hilite_function : "") << ')';
|
||||
}
|
||||
|
||||
if ((arguments && !arguments->children.empty()) || !no_empty_args)
|
||||
settings.ostr << (settings.hilite ? hilite_function : "") << ')';
|
||||
|
||||
settings.ostr << (settings.hilite ? hilite_none : "");
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,9 @@ public:
|
||||
/// parameters - for parametric aggregate function. Example: quantile(0.9)(x) - what in first parens are 'parameters'.
|
||||
ASTPtr parameters;
|
||||
|
||||
public:
|
||||
/// do not print empty parentheses if there are no args - compatibility with new AST for data types and engine names.
|
||||
bool no_empty_args = false;
|
||||
|
||||
/** Get text identifying the AST node. */
|
||||
String getID(char delim) const override;
|
||||
|
||||
@ -28,6 +30,8 @@ public:
|
||||
|
||||
ASTSelectWithUnionQuery * tryGetQueryArgument() const;
|
||||
|
||||
ASTPtr toLiteral() const; // Try to convert functions like Array or Tuple to a literal form.
|
||||
|
||||
protected:
|
||||
void formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override;
|
||||
void appendColumnNameImpl(WriteBuffer & ostr) const override;
|
||||
|
@ -73,7 +73,6 @@ private:
|
||||
void resetFullName();
|
||||
};
|
||||
|
||||
|
||||
/// ASTIdentifier Helpers: hide casts and semantic.
|
||||
|
||||
ASTPtr createTableIdentifier(const String & database_name, const String & table_name);
|
||||
|
@ -1,20 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <Core/Field.h>
|
||||
#include <Common/FieldVisitors.h>
|
||||
#include <Parsers/ASTWithAlias.h>
|
||||
#include <Parsers/TokenIterator.h>
|
||||
#include <Common/FieldVisitors.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/** Literal (atomic) - number, string, NULL
|
||||
*/
|
||||
/// Literal (atomic) - number, string, NULL
|
||||
class ASTLiteral : public ASTWithAlias
|
||||
{
|
||||
public:
|
||||
explicit ASTLiteral(Field && value_) : value(value_) {}
|
||||
explicit ASTLiteral(const Field & value_) : value(value_) {}
|
||||
|
||||
Field value;
|
||||
|
||||
/// For ConstantExpressionTemplate
|
||||
@ -30,11 +33,6 @@ public:
|
||||
*/
|
||||
String unique_column_name;
|
||||
|
||||
|
||||
public:
|
||||
ASTLiteral(Field && value_) : value(value_) {}
|
||||
ASTLiteral(const Field & value_) : value(value_) {}
|
||||
|
||||
/** Get the text that identifies this element. */
|
||||
String getID(char delim) const override { return "Literal" + (delim + applyVisitor(FieldVisitorDump(), value)); }
|
||||
|
||||
|
@ -23,20 +23,6 @@ public:
|
||||
ASTPtr fill_to;
|
||||
ASTPtr fill_step;
|
||||
|
||||
ASTOrderByElement(
|
||||
const int direction_, const int nulls_direction_, const bool nulls_direction_was_explicitly_specified_,
|
||||
ASTPtr & collation_, const bool with_fill_, ASTPtr & fill_from_, ASTPtr & fill_to_, ASTPtr & fill_step_)
|
||||
: direction(direction_)
|
||||
, nulls_direction(nulls_direction_)
|
||||
, nulls_direction_was_explicitly_specified(nulls_direction_was_explicitly_specified_)
|
||||
, collation(collation_)
|
||||
, with_fill(with_fill_)
|
||||
, fill_from(fill_from_)
|
||||
, fill_to(fill_to_)
|
||||
, fill_step(fill_step_)
|
||||
{
|
||||
}
|
||||
|
||||
String getID(char) const override { return "OrderByElement"; }
|
||||
|
||||
ASTPtr clone() const override
|
||||
|
@ -26,7 +26,7 @@ public:
|
||||
|
||||
Rational ratio;
|
||||
|
||||
ASTSampleRatio(Rational & ratio_) : ratio(ratio_) {}
|
||||
explicit ASTSampleRatio(const Rational & ratio_) : ratio(ratio_) {}
|
||||
|
||||
String getID(char delim) const override { return "SampleRatio" + (delim + toString(ratio)); }
|
||||
|
||||
|
@ -30,7 +30,7 @@ namespace DB
|
||||
* , (comma)
|
||||
*
|
||||
* In all kinds except cross and comma, there are join condition in one of following forms:
|
||||
* USING (a, b c)
|
||||
* USING (a, b, c)
|
||||
* USING a, b, c
|
||||
* ON expr...
|
||||
*
|
||||
|
@ -441,7 +441,7 @@ bool ParserCastExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expect
|
||||
expr_list_args->children.push_back(std::move(type_literal));
|
||||
|
||||
auto func_node = std::make_shared<ASTFunction>();
|
||||
func_node->name = "CAST";
|
||||
func_node->name = "cast";
|
||||
func_node->arguments = std::move(expr_list_args);
|
||||
func_node->children.push_back(func_node->arguments);
|
||||
|
||||
@ -1705,12 +1705,21 @@ bool ParserOrderByElement::parseImpl(Pos & pos, ASTPtr & node, Expected & expect
|
||||
return false;
|
||||
}
|
||||
|
||||
node = std::make_shared<ASTOrderByElement>(
|
||||
direction, nulls_direction, nulls_direction_was_explicitly_specified, locale_node,
|
||||
has_with_fill, fill_from, fill_to, fill_step);
|
||||
node->children.push_back(expr_elem);
|
||||
auto elem = std::make_shared<ASTOrderByElement>();
|
||||
|
||||
elem->direction = direction;
|
||||
elem->nulls_direction = nulls_direction;
|
||||
elem->nulls_direction_was_explicitly_specified = nulls_direction_was_explicitly_specified;
|
||||
elem->collation = locale_node;
|
||||
elem->with_fill = has_with_fill;
|
||||
elem->fill_from = fill_from;
|
||||
elem->fill_to = fill_to;
|
||||
elem->fill_step = fill_step;
|
||||
elem->children.push_back(expr_elem);
|
||||
if (locale_node)
|
||||
node->children.push_back(locale_node);
|
||||
elem->children.push_back(locale_node);
|
||||
|
||||
node = elem;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1887,13 +1896,18 @@ bool ParserIdentifierWithOptionalParameters::parseImpl(Pos & pos, ASTPtr & node,
|
||||
ParserIdentifierWithParameters parametric;
|
||||
|
||||
if (parametric.parse(pos, node, expected))
|
||||
{
|
||||
auto * func = node->as<ASTFunction>();
|
||||
func->no_empty_args = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
ASTPtr ident;
|
||||
if (non_parametric.parse(pos, ident, expected))
|
||||
{
|
||||
auto func = std::make_shared<ASTFunction>();
|
||||
tryGetIdentifierNameInto(ident, func->name);
|
||||
func->no_empty_args = true;
|
||||
node = func;
|
||||
return true;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ namespace ErrorCodes
|
||||
extern const int TOO_BIG_AST;
|
||||
extern const int TOO_DEEP_AST;
|
||||
extern const int BAD_ARGUMENTS;
|
||||
extern const int UNKNOWN_ELEMENT_IN_AST;
|
||||
}
|
||||
|
||||
|
||||
@ -154,7 +155,10 @@ void IAST::dumpTree(WriteBuffer & ostr, size_t indent) const
|
||||
writePointerHex(this, ostr);
|
||||
writeChar('\n', ostr);
|
||||
for (const auto & child : children)
|
||||
{
|
||||
if (!child) throw Exception("Can't dump nullptr child", ErrorCodes::UNKNOWN_ELEMENT_IN_AST);
|
||||
child->dumpTree(ostr, indent + 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
687
src/Parsers/New/AST/AlterTableQuery.cpp
Normal file
687
src/Parsers/New/AST/AlterTableQuery.cpp
Normal file
@ -0,0 +1,687 @@
|
||||
#include <Parsers/New/AST/AlterTableQuery.h>
|
||||
|
||||
#include <Interpreters/StorageID.h>
|
||||
#include <Parsers/ASTAlterQuery.h>
|
||||
#include <Parsers/ASTAssignment.h>
|
||||
#include <Parsers/ASTColumnDeclaration.h>
|
||||
#include <Parsers/ASTFunction.h>
|
||||
#include <Parsers/ASTIdentifier.h>
|
||||
#include <Parsers/ASTPartition.h>
|
||||
#include <Parsers/New/AST/ColumnExpr.h>
|
||||
#include <Parsers/New/AST/Identifier.h>
|
||||
#include <Parsers/New/AST/Literal.h>
|
||||
#include <Parsers/New/AST/TableElementExpr.h>
|
||||
#include <Parsers/New/ParseTreeVisitor.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
AssignmentExpr::AssignmentExpr(PtrTo<Identifier> identifier, PtrTo<ColumnExpr> expr) : INode{identifier, expr}
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr AssignmentExpr::convertToOld() const
|
||||
{
|
||||
auto expr = std::make_shared<ASTAssignment>();
|
||||
|
||||
expr->column_name = get(IDENTIFIER)->convertToOld()->getColumnName();
|
||||
expr->children.push_back(get(EXPR)->convertToOld());
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
PartitionClause::PartitionClause(PtrTo<Literal> id) : PartitionClause(ClauseType::ID, {id})
|
||||
{
|
||||
}
|
||||
|
||||
PartitionClause::PartitionClause(PtrTo<List<Literal>> list) : PartitionClause(ClauseType::LIST, {list})
|
||||
{
|
||||
}
|
||||
|
||||
PartitionClause::PartitionClause(ClauseType type, PtrList exprs) : INode(exprs), clause_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr PartitionClause::convertToOld() const
|
||||
{
|
||||
auto partition = std::make_shared<ASTPartition>();
|
||||
|
||||
switch(clause_type)
|
||||
{
|
||||
case ClauseType::ID:
|
||||
partition->id = get<StringLiteral>(ID)->as<String>();
|
||||
break;
|
||||
case ClauseType::LIST:
|
||||
{
|
||||
auto tuple = std::make_shared<ASTFunction>();
|
||||
|
||||
tuple->name = "tuple";
|
||||
tuple->arguments = std::make_shared<ASTExpressionList>();
|
||||
for (const auto & child : get(LIST)->as<List<Literal> &>())
|
||||
tuple->arguments->children.push_back(child->convertToOld());
|
||||
tuple->children.push_back(tuple->arguments);
|
||||
|
||||
partition->value = tuple;
|
||||
partition->children.push_back(partition->value);
|
||||
partition->fields_count = get<List<Literal>>(LIST)->size();
|
||||
partition->fields_str = get(LIST)->toString();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return partition;
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<AlterTableClause> AlterTableClause::createAddColumn(bool if_not_exists, PtrTo<TableElementExpr> element, PtrTo<Identifier> after)
|
||||
{
|
||||
assert(element->getType() == TableElementExpr::ExprType::COLUMN);
|
||||
PtrTo<AlterTableClause> query(new AlterTableClause(ClauseType::ADD_COLUMN, {element, after}));
|
||||
query->if_not_exists = if_not_exists;
|
||||
return query;
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<AlterTableClause> AlterTableClause::createAddIndex(bool if_not_exists, PtrTo<TableElementExpr> element, PtrTo<Identifier> after)
|
||||
{
|
||||
assert(element->getType() == TableElementExpr::ExprType::INDEX);
|
||||
PtrTo<AlterTableClause> query(new AlterTableClause(ClauseType::ADD_INDEX, {element, after}));
|
||||
query->if_not_exists = if_not_exists;
|
||||
return query;
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<AlterTableClause> AlterTableClause::createAttach(PtrTo<PartitionClause> clause, PtrTo<TableIdentifier> from)
|
||||
{
|
||||
return PtrTo<AlterTableClause>(new AlterTableClause(ClauseType::ATTACH, {clause, from}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<AlterTableClause> AlterTableClause::createClear(bool if_exists, PtrTo<Identifier> identifier, PtrTo<PartitionClause> in)
|
||||
{
|
||||
PtrTo<AlterTableClause> query(new AlterTableClause(ClauseType::CLEAR, {identifier, in}));
|
||||
query->if_exists = if_exists;
|
||||
return query;
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<AlterTableClause> AlterTableClause::createCodec(bool if_exists, PtrTo<Identifier> identifier, PtrTo<CodecExpr> codec)
|
||||
{
|
||||
PtrTo<AlterTableClause> query(new AlterTableClause(ClauseType::CODEC, {identifier, codec}));
|
||||
query->if_exists = if_exists;
|
||||
return query;
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<AlterTableClause> AlterTableClause::createComment(bool if_exists, PtrTo<Identifier> identifier, PtrTo<StringLiteral> comment)
|
||||
{
|
||||
PtrTo<AlterTableClause> query(new AlterTableClause(ClauseType::COMMENT, {identifier, comment}));
|
||||
query->if_exists = if_exists;
|
||||
return query;
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<AlterTableClause> AlterTableClause::createDelete(PtrTo<ColumnExpr> expr)
|
||||
{
|
||||
return PtrTo<AlterTableClause>(new AlterTableClause(ClauseType::DELETE, {expr}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<AlterTableClause> AlterTableClause::createDetach(PtrTo<PartitionClause> clause)
|
||||
{
|
||||
return PtrTo<AlterTableClause>(new AlterTableClause(ClauseType::DETACH, {clause}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<AlterTableClause> AlterTableClause::createDropColumn(bool if_exists, PtrTo<Identifier> identifier)
|
||||
{
|
||||
PtrTo<AlterTableClause> query(new AlterTableClause(ClauseType::DROP_COLUMN, {identifier}));
|
||||
query->if_exists = if_exists;
|
||||
return query;
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<AlterTableClause> AlterTableClause::createDropIndex(bool if_exists, PtrTo<Identifier> identifier)
|
||||
{
|
||||
PtrTo<AlterTableClause> query(new AlterTableClause(ClauseType::DROP_INDEX, {identifier}));
|
||||
query->if_exists = if_exists;
|
||||
return query;
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<AlterTableClause> AlterTableClause::createDropPartition(PtrTo<PartitionClause> clause)
|
||||
{
|
||||
return PtrTo<AlterTableClause>(new AlterTableClause(ClauseType::DROP_PARTITION, {clause}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<AlterTableClause> AlterTableClause::createFreezePartition(PtrTo<PartitionClause> clause)
|
||||
{
|
||||
return PtrTo<AlterTableClause>(new AlterTableClause(ClauseType::FREEZE_PARTITION, {clause}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<AlterTableClause> AlterTableClause::createModify(bool if_exists, PtrTo<TableElementExpr> element)
|
||||
{
|
||||
// TODO: assert(element->getType() == TableElementExpr::ExprType::COLUMN);
|
||||
PtrTo<AlterTableClause> query(new AlterTableClause(ClauseType::MODIFY, {element}));
|
||||
query->if_exists = if_exists;
|
||||
return query;
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<AlterTableClause> AlterTableClause::createMovePartitionToDisk(PtrTo<PartitionClause> clause, PtrTo<StringLiteral> literal)
|
||||
{
|
||||
return PtrTo<AlterTableClause>(new AlterTableClause(ClauseType::MOVE_PARTITION_TO_DISK, {clause, literal}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<AlterTableClause> AlterTableClause::createMovePartitionToTable(PtrTo<PartitionClause> clause, PtrTo<TableIdentifier> identifier)
|
||||
{
|
||||
return PtrTo<AlterTableClause>(new AlterTableClause(ClauseType::MOVE_PARTITION_TO_TABLE, {clause, identifier}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<AlterTableClause> AlterTableClause::createMovePartitionToVolume(PtrTo<PartitionClause> clause, PtrTo<StringLiteral> literal)
|
||||
{
|
||||
return PtrTo<AlterTableClause>(new AlterTableClause(ClauseType::MOVE_PARTITION_TO_VOLUME, {clause, literal}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<AlterTableClause> AlterTableClause::createOrderBy(PtrTo<ColumnExpr> expr)
|
||||
{
|
||||
return PtrTo<AlterTableClause>(new AlterTableClause(ClauseType::ORDER_BY, {expr}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<AlterTableClause> AlterTableClause::createRemove(bool if_exists, PtrTo<Identifier> identifier, TableColumnPropertyType type)
|
||||
{
|
||||
PtrTo<AlterTableClause> query(new AlterTableClause(ClauseType::REMOVE, {identifier}));
|
||||
query->if_exists = if_exists;
|
||||
query->property_type = type;
|
||||
return query;
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<AlterTableClause> AlterTableClause::createRemoveTTL()
|
||||
{
|
||||
return PtrTo<AlterTableClause>(new AlterTableClause(ClauseType::REMOVE_TTL, {}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<AlterTableClause> AlterTableClause::createRename(bool if_exists, PtrTo<Identifier> identifier, PtrTo<Identifier> to)
|
||||
{
|
||||
PtrTo<AlterTableClause> query(new AlterTableClause(ClauseType::RENAME, {identifier, to}));
|
||||
query->if_exists = if_exists;
|
||||
return query;
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<AlterTableClause> AlterTableClause::createReplace(PtrTo<PartitionClause> clause, PtrTo<TableIdentifier> from)
|
||||
{
|
||||
return PtrTo<AlterTableClause>(new AlterTableClause(ClauseType::REPLACE, {clause, from}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<AlterTableClause> AlterTableClause::createTTL(PtrTo<TTLClause> clause)
|
||||
{
|
||||
return PtrTo<AlterTableClause>(new AlterTableClause(ClauseType::TTL, {clause}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<AlterTableClause> AlterTableClause::createUpdate(PtrTo<AssignmentExprList> list, PtrTo<WhereClause> where)
|
||||
{
|
||||
return PtrTo<AlterTableClause>(new AlterTableClause(ClauseType::UPDATE, {list, where}));
|
||||
}
|
||||
|
||||
ASTPtr AlterTableClause::convertToOld() const
|
||||
{
|
||||
auto command = std::make_shared<ASTAlterCommand>();
|
||||
|
||||
switch(clause_type)
|
||||
{
|
||||
case ClauseType::ADD_COLUMN:
|
||||
command->type = ASTAlterCommand::ADD_COLUMN;
|
||||
command->if_not_exists = if_not_exists;
|
||||
// TODO: command->first
|
||||
command->col_decl = get(ELEMENT)->convertToOld();
|
||||
if (has(AFTER)) command->column = get(AFTER)->convertToOld();
|
||||
break;
|
||||
|
||||
case ClauseType::ADD_INDEX:
|
||||
command->type = ASTAlterCommand::ADD_INDEX;
|
||||
command->if_not_exists = if_not_exists;
|
||||
command->index_decl = get(ELEMENT)->convertToOld();
|
||||
if (has(AFTER)) command->index = get(AFTER)->convertToOld();
|
||||
break;
|
||||
|
||||
case ClauseType::ATTACH:
|
||||
command->type = ASTAlterCommand::ATTACH_PARTITION;
|
||||
command->partition = get(PARTITION)->convertToOld();
|
||||
|
||||
if (has(FROM))
|
||||
{
|
||||
auto table_id = getTableIdentifier(get(FROM)->convertToOld());
|
||||
|
||||
command->from_database = table_id.database_name;
|
||||
command->from_table = table_id.table_name;
|
||||
command->replace = false;
|
||||
command->type = ASTAlterCommand::REPLACE_PARTITION;
|
||||
}
|
||||
break;
|
||||
|
||||
case ClauseType::CLEAR:
|
||||
command->type = ASTAlterCommand::DROP_COLUMN;
|
||||
command->if_exists = if_exists;
|
||||
command->clear_column = true;
|
||||
command->detach = false;
|
||||
command->column = get(COLUMN)->convertToOld();
|
||||
if (has(IN)) command->partition = get(IN)->convertToOld();
|
||||
break;
|
||||
|
||||
case ClauseType::CODEC:
|
||||
command->type = ASTAlterCommand::MODIFY_COLUMN;
|
||||
command->if_exists = if_exists;
|
||||
|
||||
{
|
||||
auto column = std::make_shared<ASTColumnDeclaration>();
|
||||
column->name = get(COLUMN)->toString();
|
||||
column->codec = get(CODEC)->convertToOld();
|
||||
|
||||
command->col_decl = column;
|
||||
}
|
||||
break;
|
||||
|
||||
case ClauseType::COMMENT:
|
||||
command->type = ASTAlterCommand::COMMENT_COLUMN;
|
||||
command->if_exists = if_exists;
|
||||
command->column = get(COLUMN)->convertToOld();
|
||||
command->comment = get(COMMENT)->convertToOld();
|
||||
break;
|
||||
|
||||
case ClauseType::DELETE:
|
||||
command->type = ASTAlterCommand::DELETE;
|
||||
command->predicate = get(EXPR)->convertToOld();
|
||||
break;
|
||||
|
||||
case ClauseType::DETACH:
|
||||
command->type = ASTAlterCommand::DROP_PARTITION;
|
||||
command->detach = true;
|
||||
command->partition = get(PARTITION)->convertToOld();
|
||||
break;
|
||||
|
||||
case ClauseType::DROP_COLUMN:
|
||||
command->type = ASTAlterCommand::DROP_COLUMN;
|
||||
command->if_exists = if_exists;
|
||||
command->detach = false;
|
||||
command->column = get(COLUMN)->convertToOld();
|
||||
break;
|
||||
|
||||
case ClauseType::DROP_INDEX:
|
||||
command->type = ASTAlterCommand::DROP_INDEX;
|
||||
command->if_exists = if_exists;
|
||||
command->detach = false;
|
||||
command->index = get(COLUMN)->convertToOld();
|
||||
break;
|
||||
|
||||
case ClauseType::DROP_PARTITION:
|
||||
command->type = ASTAlterCommand::DROP_PARTITION;
|
||||
command->partition = get(PARTITION)->convertToOld();
|
||||
break;
|
||||
|
||||
case ClauseType::FREEZE_PARTITION:
|
||||
if (has(PARTITION))
|
||||
{
|
||||
command->type = ASTAlterCommand::FREEZE_PARTITION;
|
||||
command->partition = get(PARTITION)->convertToOld();
|
||||
}
|
||||
else
|
||||
command->type = ASTAlterCommand::FREEZE_ALL;
|
||||
break;
|
||||
|
||||
case ClauseType::MODIFY:
|
||||
command->type = ASTAlterCommand::MODIFY_COLUMN;
|
||||
command->if_exists = if_exists;
|
||||
command->col_decl = get(ELEMENT)->convertToOld();
|
||||
break;
|
||||
|
||||
case ClauseType::MOVE_PARTITION_TO_DISK:
|
||||
command->type = ASTAlterCommand::MOVE_PARTITION;
|
||||
command->partition = get(PARTITION)->convertToOld();
|
||||
command->move_destination_type = DataDestinationType::DISK;
|
||||
command->move_destination_name = get(TO)->convertToOld()->as<ASTLiteral>()->value.get<String>();
|
||||
break;
|
||||
|
||||
case ClauseType::MOVE_PARTITION_TO_TABLE:
|
||||
command->type = ASTAlterCommand::MOVE_PARTITION;
|
||||
command->partition = get(PARTITION)->convertToOld();
|
||||
command->move_destination_type = DataDestinationType::TABLE;
|
||||
{
|
||||
auto table_id = getTableIdentifier(get(TO)->convertToOld());
|
||||
command->to_database = table_id.database_name;
|
||||
command->to_table = table_id.table_name;
|
||||
}
|
||||
break;
|
||||
|
||||
case ClauseType::MOVE_PARTITION_TO_VOLUME:
|
||||
command->type = ASTAlterCommand::MOVE_PARTITION;
|
||||
command->partition = get(PARTITION)->convertToOld();
|
||||
command->move_destination_type = DataDestinationType::VOLUME;
|
||||
command->move_destination_name = get(TO)->convertToOld()->as<ASTLiteral>()->value.get<String>();
|
||||
break;
|
||||
|
||||
case ClauseType::REMOVE:
|
||||
command->type = ASTAlterCommand::MODIFY_COLUMN;
|
||||
command->if_exists = if_exists;
|
||||
{
|
||||
auto col_decl = std::make_shared<ASTColumnDeclaration>();
|
||||
col_decl->name = get(ELEMENT)->convertToOld()->getColumnName();
|
||||
command->col_decl = col_decl;
|
||||
}
|
||||
switch(property_type)
|
||||
{
|
||||
case TableColumnPropertyType::ALIAS:
|
||||
command->remove_property = "ALIAS";
|
||||
break;
|
||||
case TableColumnPropertyType::CODEC:
|
||||
command->remove_property = "CODEC";
|
||||
break;
|
||||
case TableColumnPropertyType::COMMENT:
|
||||
command->remove_property = "COMMENT";
|
||||
break;
|
||||
case TableColumnPropertyType::DEFAULT:
|
||||
command->remove_property = "DEFAULT";
|
||||
break;
|
||||
case TableColumnPropertyType::MATERIALIZED:
|
||||
command->remove_property = "MATERIALIZED";
|
||||
break;
|
||||
case TableColumnPropertyType::TTL:
|
||||
command->remove_property = "TTL";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ClauseType::REMOVE_TTL:
|
||||
command->type = ASTAlterCommand::REMOVE_TTL;
|
||||
break;
|
||||
|
||||
case ClauseType::RENAME:
|
||||
command->type = ASTAlterCommand::RENAME_COLUMN;
|
||||
command->column = get(COLUMN)->convertToOld();
|
||||
command->rename_to = get(TO)->convertToOld();
|
||||
break;
|
||||
|
||||
case ClauseType::ORDER_BY:
|
||||
command->type = ASTAlterCommand::MODIFY_ORDER_BY;
|
||||
command->order_by = get(EXPR)->convertToOld();
|
||||
break;
|
||||
|
||||
case ClauseType::REPLACE:
|
||||
command->type = ASTAlterCommand::REPLACE_PARTITION;
|
||||
command->replace = true;
|
||||
command->partition = get(PARTITION)->convertToOld();
|
||||
{
|
||||
auto table_id = getTableIdentifier(get(FROM)->convertToOld());
|
||||
command->from_database = table_id.database_name;
|
||||
command->from_table = table_id.table_name;
|
||||
}
|
||||
break;
|
||||
|
||||
case ClauseType::TTL:
|
||||
command->type = ASTAlterCommand::MODIFY_TTL;
|
||||
command->ttl = get(CLAUSE)->convertToOld();
|
||||
break;
|
||||
|
||||
case ClauseType::UPDATE:
|
||||
command->type = ASTAlterCommand::UPDATE;
|
||||
command->update_assignments = get(ASSIGNMENTS)->convertToOld();
|
||||
command->predicate = get(WHERE)->convertToOld();
|
||||
break;
|
||||
}
|
||||
|
||||
if (command->col_decl)
|
||||
command->children.push_back(command->col_decl);
|
||||
if (command->column)
|
||||
command->children.push_back(command->column);
|
||||
if (command->partition)
|
||||
command->children.push_back(command->partition);
|
||||
if (command->order_by)
|
||||
command->children.push_back(command->order_by);
|
||||
if (command->sample_by)
|
||||
command->children.push_back(command->sample_by);
|
||||
if (command->predicate)
|
||||
command->children.push_back(command->predicate);
|
||||
if (command->update_assignments)
|
||||
command->children.push_back(command->update_assignments);
|
||||
if (command->values)
|
||||
command->children.push_back(command->values);
|
||||
if (command->comment)
|
||||
command->children.push_back(command->comment);
|
||||
if (command->ttl)
|
||||
command->children.push_back(command->ttl);
|
||||
if (command->settings_changes)
|
||||
command->children.push_back(command->settings_changes);
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
AlterTableClause::AlterTableClause(ClauseType type, PtrList exprs) : INode(exprs), clause_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
AlterTableQuery::AlterTableQuery(PtrTo<ClusterClause> cluster, PtrTo<TableIdentifier> identifier, PtrTo<List<AlterTableClause>> clauses)
|
||||
: DDLQuery(cluster, {identifier, clauses})
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr AlterTableQuery::convertToOld() const
|
||||
{
|
||||
auto query = std::make_shared<ASTAlterQuery>();
|
||||
|
||||
{
|
||||
auto table_id = getTableIdentifier(get(TABLE)->convertToOld());
|
||||
query->database = table_id.database_name;
|
||||
query->table = table_id.table_name;
|
||||
}
|
||||
|
||||
query->cluster = cluster_name;
|
||||
|
||||
query->set(query->command_list, get(CLAUSES)->convertToOld());
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace AST;
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlterTableClauseAddColumn(ClickHouseParser::AlterTableClauseAddColumnContext * ctx)
|
||||
{
|
||||
auto after = ctx->AFTER() ? visit(ctx->nestedIdentifier()).as<PtrTo<Identifier>>() : nullptr;
|
||||
return AlterTableClause::createAddColumn(!!ctx->IF(), visit(ctx->tableColumnDfnt()), after);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlterTableClauseAddIndex(ClickHouseParser::AlterTableClauseAddIndexContext * ctx)
|
||||
{
|
||||
auto after = ctx->AFTER() ? visit(ctx->nestedIdentifier()).as<PtrTo<Identifier>>() : nullptr;
|
||||
return AlterTableClause::createAddIndex(!!ctx->IF(), visit(ctx->tableIndexDfnt()), after);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlterTableClauseAttach(ClickHouseParser::AlterTableClauseAttachContext *ctx)
|
||||
{
|
||||
auto from = ctx->tableIdentifier() ? visit(ctx->tableIdentifier()).as<PtrTo<TableIdentifier>>() : nullptr;
|
||||
return AlterTableClause::createAttach(visit(ctx->partitionClause()), from);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlterTableClauseClear(ClickHouseParser::AlterTableClauseClearContext * ctx)
|
||||
{
|
||||
auto partition = ctx->partitionClause() ? visit(ctx->partitionClause()).as<PtrTo<PartitionClause>>() : nullptr;
|
||||
return AlterTableClause::createClear(!!ctx->IF(), visit(ctx->nestedIdentifier()), partition);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlterTableClauseComment(ClickHouseParser::AlterTableClauseCommentContext * ctx)
|
||||
{
|
||||
return AlterTableClause::createComment(!!ctx->IF(), visit(ctx->nestedIdentifier()), Literal::createString(ctx->STRING_LITERAL()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlterTableClauseDelete(ClickHouseParser::AlterTableClauseDeleteContext *ctx)
|
||||
{
|
||||
return AlterTableClause::createDelete(visit(ctx->columnExpr()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlterTableClauseDetach(ClickHouseParser::AlterTableClauseDetachContext *ctx)
|
||||
{
|
||||
return AlterTableClause::createDetach(visit(ctx->partitionClause()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlterTableClauseDropColumn(ClickHouseParser::AlterTableClauseDropColumnContext * ctx)
|
||||
{
|
||||
return AlterTableClause::createDropColumn(!!ctx->IF(), visit(ctx->nestedIdentifier()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlterTableClauseDropIndex(ClickHouseParser::AlterTableClauseDropIndexContext * ctx)
|
||||
{
|
||||
return AlterTableClause::createDropIndex(!!ctx->IF(), visit(ctx->nestedIdentifier()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlterTableClauseDropPartition(ClickHouseParser::AlterTableClauseDropPartitionContext *ctx)
|
||||
{
|
||||
return AlterTableClause::createDropPartition(visit(ctx->partitionClause()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlterTableClauseFreezePartition(ClickHouseParser::AlterTableClauseFreezePartitionContext *ctx)
|
||||
{
|
||||
auto clause = ctx->partitionClause() ? visit(ctx->partitionClause()).as<PtrTo<PartitionClause>>() : nullptr;
|
||||
return AlterTableClause::createFreezePartition(clause);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlterTableClauseModify(ClickHouseParser::AlterTableClauseModifyContext * ctx)
|
||||
{
|
||||
return AlterTableClause::createModify(!!ctx->IF(), visit(ctx->tableColumnDfnt()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlterTableClauseModifyCodec(ClickHouseParser::AlterTableClauseModifyCodecContext * ctx)
|
||||
{
|
||||
return AlterTableClause::createCodec(!!ctx->IF(), visit(ctx->nestedIdentifier()), visit(ctx->codecExpr()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlterTableClauseModifyComment(ClickHouseParser::AlterTableClauseModifyCommentContext *ctx)
|
||||
{
|
||||
return AlterTableClause::createComment(!!ctx->IF(), visit(ctx->nestedIdentifier()), Literal::createString(ctx->STRING_LITERAL()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlterTableClauseModifyOrderBy(ClickHouseParser::AlterTableClauseModifyOrderByContext * ctx)
|
||||
{
|
||||
return AlterTableClause::createOrderBy(visit(ctx->columnExpr()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlterTableClauseModifyRemove(ClickHouseParser::AlterTableClauseModifyRemoveContext *ctx)
|
||||
{
|
||||
return AlterTableClause::createRemove(!!ctx->IF(), visit(ctx->nestedIdentifier()), visit(ctx->tableColumnPropertyType()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlterTableClauseModifyTTL(ClickHouseParser::AlterTableClauseModifyTTLContext *ctx)
|
||||
{
|
||||
return AlterTableClause::createTTL(visit(ctx->ttlClause()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlterTableClauseMovePartition(ClickHouseParser::AlterTableClauseMovePartitionContext *ctx)
|
||||
{
|
||||
if (ctx->DISK())
|
||||
return AlterTableClause::createMovePartitionToDisk(visit(ctx->partitionClause()), Literal::createString(ctx->STRING_LITERAL()));
|
||||
if (ctx->TABLE())
|
||||
return AlterTableClause::createMovePartitionToTable(visit(ctx->partitionClause()), visit(ctx->tableIdentifier()));
|
||||
if (ctx->VOLUME())
|
||||
return AlterTableClause::createMovePartitionToVolume(visit(ctx->partitionClause()), Literal::createString(ctx->STRING_LITERAL()));
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlterTableClauseRemoveTTL(ClickHouseParser::AlterTableClauseRemoveTTLContext *)
|
||||
{
|
||||
return AlterTableClause::createRemoveTTL();
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlterTableClauseRename(ClickHouseParser::AlterTableClauseRenameContext *ctx)
|
||||
{
|
||||
return AlterTableClause::createRename(!!ctx->IF(), visit(ctx->nestedIdentifier(0)), visit(ctx->nestedIdentifier(1)));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlterTableClauseReplace(ClickHouseParser::AlterTableClauseReplaceContext *ctx)
|
||||
{
|
||||
return AlterTableClause::createReplace(visit(ctx->partitionClause()), visit(ctx->tableIdentifier()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlterTableClauseUpdate(ClickHouseParser::AlterTableClauseUpdateContext *ctx)
|
||||
{
|
||||
return AlterTableClause::createUpdate(visit(ctx->assignmentExprList()), visit(ctx->whereClause()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlterTableStmt(ClickHouseParser::AlterTableStmtContext * ctx)
|
||||
{
|
||||
auto cluster = ctx->clusterClause() ? visit(ctx->clusterClause()).as<PtrTo<ClusterClause>>() : nullptr;
|
||||
auto list = std::make_shared<List<AlterTableClause>>();
|
||||
for (auto * clause : ctx->alterTableClause()) list->push(visit(clause));
|
||||
return std::make_shared<AlterTableQuery>(cluster, visit(ctx->tableIdentifier()), list);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAssignmentExpr(ClickHouseParser::AssignmentExprContext *ctx)
|
||||
{
|
||||
return std::make_shared<AssignmentExpr>(visit(ctx->nestedIdentifier()), visit(ctx->columnExpr()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAssignmentExprList(ClickHouseParser::AssignmentExprListContext *ctx)
|
||||
{
|
||||
auto list = std::make_shared<AssignmentExprList>();
|
||||
for (auto * expr : ctx->assignmentExpr()) list->push(visit(expr));
|
||||
return list;
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitTableColumnPropertyType(ClickHouseParser::TableColumnPropertyTypeContext *ctx)
|
||||
{
|
||||
if (ctx->ALIAS()) return TableColumnPropertyType::ALIAS;
|
||||
if (ctx->CODEC()) return TableColumnPropertyType::CODEC;
|
||||
if (ctx->COMMENT()) return TableColumnPropertyType::COMMENT;
|
||||
if (ctx->DEFAULT()) return TableColumnPropertyType::DEFAULT;
|
||||
if (ctx->MATERIALIZED()) return TableColumnPropertyType::MATERIALIZED;
|
||||
if (ctx->TTL()) return TableColumnPropertyType::TTL;
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitPartitionClause(ClickHouseParser::PartitionClauseContext *ctx)
|
||||
{
|
||||
if (ctx->STRING_LITERAL())
|
||||
return std::make_shared<PartitionClause>(Literal::createString(ctx->STRING_LITERAL()));
|
||||
|
||||
auto expr = visit(ctx->columnExpr()).as<PtrTo<ColumnExpr>>();
|
||||
|
||||
if (expr->getType() == ColumnExpr::ExprType::LITERAL)
|
||||
return std::make_shared<PartitionClause>(PtrTo<List<Literal>>(new List<Literal>{expr->getLiteral()}));
|
||||
|
||||
if (expr->getType() == ColumnExpr::ExprType::FUNCTION && expr->getFunctionName() == "tuple")
|
||||
{
|
||||
auto list = std::make_shared<List<Literal>>();
|
||||
|
||||
for (auto it = expr->argumentsBegin(); it != expr->argumentsEnd(); ++it)
|
||||
{
|
||||
auto * literal = (*it)->as<ColumnExpr>();
|
||||
|
||||
if (literal->getType() == ColumnExpr::ExprType::LITERAL)
|
||||
list->push(literal->getLiteral());
|
||||
else
|
||||
{
|
||||
// TODO: 'Expected tuple of literals as Partition Expression'.
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_shared<PartitionClause>(list);
|
||||
}
|
||||
|
||||
// TODO: 'Expected tuple of literals as Partition Expression'.
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
}
|
179
src/Parsers/New/AST/AlterTableQuery.h
Normal file
179
src/Parsers/New/AST/AlterTableQuery.h
Normal file
@ -0,0 +1,179 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/DDLQuery.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
class AssignmentExpr : public INode
|
||||
{
|
||||
public:
|
||||
AssignmentExpr(PtrTo<Identifier> identifier, PtrTo<ColumnExpr> expr);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
IDENTIFIER = 0, // Identifier
|
||||
EXPR = 1, // ColumnExpr
|
||||
};
|
||||
};
|
||||
|
||||
enum class TableColumnPropertyType
|
||||
{
|
||||
ALIAS,
|
||||
CODEC,
|
||||
COMMENT,
|
||||
DEFAULT,
|
||||
MATERIALIZED,
|
||||
TTL,
|
||||
};
|
||||
|
||||
class PartitionClause : public INode
|
||||
{
|
||||
public:
|
||||
explicit PartitionClause(PtrTo<Literal> id);
|
||||
explicit PartitionClause(PtrTo<List<Literal>> list);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
ID = 0, // Literal
|
||||
LIST = 0, // List<Literal>
|
||||
};
|
||||
enum class ClauseType
|
||||
{
|
||||
ID,
|
||||
LIST,
|
||||
};
|
||||
|
||||
const ClauseType clause_type;
|
||||
|
||||
PartitionClause(ClauseType type, PtrList exprs);
|
||||
};
|
||||
|
||||
class AlterTableClause : public INode
|
||||
{
|
||||
public:
|
||||
static PtrTo<AlterTableClause> createAddColumn(bool if_not_exists, PtrTo<TableElementExpr> element, PtrTo<Identifier> after);
|
||||
static PtrTo<AlterTableClause> createAddIndex(bool if_not_exists, PtrTo<TableElementExpr> element, PtrTo<Identifier> after);
|
||||
static PtrTo<AlterTableClause> createAttach(PtrTo<PartitionClause> clause, PtrTo<TableIdentifier> from);
|
||||
static PtrTo<AlterTableClause> createClear(bool if_exists, PtrTo<Identifier> identifier, PtrTo<PartitionClause> in);
|
||||
static PtrTo<AlterTableClause> createCodec(bool if_exists, PtrTo<Identifier> identifier, PtrTo<CodecExpr> codec);
|
||||
static PtrTo<AlterTableClause> createComment(bool if_exists, PtrTo<Identifier> identifier, PtrTo<StringLiteral> comment);
|
||||
static PtrTo<AlterTableClause> createDelete(PtrTo<ColumnExpr> expr);
|
||||
static PtrTo<AlterTableClause> createDetach(PtrTo<PartitionClause> clause);
|
||||
static PtrTo<AlterTableClause> createDropColumn(bool if_exists, PtrTo<Identifier> identifier);
|
||||
static PtrTo<AlterTableClause> createDropIndex(bool if_exists, PtrTo<Identifier> identifier);
|
||||
static PtrTo<AlterTableClause> createDropPartition(PtrTo<PartitionClause> clause);
|
||||
static PtrTo<AlterTableClause> createFreezePartition(PtrTo<PartitionClause> clause);
|
||||
static PtrTo<AlterTableClause> createModify(bool if_exists, PtrTo<TableElementExpr> element);
|
||||
static PtrTo<AlterTableClause> createMovePartitionToDisk(PtrTo<PartitionClause> clause, PtrTo<StringLiteral> literal);
|
||||
static PtrTo<AlterTableClause> createMovePartitionToTable(PtrTo<PartitionClause> clause, PtrTo<TableIdentifier> identifier);
|
||||
static PtrTo<AlterTableClause> createMovePartitionToVolume(PtrTo<PartitionClause> clause, PtrTo<StringLiteral> literal);
|
||||
static PtrTo<AlterTableClause> createRemove(bool if_exists, PtrTo<Identifier> identifier, TableColumnPropertyType type);
|
||||
static PtrTo<AlterTableClause> createRemoveTTL();
|
||||
static PtrTo<AlterTableClause> createRename(bool if_exists, PtrTo<Identifier> identifier, PtrTo<Identifier> to);
|
||||
static PtrTo<AlterTableClause> createOrderBy(PtrTo<ColumnExpr> expr);
|
||||
static PtrTo<AlterTableClause> createReplace(PtrTo<PartitionClause> clause, PtrTo<TableIdentifier> from);
|
||||
static PtrTo<AlterTableClause> createTTL(PtrTo<TTLClause> clause);
|
||||
static PtrTo<AlterTableClause> createUpdate(PtrTo<AssignmentExprList> list, PtrTo<WhereClause> where);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
// ADD COLUMN or INDEX
|
||||
ELEMENT = 0, // TableElementExpr
|
||||
AFTER = 1, // Identifier (optional)
|
||||
|
||||
// ATTACH/REPLACE
|
||||
PARTITION = 0, // PartitionClause
|
||||
FROM = 1, // TableIdentifier (optional)
|
||||
|
||||
// CLEAR
|
||||
COLUMN = 0, // Identifier
|
||||
IN = 1, // PartitionClause
|
||||
|
||||
// CODEC
|
||||
CODEC = 1, // CodecExpr
|
||||
|
||||
// COMMENT
|
||||
COMMENT = 1, // StringLiteral
|
||||
|
||||
// DELETE
|
||||
EXPR = 0, // ColumnExpr
|
||||
|
||||
// MOVE
|
||||
// TO = 1, // TableIdentifier or StringLiteral
|
||||
|
||||
// RENAME
|
||||
TO = 1, // Identifier
|
||||
|
||||
// TTL
|
||||
CLAUSE = 0, // TTLClause
|
||||
|
||||
// UPDATE
|
||||
ASSIGNMENTS = 0, // AssignmentExprList
|
||||
WHERE = 1, // WhereClause
|
||||
};
|
||||
|
||||
enum class ClauseType
|
||||
{
|
||||
ADD_COLUMN,
|
||||
ADD_INDEX,
|
||||
ATTACH,
|
||||
CLEAR,
|
||||
CODEC,
|
||||
COMMENT,
|
||||
DELETE,
|
||||
DETACH,
|
||||
DROP_COLUMN,
|
||||
DROP_INDEX,
|
||||
DROP_PARTITION,
|
||||
FREEZE_PARTITION,
|
||||
MODIFY,
|
||||
MOVE_PARTITION_TO_DISK,
|
||||
MOVE_PARTITION_TO_TABLE,
|
||||
MOVE_PARTITION_TO_VOLUME,
|
||||
ORDER_BY,
|
||||
REMOVE,
|
||||
REMOVE_TTL,
|
||||
RENAME,
|
||||
REPLACE,
|
||||
TTL,
|
||||
UPDATE,
|
||||
};
|
||||
|
||||
const ClauseType clause_type;
|
||||
TableColumnPropertyType property_type = TableColumnPropertyType::ALIAS; // default value to silence PVS-Studio
|
||||
union
|
||||
{
|
||||
bool if_exists;
|
||||
bool if_not_exists;
|
||||
};
|
||||
|
||||
AlterTableClause(ClauseType type, PtrList exprs);
|
||||
};
|
||||
|
||||
class AlterTableQuery : public DDLQuery
|
||||
{
|
||||
public:
|
||||
AlterTableQuery(PtrTo<ClusterClause> cluster, PtrTo<TableIdentifier> identifier, PtrTo<List<AlterTableClause>> clauses);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
TABLE = 0, // TableIdentifier
|
||||
CLAUSES = 1, // List<AlterTableClause>
|
||||
};
|
||||
};
|
||||
|
||||
}
|
57
src/Parsers/New/AST/AttachQuery.cpp
Normal file
57
src/Parsers/New/AST/AttachQuery.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
#include <Parsers/New/AST/AttachQuery.h>
|
||||
|
||||
#include <Parsers/ASTCreateQuery.h>
|
||||
#include <Parsers/New/AST/Identifier.h>
|
||||
#include <Parsers/New/ParseTreeVisitor.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
// static
|
||||
PtrTo<AttachQuery> AttachQuery::createDictionary(PtrTo<ClusterClause> clause, PtrTo<TableIdentifier> identifier)
|
||||
{
|
||||
return PtrTo<AttachQuery>(new AttachQuery(clause, QueryType::DICTIONARY, {identifier}));
|
||||
}
|
||||
|
||||
AttachQuery::AttachQuery(PtrTo<ClusterClause> clause, QueryType type, PtrList exprs) : DDLQuery(clause, exprs), query_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr AttachQuery::convertToOld() const
|
||||
{
|
||||
auto query = std::make_shared<ASTCreateQuery>();
|
||||
|
||||
query->attach = true;
|
||||
|
||||
switch(query_type)
|
||||
{
|
||||
case QueryType::DICTIONARY:
|
||||
query->is_dictionary = true;
|
||||
{
|
||||
auto table_id = getTableIdentifier(get(NAME)->convertToOld());
|
||||
query->database = table_id.database_name;
|
||||
query->table = table_id.table_name;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
query->cluster = cluster_name;
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace AST;
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAttachDictionaryStmt(ClickHouseParser::AttachDictionaryStmtContext *ctx)
|
||||
{
|
||||
auto cluster = ctx->clusterClause() ? visit(ctx->clusterClause()).as<PtrTo<ClusterClause>>() : nullptr;
|
||||
return AttachQuery::createDictionary(cluster, visit(ctx->tableIdentifier()));
|
||||
}
|
||||
|
||||
}
|
32
src/Parsers/New/AST/AttachQuery.h
Normal file
32
src/Parsers/New/AST/AttachQuery.h
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/DDLQuery.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
class AttachQuery : public DDLQuery
|
||||
{
|
||||
public:
|
||||
static PtrTo<AttachQuery> createDictionary(PtrTo<ClusterClause> clause, PtrTo<TableIdentifier> identifier);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
NAME = 0, // TableIdentifier
|
||||
};
|
||||
|
||||
enum class QueryType
|
||||
{
|
||||
DICTIONARY,
|
||||
};
|
||||
|
||||
const QueryType query_type;
|
||||
|
||||
AttachQuery(PtrTo<ClusterClause> clause, QueryType type, PtrList exprs);
|
||||
};
|
||||
|
||||
}
|
44
src/Parsers/New/AST/CheckQuery.cpp
Normal file
44
src/Parsers/New/AST/CheckQuery.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
#include <Parsers/New/AST/CheckQuery.h>
|
||||
|
||||
#include <Interpreters/StorageID.h>
|
||||
#include <Parsers/ASTCheckQuery.h>
|
||||
#include <Parsers/ASTIdentifier.h>
|
||||
#include <Parsers/New/AST/AlterTableQuery.h>
|
||||
#include <Parsers/New/AST/Identifier.h>
|
||||
#include <Parsers/New/ParseTreeVisitor.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
CheckQuery::CheckQuery(PtrTo<TableIdentifier> identifier, PtrTo<PartitionClause> clause) : Query{identifier, clause}
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr CheckQuery::convertToOld() const
|
||||
{
|
||||
auto query = std::make_shared<ASTCheckQuery>();
|
||||
|
||||
auto table_id = getTableIdentifier(get(NAME)->convertToOld());
|
||||
query->database = table_id.database_name;
|
||||
query->table = table_id.table_name;
|
||||
|
||||
if (has(PARTITION)) query->partition = get(PARTITION)->convertToOld();
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace AST;
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitCheckStmt(ClickHouseParser::CheckStmtContext *ctx)
|
||||
{
|
||||
auto partition = ctx->partitionClause() ? visit(ctx->partitionClause()).as<PtrTo<PartitionClause>>() : nullptr;
|
||||
return std::make_shared<CheckQuery>(visit(ctx->tableIdentifier()), partition);
|
||||
}
|
||||
|
||||
}
|
24
src/Parsers/New/AST/CheckQuery.h
Normal file
24
src/Parsers/New/AST/CheckQuery.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/Query.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
class CheckQuery : public Query
|
||||
{
|
||||
public:
|
||||
CheckQuery(PtrTo<TableIdentifier> identifier, PtrTo<PartitionClause> clause);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
NAME = 0, // TableIdentifier
|
||||
PARTITION = 1, // PartitionClause (optional)
|
||||
};
|
||||
};
|
||||
|
||||
}
|
588
src/Parsers/New/AST/ColumnExpr.cpp
Normal file
588
src/Parsers/New/AST/ColumnExpr.cpp
Normal file
@ -0,0 +1,588 @@
|
||||
#include <Parsers/New/AST/ColumnExpr.h>
|
||||
|
||||
#include <Parsers/ASTAsterisk.h>
|
||||
#include <Parsers/ASTFunction.h>
|
||||
#include <Parsers/ASTQualifiedAsterisk.h>
|
||||
#include <Parsers/ASTSubquery.h>
|
||||
#include <Parsers/New/AST/ColumnTypeExpr.h>
|
||||
#include <Parsers/New/AST/Identifier.h>
|
||||
#include <Parsers/New/AST/Literal.h>
|
||||
#include <Parsers/New/AST/SelectUnionQuery.h>
|
||||
#include <Parsers/New/ClickHouseLexer.h>
|
||||
#include <Parsers/New/ClickHouseParser.h>
|
||||
#include <Parsers/New/ParseTreeVisitor.h>
|
||||
|
||||
|
||||
namespace DB::ErrorCodes
|
||||
{
|
||||
extern int SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
// static
|
||||
PtrTo<ColumnExpr> ColumnExpr::createAlias(PtrTo<ColumnExpr> expr, PtrTo<Identifier> alias)
|
||||
{
|
||||
return PtrTo<ColumnExpr>(new ColumnExpr(ExprType::ALIAS, {expr, alias}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<ColumnExpr> ColumnExpr::createAsterisk(PtrTo<TableIdentifier> identifier, bool single_column)
|
||||
{
|
||||
auto expr = PtrTo<ColumnExpr>(new ColumnExpr(ExprType::ASTERISK, {identifier}));
|
||||
expr->expect_single_column = single_column;
|
||||
return expr;
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<ColumnExpr> ColumnExpr::createFunction(PtrTo<Identifier> name, PtrTo<ColumnParamList> params, PtrTo<ColumnExprList> args)
|
||||
{
|
||||
// FIXME: make sure that all function names are camel-case.
|
||||
|
||||
// Flatten some consequent binary operators to a single multi-operator, because they are left-associative.
|
||||
if ((name->getName() == "or" || name->getName() == "and") && args && args->size() == 2)
|
||||
{
|
||||
const auto * left = (*args->begin())->as<ColumnExpr>();
|
||||
const auto * right = (*++args->begin())->as<ColumnExpr>();
|
||||
|
||||
if (left && left->getType() == ExprType::FUNCTION && left->getFunctionName() == name->getName())
|
||||
{
|
||||
auto new_args = std::make_shared<ColumnExprList>();
|
||||
for (const auto & arg : left->get(ARGS)->as<ColumnExprList &>())
|
||||
new_args->push(std::static_pointer_cast<ColumnExpr>(arg));
|
||||
new_args->push(std::static_pointer_cast<ColumnExpr>(*++args->begin()));
|
||||
args = new_args;
|
||||
}
|
||||
else if (right && right->getType() == ExprType::FUNCTION && right->getFunctionName() == name->getName())
|
||||
{
|
||||
auto new_args = std::make_shared<ColumnExprList>();
|
||||
new_args->push(std::static_pointer_cast<ColumnExpr>(*args->begin()));
|
||||
for (const auto & arg : right->get(ARGS)->as<ColumnExprList &>())
|
||||
new_args->push(std::static_pointer_cast<ColumnExpr>(arg));
|
||||
args = new_args;
|
||||
}
|
||||
}
|
||||
|
||||
return PtrTo<ColumnExpr>(new ColumnExpr(ExprType::FUNCTION, {name, params, args}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<ColumnExpr> ColumnExpr::createIdentifier(PtrTo<ColumnIdentifier> identifier)
|
||||
{
|
||||
return PtrTo<ColumnExpr>(new ColumnExpr(ExprType::IDENTIFIER, {identifier}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<ColumnExpr> ColumnExpr::createLambda(PtrTo<List<Identifier>> params, PtrTo<ColumnExpr> expr)
|
||||
{
|
||||
return PtrTo<ColumnExpr>(new ColumnExpr(ExprType::LAMBDA, {params, expr}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<ColumnExpr> ColumnExpr::createLiteral(PtrTo<Literal> literal)
|
||||
{
|
||||
return PtrTo<ColumnExpr>(new ColumnExpr(ExprType::LITERAL, {literal}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<ColumnExpr> ColumnExpr::createSubquery(PtrTo<SelectUnionQuery> query, bool scalar)
|
||||
{
|
||||
if (scalar) query->shouldBeScalar();
|
||||
return PtrTo<ColumnExpr>(new ColumnExpr(ExprType::SUBQUERY, {query}));
|
||||
}
|
||||
|
||||
ColumnExpr::ColumnExpr(ColumnExpr::ExprType type, PtrList exprs) : INode(exprs), expr_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr ColumnExpr::convertToOld() const
|
||||
{
|
||||
switch (expr_type)
|
||||
{
|
||||
case ExprType::ALIAS:
|
||||
{
|
||||
ASTPtr expr = get(EXPR)->convertToOld();
|
||||
|
||||
if (auto * expr_with_alias = dynamic_cast<ASTWithAlias*>(expr.get()))
|
||||
expr_with_alias->setAlias(get<Identifier>(ALIAS)->getName());
|
||||
else
|
||||
throw std::runtime_error("Trying to convert new expression with alias to old one without alias support: " + expr->getID());
|
||||
|
||||
return expr;
|
||||
}
|
||||
case ExprType::ASTERISK:
|
||||
if (has(TABLE))
|
||||
{
|
||||
auto expr = std::make_shared<ASTQualifiedAsterisk>();
|
||||
expr->children.push_back(get(TABLE)->convertToOld());
|
||||
return expr;
|
||||
}
|
||||
return std::make_shared<ASTAsterisk>();
|
||||
case ExprType::FUNCTION:
|
||||
{
|
||||
auto func = std::make_shared<ASTFunction>();
|
||||
|
||||
func->name = get<Identifier>(NAME)->getName();
|
||||
if (has(ARGS))
|
||||
{
|
||||
func->arguments = get(ARGS)->convertToOld();
|
||||
func->children.push_back(func->arguments);
|
||||
}
|
||||
if (has(PARAMS))
|
||||
{
|
||||
func->parameters = get(PARAMS)->convertToOld();
|
||||
func->children.push_back(func->parameters);
|
||||
}
|
||||
|
||||
return func;
|
||||
}
|
||||
case ExprType::IDENTIFIER:
|
||||
return get(IDENTIFIER)->convertToOld();
|
||||
case ExprType::LAMBDA:
|
||||
{
|
||||
auto func = std::make_shared<ASTFunction>();
|
||||
auto tuple = std::make_shared<ASTFunction>();
|
||||
|
||||
func->name = "lambda";
|
||||
func->arguments = std::make_shared<ASTExpressionList>();
|
||||
func->arguments->children.push_back(tuple);
|
||||
func->arguments->children.push_back(get(LAMBDA_EXPR)->convertToOld());
|
||||
func->children.push_back(func->arguments);
|
||||
|
||||
tuple->name = "tuple";
|
||||
tuple->arguments = get(LAMBDA_ARGS)->convertToOld();
|
||||
tuple->children.push_back(tuple->arguments);
|
||||
|
||||
return func;
|
||||
}
|
||||
case ExprType::LITERAL:
|
||||
return get(LITERAL)->convertToOld();
|
||||
case ExprType::SUBQUERY:
|
||||
{
|
||||
auto subquery = std::make_shared<ASTSubquery>();
|
||||
subquery->children.push_back(get(SUBQUERY)->convertToOld());
|
||||
return subquery;
|
||||
}
|
||||
}
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
String ColumnExpr::toString() const
|
||||
{
|
||||
switch(expr_type)
|
||||
{
|
||||
case ExprType::LITERAL: return get(LITERAL)->toString();
|
||||
default: return {};
|
||||
}
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
String ColumnExpr::dumpInfo() const
|
||||
{
|
||||
switch(expr_type)
|
||||
{
|
||||
case ExprType::ALIAS: return "ALIAS";
|
||||
case ExprType::ASTERISK: return "ASTERISK";
|
||||
case ExprType::FUNCTION: return "FUNCTION";
|
||||
case ExprType::IDENTIFIER: return "IDENTIFIER";
|
||||
case ExprType::LAMBDA: return "LAMBDA";
|
||||
case ExprType::LITERAL: return "LITERAL";
|
||||
case ExprType::SUBQUERY: return "SUBQUERY";
|
||||
}
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace AST;
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnArgExpr(ClickHouseParser::ColumnArgExprContext *ctx)
|
||||
{
|
||||
if (ctx->columnExpr()) return visit(ctx->columnExpr());
|
||||
if (ctx->columnLambdaExpr()) return visit(ctx->columnLambdaExpr());
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnArgList(ClickHouseParser::ColumnArgListContext *ctx)
|
||||
{
|
||||
auto list = std::make_shared<ColumnExprList>();
|
||||
for (auto * arg : ctx->columnArgExpr()) list->push(visit(arg));
|
||||
return list;
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprAlias(ClickHouseParser::ColumnExprAliasContext *ctx)
|
||||
{
|
||||
if (ctx->AS()) return ColumnExpr::createAlias(visit(ctx->columnExpr()), visit(ctx->identifier()));
|
||||
else return ColumnExpr::createAlias(visit(ctx->columnExpr()), visit(ctx->alias()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprAnd(ClickHouseParser::ColumnExprAndContext *ctx)
|
||||
{
|
||||
auto name = std::make_shared<Identifier>("and");
|
||||
auto args = std::make_shared<ColumnExprList>();
|
||||
|
||||
for (auto * expr : ctx->columnExpr()) args->push(visit(expr));
|
||||
|
||||
return ColumnExpr::createFunction(name, nullptr, args);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprArray(ClickHouseParser::ColumnExprArrayContext *ctx)
|
||||
{
|
||||
auto name = std::make_shared<Identifier>("array");
|
||||
auto args = ctx->columnExprList() ? visit(ctx->columnExprList()).as<PtrTo<ColumnExprList>>() : nullptr;
|
||||
return ColumnExpr::createFunction(name, nullptr, args);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprArrayAccess(ClickHouseParser::ColumnExprArrayAccessContext *ctx)
|
||||
{
|
||||
auto name = std::make_shared<Identifier>("arrayElement");
|
||||
auto args = std::make_shared<ColumnExprList>();
|
||||
|
||||
for (auto * expr : ctx->columnExpr()) args->push(visit(expr));
|
||||
|
||||
return ColumnExpr::createFunction(name, nullptr, args);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprAsterisk(ClickHouseParser::ColumnExprAsteriskContext *ctx)
|
||||
{
|
||||
auto table = ctx->tableIdentifier() ? visit(ctx->tableIdentifier()).as<PtrTo<TableIdentifier>>() : nullptr;
|
||||
return ColumnExpr::createAsterisk(table, true);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprBetween(ClickHouseParser::ColumnExprBetweenContext *ctx)
|
||||
{
|
||||
PtrTo<ColumnExpr> expr1, expr2;
|
||||
|
||||
{
|
||||
auto name = std::make_shared<Identifier>(ctx->NOT() ? "lessOrEquals" : "greaterOrEquals");
|
||||
auto args = std::make_shared<ColumnExprList>();
|
||||
args->push(visit(ctx->columnExpr(0)));
|
||||
args->push(visit(ctx->columnExpr(1)));
|
||||
expr1 = ColumnExpr::createFunction(name, nullptr, args);
|
||||
}
|
||||
|
||||
{
|
||||
auto name = std::make_shared<Identifier>(ctx->NOT() ? "greaterOrEquals" : "lessOrEquals");
|
||||
auto args = std::make_shared<ColumnExprList>();
|
||||
args->push(visit(ctx->columnExpr(0)));
|
||||
args->push(visit(ctx->columnExpr(2)));
|
||||
expr2 = ColumnExpr::createFunction(name, nullptr, args);
|
||||
}
|
||||
|
||||
auto name = std::make_shared<Identifier>("and");
|
||||
auto args = std::make_shared<ColumnExprList>();
|
||||
|
||||
args->push(expr1);
|
||||
args->push(expr2);
|
||||
|
||||
return ColumnExpr::createFunction(name, nullptr, args);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprCase(ClickHouseParser::ColumnExprCaseContext *ctx)
|
||||
{
|
||||
auto has_case_expr = (ctx->ELSE() && ctx->columnExpr().size() % 2 == 0) || (!ctx->ELSE() && ctx->columnExpr().size() % 2 == 1);
|
||||
auto name = std::make_shared<Identifier>(has_case_expr ? "caseWithExpression" : "multiIf");
|
||||
auto args = std::make_shared<ColumnExprList>();
|
||||
|
||||
for (auto * expr : ctx->columnExpr()) args->push(visit(expr));
|
||||
if (!ctx->ELSE()) args->push(ColumnExpr::createLiteral(Literal::createNull()));
|
||||
|
||||
return ColumnExpr::createFunction(name, nullptr, args);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprCast(ClickHouseParser::ColumnExprCastContext *ctx)
|
||||
{
|
||||
auto args = std::make_shared<ColumnExprList>();
|
||||
|
||||
args->push(visit(ctx->columnExpr()));
|
||||
args->push(ColumnExpr::createLiteral(Literal::createString(visit(ctx->columnTypeExpr()).as<PtrTo<ColumnTypeExpr>>()->toString())));
|
||||
|
||||
return ColumnExpr::createFunction(std::make_shared<Identifier>("cast"), nullptr, args);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprDate(ClickHouseParser::ColumnExprDateContext *ctx)
|
||||
{
|
||||
auto name = std::make_shared<Identifier>("toDate");
|
||||
auto args = std::make_shared<ColumnExprList>();
|
||||
|
||||
args->push(ColumnExpr::createLiteral(Literal::createString(ctx->STRING_LITERAL())));
|
||||
|
||||
return ColumnExpr::createFunction(name, nullptr, args);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprExtract(ClickHouseParser::ColumnExprExtractContext *ctx)
|
||||
{
|
||||
String name;
|
||||
auto args = std::make_shared<ColumnExprList>();
|
||||
|
||||
if (ctx->interval()->SECOND()) name = "toSecond";
|
||||
else if (ctx->interval()->MINUTE()) name = "toMinute";
|
||||
else if (ctx->interval()->HOUR()) name = "toHour";
|
||||
else if (ctx->interval()->DAY()) name = "toDayOfMonth";
|
||||
else if (ctx->interval()->WEEK())
|
||||
throw Exception(
|
||||
"The syntax 'EXTRACT(WEEK FROM date)' is not supported, cannot extract the number of a week", ErrorCodes::SYNTAX_ERROR);
|
||||
else if (ctx->interval()->MONTH()) name = "toMonth";
|
||||
else if (ctx->interval()->QUARTER()) name = "toQuarter";
|
||||
else if (ctx->interval()->YEAR()) name = "toYear";
|
||||
else __builtin_unreachable();
|
||||
|
||||
args->push(visit(ctx->columnExpr()));
|
||||
|
||||
return ColumnExpr::createFunction(std::make_shared<Identifier>(name), nullptr, args);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprFunction(ClickHouseParser::ColumnExprFunctionContext *ctx)
|
||||
{
|
||||
auto name = visit(ctx->identifier()).as<PtrTo<Identifier>>();
|
||||
auto params = ctx->columnExprList() ? visit(ctx->columnExprList()).as<PtrTo<ColumnExprList>>() : nullptr;
|
||||
auto args = ctx->columnArgList() ? visit(ctx->columnArgList()).as<PtrTo<ColumnExprList>>() : nullptr;
|
||||
|
||||
if (ctx->DISTINCT()) name = std::make_shared<Identifier>(name->getName() + "Distinct");
|
||||
|
||||
return ColumnExpr::createFunction(name, params, args);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprIdentifier(ClickHouseParser::ColumnExprIdentifierContext *ctx)
|
||||
{
|
||||
return ColumnExpr::createIdentifier(visit(ctx->columnIdentifier()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprInterval(ClickHouseParser::ColumnExprIntervalContext *ctx)
|
||||
{
|
||||
PtrTo<Identifier> name;
|
||||
auto args = std::make_shared<ColumnExprList>();
|
||||
|
||||
if (ctx->interval()->SECOND()) name = std::make_shared<Identifier>("toIntervalSecond");
|
||||
else if (ctx->interval()->MINUTE()) name = std::make_shared<Identifier>("toIntervalMinute");
|
||||
else if (ctx->interval()->HOUR()) name = std::make_shared<Identifier>("toIntervalHour");
|
||||
else if (ctx->interval()->DAY()) name = std::make_shared<Identifier>("toIntervalDay");
|
||||
else if (ctx->interval()->WEEK()) name = std::make_shared<Identifier>("toIntervalWeek");
|
||||
else if (ctx->interval()->MONTH()) name = std::make_shared<Identifier>("toIntervalMonth");
|
||||
else if (ctx->interval()->QUARTER()) name = std::make_shared<Identifier>("toIntervalQuarter");
|
||||
else if (ctx->interval()->YEAR()) name = std::make_shared<Identifier>("toIntervalYear");
|
||||
else __builtin_unreachable();
|
||||
|
||||
args->push(visit(ctx->columnExpr()));
|
||||
|
||||
return ColumnExpr::createFunction(name, nullptr, args);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprIsNull(ClickHouseParser::ColumnExprIsNullContext *ctx)
|
||||
{
|
||||
auto name = std::make_shared<Identifier>(ctx->NOT() ? "isNotNull" : "isNull");
|
||||
auto args = std::make_shared<ColumnExprList>();
|
||||
|
||||
args->push(visit(ctx->columnExpr()));
|
||||
|
||||
return ColumnExpr::createFunction(name, nullptr, args);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprList(ClickHouseParser::ColumnExprListContext *ctx)
|
||||
{
|
||||
auto list = std::make_shared<ColumnExprList>();
|
||||
for (auto * expr : ctx->columnsExpr()) list->push(visit(expr));
|
||||
return list;
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprLiteral(ClickHouseParser::ColumnExprLiteralContext *ctx)
|
||||
{
|
||||
return ColumnExpr::createLiteral(visit(ctx->literal()).as<PtrTo<Literal>>());
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprNegate(ClickHouseParser::ColumnExprNegateContext *ctx)
|
||||
{
|
||||
auto name = std::make_shared<Identifier>("negate");
|
||||
auto args = std::make_shared<ColumnExprList>();
|
||||
|
||||
args->push(visit(ctx->columnExpr()));
|
||||
|
||||
return ColumnExpr::createFunction(name, nullptr, args);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprNot(ClickHouseParser::ColumnExprNotContext *ctx)
|
||||
{
|
||||
auto name = std::make_shared<Identifier>("not");
|
||||
auto args = std::make_shared<ColumnExprList>();
|
||||
|
||||
args->push(visit(ctx->columnExpr()));
|
||||
|
||||
return ColumnExpr::createFunction(name, nullptr, args);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprOr(ClickHouseParser::ColumnExprOrContext *ctx)
|
||||
{
|
||||
auto name = std::make_shared<Identifier>("or");
|
||||
|
||||
auto args = std::make_shared<ColumnExprList>();
|
||||
for (auto * expr : ctx->columnExpr()) args->push(visit(expr));
|
||||
|
||||
return ColumnExpr::createFunction(name, nullptr, args);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprParens(ClickHouseParser::ColumnExprParensContext *ctx)
|
||||
{
|
||||
return visit(ctx->columnExpr());
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprPrecedence1(ClickHouseParser::ColumnExprPrecedence1Context *ctx)
|
||||
{
|
||||
PtrTo<Identifier> name;
|
||||
if (ctx->ASTERISK()) name = std::make_shared<Identifier>("multiply");
|
||||
else if (ctx->SLASH()) name = std::make_shared<Identifier>("divide");
|
||||
else if (ctx->PERCENT()) name = std::make_shared<Identifier>("modulo");
|
||||
|
||||
auto args = std::make_shared<ColumnExprList>();
|
||||
for (auto * expr : ctx->columnExpr()) args->push(visit(expr));
|
||||
|
||||
return ColumnExpr::createFunction(name, nullptr, args);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprPrecedence2(ClickHouseParser::ColumnExprPrecedence2Context *ctx)
|
||||
{
|
||||
PtrTo<Identifier> name;
|
||||
if (ctx->PLUS()) name = std::make_shared<Identifier>("plus");
|
||||
else if (ctx->DASH()) name = std::make_shared<Identifier>("minus");
|
||||
else if (ctx->CONCAT()) name = std::make_shared<Identifier>("concat");
|
||||
|
||||
auto args = std::make_shared<ColumnExprList>();
|
||||
for (auto * expr : ctx->columnExpr()) args->push(visit(expr));
|
||||
|
||||
return ColumnExpr::createFunction(name, nullptr, args);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprPrecedence3(ClickHouseParser::ColumnExprPrecedence3Context *ctx)
|
||||
{
|
||||
PtrTo<Identifier> name;
|
||||
if (ctx->EQ_DOUBLE() || ctx->EQ_SINGLE()) name = std::make_shared<Identifier>("equals");
|
||||
else if (ctx->NOT_EQ()) name = std::make_shared<Identifier>("notEquals");
|
||||
else if (ctx->LE()) name = std::make_shared<Identifier>("lessOrEquals");
|
||||
else if (ctx->GE()) name = std::make_shared<Identifier>("greaterOrEquals");
|
||||
else if (ctx->LT()) name = std::make_shared<Identifier>("less");
|
||||
else if (ctx->GT()) name = std::make_shared<Identifier>("greater");
|
||||
else if (ctx->LIKE())
|
||||
{
|
||||
if (ctx->NOT()) name = std::make_shared<Identifier>("notLike");
|
||||
else name = std::make_shared<Identifier>("like");
|
||||
}
|
||||
else if (ctx->ILIKE())
|
||||
{
|
||||
if (ctx->NOT()) name = std::make_shared<Identifier>("notILike");
|
||||
else name = std::make_shared<Identifier>("ilike");
|
||||
}
|
||||
else if (ctx->IN())
|
||||
{
|
||||
if (ctx->GLOBAL())
|
||||
{
|
||||
if (ctx->NOT()) name = std::make_shared<Identifier>("globalNotIn");
|
||||
else name = std::make_shared<Identifier>("globalIn");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ctx->NOT()) name = std::make_shared<Identifier>("notIn");
|
||||
else name = std::make_shared<Identifier>("in");
|
||||
}
|
||||
}
|
||||
|
||||
auto args = std::make_shared<ColumnExprList>();
|
||||
for (auto * expr : ctx->columnExpr()) args->push(visit(expr));
|
||||
|
||||
return ColumnExpr::createFunction(name, nullptr, args);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprSubquery(ClickHouseParser::ColumnExprSubqueryContext *ctx)
|
||||
{
|
||||
// IN-operator is special since it accepts non-scalar subqueries on the right side.
|
||||
auto * parent = dynamic_cast<ClickHouseParser::ColumnExprPrecedence3Context*>(ctx->parent);
|
||||
return ColumnExpr::createSubquery(visit(ctx->selectUnionStmt()), !(parent && parent->IN()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprSubstring(ClickHouseParser::ColumnExprSubstringContext *ctx)
|
||||
{
|
||||
auto name = std::make_shared<Identifier>("substring");
|
||||
auto args = std::make_shared<ColumnExprList>();
|
||||
|
||||
for (auto * expr : ctx->columnExpr()) args->push(visit(expr));
|
||||
|
||||
return ColumnExpr::createFunction(name, nullptr, args);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprTernaryOp(ClickHouseParser::ColumnExprTernaryOpContext *ctx)
|
||||
{
|
||||
auto name = std::make_shared<Identifier>("if");
|
||||
auto args = std::make_shared<ColumnExprList>();
|
||||
|
||||
for (auto * expr : ctx->columnExpr()) args->push(visit(expr));
|
||||
|
||||
return ColumnExpr::createFunction(name, nullptr, args);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprTimestamp(ClickHouseParser::ColumnExprTimestampContext *ctx)
|
||||
{
|
||||
auto name = std::make_shared<Identifier>("toDateTime");
|
||||
auto args = std::make_shared<ColumnExprList>();
|
||||
|
||||
args->push(ColumnExpr::createLiteral(Literal::createString(ctx->STRING_LITERAL())));
|
||||
|
||||
return ColumnExpr::createFunction(name, nullptr, args);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprTrim(ClickHouseParser::ColumnExprTrimContext *ctx)
|
||||
{
|
||||
auto name = std::make_shared<Identifier>("trim");
|
||||
auto args = std::make_shared<ColumnExprList>();
|
||||
auto params = std::make_shared<ColumnParamList>();
|
||||
|
||||
args->push(visit(ctx->columnExpr()));
|
||||
// TODO: params->append(Literal::createString(???));
|
||||
params->push(ColumnExpr::createLiteral(Literal::createString(ctx->STRING_LITERAL())));
|
||||
|
||||
return ColumnExpr::createFunction(name, params, args);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprTuple(ClickHouseParser::ColumnExprTupleContext *ctx)
|
||||
{
|
||||
auto name = std::make_shared<Identifier>("tuple");
|
||||
auto args = visit(ctx->columnExprList()).as<PtrTo<ColumnExprList>>();
|
||||
return ColumnExpr::createFunction(name, nullptr, args);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnExprTupleAccess(ClickHouseParser::ColumnExprTupleAccessContext *ctx)
|
||||
{
|
||||
auto name = std::make_shared<Identifier>("tupleElement");
|
||||
auto args = std::make_shared<ColumnExprList>();
|
||||
|
||||
args->push(visit(ctx->columnExpr()));
|
||||
args->push(ColumnExpr::createLiteral(Literal::createNumber(ctx->DECIMAL_LITERAL())));
|
||||
|
||||
return ColumnExpr::createFunction(name, nullptr, args);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnLambdaExpr(ClickHouseParser::ColumnLambdaExprContext *ctx)
|
||||
{
|
||||
auto params = std::make_shared<List<Identifier>>();
|
||||
for (auto * id : ctx->identifier()) params->push(visit(id));
|
||||
return ColumnExpr::createLambda(params, visit(ctx->columnExpr()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnsExprAsterisk(ClickHouseParser::ColumnsExprAsteriskContext *ctx)
|
||||
{
|
||||
auto table = ctx->tableIdentifier() ? visit(ctx->tableIdentifier()).as<PtrTo<TableIdentifier>>() : nullptr;
|
||||
return ColumnExpr::createAsterisk(table, false);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnsExprSubquery(ClickHouseParser::ColumnsExprSubqueryContext *ctx)
|
||||
{
|
||||
return ColumnExpr::createSubquery(visit(ctx->selectUnionStmt()), false);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnsExprColumn(ClickHouseParser::ColumnsExprColumnContext *ctx)
|
||||
{
|
||||
return visit(ctx->columnExpr());
|
||||
}
|
||||
|
||||
}
|
82
src/Parsers/New/AST/ColumnExpr.h
Normal file
82
src/Parsers/New/AST/ColumnExpr.h
Normal file
@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/Identifier.h>
|
||||
#include <Parsers/New/AST/Literal.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
class ColumnExpr : public INode
|
||||
{
|
||||
public:
|
||||
static PtrTo<ColumnExpr> createAlias(PtrTo<ColumnExpr> expr, PtrTo<Identifier> alias);
|
||||
static PtrTo<ColumnExpr> createAsterisk(PtrTo<TableIdentifier> identifier, bool single_column);
|
||||
static PtrTo<ColumnExpr> createFunction(PtrTo<Identifier> name, PtrTo<ColumnParamList> params, PtrTo<ColumnExprList> args);
|
||||
static PtrTo<ColumnExpr> createIdentifier(PtrTo<ColumnIdentifier> identifier);
|
||||
static PtrTo<ColumnExpr> createLambda(PtrTo<List<Identifier>> params, PtrTo<ColumnExpr> expr);
|
||||
static PtrTo<ColumnExpr> createLiteral(PtrTo<Literal> literal);
|
||||
static PtrTo<ColumnExpr> createSubquery(PtrTo<SelectUnionQuery> query, bool scalar);
|
||||
|
||||
enum class ExprType
|
||||
{
|
||||
ALIAS,
|
||||
ASTERISK,
|
||||
FUNCTION,
|
||||
IDENTIFIER,
|
||||
LAMBDA,
|
||||
LITERAL,
|
||||
SUBQUERY,
|
||||
};
|
||||
|
||||
auto getType() const { return expr_type; };
|
||||
|
||||
// FUNCTION
|
||||
auto getFunctionName() const { return get<Identifier>(NAME)->getName(); }
|
||||
auto argumentsBegin() const { return has(ARGS) ? get<ColumnExprList>(ARGS)->begin() : end(); }
|
||||
auto argumentsEnd() const { return has(ARGS) ? get<ColumnExprList>(ARGS)->end() : end(); }
|
||||
|
||||
// LITERAL
|
||||
auto getLiteral() const { return std::static_pointer_cast<Literal>(get(LITERAL)); }
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
String toString() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
// ALIAS
|
||||
EXPR = 0, // ColumnExpr
|
||||
ALIAS = 1, // Identifier
|
||||
|
||||
// ASTERISK
|
||||
TABLE = 0, // TableIdentifier (optional)
|
||||
|
||||
// IDENTIFIER
|
||||
IDENTIFIER = 0, // ColumnIdentifier
|
||||
|
||||
// FUNCTION
|
||||
NAME = 0, // Identifier
|
||||
PARAMS = 1, // ColumnParamList (optional)
|
||||
ARGS = 2, // ColumnExprList (optional)
|
||||
|
||||
// LAMBDA
|
||||
LAMBDA_ARGS = 0,
|
||||
LAMBDA_EXPR = 1,
|
||||
|
||||
// LITERAL
|
||||
LITERAL = 0,
|
||||
|
||||
// SUBQUERY
|
||||
SUBQUERY = 0,
|
||||
};
|
||||
|
||||
const ExprType expr_type;
|
||||
bool expect_single_column = false;
|
||||
|
||||
ColumnExpr(ExprType type, PtrList exprs);
|
||||
|
||||
String dumpInfo() const override;
|
||||
};
|
||||
|
||||
}
|
166
src/Parsers/New/AST/ColumnTypeExpr.cpp
Normal file
166
src/Parsers/New/AST/ColumnTypeExpr.cpp
Normal file
@ -0,0 +1,166 @@
|
||||
#include <Parsers/New/AST/ColumnTypeExpr.h>
|
||||
|
||||
#include <Parsers/ASTFunction.h>
|
||||
#include <Parsers/ASTNameTypePair.h>
|
||||
#include <Parsers/New/AST/Identifier.h>
|
||||
#include <Parsers/New/AST/Literal.h>
|
||||
#include <Parsers/New/ParseTreeVisitor.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
EnumValue::EnumValue(PtrTo<StringLiteral> name, PtrTo<NumberLiteral> value) : INode{name, value}
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr EnumValue::convertToOld() const
|
||||
{
|
||||
auto func = std::make_shared<ASTFunction>();
|
||||
|
||||
func->name = "equals";
|
||||
func->arguments = std::make_shared<ASTExpressionList>();
|
||||
func->arguments->children.push_back(get(NAME)->convertToOld());
|
||||
func->arguments->children.push_back(get(VALUE)->convertToOld());
|
||||
func->children.push_back(func->arguments);
|
||||
|
||||
return func;
|
||||
}
|
||||
|
||||
String EnumValue::toString() const
|
||||
{
|
||||
return fmt::format("{} = {}", get(NAME)->toString(), get(VALUE)->toString());
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<ColumnTypeExpr> ColumnTypeExpr::createSimple(PtrTo<Identifier> identifier)
|
||||
{
|
||||
return PtrTo<ColumnTypeExpr>(new ColumnTypeExpr(ExprType::SIMPLE, {identifier}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<ColumnTypeExpr> ColumnTypeExpr::createNamed(PtrTo<Identifier> identifier, PtrTo<ColumnTypeExpr> type)
|
||||
{
|
||||
return PtrTo<ColumnTypeExpr>(new ColumnTypeExpr(ExprType::NAMED, {identifier, type}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<ColumnTypeExpr> ColumnTypeExpr::createComplex(PtrTo<Identifier> identifier, PtrTo<ColumnTypeExprList> list)
|
||||
{
|
||||
return PtrTo<ColumnTypeExpr>(new ColumnTypeExpr(ExprType::COMPLEX, {identifier, list}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<ColumnTypeExpr> ColumnTypeExpr::createEnum(PtrTo<Identifier> identifier, PtrTo<EnumValueList> list)
|
||||
{
|
||||
return PtrTo<ColumnTypeExpr>(new ColumnTypeExpr(ExprType::ENUM, {identifier, list}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<ColumnTypeExpr> ColumnTypeExpr::createParam(PtrTo<Identifier> identifier, PtrTo<ColumnParamList> list)
|
||||
{
|
||||
return PtrTo<ColumnTypeExpr>(new ColumnTypeExpr(ExprType::PARAM, {identifier, list}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<ColumnTypeExpr> ColumnTypeExpr::createNested(PtrTo<Identifier> identifier, PtrTo<ColumnTypeExprList> list)
|
||||
{
|
||||
// TODO: assert that |list| must contain only expressions of NAMED type
|
||||
return PtrTo<ColumnTypeExpr>(new ColumnTypeExpr(ExprType::NESTED, {identifier, list}));
|
||||
}
|
||||
|
||||
ColumnTypeExpr::ColumnTypeExpr(ExprType type, PtrList exprs) : INode(exprs), expr_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr ColumnTypeExpr::convertToOld() const
|
||||
{
|
||||
if (expr_type == ExprType::NAMED)
|
||||
{
|
||||
auto pair = std::make_shared<ASTNameTypePair>();
|
||||
|
||||
pair->name = get<Identifier>(NAME)->getName();
|
||||
pair->type = get(TYPE)->convertToOld();
|
||||
pair->children.push_back(pair->type);
|
||||
|
||||
return pair;
|
||||
}
|
||||
|
||||
auto func = std::make_shared<ASTFunction>();
|
||||
|
||||
func->name = get<Identifier>(NAME)->getName();
|
||||
func->no_empty_args = true;
|
||||
if (expr_type != ExprType::SIMPLE && has(LIST))
|
||||
{
|
||||
func->arguments = get(LIST)->convertToOld();
|
||||
func->children.push_back(func->arguments);
|
||||
}
|
||||
|
||||
return func;
|
||||
}
|
||||
|
||||
String ColumnTypeExpr::toString() const
|
||||
{
|
||||
switch(expr_type)
|
||||
{
|
||||
case ExprType::SIMPLE:
|
||||
return get(NAME)->toString();
|
||||
case ExprType::NAMED:
|
||||
return get(NAME)->toString() + " " + get(TYPE)->toString();
|
||||
case ExprType::COMPLEX:
|
||||
case ExprType::ENUM:
|
||||
case ExprType::PARAM:
|
||||
case ExprType::NESTED:
|
||||
return get(NAME)->toString() + "(" + (has(LIST) ? get(LIST)->toString() : "") + ")";
|
||||
}
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace AST;
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnTypeExprSimple(ClickHouseParser::ColumnTypeExprSimpleContext *ctx)
|
||||
{
|
||||
return ColumnTypeExpr::createSimple(visit(ctx->identifier()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnTypeExprParam(ClickHouseParser::ColumnTypeExprParamContext *ctx)
|
||||
{
|
||||
auto list = ctx->columnExprList() ? visit(ctx->columnExprList()).as<PtrTo<ColumnExprList>>() : nullptr;
|
||||
return ColumnTypeExpr::createParam(visit(ctx->identifier()), list);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnTypeExprEnum(ClickHouseParser::ColumnTypeExprEnumContext *ctx)
|
||||
{
|
||||
auto list = std::make_shared<EnumValueList>();
|
||||
for (auto * value : ctx->enumValue()) list->push(visit(value));
|
||||
return ColumnTypeExpr::createEnum(visit(ctx->identifier()), list);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnTypeExprComplex(ClickHouseParser::ColumnTypeExprComplexContext *ctx)
|
||||
{
|
||||
auto list = std::make_shared<ColumnTypeExprList>();
|
||||
for (auto * expr : ctx->columnTypeExpr()) list->push(visit(expr));
|
||||
return ColumnTypeExpr::createComplex(visit(ctx->identifier()), list);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnTypeExprNested(ClickHouseParser::ColumnTypeExprNestedContext *ctx)
|
||||
{
|
||||
auto list = std::make_shared<ColumnTypeExprList>();
|
||||
|
||||
for (size_t i = 0; i < ctx->columnTypeExpr().size(); ++i)
|
||||
list->push(ColumnTypeExpr::createNamed(visit(ctx->identifier(i + 1)), visit(ctx->columnTypeExpr(i))));
|
||||
|
||||
return ColumnTypeExpr::createNested(visit(ctx->identifier(0)), list);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitEnumValue(ClickHouseParser::EnumValueContext *ctx)
|
||||
{
|
||||
return std::make_shared<EnumValue>(Literal::createString(ctx->STRING_LITERAL()), visit(ctx->numberLiteral()));
|
||||
}
|
||||
|
||||
}
|
62
src/Parsers/New/AST/ColumnTypeExpr.h
Normal file
62
src/Parsers/New/AST/ColumnTypeExpr.h
Normal file
@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/INode.h>
|
||||
|
||||
#include <list>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
class EnumValue : public INode
|
||||
{
|
||||
public:
|
||||
EnumValue(PtrTo<StringLiteral> name, PtrTo<NumberLiteral> value);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
String toString() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
NAME = 0, // StringLiteral
|
||||
VALUE = 1, // NumberLiteral
|
||||
};
|
||||
};
|
||||
|
||||
class ColumnTypeExpr : public INode
|
||||
{
|
||||
public:
|
||||
static PtrTo<ColumnTypeExpr> createSimple(PtrTo<Identifier> identifier);
|
||||
static PtrTo<ColumnTypeExpr> createNamed(PtrTo<Identifier> identifier, PtrTo<ColumnTypeExpr> type);
|
||||
static PtrTo<ColumnTypeExpr> createComplex(PtrTo<Identifier> identifier, PtrTo<ColumnTypeExprList> list);
|
||||
static PtrTo<ColumnTypeExpr> createEnum(PtrTo<Identifier> identifier, PtrTo<EnumValueList> list);
|
||||
static PtrTo<ColumnTypeExpr> createParam(PtrTo<Identifier> identifier, PtrTo<ColumnParamList> list);
|
||||
static PtrTo<ColumnTypeExpr> createNested(PtrTo<Identifier> identifier, PtrTo<ColumnTypeExprList> list);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
String toString() const override;
|
||||
|
||||
private:
|
||||
enum class ExprType
|
||||
{
|
||||
SIMPLE,
|
||||
NAMED,
|
||||
COMPLEX,
|
||||
ENUM,
|
||||
PARAM,
|
||||
NESTED,
|
||||
};
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
NAME = 0, // Identifier
|
||||
TYPE = 1, // ColumnTypeExpr
|
||||
LIST = 1, // depends on |expr_type|
|
||||
};
|
||||
|
||||
ExprType expr_type;
|
||||
|
||||
ColumnTypeExpr(ExprType type, PtrList exprs);
|
||||
};
|
||||
|
||||
}
|
51
src/Parsers/New/AST/CreateDatabaseQuery.cpp
Normal file
51
src/Parsers/New/AST/CreateDatabaseQuery.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
#include <Parsers/New/AST/CreateDatabaseQuery.h>
|
||||
|
||||
#include <Parsers/ASTCreateQuery.h>
|
||||
#include <Parsers/ASTFunction.h>
|
||||
#include <Parsers/New/AST/EngineExpr.h>
|
||||
#include <Parsers/New/AST/Identifier.h>
|
||||
#include <Parsers/New/ParseTreeVisitor.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
CreateDatabaseQuery::CreateDatabaseQuery(
|
||||
PtrTo<ClusterClause> cluster, bool if_not_exists_, PtrTo<DatabaseIdentifier> identifier, PtrTo<EngineExpr> expr)
|
||||
: DDLQuery(cluster, {identifier, expr}), if_not_exists(if_not_exists_)
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr CreateDatabaseQuery::convertToOld() const
|
||||
{
|
||||
auto query = std::make_shared<ASTCreateQuery>();
|
||||
|
||||
query->if_not_exists = if_not_exists;
|
||||
query->database = get<DatabaseIdentifier>(NAME)->getName();
|
||||
query->cluster = cluster_name;
|
||||
if (has(ENGINE))
|
||||
{
|
||||
auto engine = std::make_shared<ASTStorage>();
|
||||
engine->set(engine->engine, get(ENGINE)->convertToOld());
|
||||
query->set(query->storage, engine);
|
||||
}
|
||||
// TODO: query->uuid
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace AST;
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitCreateDatabaseStmt(ClickHouseParser::CreateDatabaseStmtContext *ctx)
|
||||
{
|
||||
auto engine = ctx->engineExpr() ? visit(ctx->engineExpr()).as<PtrTo<EngineExpr>>() : nullptr;
|
||||
auto cluster = ctx->clusterClause() ? visit(ctx->clusterClause()).as<PtrTo<ClusterClause>>() : nullptr;
|
||||
return std::make_shared<CreateDatabaseQuery>(cluster, !!ctx->IF(), visit(ctx->databaseIdentifier()), engine);
|
||||
}
|
||||
|
||||
}
|
26
src/Parsers/New/AST/CreateDatabaseQuery.h
Normal file
26
src/Parsers/New/AST/CreateDatabaseQuery.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/DDLQuery.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
class CreateDatabaseQuery: public DDLQuery
|
||||
{
|
||||
public:
|
||||
CreateDatabaseQuery(PtrTo<ClusterClause> cluster, bool if_not_exists, PtrTo<DatabaseIdentifier> identifier, PtrTo<EngineExpr> expr);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
NAME = 0, // DatabaseIdentifier
|
||||
ENGINE = 1, // EngineExpr (optional)
|
||||
};
|
||||
|
||||
const bool if_not_exists;
|
||||
};
|
||||
|
||||
}
|
361
src/Parsers/New/AST/CreateDictionaryQuery.cpp
Normal file
361
src/Parsers/New/AST/CreateDictionaryQuery.cpp
Normal file
@ -0,0 +1,361 @@
|
||||
#include <Parsers/New/AST/CreateDictionaryQuery.h>
|
||||
|
||||
#include <Parsers/ASTCreateQuery.h>
|
||||
#include <Parsers/New/AST/ColumnExpr.h>
|
||||
#include <Parsers/New/AST/ColumnTypeExpr.h>
|
||||
#include <Parsers/New/AST/Identifier.h>
|
||||
#include <Parsers/New/AST/Literal.h>
|
||||
#include <Parsers/New/AST/SelectUnionQuery.h>
|
||||
#include <Parsers/New/AST/SettingExpr.h>
|
||||
#include <Parsers/New/ParseTreeVisitor.h>
|
||||
|
||||
#include <Poco/String.h>
|
||||
|
||||
|
||||
namespace DB::ErrorCodes
|
||||
{
|
||||
extern const int SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
// DictionaryAttributeExpr
|
||||
|
||||
DictionaryAttributeExpr::DictionaryAttributeExpr(PtrTo<Identifier> identifier, PtrTo<ColumnTypeExpr> type) : INode(MAX_INDEX)
|
||||
{
|
||||
set(NAME, identifier);
|
||||
set(TYPE, type);
|
||||
}
|
||||
|
||||
void DictionaryAttributeExpr::setDefaultClause(PtrTo<Literal> literal)
|
||||
{
|
||||
set(DEFAULT, literal);
|
||||
}
|
||||
|
||||
void DictionaryAttributeExpr::setExpressionClause(PtrTo<ColumnExpr> expr)
|
||||
{
|
||||
set(EXPRESSION, expr);
|
||||
}
|
||||
|
||||
ASTPtr DictionaryAttributeExpr::convertToOld() const
|
||||
{
|
||||
auto expr = std::make_shared<ASTDictionaryAttributeDeclaration>();
|
||||
|
||||
expr->name = get<Identifier>(NAME)->getName();
|
||||
if (has(TYPE))
|
||||
{
|
||||
expr->type = get(TYPE)->convertToOld();
|
||||
expr->children.push_back(expr->type);
|
||||
}
|
||||
if (has(DEFAULT))
|
||||
{
|
||||
expr->default_value = get(DEFAULT)->convertToOld();
|
||||
expr->children.push_back(expr->default_value);
|
||||
}
|
||||
if (has(EXPRESSION))
|
||||
{
|
||||
expr->expression = get(EXPRESSION)->convertToOld();
|
||||
expr->children.push_back(expr->expression);
|
||||
}
|
||||
expr->hierarchical = hierarchical;
|
||||
expr->injective = injective;
|
||||
expr->is_object_id = is_object_id;
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
// DictionaryArgExpr
|
||||
|
||||
DictionaryArgExpr::DictionaryArgExpr(PtrTo<Identifier> identifier, PtrTo<ColumnExpr> expr) : INode{identifier, expr}
|
||||
{
|
||||
if (expr->getType() != ColumnExpr::ExprType::LITERAL && expr->getType() != ColumnExpr::ExprType::IDENTIFIER
|
||||
&& expr->getType() != ColumnExpr::ExprType::FUNCTION)
|
||||
throw DB::Exception(ErrorCodes::SYNTAX_ERROR, "Expected literal, identifier or function");
|
||||
}
|
||||
|
||||
ASTPtr DictionaryArgExpr::convertToOld() const
|
||||
{
|
||||
auto expr = std::make_shared<ASTPair>(false); // FIXME: always true?
|
||||
|
||||
// TODO: probably there are more variants to parse.
|
||||
|
||||
expr->first = Poco::toLower(get<Identifier>(KEY)->getName());
|
||||
expr->set(expr->second, get(VALUE)->convertToOld());
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
// SourceClause
|
||||
|
||||
SourceClause::SourceClause(PtrTo<Identifier> identifier, PtrTo<DictionaryArgList> list) : INode{identifier, list}
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr SourceClause::convertToOld() const
|
||||
{
|
||||
auto clause = std::make_shared<ASTFunctionWithKeyValueArguments>(true); // FIXME: always true?
|
||||
|
||||
clause->name = Poco::toLower(get<Identifier>(NAME)->getName());
|
||||
if (has(ARGS))
|
||||
{
|
||||
clause->elements = get(ARGS)->convertToOld();
|
||||
clause->children.push_back(clause->elements);
|
||||
}
|
||||
|
||||
return clause;
|
||||
}
|
||||
|
||||
// LifetimeClause
|
||||
|
||||
LifetimeClause::LifetimeClause(PtrTo<NumberLiteral> max, PtrTo<NumberLiteral> min) : INode{max, min}
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr LifetimeClause::convertToOld() const
|
||||
{
|
||||
auto clause = std::make_shared<ASTDictionaryLifetime>();
|
||||
|
||||
clause->max_sec = get(MAX)->convertToOld()->as<ASTLiteral>()->value.get<UInt64>();
|
||||
if (has(MIN)) clause->min_sec = get(MIN)->convertToOld()->as<ASTLiteral>()->value.get<UInt64>();
|
||||
|
||||
return clause;
|
||||
}
|
||||
|
||||
// LayoutClause
|
||||
|
||||
LayoutClause::LayoutClause(PtrTo<Identifier> identifier, PtrTo<DictionaryArgList> list) : INode{identifier, list}
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr LayoutClause::convertToOld() const
|
||||
{
|
||||
auto clause = std::make_shared<ASTDictionaryLayout>();
|
||||
|
||||
clause->layout_type = Poco::toLower(get<Identifier>(NAME)->getName());
|
||||
clause->has_brackets = true; // FIXME: maybe not?
|
||||
if (has(ARGS)) clause->set(clause->parameters, get(ARGS)->convertToOld());
|
||||
|
||||
return clause;
|
||||
}
|
||||
|
||||
// RangeClause
|
||||
|
||||
RangeClause::RangeClause(PtrTo<Identifier> max, PtrTo<Identifier> min) : INode{max, min}
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr RangeClause::convertToOld() const
|
||||
{
|
||||
auto clause = std::make_shared<ASTDictionaryRange>();
|
||||
|
||||
clause->max_attr_name = get<Identifier>(MAX)->getName();
|
||||
clause->min_attr_name = get<Identifier>(MIN)->getName();
|
||||
|
||||
return clause;
|
||||
}
|
||||
|
||||
// DictionarySettingsClause
|
||||
|
||||
DictionarySettingsClause::DictionarySettingsClause(PtrTo<SettingExprList> list) : INode{list}
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr DictionarySettingsClause::convertToOld() const
|
||||
{
|
||||
auto clause = std::make_shared<ASTDictionarySettings>();
|
||||
|
||||
for (const auto & child : get(LIST)->as<SettingExprList &>())
|
||||
{
|
||||
const auto * setting = child->as<SettingExpr>();
|
||||
clause->changes.emplace_back(setting->getName()->getName(), setting->getValue()->convertToOld()->as<ASTLiteral>()->value);
|
||||
}
|
||||
|
||||
return clause;
|
||||
}
|
||||
|
||||
// DictionaryEngineClause
|
||||
|
||||
DictionaryEngineClause::DictionaryEngineClause(PtrTo<DictionaryPrimaryKeyClause> clause) : INode(MAX_INDEX)
|
||||
{
|
||||
set(PRIMARY_KEY, clause);
|
||||
}
|
||||
|
||||
void DictionaryEngineClause::setSourceClause(PtrTo<SourceClause> clause)
|
||||
{
|
||||
set(SOURCE, clause);
|
||||
}
|
||||
|
||||
void DictionaryEngineClause::setLifetimeClause(PtrTo<LifetimeClause> clause)
|
||||
{
|
||||
set(LIFETIME, clause);
|
||||
}
|
||||
|
||||
void DictionaryEngineClause::setLayoutClause(PtrTo<LayoutClause> clause)
|
||||
{
|
||||
set(LAYOUT, clause);
|
||||
}
|
||||
|
||||
void DictionaryEngineClause::setRangeClause(PtrTo<RangeClause> clause)
|
||||
{
|
||||
set(RANGE, clause);
|
||||
}
|
||||
|
||||
void DictionaryEngineClause::setSettingsClause(PtrTo<DictionarySettingsClause> clause)
|
||||
{
|
||||
set(SETTINGS, clause);
|
||||
}
|
||||
|
||||
ASTPtr DictionaryEngineClause::convertToOld() const
|
||||
{
|
||||
auto clause = std::make_shared<ASTDictionary>();
|
||||
|
||||
if (has(PRIMARY_KEY)) clause->set(clause->primary_key, get(PRIMARY_KEY)->convertToOld());
|
||||
if (has(SOURCE)) clause->set(clause->source, get(SOURCE)->convertToOld());
|
||||
if (has(LIFETIME)) clause->set(clause->lifetime, get(LIFETIME)->convertToOld());
|
||||
if (has(LAYOUT)) clause->set(clause->layout, get(LAYOUT)->convertToOld());
|
||||
if (has(RANGE)) clause->set(clause->range, get(RANGE)->convertToOld());
|
||||
if (has(SETTINGS)) clause->set(clause->dict_settings, get(SETTINGS)->convertToOld());
|
||||
|
||||
return clause;
|
||||
}
|
||||
|
||||
// CreateDictionaryQuery
|
||||
|
||||
CreateDictionaryQuery::CreateDictionaryQuery(
|
||||
PtrTo<ClusterClause> cluster,
|
||||
bool attach_,
|
||||
bool if_not_exists_,
|
||||
PtrTo<TableIdentifier> identifier,
|
||||
PtrTo<UUIDClause> uuid,
|
||||
PtrTo<DictionarySchemaClause> schema,
|
||||
PtrTo<DictionaryEngineClause> engine)
|
||||
: DDLQuery(cluster, {identifier, uuid, schema, engine}), attach(attach_), if_not_exists(if_not_exists_)
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr CreateDictionaryQuery::convertToOld() const
|
||||
{
|
||||
auto query = std::make_shared<ASTCreateQuery>();
|
||||
|
||||
{
|
||||
auto table_id = getTableIdentifier(get(NAME)->convertToOld());
|
||||
query->database = table_id.database_name;
|
||||
query->table = table_id.table_name;
|
||||
query->uuid
|
||||
= has(UUID) ? parseFromString<DB::UUID>(get(UUID)->convertToOld()->as<ASTLiteral>()->value.get<String>()) : table_id.uuid;
|
||||
}
|
||||
|
||||
query->cluster = cluster_name;
|
||||
|
||||
query->is_dictionary = true;
|
||||
query->attach = attach;
|
||||
query->if_not_exists = if_not_exists;
|
||||
|
||||
query->set(query->dictionary_attributes_list, get(SCHEMA)->convertToOld());
|
||||
query->set(query->dictionary, get(ENGINE)->convertToOld());
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace AST;
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitCreateDictionaryStmt(ClickHouseParser::CreateDictionaryStmtContext *ctx)
|
||||
{
|
||||
auto uuid = ctx->uuidClause() ? visit(ctx->uuidClause()).as<PtrTo<UUIDClause>>() : nullptr;
|
||||
auto cluster = ctx->clusterClause() ? visit(ctx->clusterClause()).as<PtrTo<ClusterClause>>() : nullptr;
|
||||
auto schema = ctx->dictionarySchemaClause() ? visit(ctx->dictionarySchemaClause()).as<PtrTo<DictionarySchemaClause>>() : nullptr;
|
||||
auto engine = ctx->dictionaryEngineClause() ? visit(ctx->dictionaryEngineClause()).as<PtrTo<DictionaryEngineClause>>() : nullptr;
|
||||
return std::make_shared<CreateDictionaryQuery>(
|
||||
cluster, !!ctx->ATTACH(), !!ctx->IF(), visit(ctx->tableIdentifier()), uuid, schema, engine);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitDictionaryArgExpr(ClickHouseParser::DictionaryArgExprContext *ctx)
|
||||
{
|
||||
PtrTo<ColumnExpr> expr;
|
||||
if (ctx->literal()) expr = ColumnExpr::createLiteral(visit(ctx->literal()));
|
||||
else if (ctx->LPAREN()) expr = ColumnExpr::createFunction(visit(ctx->identifier(1)), nullptr, nullptr);
|
||||
else expr = ColumnExpr::createIdentifier(visit(ctx->identifier(1)));
|
||||
return std::make_shared<DictionaryArgExpr>(visit(ctx->identifier(0)), expr);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitDictionaryAttrDfnt(ClickHouseParser::DictionaryAttrDfntContext *ctx)
|
||||
{
|
||||
auto expr = std::make_shared<DictionaryAttributeExpr>(visit(ctx->identifier()), visit(ctx->columnTypeExpr()));
|
||||
if (!ctx->DEFAULT().empty()) expr->setDefaultClause(visit(ctx->literal(0)));
|
||||
if (!ctx->EXPRESSION().empty()) expr->setExpressionClause(visit(ctx->columnExpr(0)));
|
||||
if (!ctx->HIERARCHICAL().empty()) expr->setHierarchicalFlag();
|
||||
if (!ctx->INJECTIVE().empty()) expr->setInjectiveFlag();
|
||||
if (!ctx->IS_OBJECT_ID().empty()) expr->setIsObjectIdFlag();
|
||||
return expr;
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitDictionaryEngineClause(ClickHouseParser::DictionaryEngineClauseContext *ctx)
|
||||
{
|
||||
auto primary_key
|
||||
= ctx->dictionaryPrimaryKeyClause() ? visit(ctx->dictionaryPrimaryKeyClause()).as<PtrTo<DictionaryPrimaryKeyClause>>() : nullptr;
|
||||
auto clause = std::make_shared<DictionaryEngineClause>(primary_key);
|
||||
if (!ctx->sourceClause().empty()) clause->setSourceClause(visit(ctx->sourceClause(0)));
|
||||
if (!ctx->lifetimeClause().empty()) clause->setLifetimeClause(visit(ctx->lifetimeClause(0)));
|
||||
if (!ctx->layoutClause().empty()) clause->setLayoutClause(visit(ctx->layoutClause(0)));
|
||||
if (!ctx->rangeClause().empty()) clause->setRangeClause(visit(ctx->rangeClause(0)));
|
||||
if (!ctx->dictionarySettingsClause().empty()) clause->setSettingsClause(visit(ctx->dictionarySettingsClause(0)));
|
||||
return clause;
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitDictionaryPrimaryKeyClause(ClickHouseParser::DictionaryPrimaryKeyClauseContext *ctx)
|
||||
{
|
||||
return std::make_shared<DictionaryPrimaryKeyClause>(visit(ctx->columnExprList()).as<PtrTo<ColumnExprList>>());
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitDictionarySchemaClause(ClickHouseParser::DictionarySchemaClauseContext *ctx)
|
||||
{
|
||||
auto list = std::make_shared<DictionaryAttributeList>();
|
||||
for (auto * attr : ctx->dictionaryAttrDfnt()) list->push(visit(attr));
|
||||
return std::make_shared<DictionarySchemaClause>(list);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitDictionarySettingsClause(ClickHouseParser::DictionarySettingsClauseContext *ctx)
|
||||
{
|
||||
return std::make_shared<DictionarySettingsClause>(visit(ctx->settingExprList()).as<PtrTo<SettingExprList>>());
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitLayoutClause(ClickHouseParser::LayoutClauseContext *ctx)
|
||||
{
|
||||
auto list = ctx->dictionaryArgExpr().empty() ? nullptr : std::make_shared<DictionaryArgList>();
|
||||
for (auto * arg : ctx->dictionaryArgExpr()) list->push(visit(arg));
|
||||
return std::make_shared<LayoutClause>(visit(ctx->identifier()), list);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitLifetimeClause(ClickHouseParser::LifetimeClauseContext *ctx)
|
||||
{
|
||||
if (ctx->DECIMAL_LITERAL().size() == 1) return std::make_shared<LifetimeClause>(Literal::createNumber(ctx->DECIMAL_LITERAL(0)));
|
||||
if (ctx->MAX()->getSymbol()->getTokenIndex() < ctx->MIN()->getSymbol()->getTokenIndex())
|
||||
return std::make_shared<LifetimeClause>(
|
||||
Literal::createNumber(ctx->DECIMAL_LITERAL(0)), Literal::createNumber(ctx->DECIMAL_LITERAL(1)));
|
||||
else
|
||||
return std::make_shared<LifetimeClause>(
|
||||
Literal::createNumber(ctx->DECIMAL_LITERAL(1)), Literal::createNumber(ctx->DECIMAL_LITERAL(0)));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitRangeClause(ClickHouseParser::RangeClauseContext *ctx)
|
||||
{
|
||||
if (ctx->MAX()->getSymbol()->getTokenIndex() < ctx->MIN()->getSymbol()->getTokenIndex())
|
||||
return std::make_shared<RangeClause>(visit(ctx->identifier(0)), visit(ctx->identifier(1)));
|
||||
else
|
||||
return std::make_shared<RangeClause>(visit(ctx->identifier(1)), visit(ctx->identifier(0)));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitSourceClause(ClickHouseParser::SourceClauseContext *ctx)
|
||||
{
|
||||
auto list = ctx->dictionaryArgExpr().empty() ? nullptr : std::make_shared<DictionaryArgList>();
|
||||
for (auto * arg : ctx->dictionaryArgExpr()) list->push(visit(arg));
|
||||
return std::make_shared<SourceClause>(visit(ctx->identifier()), list);
|
||||
}
|
||||
|
||||
}
|
183
src/Parsers/New/AST/CreateDictionaryQuery.h
Normal file
183
src/Parsers/New/AST/CreateDictionaryQuery.h
Normal file
@ -0,0 +1,183 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/DDLQuery.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
class DictionaryAttributeExpr : public INode
|
||||
{
|
||||
public:
|
||||
DictionaryAttributeExpr(PtrTo<Identifier> identifier, PtrTo<ColumnTypeExpr> type);
|
||||
|
||||
void setDefaultClause(PtrTo<Literal> literal);
|
||||
void setExpressionClause(PtrTo<ColumnExpr> expr);
|
||||
|
||||
void setHierarchicalFlag() { hierarchical = true; }
|
||||
void setInjectiveFlag() { injective = true; }
|
||||
void setIsObjectIdFlag() { is_object_id = true; }
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
NAME = 0, // Identifier
|
||||
TYPE, // ColumnTypeExpr
|
||||
DEFAULT, // Literal (optional)
|
||||
EXPRESSION, // ColumnExpr (optional)
|
||||
|
||||
MAX_INDEX,
|
||||
};
|
||||
|
||||
bool hierarchical = false, injective = false, is_object_id = false;
|
||||
};
|
||||
|
||||
using DictionaryPrimaryKeyClause = SimpleClause<ColumnExprList>;
|
||||
|
||||
using DictionarySchemaClause = SimpleClause<DictionaryAttributeList>;
|
||||
|
||||
class DictionaryArgExpr : public INode
|
||||
{
|
||||
public:
|
||||
explicit DictionaryArgExpr(PtrTo<Identifier> identifier, PtrTo<ColumnExpr> expr);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
KEY = 0, // Identifier
|
||||
VALUE, // ColumnExpr: literal, identifier or function
|
||||
};
|
||||
};
|
||||
|
||||
class SourceClause : public INode
|
||||
{
|
||||
public:
|
||||
SourceClause(PtrTo<Identifier> identifier, PtrTo<DictionaryArgList> list);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
NAME = 0, // Identifier
|
||||
ARGS = 1, // DictionaryArgList (optional)
|
||||
};
|
||||
};
|
||||
|
||||
class LifetimeClause : public INode
|
||||
{
|
||||
public:
|
||||
explicit LifetimeClause(PtrTo<NumberLiteral> max, PtrTo<NumberLiteral> min = nullptr);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
MAX = 0, // NumberLiteral
|
||||
MIN, // NumberLiteral (optional)
|
||||
};
|
||||
};
|
||||
|
||||
class LayoutClause : public INode
|
||||
{
|
||||
public:
|
||||
LayoutClause(PtrTo<Identifier> identifier, PtrTo<DictionaryArgList> list);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
NAME = 0, // Identifier
|
||||
ARGS = 1, // DictionaryArgList (optional)
|
||||
};
|
||||
};
|
||||
|
||||
class RangeClause : public INode
|
||||
{
|
||||
public:
|
||||
RangeClause(PtrTo<Identifier> max, PtrTo<Identifier> min);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
MAX = 0, // Identifier
|
||||
MIN, // Identifier
|
||||
};
|
||||
};
|
||||
|
||||
class DictionarySettingsClause : public INode
|
||||
{
|
||||
public:
|
||||
explicit DictionarySettingsClause(PtrTo<SettingExprList> list);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
LIST = 0, // SettingExprList
|
||||
};
|
||||
};
|
||||
|
||||
class DictionaryEngineClause : public INode
|
||||
{
|
||||
public:
|
||||
explicit DictionaryEngineClause(PtrTo<DictionaryPrimaryKeyClause> clause);
|
||||
|
||||
void setSourceClause(PtrTo<SourceClause> clause);
|
||||
void setLifetimeClause(PtrTo<LifetimeClause> clause);
|
||||
void setLayoutClause(PtrTo<LayoutClause> clause);
|
||||
void setRangeClause(PtrTo<RangeClause> clause);
|
||||
void setSettingsClause(PtrTo<DictionarySettingsClause> clause);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
PRIMARY_KEY = 0, // DictionaryPrimaryKeyClause
|
||||
SOURCE, // SourceClause (optional)
|
||||
LIFETIME, // LifetimeClause (optional)
|
||||
LAYOUT, // LayoutClause (optional)
|
||||
RANGE, // RangeClause (optional)
|
||||
SETTINGS, // DictionarySettingsClause (optional)
|
||||
|
||||
MAX_INDEX,
|
||||
};
|
||||
};
|
||||
|
||||
class CreateDictionaryQuery : public DDLQuery
|
||||
{
|
||||
public:
|
||||
CreateDictionaryQuery(
|
||||
PtrTo<ClusterClause> cluster,
|
||||
bool attach,
|
||||
bool if_not_exists,
|
||||
PtrTo<TableIdentifier> identifier,
|
||||
PtrTo<UUIDClause> uuid,
|
||||
PtrTo<DictionarySchemaClause> schema,
|
||||
PtrTo<DictionaryEngineClause> engine);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
NAME = 0, // TableIdentifier
|
||||
UUID, // UUIDClause (optional)
|
||||
SCHEMA, // DictionarySchemaClause
|
||||
ENGINE, // DictionaryEngineClause
|
||||
};
|
||||
|
||||
const bool attach, if_not_exists;
|
||||
};
|
||||
|
||||
}
|
87
src/Parsers/New/AST/CreateLiveViewQuery.cpp
Normal file
87
src/Parsers/New/AST/CreateLiveViewQuery.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
#include <Parsers/New/AST/CreateLiveViewQuery.h>
|
||||
|
||||
#include <Parsers/ASTCreateQuery.h>
|
||||
#include <Parsers/New/AST/CreateTableQuery.h>
|
||||
#include <Parsers/New/AST/Literal.h>
|
||||
#include <Parsers/New/AST/SelectUnionQuery.h>
|
||||
#include <Parsers/New/ParseTreeVisitor.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
CreateLiveViewQuery::CreateLiveViewQuery(
|
||||
PtrTo<ClusterClause> cluster,
|
||||
bool attach_,
|
||||
bool if_not_exists_,
|
||||
PtrTo<TableIdentifier> identifier,
|
||||
PtrTo<UUIDClause> uuid,
|
||||
PtrTo<NumberLiteral> timeout,
|
||||
PtrTo<DestinationClause> destination,
|
||||
PtrTo<TableSchemaClause> schema,
|
||||
PtrTo<SelectUnionQuery> query)
|
||||
: DDLQuery(cluster, {identifier, uuid, timeout, destination, schema, query}), attach(attach_), if_not_exists(if_not_exists_)
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr CreateLiveViewQuery::convertToOld() const
|
||||
{
|
||||
auto query = std::make_shared<ASTCreateQuery>();
|
||||
|
||||
{
|
||||
auto table_id = getTableIdentifier(get(NAME)->convertToOld());
|
||||
query->database = table_id.database_name;
|
||||
query->table = table_id.table_name;
|
||||
query->uuid
|
||||
= has(UUID) ? parseFromString<DB::UUID>(get(UUID)->convertToOld()->as<ASTLiteral>()->value.get<String>()) : table_id.uuid;
|
||||
}
|
||||
|
||||
if (has(TIMEOUT))
|
||||
query->live_view_timeout.emplace(get(TIMEOUT)->convertToOld()->as<ASTLiteral>()->value.get<UInt64>());
|
||||
|
||||
if (has(DESTINATION))
|
||||
query->to_table_id = getTableIdentifier(get(DESTINATION)->convertToOld());
|
||||
|
||||
if (has(SCHEMA))
|
||||
{
|
||||
assert(get<TableSchemaClause>(SCHEMA)->getType() == TableSchemaClause::ClauseType::DESCRIPTION);
|
||||
query->set(query->columns_list, get(SCHEMA)->convertToOld());
|
||||
}
|
||||
|
||||
query->attach = attach;
|
||||
query->if_not_exists = if_not_exists;
|
||||
query->is_live_view = true;
|
||||
query->set(query->select, get(SUBQUERY)->convertToOld());
|
||||
query->cluster = cluster_name;
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace AST;
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitCreateLiveViewStmt(ClickHouseParser::CreateLiveViewStmtContext *ctx)
|
||||
{
|
||||
auto uuid = ctx->uuidClause() ? visit(ctx->uuidClause()).as<PtrTo<UUIDClause>>() : nullptr;
|
||||
auto cluster = ctx->clusterClause() ? visit(ctx->clusterClause()).as<PtrTo<ClusterClause>>() : nullptr;
|
||||
auto timeout = ctx->DECIMAL_LITERAL() ? Literal::createNumber(ctx->DECIMAL_LITERAL()) : nullptr;
|
||||
auto destination = ctx->destinationClause() ? visit(ctx->destinationClause()).as<PtrTo<DestinationClause>>() : nullptr;
|
||||
auto schema = ctx->tableSchemaClause() ? visit(ctx->tableSchemaClause()).as<PtrTo<TableSchemaClause>>() : nullptr;
|
||||
if (ctx->TIMEOUT() && !timeout) timeout = Literal::createNumber(std::to_string(DEFAULT_TEMPORARY_LIVE_VIEW_TIMEOUT_SEC));
|
||||
return std::make_shared<CreateLiveViewQuery>(
|
||||
cluster,
|
||||
!!ctx->ATTACH(),
|
||||
!!ctx->IF(),
|
||||
visit(ctx->tableIdentifier()),
|
||||
uuid,
|
||||
timeout,
|
||||
destination,
|
||||
schema,
|
||||
visit(ctx->subqueryClause()));
|
||||
}
|
||||
|
||||
}
|
39
src/Parsers/New/AST/CreateLiveViewQuery.h
Normal file
39
src/Parsers/New/AST/CreateLiveViewQuery.h
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/DDLQuery.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
class CreateLiveViewQuery : public DDLQuery
|
||||
{
|
||||
public:
|
||||
CreateLiveViewQuery(
|
||||
PtrTo<ClusterClause> cluster,
|
||||
bool attach,
|
||||
bool if_not_exists,
|
||||
PtrTo<TableIdentifier> identifier,
|
||||
PtrTo<UUIDClause> uuid,
|
||||
PtrTo<NumberLiteral> timeout,
|
||||
PtrTo<DestinationClause> destination,
|
||||
PtrTo<TableSchemaClause> schema,
|
||||
PtrTo<SelectUnionQuery> query);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
NAME = 0, // TableIdentifier
|
||||
UUID, // UUIDClause (optional)
|
||||
TIMEOUT, // NumberLiteral (optional)
|
||||
DESTINATION, // DestinationClause (optional)
|
||||
SCHEMA, // TableSchemaClause (optional)
|
||||
SUBQUERY, // SelectUnionQuery
|
||||
};
|
||||
|
||||
const bool attach, if_not_exists;
|
||||
};
|
||||
|
||||
}
|
100
src/Parsers/New/AST/CreateMaterializedViewQuery.cpp
Normal file
100
src/Parsers/New/AST/CreateMaterializedViewQuery.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
#include <Parsers/New/AST/CreateMaterializedViewQuery.h>
|
||||
|
||||
#include <IO/ReadHelpers.h>
|
||||
#include <Parsers/ASTCreateQuery.h>
|
||||
#include <Parsers/New/AST/CreateTableQuery.h>
|
||||
#include <Parsers/New/AST/EngineExpr.h>
|
||||
#include <Parsers/New/AST/Identifier.h>
|
||||
#include <Parsers/New/AST/SelectUnionQuery.h>
|
||||
#include <Parsers/New/ParseTreeVisitor.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
CreateMaterializedViewQuery::CreateMaterializedViewQuery(
|
||||
PtrTo<ClusterClause> cluster,
|
||||
bool attach_,
|
||||
bool if_not_exists_,
|
||||
bool populate_,
|
||||
PtrTo<TableIdentifier> identifier,
|
||||
PtrTo<UUIDClause> uuid,
|
||||
PtrTo<TableSchemaClause> schema,
|
||||
PtrTo<DestinationClause> destination,
|
||||
PtrTo<EngineClause> engine,
|
||||
PtrTo<SelectUnionQuery> query)
|
||||
: DDLQuery(cluster, {identifier, uuid, schema, destination, engine, query})
|
||||
, attach(attach_)
|
||||
, if_not_exists(if_not_exists_)
|
||||
, populate(populate_)
|
||||
{
|
||||
assert(!destination != !engine);
|
||||
}
|
||||
|
||||
ASTPtr CreateMaterializedViewQuery::convertToOld() const
|
||||
{
|
||||
auto query = std::make_shared<ASTCreateQuery>();
|
||||
|
||||
{
|
||||
auto table_id = getTableIdentifier(get(NAME)->convertToOld());
|
||||
query->database = table_id.database_name;
|
||||
query->table = table_id.table_name;
|
||||
query->uuid
|
||||
= has(UUID) ? parseFromString<DB::UUID>(get(UUID)->convertToOld()->as<ASTLiteral>()->value.get<String>()) : table_id.uuid;
|
||||
}
|
||||
|
||||
if (has(DESTINATION))
|
||||
query->to_table_id = getTableIdentifier(get(DESTINATION)->convertToOld());
|
||||
else if (has(ENGINE))
|
||||
{
|
||||
query->set(query->storage, get(ENGINE)->convertToOld());
|
||||
query->is_populate = populate;
|
||||
}
|
||||
|
||||
if (has(SCHEMA))
|
||||
{
|
||||
assert(get<TableSchemaClause>(SCHEMA)->getType() == TableSchemaClause::ClauseType::DESCRIPTION);
|
||||
query->set(query->columns_list, get(SCHEMA)->convertToOld());
|
||||
}
|
||||
|
||||
query->attach = attach;
|
||||
query->if_not_exists = if_not_exists;
|
||||
query->is_materialized_view = true;
|
||||
query->set(query->select, get(SUBQUERY)->convertToOld());
|
||||
query->cluster = cluster_name;
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace AST;
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitCreateMaterializedViewStmt(ClickHouseParser::CreateMaterializedViewStmtContext *ctx)
|
||||
{
|
||||
auto uuid = ctx->uuidClause() ? visit(ctx->uuidClause()).as<PtrTo<UUIDClause>>() : nullptr;
|
||||
auto cluster = ctx->clusterClause() ? visit(ctx->clusterClause()).as<PtrTo<ClusterClause>>() : nullptr;
|
||||
auto schema = ctx->tableSchemaClause() ? visit(ctx->tableSchemaClause()).as<PtrTo<TableSchemaClause>>() : nullptr;
|
||||
auto engine = ctx->engineClause() ? visit(ctx->engineClause()).as<PtrTo<EngineClause>>() : nullptr;
|
||||
auto destination = ctx->destinationClause() ? visit(ctx->destinationClause()).as<PtrTo<DestinationClause>>() : nullptr;
|
||||
return std::make_shared<CreateMaterializedViewQuery>(
|
||||
cluster,
|
||||
!!ctx->ATTACH(),
|
||||
!!ctx->IF(),
|
||||
!!ctx->POPULATE(),
|
||||
visit(ctx->tableIdentifier()),
|
||||
uuid,
|
||||
schema,
|
||||
destination,
|
||||
engine,
|
||||
visit(ctx->subqueryClause()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitDestinationClause(ClickHouseParser::DestinationClauseContext *ctx)
|
||||
{
|
||||
return std::make_shared<DestinationClause>(visit(ctx->tableIdentifier()).as<PtrTo<TableIdentifier>>());
|
||||
}
|
||||
|
||||
}
|
40
src/Parsers/New/AST/CreateMaterializedViewQuery.h
Normal file
40
src/Parsers/New/AST/CreateMaterializedViewQuery.h
Normal file
@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/DDLQuery.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
class CreateMaterializedViewQuery : public DDLQuery
|
||||
{
|
||||
public:
|
||||
CreateMaterializedViewQuery(
|
||||
PtrTo<ClusterClause> cluster,
|
||||
bool attach,
|
||||
bool if_not_exists,
|
||||
bool populate,
|
||||
PtrTo<TableIdentifier> identifier,
|
||||
PtrTo<UUIDClause> uuid,
|
||||
PtrTo<TableSchemaClause> schema,
|
||||
PtrTo<DestinationClause> destination,
|
||||
PtrTo<EngineClause> engine,
|
||||
PtrTo<SelectUnionQuery> query);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
NAME = 0, // TableIdentifier
|
||||
UUID, // UUIDClause (optional)
|
||||
SCHEMA, // TableSchemaClause (optional)
|
||||
DESTINATION, // DestinationClause (optional)
|
||||
ENGINE, // EngineClause (optional)
|
||||
SUBQUERY, // SelectUnionQuery
|
||||
};
|
||||
|
||||
const bool attach, if_not_exists, populate;
|
||||
};
|
||||
|
||||
}
|
219
src/Parsers/New/AST/CreateTableQuery.cpp
Normal file
219
src/Parsers/New/AST/CreateTableQuery.cpp
Normal file
@ -0,0 +1,219 @@
|
||||
#include <Parsers/New/AST/CreateTableQuery.h>
|
||||
|
||||
#include <IO/ReadHelpers.h>
|
||||
#include <Parsers/ASTCreateQuery.h>
|
||||
#include <Parsers/ASTIdentifier.h>
|
||||
#include <Parsers/New/AST/EngineExpr.h>
|
||||
#include <Parsers/New/AST/Identifier.h>
|
||||
#include <Parsers/New/AST/Literal.h>
|
||||
#include <Parsers/New/AST/SelectUnionQuery.h>
|
||||
#include <Parsers/New/AST/TableElementExpr.h>
|
||||
#include <Parsers/New/AST/TableExpr.h>
|
||||
#include <Parsers/New/ParseTreeVisitor.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
// static
|
||||
PtrTo<TableSchemaClause> TableSchemaClause::createDescription(PtrTo<TableElementList> list)
|
||||
{
|
||||
return PtrTo<TableSchemaClause>(new TableSchemaClause(ClauseType::DESCRIPTION, {list}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<TableSchemaClause> TableSchemaClause::createAsTable(PtrTo<TableIdentifier> identifier)
|
||||
{
|
||||
return PtrTo<TableSchemaClause>(new TableSchemaClause(ClauseType::TABLE, {identifier}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<TableSchemaClause> TableSchemaClause::createAsFunction(PtrTo<TableFunctionExpr> expr)
|
||||
{
|
||||
return PtrTo<TableSchemaClause>(new TableSchemaClause(ClauseType::FUNCTION, {expr}));
|
||||
}
|
||||
|
||||
TableSchemaClause::TableSchemaClause(ClauseType type, PtrList exprs) : INode(exprs), clause_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr TableSchemaClause::convertToOld() const
|
||||
{
|
||||
switch(clause_type)
|
||||
{
|
||||
case ClauseType::DESCRIPTION:
|
||||
{
|
||||
auto columns = std::make_shared<ASTColumns>();
|
||||
|
||||
auto column_list = std::make_shared<ASTExpressionList>();
|
||||
auto constraint_list = std::make_shared<ASTExpressionList>();
|
||||
auto index_list = std::make_shared<ASTExpressionList>();
|
||||
|
||||
for (const auto & element : get(ELEMENTS)->as<TableElementList &>())
|
||||
{
|
||||
switch(element->as<TableElementExpr>()->getType())
|
||||
{
|
||||
case TableElementExpr::ExprType::COLUMN:
|
||||
column_list->children.push_back(element->convertToOld());
|
||||
break;
|
||||
case TableElementExpr::ExprType::CONSTRAINT:
|
||||
constraint_list->children.push_back(element->convertToOld());
|
||||
break;
|
||||
case TableElementExpr::ExprType::INDEX:
|
||||
index_list->children.push_back(element->convertToOld());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!column_list->children.empty()) columns->set(columns->columns, column_list);
|
||||
if (!constraint_list->children.empty()) columns->set(columns->constraints, constraint_list);
|
||||
if (!index_list->children.empty()) columns->set(columns->indices, index_list);
|
||||
|
||||
return columns;
|
||||
}
|
||||
case ClauseType::FUNCTION:
|
||||
case ClauseType::TABLE:
|
||||
return get(EXPR)->convertToOld();
|
||||
}
|
||||
__builtin_unreachable(); // FIXME: old gcc compilers complain about reaching end of non-void function
|
||||
}
|
||||
|
||||
String TableSchemaClause::dumpInfo() const
|
||||
{
|
||||
switch(clause_type)
|
||||
{
|
||||
case ClauseType::DESCRIPTION: return "Description";
|
||||
case ClauseType::FUNCTION: return "Function";
|
||||
case ClauseType::TABLE: return "Table";
|
||||
}
|
||||
__builtin_unreachable(); // FIXME: old gcc compilers complain about reaching end of non-void function
|
||||
}
|
||||
|
||||
CreateTableQuery::CreateTableQuery(
|
||||
PtrTo<ClusterClause> cluster,
|
||||
bool attach_,
|
||||
bool temporary_,
|
||||
bool if_not_exists_,
|
||||
PtrTo<TableIdentifier> identifier,
|
||||
PtrTo<UUIDClause> uuid,
|
||||
PtrTo<TableSchemaClause> schema,
|
||||
PtrTo<EngineClause> engine,
|
||||
PtrTo<SelectUnionQuery> query)
|
||||
: DDLQuery(cluster, {identifier, uuid, schema, engine, query}), attach(attach_), temporary(temporary_), if_not_exists(if_not_exists_)
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr CreateTableQuery::convertToOld() const
|
||||
{
|
||||
auto query = std::make_shared<ASTCreateQuery>();
|
||||
|
||||
{
|
||||
auto table_id = getTableIdentifier(get(NAME)->convertToOld());
|
||||
query->database = table_id.database_name;
|
||||
query->table = table_id.table_name;
|
||||
query->uuid
|
||||
= has(UUID) ? parseFromString<DB::UUID>(get(UUID)->convertToOld()->as<ASTLiteral>()->value.get<String>()) : table_id.uuid;
|
||||
}
|
||||
|
||||
query->cluster = cluster_name;
|
||||
|
||||
query->attach = attach;
|
||||
query->if_not_exists = if_not_exists;
|
||||
query->temporary = temporary;
|
||||
|
||||
if (has(SCHEMA))
|
||||
{
|
||||
switch(get<TableSchemaClause>(SCHEMA)->getType())
|
||||
{
|
||||
case TableSchemaClause::ClauseType::DESCRIPTION:
|
||||
{
|
||||
query->set(query->columns_list, get(SCHEMA)->convertToOld());
|
||||
break;
|
||||
}
|
||||
case TableSchemaClause::ClauseType::TABLE:
|
||||
{
|
||||
auto table_id = getTableIdentifier(get(SCHEMA)->convertToOld());
|
||||
query->as_database = table_id.database_name;
|
||||
query->as_table = table_id.table_name;
|
||||
break;
|
||||
}
|
||||
case TableSchemaClause::ClauseType::FUNCTION:
|
||||
{
|
||||
query->as_table_function = get(SCHEMA)->convertToOld();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (has(ENGINE)) query->set(query->storage, get(ENGINE)->convertToOld());
|
||||
if (has(SUBQUERY)) query->set(query->select, get(SUBQUERY)->convertToOld());
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
String CreateTableQuery::dumpInfo() const
|
||||
{
|
||||
String info;
|
||||
if (attach) info += "attach=true, ";
|
||||
else info += "attach=false, ";
|
||||
if (temporary) info += "temporary=true, ";
|
||||
else info += "temporary=false, ";
|
||||
if (if_not_exists) info += "if_not_exists=true";
|
||||
else info += "if_not_exists=false";
|
||||
return info;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace AST;
|
||||
|
||||
// TODO: assert(!(ctx->parent->TEMPORARY() ^ ctx->engineClause()))
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitClusterClause(ClickHouseParser::ClusterClauseContext *ctx)
|
||||
{
|
||||
auto literal = ctx->STRING_LITERAL() ? Literal::createString(ctx->STRING_LITERAL())
|
||||
: Literal::createString(ctx->identifier()->getText());
|
||||
return std::make_shared<ClusterClause>(literal);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitCreateTableStmt(ClickHouseParser::CreateTableStmtContext *ctx)
|
||||
{
|
||||
auto uuid = ctx->uuidClause() ? visit(ctx->uuidClause()).as<PtrTo<UUIDClause>>() : nullptr;
|
||||
auto cluster = ctx->clusterClause() ? visit(ctx->clusterClause()).as<PtrTo<ClusterClause>>() : nullptr;
|
||||
auto schema = ctx->tableSchemaClause() ? visit(ctx->tableSchemaClause()).as<PtrTo<TableSchemaClause>>() : nullptr;
|
||||
auto engine = ctx->engineClause() ? visit(ctx->engineClause()).as<PtrTo<EngineClause>>() : nullptr;
|
||||
auto query = ctx->subqueryClause() ? visit(ctx->subqueryClause()).as<PtrTo<SelectUnionQuery>>() : nullptr;
|
||||
return std::make_shared<CreateTableQuery>(
|
||||
cluster, !!ctx->ATTACH(), !!ctx->TEMPORARY(), !!ctx->IF(), visit(ctx->tableIdentifier()), uuid, schema, engine, query);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitSchemaDescriptionClause(ClickHouseParser::SchemaDescriptionClauseContext *ctx)
|
||||
{
|
||||
auto elems = std::make_shared<TableElementList>();
|
||||
for (auto * elem : ctx->tableElementExpr()) elems->push(visit(elem));
|
||||
return TableSchemaClause::createDescription(elems);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitSchemaAsTableClause(ClickHouseParser::SchemaAsTableClauseContext *ctx)
|
||||
{
|
||||
return TableSchemaClause::createAsTable(visit(ctx->tableIdentifier()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitSchemaAsFunctionClause(ClickHouseParser::SchemaAsFunctionClauseContext *ctx)
|
||||
{
|
||||
return TableSchemaClause::createAsFunction(visit(ctx->tableFunctionExpr()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitSubqueryClause(ClickHouseParser::SubqueryClauseContext *ctx)
|
||||
{
|
||||
return visit(ctx->selectUnionStmt());
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitUuidClause(ClickHouseParser::UuidClauseContext *ctx)
|
||||
{
|
||||
return std::make_shared<UUIDClause>(Literal::createString(ctx->STRING_LITERAL()));
|
||||
}
|
||||
|
||||
}
|
76
src/Parsers/New/AST/CreateTableQuery.h
Normal file
76
src/Parsers/New/AST/CreateTableQuery.h
Normal file
@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/DDLQuery.h>
|
||||
#include "Parsers/New/AST/SelectUnionQuery.h"
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
class TableSchemaClause : public INode
|
||||
{
|
||||
public:
|
||||
static PtrTo<TableSchemaClause> createDescription(PtrTo<TableElementList> list);
|
||||
static PtrTo<TableSchemaClause> createAsTable(PtrTo<TableIdentifier> identifier);
|
||||
static PtrTo<TableSchemaClause> createAsFunction(PtrTo<TableFunctionExpr> expr);
|
||||
|
||||
enum class ClauseType
|
||||
{
|
||||
DESCRIPTION,
|
||||
TABLE,
|
||||
FUNCTION,
|
||||
};
|
||||
|
||||
auto getType() const { return clause_type; }
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
// DESCRIPTION
|
||||
ELEMENTS = 0, // TableElementList
|
||||
|
||||
// TABLE and FUNCTION
|
||||
EXPR = 0, // TableIdentifier or TableFunctionExpr
|
||||
};
|
||||
|
||||
ClauseType clause_type;
|
||||
|
||||
TableSchemaClause(ClauseType type, PtrList exprs);
|
||||
|
||||
String dumpInfo() const override;
|
||||
};
|
||||
|
||||
class CreateTableQuery : public DDLQuery
|
||||
{
|
||||
public:
|
||||
CreateTableQuery(
|
||||
PtrTo<ClusterClause> cluster,
|
||||
bool attach,
|
||||
bool temporary,
|
||||
bool if_not_exists,
|
||||
PtrTo<TableIdentifier> identifier,
|
||||
PtrTo<UUIDClause> uuid,
|
||||
PtrTo<TableSchemaClause> schema,
|
||||
PtrTo<EngineClause> engine,
|
||||
PtrTo<SelectUnionQuery> query);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
NAME = 0, // TableIdentifier
|
||||
UUID, // UUIDClause (optional)
|
||||
SCHEMA, // TableSchemaClause
|
||||
ENGINE, // EngineClause
|
||||
SUBQUERY, // SelectUnionQuery
|
||||
};
|
||||
|
||||
const bool attach, temporary, if_not_exists;
|
||||
|
||||
String dumpInfo() const override;
|
||||
};
|
||||
|
||||
}
|
62
src/Parsers/New/AST/CreateViewQuery.cpp
Normal file
62
src/Parsers/New/AST/CreateViewQuery.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
#include <Parsers/New/AST/CreateViewQuery.h>
|
||||
|
||||
#include <Parsers/ASTCreateQuery.h>
|
||||
#include <Parsers/New/AST/CreateTableQuery.h>
|
||||
#include <Parsers/New/AST/Identifier.h>
|
||||
#include <Parsers/New/AST/SelectUnionQuery.h>
|
||||
#include <Parsers/New/ParseTreeVisitor.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
CreateViewQuery::CreateViewQuery(
|
||||
PtrTo<ClusterClause> cluster,
|
||||
bool attach_,
|
||||
bool replace_,
|
||||
bool if_not_exists_,
|
||||
PtrTo<TableIdentifier> identifier,
|
||||
PtrTo<TableSchemaClause> clause,
|
||||
PtrTo<SelectUnionQuery> query)
|
||||
: DDLQuery(cluster, {identifier, clause, query}), attach(attach_), replace(replace_), if_not_exists(if_not_exists_)
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr CreateViewQuery::convertToOld() const
|
||||
{
|
||||
auto query = std::make_shared<ASTCreateQuery>();
|
||||
|
||||
{
|
||||
auto table_id = getTableIdentifier(get(NAME)->convertToOld());
|
||||
query->database = table_id.database_name;
|
||||
query->table = table_id.table_name;
|
||||
query->uuid = table_id.uuid;
|
||||
}
|
||||
|
||||
query->attach = attach;
|
||||
query->replace_view = replace;
|
||||
query->if_not_exists = if_not_exists;
|
||||
query->is_view = true;
|
||||
query->cluster = cluster_name;
|
||||
|
||||
if (has(SCHEMA)) query->set(query->columns_list, get(SCHEMA)->convertToOld());
|
||||
query->set(query->select, get(SUBQUERY)->convertToOld());
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace AST;
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitCreateViewStmt(ClickHouseParser::CreateViewStmtContext *ctx)
|
||||
{
|
||||
auto cluster = ctx->clusterClause() ? visit(ctx->clusterClause()).as<PtrTo<ClusterClause>>() : nullptr;
|
||||
auto schema = ctx->tableSchemaClause() ? visit(ctx->tableSchemaClause()).as<PtrTo<TableSchemaClause>>() : nullptr;
|
||||
return std::make_shared<CreateViewQuery>(
|
||||
cluster, !!ctx->ATTACH(), !!ctx->REPLACE(), !!ctx->IF(), visit(ctx->tableIdentifier()), schema, visit(ctx->subqueryClause()));
|
||||
}
|
||||
|
||||
}
|
34
src/Parsers/New/AST/CreateViewQuery.h
Normal file
34
src/Parsers/New/AST/CreateViewQuery.h
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/DDLQuery.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
class CreateViewQuery : public DDLQuery
|
||||
{
|
||||
public:
|
||||
CreateViewQuery(
|
||||
PtrTo<ClusterClause> cluster,
|
||||
bool attach,
|
||||
bool replace,
|
||||
bool if_not_exists,
|
||||
PtrTo<TableIdentifier> identifier,
|
||||
PtrTo<TableSchemaClause> clause,
|
||||
PtrTo<SelectUnionQuery> query);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
NAME = 0, // TableIdentifier
|
||||
SCHEMA = 1, // TableSchemaClause (optional)
|
||||
SUBQUERY = 2, // SelectUnionQuery
|
||||
};
|
||||
|
||||
const bool attach, replace, if_not_exists;
|
||||
};
|
||||
|
||||
}
|
6
src/Parsers/New/AST/DDLQuery.cpp
Normal file
6
src/Parsers/New/AST/DDLQuery.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include <Parsers/New/AST/DDLQuery.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
}
|
29
src/Parsers/New/AST/DDLQuery.h
Normal file
29
src/Parsers/New/AST/DDLQuery.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/Query.h>
|
||||
|
||||
#include <Parsers/ASTLiteral.h>
|
||||
#include <Parsers/ASTQueryWithOnCluster.h>
|
||||
#include <Parsers/New/AST/Identifier.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
class DDLQuery : public Query
|
||||
{
|
||||
protected:
|
||||
DDLQuery(PtrTo<ClusterClause> cluster, std::initializer_list<Ptr> list)
|
||||
: Query(list), cluster_name(cluster ? cluster->convertToOld()->as<ASTLiteral>()->value.get<String>() : String{})
|
||||
{
|
||||
}
|
||||
|
||||
DDLQuery(PtrTo<ClusterClause> cluster, PtrList list)
|
||||
: Query(list), cluster_name(cluster ? cluster->convertToOld()->as<ASTLiteral>()->value.get<String>() : String{})
|
||||
{
|
||||
}
|
||||
|
||||
const String cluster_name;
|
||||
};
|
||||
|
||||
}
|
36
src/Parsers/New/AST/DescribeQuery.cpp
Normal file
36
src/Parsers/New/AST/DescribeQuery.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
#include <Parsers/New/AST/DescribeQuery.h>
|
||||
|
||||
#include <Parsers/TablePropertiesQueriesASTs.h>
|
||||
#include <Parsers/New/AST/TableExpr.h>
|
||||
#include <Parsers/New/ParseTreeVisitor.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
DescribeQuery::DescribeQuery(PtrTo<TableExpr> expr) : Query{expr}
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr DescribeQuery::convertToOld() const
|
||||
{
|
||||
auto query = std::make_shared<ASTDescribeQuery>();
|
||||
|
||||
query->table_expression = get(EXPR)->convertToOld();
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace AST;
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitDescribeStmt(ClickHouseParser::DescribeStmtContext *ctx)
|
||||
{
|
||||
return std::make_shared<DescribeQuery>(visit(ctx->tableExpr()).as<PtrTo<TableExpr>>());
|
||||
}
|
||||
|
||||
}
|
27
src/Parsers/New/AST/DescribeQuery.h
Normal file
27
src/Parsers/New/AST/DescribeQuery.h
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/Query.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
// TODO: rewrite to
|
||||
// `SELECT name, type, default_type, default_expression, comment, codec_expression, ttl_expression FROM system.columns
|
||||
// WHERE database=db AND table=table`
|
||||
|
||||
class DescribeQuery : public Query
|
||||
{
|
||||
public:
|
||||
explicit DescribeQuery(PtrTo<TableExpr> expr);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
EXPR = 0,
|
||||
};
|
||||
};
|
||||
|
||||
}
|
106
src/Parsers/New/AST/DropQuery.cpp
Normal file
106
src/Parsers/New/AST/DropQuery.cpp
Normal file
@ -0,0 +1,106 @@
|
||||
#include <Parsers/New/AST/DropQuery.h>
|
||||
|
||||
#include <Parsers/New/AST/Identifier.h>
|
||||
|
||||
#include <Parsers/New/ParseTreeVisitor.h>
|
||||
|
||||
#include <Parsers/ASTDropQuery.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
// static
|
||||
PtrTo<DropQuery>
|
||||
DropQuery::createDropDatabase(bool detach, bool if_exists, PtrTo<DatabaseIdentifier> identifier, PtrTo<ClusterClause> cluster)
|
||||
{
|
||||
auto query = PtrTo<DropQuery>(new DropQuery(cluster, QueryType::DATABASE, {identifier}));
|
||||
query->detach = detach;
|
||||
query->if_exists = if_exists;
|
||||
return query;
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<DropQuery>
|
||||
DropQuery::createDropDictionary(bool detach, bool if_exists, PtrTo<TableIdentifier> identifier, PtrTo<ClusterClause> cluster)
|
||||
{
|
||||
auto query = PtrTo<DropQuery>(new DropQuery(cluster, QueryType::DICTIONARY, {identifier}));
|
||||
query->detach = detach;
|
||||
query->if_exists = if_exists;
|
||||
return query;
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<DropQuery>
|
||||
DropQuery::createDropTable(bool detach, bool if_exists, bool temporary, PtrTo<TableIdentifier> identifier, PtrTo<ClusterClause> cluster)
|
||||
{
|
||||
auto query = PtrTo<DropQuery>(new DropQuery(cluster, QueryType::TABLE, {identifier}));
|
||||
query->detach = detach;
|
||||
query->if_exists = if_exists;
|
||||
query->temporary = temporary;
|
||||
return query;
|
||||
}
|
||||
|
||||
DropQuery::DropQuery(PtrTo<ClusterClause> cluster, QueryType type, PtrList exprs) : DDLQuery(cluster, exprs), query_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr DropQuery::convertToOld() const
|
||||
{
|
||||
auto query = std::make_shared<ASTDropQuery>();
|
||||
|
||||
query->kind = detach ? ASTDropQuery::Detach : ASTDropQuery::Drop;
|
||||
query->if_exists = if_exists;
|
||||
query->temporary = temporary;
|
||||
query->cluster = cluster_name;
|
||||
|
||||
// TODO: refactor |ASTQueryWithTableAndOutput| to accept |ASTIdentifier|
|
||||
switch(query_type)
|
||||
{
|
||||
case QueryType::DATABASE:
|
||||
query->database = get<DatabaseIdentifier>(NAME)->getName();
|
||||
break;
|
||||
case QueryType::DICTIONARY:
|
||||
query->is_dictionary = true;
|
||||
query->table = get<TableIdentifier>(NAME)->getName();
|
||||
if (auto database = get<TableIdentifier>(NAME)->getDatabase())
|
||||
query->database = database->getName();
|
||||
break;
|
||||
case QueryType::TABLE:
|
||||
{
|
||||
query->table = get<TableIdentifier>(NAME)->getName();
|
||||
if (auto database = get<TableIdentifier>(NAME)->getDatabase())
|
||||
query->database = database->getName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
convertToOldPartially(query);
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace AST;
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitDropDatabaseStmt(ClickHouseParser::DropDatabaseStmtContext *ctx)
|
||||
{
|
||||
auto cluster = ctx->clusterClause() ? visit(ctx->clusterClause()).as<PtrTo<ClusterClause>>() : nullptr;
|
||||
return DropQuery::createDropDatabase(!!ctx->DETACH(), !!ctx->EXISTS(), visit(ctx->databaseIdentifier()), cluster);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitDropTableStmt(ClickHouseParser::DropTableStmtContext *ctx)
|
||||
{
|
||||
auto cluster = ctx->clusterClause() ? visit(ctx->clusterClause()).as<PtrTo<ClusterClause>>() : nullptr;
|
||||
if (ctx->TABLE())
|
||||
return DropQuery::createDropTable(!!ctx->DETACH(), !!ctx->EXISTS(), !!ctx->TEMPORARY(), visit(ctx->tableIdentifier()), cluster);
|
||||
if (ctx->DICTIONARY())
|
||||
return DropQuery::createDropDictionary(!!ctx->DETACH(), !!ctx->EXISTS(), visit(ctx->tableIdentifier()), cluster);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
}
|
43
src/Parsers/New/AST/DropQuery.h
Normal file
43
src/Parsers/New/AST/DropQuery.h
Normal file
@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/DDLQuery.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
class DropQuery : public DDLQuery
|
||||
{
|
||||
public:
|
||||
static PtrTo<DropQuery>
|
||||
createDropDatabase(bool detach, bool if_exists, PtrTo<DatabaseIdentifier> identifier, PtrTo<ClusterClause> cluster);
|
||||
static PtrTo<DropQuery>
|
||||
createDropTable(bool detach, bool if_exists, bool temporary, PtrTo<TableIdentifier> identifier, PtrTo<ClusterClause> cluster);
|
||||
static PtrTo<DropQuery>
|
||||
createDropDictionary(bool detach, bool if_exists, PtrTo<TableIdentifier> identifier, PtrTo<ClusterClause> cluster);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
NAME = 0,
|
||||
};
|
||||
|
||||
enum class QueryType
|
||||
{
|
||||
DATABASE,
|
||||
DICTIONARY,
|
||||
TABLE,
|
||||
};
|
||||
|
||||
const QueryType query_type;
|
||||
|
||||
bool detach = false;
|
||||
bool if_exists = false;
|
||||
bool temporary = false;
|
||||
|
||||
DropQuery(PtrTo<ClusterClause> cluster, QueryType type, PtrList exprs);
|
||||
};
|
||||
|
||||
}
|
199
src/Parsers/New/AST/EngineExpr.cpp
Normal file
199
src/Parsers/New/AST/EngineExpr.cpp
Normal file
@ -0,0 +1,199 @@
|
||||
#include <Parsers/New/AST/EngineExpr.h>
|
||||
|
||||
#include <Parsers/ASTCreateQuery.h>
|
||||
#include <Parsers/ASTFunction.h>
|
||||
#include <Parsers/ASTTTLElement.h>
|
||||
#include <Parsers/New/AST/ColumnExpr.h>
|
||||
#include <Parsers/New/AST/Identifier.h>
|
||||
#include <Parsers/New/AST/Literal.h>
|
||||
#include <Parsers/New/AST/SelectUnionQuery.h>
|
||||
#include <Parsers/New/ParseTreeVisitor.h>
|
||||
#include <Storages/DataDestinationType.h>
|
||||
#include <Storages/TTLMode.h>
|
||||
|
||||
|
||||
namespace DB::ErrorCodes
|
||||
{
|
||||
extern const int UNEXPECTED_AST_STRUCTURE;
|
||||
}
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
EngineClause::EngineClause(PtrTo<EngineExpr> expr) : INode(MAX_INDEX)
|
||||
{
|
||||
set(ENGINE, expr);
|
||||
}
|
||||
|
||||
void EngineClause::setOrderByClause(PtrTo<OrderByClause> clause)
|
||||
{
|
||||
set(ORDER_BY, clause);
|
||||
}
|
||||
|
||||
void EngineClause::setPartitionByClause(PtrTo<PartitionByClause> clause)
|
||||
{
|
||||
set(PARTITION_BY, clause);
|
||||
}
|
||||
|
||||
void EngineClause::setPrimaryKeyClause(PtrTo<PrimaryKeyClause> clause)
|
||||
{
|
||||
set(PRIMARY_KEY, clause);
|
||||
}
|
||||
|
||||
void EngineClause::setSampleByClause(PtrTo<SampleByClause> clause)
|
||||
{
|
||||
set(SAMPLE_BY, clause);
|
||||
}
|
||||
|
||||
void EngineClause::setTTLClause(PtrTo<TTLClause> clause)
|
||||
{
|
||||
set(TTL, clause);
|
||||
}
|
||||
|
||||
void EngineClause::setSettingsClause(PtrTo<SettingsClause> clause)
|
||||
{
|
||||
set(SETTINGS, clause);
|
||||
}
|
||||
|
||||
ASTPtr EngineClause::convertToOld() const
|
||||
{
|
||||
auto storage = std::make_shared<ASTStorage>();
|
||||
|
||||
storage->set(storage->engine, get(ENGINE)->convertToOld());
|
||||
if (has(PARTITION_BY)) storage->set(storage->partition_by, get(PARTITION_BY)->convertToOld());
|
||||
if (has(PRIMARY_KEY)) storage->set(storage->primary_key, get(PRIMARY_KEY)->convertToOld());
|
||||
if (has(ORDER_BY))
|
||||
{
|
||||
/// XXX: old parser used very strange grammar for this case, instead of using OrderByElement's.
|
||||
auto expr_list = get(ORDER_BY)->convertToOld();
|
||||
if (expr_list->children.size() > 1)
|
||||
throw DB::Exception(ErrorCodes::UNEXPECTED_AST_STRUCTURE, "Cannot convert multiple ORDER expression to old AST");
|
||||
storage->set(storage->order_by, expr_list->children[0]->children[0]);
|
||||
}
|
||||
if (has(SAMPLE_BY)) storage->set(storage->sample_by, get(SAMPLE_BY)->convertToOld());
|
||||
if (has(TTL)) storage->set(storage->ttl_table, get(TTL)->convertToOld());
|
||||
if (has(SETTINGS))
|
||||
{
|
||||
storage->set(storage->settings, get(SETTINGS)->convertToOld());
|
||||
storage->settings->is_standalone = false;
|
||||
}
|
||||
|
||||
return storage;
|
||||
}
|
||||
|
||||
EngineExpr::EngineExpr(PtrTo<Identifier> identifier, PtrTo<ColumnExprList> args) : INode{identifier, args}
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr EngineExpr::convertToOld() const
|
||||
{
|
||||
auto expr = std::make_shared<ASTFunction>();
|
||||
|
||||
expr->name = get<Identifier>(NAME)->getName();
|
||||
expr->no_empty_args = true;
|
||||
if (has(ARGS))
|
||||
{
|
||||
expr->arguments = get(ARGS)->convertToOld();
|
||||
expr->children.push_back(expr->arguments);
|
||||
}
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
TTLExpr::TTLExpr(PtrTo<ColumnExpr> expr, TTLType type, PtrTo<StringLiteral> literal) : INode{expr, literal}, ttl_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr TTLExpr::convertToOld() const
|
||||
{
|
||||
TTLMode mode = TTLMode::DELETE;
|
||||
DataDestinationType destination_type = DataDestinationType::DELETE;
|
||||
String destination_name;
|
||||
|
||||
switch(ttl_type)
|
||||
{
|
||||
case TTLType::DELETE:
|
||||
mode = TTLMode::DELETE;
|
||||
destination_type = DataDestinationType::DELETE;
|
||||
break;
|
||||
case TTLType::TO_DISK:
|
||||
mode = TTLMode::MOVE;
|
||||
destination_type = DataDestinationType::DISK;
|
||||
destination_name = get(TYPE)->convertToOld()->as<ASTLiteral>()->value.get<String>();
|
||||
break;
|
||||
case TTLType::TO_VOLUME:
|
||||
mode = TTLMode::MOVE;
|
||||
destination_type = DataDestinationType::VOLUME;
|
||||
destination_name = get(TYPE)->convertToOld()->as<ASTLiteral>()->value.get<String>();
|
||||
break;
|
||||
}
|
||||
|
||||
auto expr = std::make_shared<ASTTTLElement>(mode, destination_type, destination_name);
|
||||
expr->setTTL(get(EXPR)->convertToOld());
|
||||
return expr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace AST;
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitEngineClause(ClickHouseParser::EngineClauseContext *ctx)
|
||||
{
|
||||
auto clause = std::make_shared<EngineClause>(visit(ctx->engineExpr()).as<PtrTo<EngineExpr>>());
|
||||
|
||||
if (!ctx->orderByClause().empty()) clause->setOrderByClause(visit(ctx->orderByClause(0)));
|
||||
if (!ctx->partitionByClause().empty()) clause->setPartitionByClause(visit(ctx->partitionByClause(0)));
|
||||
if (!ctx->primaryKeyClause().empty()) clause->setPrimaryKeyClause(visit(ctx->primaryKeyClause(0)));
|
||||
if (!ctx->sampleByClause().empty()) clause->setSampleByClause(visit(ctx->sampleByClause(0)));
|
||||
if (!ctx->ttlClause().empty()) clause->setTTLClause(visit(ctx->ttlClause(0)));
|
||||
if (!ctx->settingsClause().empty()) clause->setSettingsClause(visit(ctx->settingsClause(0)));
|
||||
|
||||
return clause;
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitEngineExpr(ClickHouseParser::EngineExprContext *ctx)
|
||||
{
|
||||
auto list = ctx->columnExprList() ? visit(ctx->columnExprList()).as<PtrTo<ColumnExprList>>() : nullptr;
|
||||
return std::make_shared<EngineExpr>(visit(ctx->identifierOrNull()), list);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitPartitionByClause(ClickHouseParser::PartitionByClauseContext *ctx)
|
||||
{
|
||||
return std::make_shared<PartitionByClause>(visit(ctx->columnExpr()).as<PtrTo<ColumnExpr>>());
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitPrimaryKeyClause(ClickHouseParser::PrimaryKeyClauseContext *ctx)
|
||||
{
|
||||
return std::make_shared<PrimaryKeyClause>(visit(ctx->columnExpr()).as<PtrTo<ColumnExpr>>());
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitSampleByClause(ClickHouseParser::SampleByClauseContext *ctx)
|
||||
{
|
||||
return std::make_shared<SampleByClause>(visit(ctx->columnExpr()).as<PtrTo<ColumnExpr>>());
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitTtlClause(ClickHouseParser::TtlClauseContext *ctx)
|
||||
{
|
||||
auto list = std::make_shared<TTLExprList>();
|
||||
for (auto * expr : ctx->ttlExpr()) list->push(visit(expr));
|
||||
return std::make_shared<TTLClause>(list);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitTtlExpr(ClickHouseParser::TtlExprContext *ctx)
|
||||
{
|
||||
TTLExpr::TTLType type;
|
||||
PtrTo<StringLiteral> literal;
|
||||
|
||||
if (ctx->DISK()) type = TTLExpr::TTLType::TO_DISK;
|
||||
else if (ctx->VOLUME()) type = TTLExpr::TTLType::TO_VOLUME;
|
||||
else type = TTLExpr::TTLType::DELETE;
|
||||
|
||||
if (ctx->STRING_LITERAL()) literal = Literal::createString(ctx->STRING_LITERAL());
|
||||
|
||||
return std::make_shared<TTLExpr>(visit(ctx->columnExpr()), type, literal);
|
||||
}
|
||||
|
||||
}
|
85
src/Parsers/New/AST/EngineExpr.h
Normal file
85
src/Parsers/New/AST/EngineExpr.h
Normal file
@ -0,0 +1,85 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/INode.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
// Clauses
|
||||
|
||||
using PartitionByClause = SimpleClause<ColumnExpr>;
|
||||
|
||||
using SampleByClause = SimpleClause<ColumnExpr>;
|
||||
|
||||
class EngineClause : public INode
|
||||
{
|
||||
public:
|
||||
explicit EngineClause(PtrTo<EngineExpr> expr);
|
||||
|
||||
void setOrderByClause(PtrTo<OrderByClause> clause);
|
||||
void setPartitionByClause(PtrTo<PartitionByClause> clause);
|
||||
void setPrimaryKeyClause(PtrTo<PrimaryKeyClause> clause);
|
||||
void setSampleByClause(PtrTo<SampleByClause> clause);
|
||||
void setTTLClause(PtrTo<TTLClause> clause);
|
||||
void setSettingsClause(PtrTo<SettingsClause> clause);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
ENGINE = 0, // EngineExpr
|
||||
ORDER_BY, // OrderByClause (optional)
|
||||
PARTITION_BY, // PartitionByClause (optional)
|
||||
PRIMARY_KEY, // PrimaryKeyClause (optional)
|
||||
SAMPLE_BY, // SampleByClause (optional)
|
||||
TTL, // TTLClause (optional)
|
||||
SETTINGS, // SettingsClause (optional)
|
||||
|
||||
MAX_INDEX,
|
||||
};
|
||||
};
|
||||
|
||||
// Expressions
|
||||
|
||||
class EngineExpr : public INode
|
||||
{
|
||||
public:
|
||||
EngineExpr(PtrTo<Identifier> identifier, PtrTo<ColumnExprList> args);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
NAME = 0, // Identifier
|
||||
ARGS, // ColumnExprList (optional)
|
||||
};
|
||||
};
|
||||
|
||||
class TTLExpr : public INode
|
||||
{
|
||||
public:
|
||||
enum class TTLType
|
||||
{
|
||||
DELETE,
|
||||
TO_DISK,
|
||||
TO_VOLUME,
|
||||
};
|
||||
|
||||
TTLExpr(PtrTo<ColumnExpr> expr, TTLType type, PtrTo<StringLiteral> literal);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
EXPR = 0, // ColumnExpr
|
||||
TYPE = 1, // StringLiteral (optional)
|
||||
};
|
||||
|
||||
TTLType ttl_type;
|
||||
};
|
||||
|
||||
}
|
55
src/Parsers/New/AST/ExistsQuery.cpp
Normal file
55
src/Parsers/New/AST/ExistsQuery.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include <Parsers/New/AST/ExistsQuery.h>
|
||||
|
||||
#include <Interpreters/StorageID.h>
|
||||
#include <Parsers/ASTIdentifier.h>
|
||||
#include <Parsers/New/AST/Identifier.h>
|
||||
#include <Parsers/New/ParseTreeVisitor.h>
|
||||
#include <Parsers/TablePropertiesQueriesASTs.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
ExistsQuery::ExistsQuery(QueryType type, bool temporary_, PtrTo<TableIdentifier> identifier)
|
||||
: Query{identifier}, query_type(type), temporary(temporary_)
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr ExistsQuery::convertToOld() const
|
||||
{
|
||||
std::shared_ptr<ASTQueryWithTableAndOutput> query;
|
||||
|
||||
switch(query_type)
|
||||
{
|
||||
case QueryType::DICTIONARY:
|
||||
query = std::make_shared<ASTExistsDictionaryQuery>();
|
||||
break;
|
||||
case QueryType::TABLE:
|
||||
query = std::make_shared<ASTExistsTableQuery>();
|
||||
query->temporary = temporary;
|
||||
break;
|
||||
}
|
||||
|
||||
// FIXME: this won't work if table doesn't exist
|
||||
auto table_id = getTableIdentifier(get(TABLE)->convertToOld());
|
||||
query->database = table_id.database_name;
|
||||
query->table = table_id.table_name;
|
||||
query->uuid = table_id.uuid;
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace AST;
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitExistsStmt(ClickHouseParser::ExistsStmtContext *ctx)
|
||||
{
|
||||
auto type = ctx->TABLE() ? ExistsQuery::QueryType::TABLE : ExistsQuery::QueryType::DICTIONARY;
|
||||
return std::make_shared<ExistsQuery>(type, !!ctx->TEMPORARY(), visit(ctx->tableIdentifier()));
|
||||
}
|
||||
|
||||
}
|
32
src/Parsers/New/AST/ExistsQuery.h
Normal file
32
src/Parsers/New/AST/ExistsQuery.h
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/Query.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
class ExistsQuery : public Query
|
||||
{
|
||||
public:
|
||||
enum class QueryType
|
||||
{
|
||||
DICTIONARY,
|
||||
TABLE,
|
||||
};
|
||||
|
||||
ExistsQuery(QueryType type, bool temporary, PtrTo<TableIdentifier> identifier);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
TABLE = 0, // TableIdentifier
|
||||
};
|
||||
|
||||
const QueryType query_type;
|
||||
const bool temporary;
|
||||
};
|
||||
|
||||
}
|
35
src/Parsers/New/AST/ExplainQuery.cpp
Normal file
35
src/Parsers/New/AST/ExplainQuery.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
#include <Parsers/New/AST/ExplainQuery.h>
|
||||
|
||||
#include <Parsers/ASTExplainQuery.h>
|
||||
#include <Parsers/New/ParseTreeVisitor.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
ExplainQuery::ExplainQuery(PtrTo<Query> query) : Query{query}
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr ExplainQuery::convertToOld() const
|
||||
{
|
||||
auto query = std::make_shared<ASTExplainQuery>(ASTExplainQuery::AnalyzedSyntax);
|
||||
|
||||
query->setExplainedQuery(get(QUERY)->convertToOld());
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace DB::AST;
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitExplainStmt(ClickHouseParser::ExplainStmtContext *ctx)
|
||||
{
|
||||
return std::make_shared<ExplainQuery>(visit(ctx->query()).as<PtrTo<Query>>());
|
||||
}
|
||||
|
||||
}
|
23
src/Parsers/New/AST/ExplainQuery.h
Normal file
23
src/Parsers/New/AST/ExplainQuery.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/Query.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
class ExplainQuery : public Query
|
||||
{
|
||||
public:
|
||||
explicit ExplainQuery(PtrTo<Query> query);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
QUERY = 0, // Query
|
||||
};
|
||||
};
|
||||
|
||||
}
|
103
src/Parsers/New/AST/INode.h
Normal file
103
src/Parsers/New/AST/INode.h
Normal file
@ -0,0 +1,103 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/fwd_decl.h>
|
||||
|
||||
#include <common/demangle.h>
|
||||
#include <Common/TypePromotion.h>
|
||||
#include <Parsers/ASTExpressionList.h>
|
||||
|
||||
#include <initializer_list>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
class INode : public TypePromotion<INode>
|
||||
{
|
||||
public:
|
||||
virtual ~INode() = default;
|
||||
|
||||
virtual ASTPtr convertToOld() const { return ASTPtr(); }
|
||||
virtual String toString() const { return {}; }
|
||||
|
||||
void dump() const { dump(0); }
|
||||
|
||||
protected:
|
||||
INode() = default;
|
||||
INode(std::initializer_list<Ptr> list) { children = list; }
|
||||
explicit INode(PtrList list) { children = list; }
|
||||
explicit INode(size_t size) { children.resize(size); }
|
||||
|
||||
void push(const Ptr& child) { children.push_back(child); }
|
||||
void set(size_t i, const Ptr& child) { children[i] = child; }
|
||||
bool has(size_t i) const { return i < children.size() && children[i]; }
|
||||
const Ptr & get(size_t i) const { return children[i]; }
|
||||
|
||||
template <class ChildType>
|
||||
bool has(size_t i) const { return has(i) && children[i]->as<ChildType>(); }
|
||||
|
||||
template <class ChildType>
|
||||
ChildType * get(size_t i) const { return children[i]->template as<ChildType>(); }
|
||||
|
||||
auto begin() const { return children.cbegin(); }
|
||||
auto end() const { return children.cend(); }
|
||||
auto size() const { return children.size(); }
|
||||
|
||||
private:
|
||||
PtrList children; // any child potentially may point to |nullptr|
|
||||
|
||||
void dump(int indentation) const
|
||||
{
|
||||
for (auto i = 0; i < indentation; ++i) std::cout << " ";
|
||||
std::cout << "⭸ " << demangle(typeid(*this).name()) << " (" << dumpInfo() << ")" << std::endl;
|
||||
for (const auto & child : children) if (child) child->dump(indentation + 1);
|
||||
}
|
||||
|
||||
virtual String dumpInfo() const { return ""; }
|
||||
};
|
||||
|
||||
template <class T, char Separator>
|
||||
class List : public INode {
|
||||
public:
|
||||
List() = default;
|
||||
List(std::initializer_list<PtrTo<T>> list)
|
||||
{
|
||||
for (const auto & i : list) push(i);
|
||||
}
|
||||
|
||||
using INode::begin;
|
||||
using INode::end;
|
||||
using INode::size;
|
||||
|
||||
void push(const PtrTo<T> & node) { INode::push(node); }
|
||||
|
||||
ASTPtr convertToOld() const override
|
||||
{
|
||||
auto list = std::make_shared<ASTExpressionList>(Separator);
|
||||
for (const auto & child : *this) list->children.emplace_back(child->convertToOld());
|
||||
return list;
|
||||
}
|
||||
|
||||
String toString() const override
|
||||
{
|
||||
if (!size()) return {};
|
||||
|
||||
auto string = (*begin())->toString();
|
||||
|
||||
for (auto next = ++begin(); next != end(); ++next)
|
||||
string += String(1, Separator) + " " + (*next)->toString();
|
||||
|
||||
return string;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class SimpleClause : public INode
|
||||
{
|
||||
public:
|
||||
explicit SimpleClause(PtrTo<T> expr) : INode{expr} {}
|
||||
ASTPtr convertToOld() const override { return get(0)->convertToOld(); }
|
||||
};
|
||||
|
||||
}
|
175
src/Parsers/New/AST/Identifier.cpp
Normal file
175
src/Parsers/New/AST/Identifier.cpp
Normal file
@ -0,0 +1,175 @@
|
||||
#include <Parsers/New/AST/Identifier.h>
|
||||
|
||||
#include <IO/ReadHelpers.h>
|
||||
#include <Parsers/ASTIdentifier.h>
|
||||
#include <Parsers/New/ParseTreeVisitor.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
Identifier::Identifier(const String & name_) : name(name_)
|
||||
{
|
||||
if (name.front() == '`' || name.front() == '"')
|
||||
{
|
||||
String s;
|
||||
ReadBufferFromMemory in(name.data(), name.size());
|
||||
|
||||
if (name.front() == '`')
|
||||
readBackQuotedStringWithSQLStyle(s, in);
|
||||
else
|
||||
readDoubleQuotedStringWithSQLStyle(s, in);
|
||||
|
||||
assert(in.count() == name.size());
|
||||
name = s;
|
||||
}
|
||||
}
|
||||
|
||||
Identifier::Identifier(const String & name_, const String & nested_name) : name(name_ + "." + nested_name)
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr Identifier::convertToOld() const
|
||||
{
|
||||
return std::make_shared<ASTIdentifier>(getQualifiedName());
|
||||
}
|
||||
|
||||
String Identifier::toString() const
|
||||
{
|
||||
return getQualifiedName();
|
||||
}
|
||||
|
||||
DatabaseIdentifier::DatabaseIdentifier(PtrTo<Identifier> name) : Identifier(*name)
|
||||
{
|
||||
}
|
||||
|
||||
TableIdentifier::TableIdentifier(PtrTo<DatabaseIdentifier> database, PtrTo<Identifier> name) : Identifier(*name), db(database)
|
||||
{
|
||||
}
|
||||
|
||||
void TableIdentifier::makeCompound() const
|
||||
{
|
||||
if (db)
|
||||
{
|
||||
name = db->getName();
|
||||
db.reset();
|
||||
}
|
||||
}
|
||||
|
||||
ASTPtr TableIdentifier::convertToOld() const
|
||||
{
|
||||
std::vector<String> parts;
|
||||
|
||||
if (db && !db->getName().empty()) parts.push_back(db->getName());
|
||||
parts.push_back(getName());
|
||||
|
||||
return std::make_shared<ASTIdentifier>(std::move(parts));
|
||||
}
|
||||
|
||||
ColumnIdentifier::ColumnIdentifier(PtrTo<TableIdentifier> table_, PtrTo<Identifier> name) : Identifier(name->getName()), table(table_)
|
||||
{
|
||||
}
|
||||
|
||||
void ColumnIdentifier::makeCompound() const
|
||||
{
|
||||
if (table)
|
||||
{
|
||||
name = table->getName() + "." + getName();
|
||||
if (table->getDatabase()) table->makeCompound();
|
||||
else table.reset();
|
||||
}
|
||||
}
|
||||
|
||||
ASTPtr ColumnIdentifier::convertToOld() const
|
||||
{
|
||||
std::vector<String> parts;
|
||||
|
||||
if (table)
|
||||
{
|
||||
if (table->getDatabase()) parts.push_back(table->getDatabase()->getName());
|
||||
parts.push_back(table->getName());
|
||||
}
|
||||
parts.push_back(getName());
|
||||
|
||||
return std::make_shared<ASTIdentifier>(std::move(parts));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace AST;
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitAlias(ClickHouseParser::AliasContext *ctx)
|
||||
{
|
||||
if (ctx->IDENTIFIER()) return std::make_shared<Identifier>(ctx->IDENTIFIER()->getText());
|
||||
if (ctx->keywordForAlias()) return std::make_shared<Identifier>(ctx->keywordForAlias()->getText());
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnIdentifier(ClickHouseParser::ColumnIdentifierContext *ctx)
|
||||
{
|
||||
auto table = ctx->tableIdentifier() ? visit(ctx->tableIdentifier()).as<PtrTo<TableIdentifier>>() : nullptr;
|
||||
return std::make_shared<ColumnIdentifier>(table, visit(ctx->nestedIdentifier()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitDatabaseIdentifier(ClickHouseParser::DatabaseIdentifierContext *ctx)
|
||||
{
|
||||
return std::make_shared<DatabaseIdentifier>(visit(ctx->identifier()).as<PtrTo<Identifier>>());
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitIdentifier(ClickHouseParser::IdentifierContext *ctx)
|
||||
{
|
||||
if (ctx->IDENTIFIER()) return std::make_shared<Identifier>(ctx->IDENTIFIER()->getText());
|
||||
if (ctx->interval()) return std::make_shared<Identifier>(ctx->interval()->getText());
|
||||
if (ctx->keyword()) return std::make_shared<Identifier>(ctx->keyword()->getText());
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitIdentifierOrNull(ClickHouseParser::IdentifierOrNullContext *ctx)
|
||||
{
|
||||
if (ctx->identifier()) return visit(ctx->identifier());
|
||||
if (ctx->NULL_SQL())
|
||||
{
|
||||
if (ctx->NULL_SQL()->getSymbol()->getText() == "Null") return std::make_shared<Identifier>("Null");
|
||||
else {
|
||||
// TODO: raise error
|
||||
}
|
||||
}
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitInterval(ClickHouseParser::IntervalContext *)
|
||||
{
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitKeyword(ClickHouseParser::KeywordContext *)
|
||||
{
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitKeywordForAlias(ClickHouseParser::KeywordForAliasContext *)
|
||||
{
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitNestedIdentifier(ClickHouseParser::NestedIdentifierContext *ctx)
|
||||
{
|
||||
if (ctx->identifier().size() == 2)
|
||||
{
|
||||
auto name1 = visit(ctx->identifier(0)).as<PtrTo<Identifier>>()->getName();
|
||||
auto name2 = visit(ctx->identifier(1)).as<PtrTo<Identifier>>()->getName();
|
||||
return std::make_shared<Identifier>(name1, name2);
|
||||
}
|
||||
else return visit(ctx->identifier(0));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitTableIdentifier(ClickHouseParser::TableIdentifierContext *ctx)
|
||||
{
|
||||
auto database = ctx->databaseIdentifier() ? visit(ctx->databaseIdentifier()).as<PtrTo<DatabaseIdentifier>>() : nullptr;
|
||||
return std::make_shared<TableIdentifier>(database, visit(ctx->identifier()));
|
||||
}
|
||||
|
||||
}
|
66
src/Parsers/New/AST/Identifier.h
Normal file
66
src/Parsers/New/AST/Identifier.h
Normal file
@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/INode.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
class Identifier : public INode
|
||||
{
|
||||
public:
|
||||
explicit Identifier(const String & name_);
|
||||
Identifier(const String & name_, const String & nested_name);
|
||||
|
||||
const auto & getName() const { return name; }
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
String toString() const override;
|
||||
|
||||
virtual String getQualifiedName() const { return name; };
|
||||
|
||||
protected:
|
||||
mutable String name; // protected and non-const because identifiers may become `column.nested` from `table.column`
|
||||
|
||||
String dumpInfo() const override { return getQualifiedName(); }
|
||||
};
|
||||
|
||||
class DatabaseIdentifier : public Identifier
|
||||
{
|
||||
public:
|
||||
explicit DatabaseIdentifier(PtrTo<Identifier> name);
|
||||
};
|
||||
|
||||
class TableIdentifier : public Identifier
|
||||
{
|
||||
public:
|
||||
TableIdentifier(PtrTo<DatabaseIdentifier> database, PtrTo<Identifier> name);
|
||||
|
||||
auto getDatabase() const { return db; }
|
||||
void makeCompound() const;
|
||||
|
||||
String getQualifiedName() const override { return (db ? db->getQualifiedName() + "." : String()) + getName(); }
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
mutable PtrTo<DatabaseIdentifier> db;
|
||||
};
|
||||
|
||||
class ColumnIdentifier : public Identifier
|
||||
{
|
||||
public:
|
||||
ColumnIdentifier(PtrTo<TableIdentifier> table, PtrTo<Identifier> name);
|
||||
|
||||
auto getTable() const { return table; }
|
||||
void makeCompound() const;
|
||||
|
||||
String getQualifiedName() const override { return (table ? table->getQualifiedName() + "." : String()) + getName(); }
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
mutable PtrTo<TableIdentifier> table;
|
||||
};
|
||||
|
||||
}
|
125
src/Parsers/New/AST/InsertQuery.cpp
Normal file
125
src/Parsers/New/AST/InsertQuery.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
#include <Parsers/New/AST/InsertQuery.h>
|
||||
|
||||
#include <Parsers/ASTIdentifier.h>
|
||||
#include <Parsers/ASTInsertQuery.h>
|
||||
#include <Parsers/New/AST/ColumnExpr.h>
|
||||
#include <Parsers/New/AST/Identifier.h>
|
||||
#include <Parsers/New/AST/SelectUnionQuery.h>
|
||||
#include <Parsers/New/AST/TableExpr.h>
|
||||
#include <Parsers/New/ParseTreeVisitor.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
// static
|
||||
PtrTo<DataClause> DataClause::createFormat(PtrTo<Identifier> identifier, size_t data_offset)
|
||||
{
|
||||
PtrTo<DataClause> clause(new DataClause(ClauseType::FORMAT, {identifier}));
|
||||
clause->offset = data_offset;
|
||||
return clause;
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<DataClause> DataClause::createSelect(PtrTo<SelectUnionQuery> query)
|
||||
{
|
||||
return PtrTo<DataClause>(new DataClause(ClauseType::SELECT, {query}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<DataClause> DataClause::createValues(size_t data_offset)
|
||||
{
|
||||
PtrTo<DataClause> clause(new DataClause(ClauseType::VALUES, {}));
|
||||
clause->offset = data_offset;
|
||||
return clause;
|
||||
}
|
||||
|
||||
DataClause::DataClause(ClauseType type, PtrList exprs) : INode(exprs), clause_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr DataClause::convertToOld() const
|
||||
{
|
||||
if (clause_type != ClauseType::SELECT) return {};
|
||||
return get(SUBQUERY)->convertToOld();
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<InsertQuery> InsertQuery::createTable(PtrTo<TableIdentifier> identifier, PtrTo<ColumnNameList> list, PtrTo<DataClause> clause)
|
||||
{
|
||||
return PtrTo<InsertQuery>(new InsertQuery(QueryType::TABLE, {identifier, list, clause}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<InsertQuery> InsertQuery::createFunction(PtrTo<TableFunctionExpr> function, PtrTo<ColumnNameList> list, PtrTo<DataClause> clause)
|
||||
{
|
||||
return PtrTo<InsertQuery>(new InsertQuery(QueryType::FUNCTION, {function, list, clause}));
|
||||
}
|
||||
|
||||
InsertQuery::InsertQuery(QueryType type, PtrList exprs) : Query(exprs), query_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr InsertQuery::convertToOld() const
|
||||
{
|
||||
auto query = std::make_shared<ASTInsertQuery>();
|
||||
|
||||
switch(query_type)
|
||||
{
|
||||
case QueryType::FUNCTION:
|
||||
query->table_function = get(FUNCTION)->convertToOld();
|
||||
break;
|
||||
case QueryType::TABLE:
|
||||
query->table_id = getTableIdentifier(get(IDENTIFIER)->convertToOld());
|
||||
break;
|
||||
}
|
||||
|
||||
if (has(COLUMNS)) query->columns = get(COLUMNS)->convertToOld();
|
||||
if (get<DataClause>(DATA)->getType() == DataClause::ClauseType::SELECT)
|
||||
{
|
||||
query->select = get(DATA)->convertToOld();
|
||||
query->children.push_back(query->select);
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace AST;
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitColumnsClause(ClickHouseParser::ColumnsClauseContext *ctx)
|
||||
{
|
||||
auto list = std::make_shared<ColumnNameList>();
|
||||
for (auto * name : ctx->nestedIdentifier()) list->push(visit(name));
|
||||
return list;
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitDataClauseFormat(ClickHouseParser::DataClauseFormatContext *ctx)
|
||||
{
|
||||
return DataClause::createFormat(visit(ctx->identifier()), ctx->getStop()->getStopIndex() + 1);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitDataClauseSelect(ClickHouseParser::DataClauseSelectContext *ctx)
|
||||
{
|
||||
return DataClause::createSelect(visit(ctx->selectUnionStmt()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitDataClauseValues(ClickHouseParser::DataClauseValuesContext *ctx)
|
||||
{
|
||||
return DataClause::createValues(ctx->getStop()->getStopIndex() + 1);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitInsertStmt(ClickHouseParser::InsertStmtContext *ctx)
|
||||
{
|
||||
auto columns = ctx->columnsClause() ? visit(ctx->columnsClause()).as<PtrTo<ColumnNameList>>() : nullptr;
|
||||
|
||||
if (ctx->FUNCTION()) return InsertQuery::createFunction(visit(ctx->tableFunctionExpr()), columns, visit(ctx->dataClause()));
|
||||
if (ctx->tableIdentifier()) return InsertQuery::createTable(visit(ctx->tableIdentifier()), columns, visit(ctx->dataClause()));
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
}
|
73
src/Parsers/New/AST/InsertQuery.h
Normal file
73
src/Parsers/New/AST/InsertQuery.h
Normal file
@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/Query.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
class DataClause : public INode
|
||||
{
|
||||
public:
|
||||
enum class ClauseType
|
||||
{
|
||||
FORMAT,
|
||||
SELECT,
|
||||
VALUES,
|
||||
};
|
||||
|
||||
static PtrTo<DataClause> createFormat(PtrTo<Identifier> identifier, size_t data_offset);
|
||||
static PtrTo<DataClause> createSelect(PtrTo<SelectUnionQuery> query);
|
||||
static PtrTo<DataClause> createValues(size_t data_offset);
|
||||
|
||||
auto getType() const { return clause_type; }
|
||||
auto getOffset() const { return offset; }
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
FORMAT = 0, // Identifier
|
||||
SUBQUERY = 0, // SelectUnionQuery
|
||||
};
|
||||
|
||||
ClauseType clause_type;
|
||||
size_t offset = 0;
|
||||
|
||||
DataClause(ClauseType type, PtrList exprs);
|
||||
};
|
||||
|
||||
class InsertQuery : public Query
|
||||
{
|
||||
public:
|
||||
static PtrTo<InsertQuery> createFunction(PtrTo<TableFunctionExpr> function, PtrTo<ColumnNameList> list, PtrTo<DataClause> clause);
|
||||
static PtrTo<InsertQuery> createTable(PtrTo<TableIdentifier> identifier, PtrTo<ColumnNameList> list, PtrTo<DataClause> clause);
|
||||
|
||||
bool hasData() const { return get<DataClause>(DATA)->getType() != DataClause::ClauseType::SELECT; }
|
||||
size_t getDataOffset() const { return get<DataClause>(DATA)->getOffset(); }
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
IDENTIFIER = 0, // TableIdentifier
|
||||
FUNCTION = 0, // TableFunctionExpr
|
||||
COLUMNS = 1, // ColumnNameList
|
||||
DATA = 2, // DataClause
|
||||
};
|
||||
enum class QueryType
|
||||
{
|
||||
FUNCTION,
|
||||
TABLE,
|
||||
};
|
||||
|
||||
QueryType query_type;
|
||||
|
||||
InsertQuery(QueryType type, PtrList exprs);
|
||||
|
||||
String dumpInfo() const override { return String("has_data=") + (hasData() ? "true" : "false"); }
|
||||
};
|
||||
|
||||
}
|
326
src/Parsers/New/AST/JoinExpr.cpp
Normal file
326
src/Parsers/New/AST/JoinExpr.cpp
Normal file
@ -0,0 +1,326 @@
|
||||
#include <Parsers/New/AST/JoinExpr.h>
|
||||
|
||||
#include <Parsers/ASTExpressionList.h>
|
||||
#include <Parsers/ASTTablesInSelectQuery.h>
|
||||
#include <Parsers/New/AST/RatioExpr.h>
|
||||
#include <Parsers/New/AST/TableExpr.h>
|
||||
#include <Parsers/New/ParseTreeVisitor.h>
|
||||
|
||||
|
||||
namespace DB::ErrorCodes
|
||||
{
|
||||
extern const int UNEXPECTED_AST_STRUCTURE;
|
||||
}
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
JoinConstraintClause::JoinConstraintClause(ConstraintType type_, PtrTo<ColumnExprList> list) : SimpleClause{list}, type(type_)
|
||||
{
|
||||
}
|
||||
|
||||
SampleClause::SampleClause(PtrTo<RatioExpr> ratio, PtrTo<RatioExpr> offset) : INode{ratio, offset}
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr SampleClause::convertToOld() const
|
||||
{
|
||||
auto list = std::make_shared<ASTExpressionList>();
|
||||
|
||||
list->children.push_back(get(RATIO)->convertToOld());
|
||||
if (has(OFFSET)) list->children.push_back(get(OFFSET)->convertToOld());
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<JoinExpr> JoinExpr::createTableExpr(PtrTo<TableExpr> expr, PtrTo<SampleClause> clause, bool final)
|
||||
{
|
||||
return PtrTo<JoinExpr>(new JoinExpr(JoinExpr::ExprType::TABLE, final, {expr, clause}));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<JoinExpr> JoinExpr::createJoinOp(
|
||||
PtrTo<JoinExpr> left_expr, PtrTo<JoinExpr> right_expr, JoinOpType op, JoinOpMode mode, PtrTo<JoinConstraintClause> clause)
|
||||
{
|
||||
return PtrTo<JoinExpr>(new JoinExpr(ExprType::JOIN_OP, op, mode, {left_expr, right_expr, clause}));
|
||||
}
|
||||
|
||||
JoinExpr::JoinExpr(JoinExpr::ExprType type, bool final_, PtrList exprs) : INode(exprs), expr_type(type), final(final_)
|
||||
{
|
||||
}
|
||||
|
||||
JoinExpr::JoinExpr(JoinExpr::ExprType type, JoinExpr::JoinOpType op, JoinExpr::JoinOpMode mode, PtrList exprs)
|
||||
: INode(exprs), expr_type(type), op_type(op), op_mode(mode)
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr JoinExpr::convertToOld() const
|
||||
{
|
||||
/** The sole convertable chain of Join's may look like:
|
||||
*
|
||||
* … FROM table1 JOIN table2 ON SMTH JOIN table3 ON SMTH JOIN …
|
||||
*
|
||||
* Since Join is a left-associative operation then the tree will look like:
|
||||
*
|
||||
* JoinExpr
|
||||
* / \
|
||||
* JoinExpr …
|
||||
* / \
|
||||
* JoinExpr table3
|
||||
* / \
|
||||
* table1 table2
|
||||
*
|
||||
* To linearize this tree we have to start from the top-most expression.
|
||||
*/
|
||||
|
||||
auto list = std::make_shared<ASTExpressionList>();
|
||||
|
||||
if (expr_type == ExprType::TABLE)
|
||||
{
|
||||
auto element = std::make_shared<ASTTablesInSelectQueryElement>();
|
||||
element->children.emplace_back(get(TABLE)->convertToOld());
|
||||
element->table_expression = element->children.back();
|
||||
element->table_expression->as<ASTTableExpression>()->final = final;
|
||||
if (has(SAMPLE))
|
||||
{
|
||||
auto old_list = get(SAMPLE)->convertToOld();
|
||||
|
||||
element->table_expression->as<ASTTableExpression>()->sample_size = old_list->children[0];
|
||||
element->table_expression->children.push_back(element->table_expression->as<ASTTableExpression>()->sample_size);
|
||||
|
||||
if (old_list->children.size() > 1)
|
||||
{
|
||||
element->table_expression->as<ASTTableExpression>()->sample_offset = old_list->children[1];
|
||||
element->table_expression->children.push_back(element->table_expression->as<ASTTableExpression>()->sample_offset);
|
||||
}
|
||||
}
|
||||
|
||||
list->children.emplace_back(element);
|
||||
}
|
||||
else if (expr_type == ExprType::JOIN_OP)
|
||||
{
|
||||
if (get<JoinExpr>(RIGHT_EXPR)->expr_type != ExprType::TABLE)
|
||||
throw Exception(ErrorCodes::UNEXPECTED_AST_STRUCTURE, "Cannot convert new tree-like JoinExpr to old AST");
|
||||
|
||||
auto left = get(LEFT_EXPR)->convertToOld(), right = get(RIGHT_EXPR)->convertToOld(); // ASTExpressionList's
|
||||
list->children.insert(list->children.end(), left->children.begin(), left->children.end()); // Insert all the previously parsed left subtree
|
||||
list->children.emplace_back(right->children[0]); // Insert only first (single) ASTTablesInSelectQueryElement which should contain only ASTTableExpression
|
||||
|
||||
auto element = std::make_shared<ASTTableJoin>();
|
||||
switch (op_mode)
|
||||
{
|
||||
case JoinOpMode::DEFAULT:
|
||||
element->locality = ASTTableJoin::Locality::Unspecified;
|
||||
break;
|
||||
case JoinOpMode::GLOBAL:
|
||||
element->locality = ASTTableJoin::Locality::Global;
|
||||
break;
|
||||
case JoinOpMode::LOCAL:
|
||||
element->locality = ASTTableJoin::Locality::Local;
|
||||
break;
|
||||
}
|
||||
switch (op_type)
|
||||
{
|
||||
case JoinOpType::CROSS:
|
||||
element->kind = ASTTableJoin::Kind::Cross;
|
||||
break;
|
||||
case JoinOpType::FULL:
|
||||
element->kind = ASTTableJoin::Kind::Full;
|
||||
break;
|
||||
case JoinOpType::FULL_ALL:
|
||||
element->kind = ASTTableJoin::Kind::Full;
|
||||
element->strictness = ASTTableJoin::Strictness::All;
|
||||
break;
|
||||
case JoinOpType::FULL_ANY:
|
||||
element->kind = ASTTableJoin::Kind::Full;
|
||||
element->strictness = ASTTableJoin::Strictness::Any;
|
||||
break;
|
||||
case JoinOpType::INNER:
|
||||
element->kind = ASTTableJoin::Kind::Inner;
|
||||
break;
|
||||
case JoinOpType::INNER_ALL:
|
||||
element->kind = ASTTableJoin::Kind::Inner;
|
||||
element->strictness = ASTTableJoin::Strictness::All;
|
||||
break;
|
||||
case JoinOpType::INNER_ANY:
|
||||
element->kind = ASTTableJoin::Kind::Inner;
|
||||
element->strictness = ASTTableJoin::Strictness::Any;
|
||||
break;
|
||||
case JoinOpType::INNER_ASOF:
|
||||
element->kind = ASTTableJoin::Kind::Inner;
|
||||
element->strictness = ASTTableJoin::Strictness::Asof;
|
||||
break;
|
||||
case JoinOpType::LEFT:
|
||||
element->kind = ASTTableJoin::Kind::Left;
|
||||
break;
|
||||
case JoinOpType::LEFT_ALL:
|
||||
element->kind = ASTTableJoin::Kind::Left;
|
||||
element->strictness = ASTTableJoin::Strictness::All;
|
||||
break;
|
||||
case JoinOpType::LEFT_ANTI:
|
||||
element->kind = ASTTableJoin::Kind::Left;
|
||||
element->strictness = ASTTableJoin::Strictness::Anti;
|
||||
break;
|
||||
case JoinOpType::LEFT_ANY:
|
||||
element->kind = ASTTableJoin::Kind::Left;
|
||||
element->strictness = ASTTableJoin::Strictness::Any;
|
||||
break;
|
||||
case JoinOpType::LEFT_ASOF:
|
||||
element->kind = ASTTableJoin::Kind::Left;
|
||||
element->strictness = ASTTableJoin::Strictness::Asof;
|
||||
break;
|
||||
case JoinOpType::LEFT_SEMI:
|
||||
element->kind = ASTTableJoin::Kind::Left;
|
||||
element->strictness = ASTTableJoin::Strictness::Semi;
|
||||
break;
|
||||
case JoinOpType::RIGHT:
|
||||
element->kind = ASTTableJoin::Kind::Right;
|
||||
break;
|
||||
case JoinOpType::RIGHT_ANTI:
|
||||
element->kind = ASTTableJoin::Kind::Right;
|
||||
element->strictness = ASTTableJoin::Strictness::Anti;
|
||||
break;
|
||||
case JoinOpType::RIGHT_ALL:
|
||||
element->kind = ASTTableJoin::Kind::Right;
|
||||
element->strictness = ASTTableJoin::Strictness::All;
|
||||
break;
|
||||
case JoinOpType::RIGHT_ANY:
|
||||
element->kind = ASTTableJoin::Kind::Right;
|
||||
element->strictness = ASTTableJoin::Strictness::Any;
|
||||
break;
|
||||
case JoinOpType::RIGHT_ASOF:
|
||||
element->kind = ASTTableJoin::Kind::Right;
|
||||
element->strictness = ASTTableJoin::Strictness::Asof;
|
||||
break;
|
||||
case JoinOpType::RIGHT_SEMI:
|
||||
element->kind = ASTTableJoin::Kind::Right;
|
||||
element->strictness = ASTTableJoin::Strictness::Semi;
|
||||
break;
|
||||
}
|
||||
|
||||
if (has(CONSTRAINT))
|
||||
{
|
||||
const auto * constraint = get<JoinConstraintClause>(CONSTRAINT);
|
||||
switch(constraint->getType())
|
||||
{
|
||||
case JoinConstraintClause::ConstraintType::ON:
|
||||
element->on_expression = constraint->convertToOld();
|
||||
if (element->on_expression->children.size() > 1)
|
||||
throw Exception(ErrorCodes::UNEXPECTED_AST_STRUCTURE, "Cannot convert JoinExpr with more than one ON expression");
|
||||
element->on_expression = element->on_expression->children[0];
|
||||
element->children.push_back(element->on_expression);
|
||||
break;
|
||||
case JoinConstraintClause::ConstraintType::USING:
|
||||
element->using_expression_list = constraint->convertToOld();
|
||||
element->children.push_back(element->using_expression_list);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
list->children.back()->children.emplace_back(element);
|
||||
list->children.back()->as<ASTTablesInSelectQueryElement>()->table_join = element;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace AST;
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitJoinConstraintClause(ClickHouseParser::JoinConstraintClauseContext *ctx)
|
||||
{
|
||||
return std::make_shared<JoinConstraintClause>(
|
||||
ctx->ON() ? JoinConstraintClause::ConstraintType::ON : JoinConstraintClause::ConstraintType::USING,
|
||||
visit(ctx->columnExprList()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitJoinExprCrossOp(ClickHouseParser::JoinExprCrossOpContext *ctx)
|
||||
{
|
||||
auto [op, mode] = std::pair<JoinExpr::JoinOpType, JoinExpr::JoinOpMode>(visit(ctx->joinOpCross()));
|
||||
|
||||
return JoinExpr::createJoinOp(visit(ctx->joinExpr(0)), visit(ctx->joinExpr(1)), op, mode, nullptr);
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitJoinExprOp(ClickHouseParser::JoinExprOpContext *ctx)
|
||||
{
|
||||
auto mode = JoinExpr::JoinOpMode::DEFAULT;
|
||||
auto op = ctx->joinOp() ? visit(ctx->joinOp()).as<JoinExpr::JoinOpType>() : JoinExpr::JoinOpType::INNER;
|
||||
|
||||
if (ctx->GLOBAL()) mode = JoinExpr::JoinOpMode::GLOBAL;
|
||||
else if (ctx->LOCAL()) mode = JoinExpr::JoinOpMode::LOCAL;
|
||||
|
||||
return JoinExpr::createJoinOp(visit(ctx->joinExpr(0)), visit(ctx->joinExpr(1)), op, mode, visit(ctx->joinConstraintClause()));
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitJoinExprParens(ClickHouseParser::JoinExprParensContext *ctx)
|
||||
{
|
||||
return visit(ctx->joinExpr());
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitJoinExprTable(ClickHouseParser::JoinExprTableContext *ctx)
|
||||
{
|
||||
auto sample = ctx->sampleClause() ? visit(ctx->sampleClause()).as<PtrTo<SampleClause>>() : nullptr;
|
||||
return JoinExpr::createTableExpr(visit(ctx->tableExpr()), sample, !!ctx->FINAL());
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitJoinOpCross(ClickHouseParser::JoinOpCrossContext *ctx)
|
||||
{
|
||||
std::pair<JoinExpr::JoinOpType, JoinExpr::JoinOpMode> op{
|
||||
JoinExpr::JoinOpType::CROSS, JoinExpr::JoinOpMode::DEFAULT};
|
||||
|
||||
if (ctx->GLOBAL()) op.second = JoinExpr::JoinOpMode::GLOBAL;
|
||||
else if (ctx->LOCAL()) op.second = JoinExpr::JoinOpMode::LOCAL;
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitJoinOpFull(ClickHouseParser::JoinOpFullContext *ctx)
|
||||
{
|
||||
if (ctx->ALL()) return JoinExpr::JoinOpType::FULL_ALL;
|
||||
if (ctx->ANY()) return JoinExpr::JoinOpType::FULL_ANY;
|
||||
return JoinExpr::JoinOpType::FULL;
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitJoinOpInner(ClickHouseParser::JoinOpInnerContext *ctx)
|
||||
{
|
||||
if (ctx->ALL()) return JoinExpr::JoinOpType::INNER_ALL;
|
||||
if (ctx->ANY()) return JoinExpr::JoinOpType::INNER_ANY;
|
||||
if (ctx->ASOF()) return JoinExpr::JoinOpType::INNER_ASOF;
|
||||
return JoinExpr::JoinOpType::INNER;
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitJoinOpLeftRight(ClickHouseParser::JoinOpLeftRightContext *ctx)
|
||||
{
|
||||
if (ctx->LEFT())
|
||||
{
|
||||
if (ctx->SEMI()) return JoinExpr::JoinOpType::LEFT_SEMI;
|
||||
if (ctx->ALL()) return JoinExpr::JoinOpType::LEFT_ALL;
|
||||
if (ctx->ANTI()) return JoinExpr::JoinOpType::LEFT_ANTI;
|
||||
if (ctx->ANY()) return JoinExpr::JoinOpType::LEFT_ANY;
|
||||
if (ctx->ASOF()) return JoinExpr::JoinOpType::LEFT_ASOF;
|
||||
return JoinExpr::JoinOpType::LEFT;
|
||||
}
|
||||
else if (ctx->RIGHT())
|
||||
{
|
||||
if (ctx->SEMI()) return JoinExpr::JoinOpType::RIGHT_SEMI;
|
||||
if (ctx->ALL()) return JoinExpr::JoinOpType::RIGHT_ALL;
|
||||
if (ctx->ANTI()) return JoinExpr::JoinOpType::RIGHT_ANTI;
|
||||
if (ctx->ANY()) return JoinExpr::JoinOpType::RIGHT_ANY;
|
||||
if (ctx->ASOF()) return JoinExpr::JoinOpType::RIGHT_ASOF;
|
||||
return JoinExpr::JoinOpType::RIGHT;
|
||||
}
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitSampleClause(ClickHouseParser::SampleClauseContext *ctx)
|
||||
{
|
||||
auto offset = ctx->ratioExpr().size() == 2 ? visit(ctx->ratioExpr(1)).as<PtrTo<RatioExpr>>() : nullptr;
|
||||
return std::make_shared<SampleClause>(visit(ctx->ratioExpr(0)), offset);
|
||||
}
|
||||
|
||||
}
|
103
src/Parsers/New/AST/JoinExpr.h
Normal file
103
src/Parsers/New/AST/JoinExpr.h
Normal file
@ -0,0 +1,103 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/INode.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
class JoinConstraintClause : public SimpleClause<ColumnExprList>
|
||||
{
|
||||
public:
|
||||
enum class ConstraintType
|
||||
{
|
||||
ON,
|
||||
USING,
|
||||
};
|
||||
|
||||
JoinConstraintClause(ConstraintType type, PtrTo<ColumnExprList> list);
|
||||
|
||||
auto getType() const { return type; }
|
||||
|
||||
private:
|
||||
const ConstraintType type;
|
||||
};
|
||||
|
||||
class SampleClause : public INode
|
||||
{
|
||||
public:
|
||||
SampleClause(PtrTo<RatioExpr> ratio_, PtrTo<RatioExpr> offset_);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
RATIO = 0, // RatioExpr
|
||||
OFFSET = 1, // RatioExpr (optional)
|
||||
};
|
||||
};
|
||||
|
||||
class JoinExpr : public INode
|
||||
{
|
||||
public:
|
||||
enum class JoinOpType
|
||||
{
|
||||
INNER,
|
||||
INNER_ALL,
|
||||
INNER_ANY,
|
||||
INNER_ASOF,
|
||||
LEFT,
|
||||
LEFT_SEMI,
|
||||
LEFT_ALL,
|
||||
LEFT_ANTI,
|
||||
LEFT_ANY,
|
||||
LEFT_ASOF,
|
||||
RIGHT,
|
||||
RIGHT_SEMI,
|
||||
RIGHT_ALL,
|
||||
RIGHT_ANTI,
|
||||
RIGHT_ANY,
|
||||
RIGHT_ASOF,
|
||||
FULL,
|
||||
FULL_ALL,
|
||||
FULL_ANY,
|
||||
CROSS,
|
||||
};
|
||||
enum class JoinOpMode
|
||||
{
|
||||
DEFAULT, // actual mode depends on setting's 'distributed_product_mode' value
|
||||
GLOBAL,
|
||||
LOCAL,
|
||||
};
|
||||
|
||||
static PtrTo<JoinExpr> createTableExpr(PtrTo<TableExpr> expr, PtrTo<SampleClause> clause, bool final);
|
||||
static PtrTo<JoinExpr> createJoinOp(PtrTo<JoinExpr> left_expr, PtrTo<JoinExpr> right_expr, JoinOpType op, JoinOpMode mode, PtrTo<JoinConstraintClause> clause);
|
||||
|
||||
ASTPtr convertToOld() const override; // returns topologically sorted elements as ASTExpressionList
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
TABLE = 0, // TableExpr
|
||||
SAMPLE = 1, // SampleClause (optional)
|
||||
LEFT_EXPR = 0, // JoinExpr
|
||||
RIGHT_EXPR = 1, // JoinExpr
|
||||
CONSTRAINT = 2, // JoinConstraintClause
|
||||
};
|
||||
enum class ExprType
|
||||
{
|
||||
TABLE,
|
||||
JOIN_OP,
|
||||
};
|
||||
|
||||
const ExprType expr_type;
|
||||
const JoinOpType op_type = JoinOpType::INNER;
|
||||
const JoinOpMode op_mode = JoinOpMode::DEFAULT;
|
||||
const bool final = false;
|
||||
|
||||
JoinExpr(ExprType type, bool final, PtrList exprs);
|
||||
JoinExpr(ExprType type, JoinOpType op, JoinOpMode mode, PtrList exprs);
|
||||
};
|
||||
|
||||
}
|
56
src/Parsers/New/AST/KillQuery.cpp
Normal file
56
src/Parsers/New/AST/KillQuery.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
#include <Parsers/New/AST/KillQuery.h>
|
||||
|
||||
#include <Parsers/ASTKillQueryQuery.h>
|
||||
#include <Parsers/New/ParseTreeVisitor.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
// static
|
||||
PtrTo<KillQuery> KillQuery::createMutation(PtrTo<ClusterClause> cluster, bool sync, bool test, PtrTo<WhereClause> where)
|
||||
{
|
||||
PtrTo<KillQuery> query(new KillQuery(cluster, QueryType::MUTATION, {where}));
|
||||
query->sync = sync;
|
||||
query->test = test;
|
||||
return query;
|
||||
}
|
||||
|
||||
KillQuery::KillQuery(PtrTo<ClusterClause> cluster, QueryType type, PtrList exprs) : DDLQuery(cluster, exprs), query_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr KillQuery::convertToOld() const
|
||||
{
|
||||
auto query = std::make_shared<ASTKillQueryQuery>();
|
||||
|
||||
query->cluster = cluster_name;
|
||||
|
||||
switch(query_type)
|
||||
{
|
||||
case QueryType::MUTATION:
|
||||
query->type = ASTKillQueryQuery::Type::Mutation;
|
||||
query->sync = sync;
|
||||
query->test = test;
|
||||
query->where_expression = get(WHERE)->convertToOld();
|
||||
query->children.push_back(query->where_expression);
|
||||
break;
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace AST;
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitKillMutationStmt(ClickHouseParser::KillMutationStmtContext * ctx)
|
||||
{
|
||||
auto cluster = ctx->clusterClause() ? visit(ctx->clusterClause()).as<PtrTo<ClusterClause>>() : nullptr;
|
||||
return KillQuery::createMutation(cluster, !!ctx->SYNC(), !!ctx->TEST(), visit(ctx->whereClause()));
|
||||
}
|
||||
|
||||
}
|
33
src/Parsers/New/AST/KillQuery.h
Normal file
33
src/Parsers/New/AST/KillQuery.h
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/DDLQuery.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
class KillQuery : public DDLQuery
|
||||
{
|
||||
public:
|
||||
static PtrTo<KillQuery> createMutation(PtrTo<ClusterClause> cluster, bool sync, bool test, PtrTo<WhereClause> where);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
WHERE = 0, // WhereClause
|
||||
};
|
||||
|
||||
enum class QueryType
|
||||
{
|
||||
MUTATION,
|
||||
};
|
||||
|
||||
const QueryType query_type;
|
||||
bool sync = false, test = false;
|
||||
|
||||
KillQuery(PtrTo<ClusterClause> cluster, QueryType type, PtrList exprs);
|
||||
};
|
||||
|
||||
}
|
39
src/Parsers/New/AST/LimitExpr.cpp
Normal file
39
src/Parsers/New/AST/LimitExpr.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
#include <Parsers/New/AST/LimitExpr.h>
|
||||
|
||||
#include <Parsers/New/AST/ColumnExpr.h>
|
||||
#include <Parsers/New/ParseTreeVisitor.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
LimitExpr::LimitExpr(PtrTo<ColumnExpr> limit, PtrTo<ColumnExpr> offset) : INode{limit, offset}
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr LimitExpr::convertToOld() const
|
||||
{
|
||||
auto list = std::make_shared<ASTExpressionList>();
|
||||
|
||||
if (has(OFFSET)) list->children.push_back(get(OFFSET)->convertToOld());
|
||||
list->children.push_back(get(LIMIT)->convertToOld());
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace AST;
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitLimitExpr(ClickHouseParser::LimitExprContext *ctx)
|
||||
{
|
||||
if (ctx->columnExpr().size() == 2)
|
||||
return std::make_shared<LimitExpr>(visit(ctx->columnExpr(0)), visit(ctx->columnExpr(1)));
|
||||
else
|
||||
return std::make_shared<LimitExpr>(visit(ctx->columnExpr(0)).as<PtrTo<ColumnExpr>>());
|
||||
}
|
||||
|
||||
}
|
24
src/Parsers/New/AST/LimitExpr.h
Normal file
24
src/Parsers/New/AST/LimitExpr.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/INode.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
class LimitExpr : public INode
|
||||
{
|
||||
public:
|
||||
explicit LimitExpr(PtrTo<ColumnExpr> limit, PtrTo<ColumnExpr> offset = nullptr);
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
|
||||
private:
|
||||
enum ChildIndex : UInt8
|
||||
{
|
||||
LIMIT = 0, // ColumnExpr
|
||||
OFFSET = 1, // ColumnExpr (optional)
|
||||
};
|
||||
};
|
||||
|
||||
}
|
222
src/Parsers/New/AST/Literal.cpp
Normal file
222
src/Parsers/New/AST/Literal.cpp
Normal file
@ -0,0 +1,222 @@
|
||||
#include <Parsers/New/AST/Literal.h>
|
||||
|
||||
#include <IO/ReadHelpers.h>
|
||||
#include <IO/WriteBufferFromString.h>
|
||||
#include <IO/WriteHelpers.h>
|
||||
#include <Parsers/ASTLiteral.h>
|
||||
#include <Parsers/New/ParseTreeVisitor.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
// static
|
||||
PtrTo<Literal> Literal::createNull()
|
||||
{
|
||||
return PtrTo<Literal>(new Literal(LiteralType::NULL_LITERAL, String()));
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<NumberLiteral> Literal::createNumber(antlr4::tree::TerminalNode * literal, bool negative)
|
||||
{
|
||||
auto number = std::make_shared<NumberLiteral>(literal);
|
||||
if (negative) number->makeNegative();
|
||||
return number;
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<NumberLiteral> Literal::createNumber(const String & literal)
|
||||
{
|
||||
bool has_minus = literal[0] == '-';
|
||||
auto number = std::make_shared<NumberLiteral>(has_minus ? literal.substr(1) : literal);
|
||||
if (has_minus) number->makeNegative();
|
||||
return number;
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<StringLiteral> Literal::createString(antlr4::tree::TerminalNode * literal)
|
||||
{
|
||||
return std::make_shared<StringLiteral>(literal);
|
||||
}
|
||||
|
||||
// static
|
||||
PtrTo<StringLiteral> Literal::createString(const String & literal)
|
||||
{
|
||||
return std::make_shared<StringLiteral>(literal);
|
||||
}
|
||||
|
||||
Literal::Literal(LiteralType type_, const String & token_) : token(token_), type(type_)
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr Literal::convertToOld() const
|
||||
{
|
||||
auto as_field = [this] () -> Field
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case LiteralType::NULL_LITERAL:
|
||||
return Field(Null());
|
||||
case LiteralType::NUMBER:
|
||||
{
|
||||
const auto * number = this->as<NumberLiteral>();
|
||||
|
||||
if (!number->isNegative())
|
||||
if (auto value = number->as<UInt64>()) return Field(*value);
|
||||
if (auto value = number->as<Int64>()) return Field(*value);
|
||||
if (auto value = number->as<Float64>()) return Field(*value);
|
||||
|
||||
return Field();
|
||||
}
|
||||
case LiteralType::STRING:
|
||||
return asString();
|
||||
}
|
||||
__builtin_unreachable();
|
||||
};
|
||||
|
||||
return std::make_shared<ASTLiteral>(as_field());
|
||||
}
|
||||
|
||||
String Literal::toString() const
|
||||
{
|
||||
WriteBufferFromOwnString wb;
|
||||
writeEscapedString(token, wb);
|
||||
return type == LiteralType::STRING ? "'" + wb.str() + "'" : wb.str();
|
||||
}
|
||||
|
||||
NumberLiteral::NumberLiteral(antlr4::tree::TerminalNode * literal) : Literal(LiteralType::NUMBER, literal->getSymbol()->getText())
|
||||
{
|
||||
}
|
||||
|
||||
NumberLiteral::NumberLiteral(const String & literal) : Literal(LiteralType::NUMBER, literal)
|
||||
{
|
||||
}
|
||||
|
||||
String NumberLiteral::toString() const
|
||||
{
|
||||
return (minus ? String("-") : String()) + Literal::toString();
|
||||
}
|
||||
|
||||
ASTSampleRatio::Rational NumberLiteral::convertToOldRational() const
|
||||
{
|
||||
UInt64 num_before = 0;
|
||||
UInt64 num_after = 0;
|
||||
Int64 exponent = 0;
|
||||
|
||||
const char * pos = token.data(), * end = token.data() + token.size();
|
||||
const char * pos_after_first_num = tryReadIntText(num_before, pos, end);
|
||||
|
||||
bool has_num_before_point [[maybe_unused]] = pos_after_first_num > pos;
|
||||
pos = pos_after_first_num;
|
||||
bool has_point = pos < end && *pos == '.';
|
||||
|
||||
if (has_point)
|
||||
++pos;
|
||||
|
||||
assert (has_num_before_point || has_point);
|
||||
|
||||
size_t number_of_digits_after_point = 0;
|
||||
|
||||
if (has_point)
|
||||
{
|
||||
const char * pos_after_second_num = tryReadIntText(num_after, pos, end);
|
||||
number_of_digits_after_point = pos_after_second_num - pos;
|
||||
pos = pos_after_second_num;
|
||||
}
|
||||
|
||||
bool has_exponent = pos < end && (*pos == 'e' || *pos == 'E');
|
||||
|
||||
if (has_exponent)
|
||||
{
|
||||
++pos;
|
||||
const char * pos_after_exponent [[maybe_unused]] = tryReadIntText(exponent, pos, end);
|
||||
assert (pos_after_exponent != pos);
|
||||
}
|
||||
|
||||
ASTSampleRatio::Rational res;
|
||||
res.numerator = num_before * intExp10(number_of_digits_after_point) + num_after;
|
||||
res.denominator = intExp10(number_of_digits_after_point);
|
||||
|
||||
if (exponent > 0)
|
||||
res.numerator *= intExp10(exponent);
|
||||
if (exponent < 0)
|
||||
res.denominator *= intExp10(-exponent);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
StringLiteral::StringLiteral(antlr4::tree::TerminalNode * literal) : Literal(LiteralType::STRING, literal->getSymbol()->getText())
|
||||
{
|
||||
String s;
|
||||
ReadBufferFromMemory in(token.data(), token.size());
|
||||
|
||||
readQuotedStringWithSQLStyle(s, in);
|
||||
|
||||
assert(in.count() == token.size());
|
||||
token = s;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace AST;
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitFloatingLiteral(ClickHouseParser::FloatingLiteralContext * ctx)
|
||||
{
|
||||
if (ctx->FLOATING_LITERAL()) return Literal::createNumber(ctx->FLOATING_LITERAL());
|
||||
|
||||
const auto * dot = ctx->DOT()->getSymbol();
|
||||
|
||||
if (!ctx->DECIMAL_LITERAL().empty())
|
||||
{
|
||||
// .1234
|
||||
if (dot->getTokenIndex() < ctx->DECIMAL_LITERAL(0)->getSymbol()->getTokenIndex())
|
||||
return Literal::createNumber(dot->getText() + ctx->DECIMAL_LITERAL(0)->getSymbol()->getText());
|
||||
// 1234.
|
||||
else if (ctx->DECIMAL_LITERAL().size() == 1 && !ctx->OCTAL_LITERAL())
|
||||
return Literal::createNumber(ctx->DECIMAL_LITERAL(0)->getSymbol()->getText() + dot->getText());
|
||||
// 1234.1234
|
||||
else if (ctx->DECIMAL_LITERAL().size() == 2)
|
||||
return Literal::createNumber(
|
||||
ctx->DECIMAL_LITERAL(0)->getSymbol()->getText() + dot->getText() + ctx->DECIMAL_LITERAL(1)->getSymbol()->getText());
|
||||
// 1234.0123
|
||||
else
|
||||
return Literal::createNumber(
|
||||
ctx->DECIMAL_LITERAL(0)->getSymbol()->getText() + dot->getText() + ctx->OCTAL_LITERAL()->getSymbol()->getText());
|
||||
}
|
||||
else
|
||||
// .0123
|
||||
return Literal::createNumber(dot->getText() + ctx->OCTAL_LITERAL()->getSymbol()->getText());
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitLiteral(ClickHouseParser::LiteralContext * ctx)
|
||||
{
|
||||
if (ctx->NULL_SQL())
|
||||
return Literal::createNull();
|
||||
if (ctx->STRING_LITERAL())
|
||||
return std::static_pointer_cast<Literal>(Literal::createString(ctx->STRING_LITERAL()));
|
||||
if (ctx->numberLiteral())
|
||||
return std::static_pointer_cast<Literal>(visit(ctx->numberLiteral()).as<PtrTo<NumberLiteral>>());
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitNumberLiteral(ClickHouseParser::NumberLiteralContext *ctx)
|
||||
{
|
||||
if (ctx->floatingLiteral())
|
||||
{
|
||||
auto number = visit(ctx->floatingLiteral()).as<PtrTo<NumberLiteral>>();
|
||||
if (ctx->DASH()) number->makeNegative();
|
||||
return number;
|
||||
}
|
||||
if (ctx->OCTAL_LITERAL()) return Literal::createNumber(ctx->OCTAL_LITERAL(), !!ctx->DASH());
|
||||
if (ctx->DECIMAL_LITERAL()) return Literal::createNumber(ctx->DECIMAL_LITERAL(), !!ctx->DASH());
|
||||
if (ctx->HEXADECIMAL_LITERAL()) return Literal::createNumber(ctx->HEXADECIMAL_LITERAL(), !!ctx->DASH());
|
||||
if (ctx->INF()) return Literal::createNumber(ctx->INF(), !!ctx->DASH());
|
||||
if (ctx->NAN_SQL()) return Literal::createNumber(ctx->NAN_SQL());
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
}
|
96
src/Parsers/New/AST/Literal.h
Normal file
96
src/Parsers/New/AST/Literal.h
Normal file
@ -0,0 +1,96 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/New/AST/INode.h>
|
||||
|
||||
#include <Core/Field.h>
|
||||
#include <Parsers/ASTSampleRatio.h>
|
||||
|
||||
#include <Token.h>
|
||||
#include <tree/TerminalNode.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
class Literal : public INode
|
||||
{
|
||||
public:
|
||||
enum class LiteralType
|
||||
{
|
||||
NULL_LITERAL,
|
||||
NUMBER,
|
||||
STRING,
|
||||
};
|
||||
|
||||
static PtrTo<Literal> createNull();
|
||||
static PtrTo<NumberLiteral> createNumber(antlr4::tree::TerminalNode * literal, bool negative = false);
|
||||
static PtrTo<NumberLiteral> createNumber(const String& literal); // checks first symbol for '-' character
|
||||
static PtrTo<StringLiteral> createString(antlr4::tree::TerminalNode * literal);
|
||||
static PtrTo<StringLiteral> createString(const String& literal); // without quotes
|
||||
|
||||
ASTPtr convertToOld() const override;
|
||||
String toString() const override;
|
||||
|
||||
bool is(LiteralType what) const { return type == what; }
|
||||
|
||||
protected:
|
||||
String token; // STRING is stored without quotes and interpolated with escape-sequences.
|
||||
|
||||
Literal(LiteralType type, const String & token);
|
||||
|
||||
template <typename T>
|
||||
std::optional<T> asNumber(bool minus) const
|
||||
{
|
||||
T number;
|
||||
std::stringstream ss(String(minus ? "-" : "+") + token);
|
||||
if (token.size() > 2 && (token[1] == 'x' || token[1] == 'X')) ss >> std::hex >> number;
|
||||
else if (token.size() > 1 && (token[0] == '0')) ss >> std::oct >> number;
|
||||
else ss >> number;
|
||||
if (ss.fail() || !ss.eof())
|
||||
return {};
|
||||
return number;
|
||||
}
|
||||
|
||||
auto asString() const { return token; }
|
||||
|
||||
private:
|
||||
LiteralType type;
|
||||
|
||||
String dumpInfo() const override { return token; }
|
||||
};
|
||||
|
||||
class NumberLiteral : public Literal
|
||||
{
|
||||
public:
|
||||
explicit NumberLiteral(antlr4::tree::TerminalNode * literal);
|
||||
explicit NumberLiteral(const String & literal);
|
||||
|
||||
String toString() const override;
|
||||
|
||||
void makeNegative() { minus = true; }
|
||||
bool isNegative() const { return minus; }
|
||||
|
||||
template <typename T> std::optional<T> as() const { return asNumber<T>(minus); }
|
||||
|
||||
ASTSampleRatio::Rational convertToOldRational() const;
|
||||
|
||||
private:
|
||||
bool minus = false;
|
||||
};
|
||||
|
||||
class StringLiteral : public Literal
|
||||
{
|
||||
public:
|
||||
explicit StringLiteral(antlr4::tree::TerminalNode * literal);
|
||||
explicit StringLiteral(const String & literal) : Literal(LiteralType::STRING, literal) {}
|
||||
|
||||
template <typename T>
|
||||
T as() const
|
||||
{
|
||||
return asString();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
59
src/Parsers/New/AST/OptimizeQuery.cpp
Normal file
59
src/Parsers/New/AST/OptimizeQuery.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
#include <Parsers/New/AST/OptimizeQuery.h>
|
||||
|
||||
#include <Interpreters/StorageID.h>
|
||||
#include <Parsers/ASTIdentifier.h>
|
||||
#include <Parsers/ASTOptimizeQuery.h>
|
||||
#include <Parsers/New/AST/AlterTableQuery.h>
|
||||
#include <Parsers/New/AST/ColumnExpr.h>
|
||||
#include <Parsers/New/AST/Identifier.h>
|
||||
#include <Parsers/New/AST/Literal.h>
|
||||
#include <Parsers/New/ParseTreeVisitor.h>
|
||||
|
||||
|
||||
namespace DB::AST
|
||||
{
|
||||
|
||||
OptimizeQuery::OptimizeQuery(PtrTo<ClusterClause> cluster, PtrTo<TableIdentifier> identifier, PtrTo<PartitionClause> clause, bool final_, bool deduplicate_)
|
||||
: DDLQuery(cluster, {identifier, clause}), final(final_), deduplicate(deduplicate_)
|
||||
{
|
||||
}
|
||||
|
||||
ASTPtr OptimizeQuery::convertToOld() const
|
||||
{
|
||||
auto query = std::make_shared<ASTOptimizeQuery>();
|
||||
|
||||
{
|
||||
auto table_id = getTableIdentifier(get(TABLE)->convertToOld());
|
||||
query->database = table_id.database_name;
|
||||
query->table = table_id.table_name;
|
||||
query->uuid = table_id.uuid;
|
||||
}
|
||||
|
||||
if (has(PARTITION))
|
||||
{
|
||||
query->partition = get(PARTITION)->convertToOld();
|
||||
query->children.push_back(query->partition);
|
||||
}
|
||||
|
||||
query->final = final;
|
||||
query->deduplicate = deduplicate;
|
||||
query->cluster = cluster_name;
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using namespace AST;
|
||||
|
||||
antlrcpp::Any ParseTreeVisitor::visitOptimizeStmt(ClickHouseParser::OptimizeStmtContext *ctx)
|
||||
{
|
||||
auto cluster = ctx->clusterClause() ? visit(ctx->clusterClause()).as<PtrTo<ClusterClause>>() : nullptr;
|
||||
auto clause = ctx->partitionClause() ? visit(ctx->partitionClause()).as<PtrTo<PartitionClause>>() : nullptr;
|
||||
return std::make_shared<OptimizeQuery>(cluster, visit(ctx->tableIdentifier()), clause, !!ctx->FINAL(), !!ctx->DEDUPLICATE());
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user