mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-28 20:50:49 +00:00
ISSUES-4006 support parse MySQL create query
This commit is contained in:
parent
5f80db7569
commit
c53a48fe01
@ -144,6 +144,7 @@ add_object_library(clickhouse_compression Compression)
|
|||||||
add_object_library(clickhouse_datastreams DataStreams)
|
add_object_library(clickhouse_datastreams DataStreams)
|
||||||
add_object_library(clickhouse_datatypes DataTypes)
|
add_object_library(clickhouse_datatypes DataTypes)
|
||||||
add_object_library(clickhouse_databases Databases)
|
add_object_library(clickhouse_databases Databases)
|
||||||
|
add_object_library(clickhouse_databases_mysql Databases/MySQL)
|
||||||
add_object_library(clickhouse_disks Disks)
|
add_object_library(clickhouse_disks Disks)
|
||||||
add_object_library(clickhouse_interpreters Interpreters)
|
add_object_library(clickhouse_interpreters Interpreters)
|
||||||
add_object_library(clickhouse_interpreters_clusterproxy Interpreters/ClusterProxy)
|
add_object_library(clickhouse_interpreters_clusterproxy Interpreters/ClusterProxy)
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
|
#include <Databases/DatabaseFactory.h>
|
||||||
|
|
||||||
#include <Databases/DatabaseAtomic.h>
|
#include <Databases/DatabaseAtomic.h>
|
||||||
#include <Databases/DatabaseDictionary.h>
|
#include <Databases/DatabaseDictionary.h>
|
||||||
#include <Databases/DatabaseFactory.h>
|
|
||||||
#include <Databases/DatabaseLazy.h>
|
#include <Databases/DatabaseLazy.h>
|
||||||
#include <Databases/DatabaseMemory.h>
|
#include <Databases/DatabaseMemory.h>
|
||||||
#include <Databases/DatabaseOrdinary.h>
|
#include <Databases/DatabaseOrdinary.h>
|
||||||
|
#include <Databases/MySQL/createMySQLDatabase.h>
|
||||||
#include <Parsers/ASTLiteral.h>
|
#include <Parsers/ASTLiteral.h>
|
||||||
#include <Parsers/ASTIdentifier.h>
|
#include <Parsers/ASTIdentifier.h>
|
||||||
#include <Parsers/formatAST.h>
|
#include <Parsers/formatAST.h>
|
||||||
#include <Parsers/ASTCreateQuery.h>
|
#include <Parsers/ASTCreateQuery.h>
|
||||||
#include <Parsers/ASTFunction.h>
|
#include <Parsers/ASTFunction.h>
|
||||||
#include <Common/parseAddress.h>
|
#include <Common/parseAddress.h>
|
||||||
#include "DatabaseFactory.h"
|
|
||||||
#include <Poco/File.h>
|
#include <Poco/File.h>
|
||||||
#include <Poco/Path.h>
|
#include <Poco/Path.h>
|
||||||
|
|
||||||
@ -18,12 +19,6 @@
|
|||||||
# include "config_core.h"
|
# include "config_core.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if USE_MYSQL
|
|
||||||
# include <Databases/DatabaseMySQL.h>
|
|
||||||
# include <Interpreters/evaluateConstantExpression.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
namespace DB
|
namespace DB
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -94,42 +89,8 @@ DatabasePtr DatabaseFactory::getImpl(const ASTCreateQuery & create, const String
|
|||||||
return std::make_shared<DatabaseDictionary>(database_name, context);
|
return std::make_shared<DatabaseDictionary>(database_name, context);
|
||||||
|
|
||||||
#if USE_MYSQL
|
#if USE_MYSQL
|
||||||
|
|
||||||
else if (engine_name == "MySQL")
|
else if (engine_name == "MySQL")
|
||||||
{
|
return createMySQLDatabase(database_name, metadata_path, engine_define, context);
|
||||||
const ASTFunction * engine = engine_define->engine;
|
|
||||||
|
|
||||||
if (!engine->arguments || engine->arguments->children.size() != 4)
|
|
||||||
throw Exception("MySQL Database require mysql_hostname, mysql_database_name, mysql_username, mysql_password arguments.",
|
|
||||||
ErrorCodes::BAD_ARGUMENTS);
|
|
||||||
|
|
||||||
|
|
||||||
ASTs & arguments = engine->arguments->children;
|
|
||||||
arguments[1] = evaluateConstantExpressionOrIdentifierAsLiteral(arguments[1], context);
|
|
||||||
|
|
||||||
const auto & host_name_and_port = safeGetLiteralValue<String>(arguments[0], "MySQL");
|
|
||||||
const auto & database_name_in_mysql = safeGetLiteralValue<String>(arguments[1], "MySQL");
|
|
||||||
const auto & mysql_user_name = safeGetLiteralValue<String>(arguments[2], "MySQL");
|
|
||||||
const auto & mysql_user_password = safeGetLiteralValue<String>(arguments[3], "MySQL");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
const auto & [remote_host_name, remote_port] = parseAddress(host_name_and_port, 3306);
|
|
||||||
auto mysql_pool = mysqlxx::Pool(database_name_in_mysql, remote_host_name, mysql_user_name, mysql_user_password, remote_port);
|
|
||||||
|
|
||||||
auto mysql_database = std::make_shared<DatabaseMySQL>(
|
|
||||||
context, database_name, metadata_path, engine_define, database_name_in_mysql, std::move(mysql_pool));
|
|
||||||
|
|
||||||
mysql_database->empty(); /// test database is works fine.
|
|
||||||
return mysql_database;
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
const auto & exception_message = getCurrentExceptionMessage(true);
|
|
||||||
throw Exception("Cannot create MySQL database, because " + exception_message, ErrorCodes::CANNOT_CREATE_DATABASE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
else if (engine_name == "Lazy")
|
else if (engine_name == "Lazy")
|
||||||
|
97
src/Databases/MySQL/DatabaseMaterializeMySQL.cpp
Normal file
97
src/Databases/MySQL/DatabaseMaterializeMySQL.cpp
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
//#include <Databases/MySQL/DatabaseMaterializeMySQL.h>
|
||||||
|
//
|
||||||
|
//#include <Common/quoteString.h>
|
||||||
|
//#include <Interpreters/Context.h>
|
||||||
|
//#include <DataTypes/DataTypeString.h>
|
||||||
|
//#include <DataTypes/DataTypesNumber.h>
|
||||||
|
//#include <Formats/MySQLBlockInputStream.h>
|
||||||
|
//#include <Databases/MySQL/MasterStatusInfo.h>
|
||||||
|
//#include <IO/Operators.h>
|
||||||
|
//
|
||||||
|
//namespace DB
|
||||||
|
//{
|
||||||
|
//
|
||||||
|
//static MasterStatusInfo fetchMasterStatus(const mysqlxx::PoolWithFailover::Entry & connection)
|
||||||
|
//{
|
||||||
|
// Block header
|
||||||
|
// {
|
||||||
|
// {std::make_shared<DataTypeString>(), "File"},
|
||||||
|
// {std::make_shared<DataTypeUInt64>(), "Position"},
|
||||||
|
// {std::make_shared<DataTypeString>(), "Binlog_Do_DB"},
|
||||||
|
// {std::make_shared<DataTypeString>(), "Binlog_Ignore_DB"},
|
||||||
|
// {std::make_shared<DataTypeString>(), "Executed_Gtid_Set"},
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// MySQLBlockInputStream input(connection, "SHOW MASTER STATUS;", header, DEFAULT_BLOCK_SIZE);
|
||||||
|
// Block master_status = input.read();
|
||||||
|
//
|
||||||
|
// if (!master_status || master_status.rows() != 1)
|
||||||
|
// throw Exception("Unable to get master status from MySQL.", ErrorCodes::LOGICAL_ERROR);
|
||||||
|
//
|
||||||
|
// return MasterStatusInfo
|
||||||
|
// {
|
||||||
|
// (*master_status.getByPosition(0).column)[0].safeGet<String>(),
|
||||||
|
// (*master_status.getByPosition(1).column)[0].safeGet<UInt64>(),
|
||||||
|
// (*master_status.getByPosition(2).column)[0].safeGet<String>(),
|
||||||
|
// (*master_status.getByPosition(3).column)[0].safeGet<String>(),
|
||||||
|
// (*master_status.getByPosition(4).column)[0].safeGet<String>()
|
||||||
|
// };
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//static std::vector<String> fetchTablesInDB(const mysqlxx::PoolWithFailover::Entry & connection, const std::string & database)
|
||||||
|
//{
|
||||||
|
// Block header{{std::make_shared<DataTypeString>(), "table_name"}};
|
||||||
|
// String query = "SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = " + quoteString(database);
|
||||||
|
//
|
||||||
|
// std::vector<String> tables_in_db;
|
||||||
|
// MySQLBlockInputStream input(connection, query, header, DEFAULT_BLOCK_SIZE);
|
||||||
|
//
|
||||||
|
// while (Block block = input.read())
|
||||||
|
// {
|
||||||
|
// tables_in_db.reserve(tables_in_db.size() + block.rows());
|
||||||
|
// for (size_t index = 0; index < block.rows(); ++index)
|
||||||
|
// tables_in_db.emplace_back((*block.getByPosition(0).column)[index].safeGet<String>());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return tables_in_db;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//DatabaseMaterializeMySQL::DatabaseMaterializeMySQL(
|
||||||
|
// const Context & context, const String & database_name_, const String & metadata_path_,
|
||||||
|
// const ASTStorage * database_engine_define_, const String & mysql_database_name_, mysqlxx::Pool && pool_)
|
||||||
|
// : IDatabase(database_name_)
|
||||||
|
// , global_context(context.getGlobalContext()), metadata_path(metadata_path_)
|
||||||
|
// , database_engine_define(database_engine_define_->clone()), mysql_database_name(mysql_database_name_), pool(std::move(pool_))
|
||||||
|
//{
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// mysqlxx::PoolWithFailover::Entry connection = pool.get();
|
||||||
|
//
|
||||||
|
// connection->query("FLUSH TABLES;").execute();
|
||||||
|
// connection->query("FLUSH TABLES WITH READ LOCK;").execute();
|
||||||
|
//
|
||||||
|
// MasterStatusInfo master_status = fetchMasterStatus(connection);
|
||||||
|
// connection->query("SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;").execute();
|
||||||
|
// connection->query("START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */;").execute();
|
||||||
|
//
|
||||||
|
// std::vector<String> tables_in_db = fetchTablesInDB(connection, mysql_database_name);
|
||||||
|
// connection->query("UNLOCK TABLES;");
|
||||||
|
//
|
||||||
|
// for (const auto & dumping_table_name : tables_in_db)
|
||||||
|
// {
|
||||||
|
// /// TODO: 查询表结构, 根据不同的模式创建对应的表(暂时只支持多version即可)
|
||||||
|
//// connection->query("SHOW CREATE TABLE " + doubleQuoteString())
|
||||||
|
// MySQLBlockInputStream input(
|
||||||
|
// "SELECT * FROM " + backQuoteIfNeed(mysql_database_name) + "." + backQuoteIfNeed(dumping_table_name));
|
||||||
|
// /// TODO: 查询所有数据写入对应表中(全量dump)
|
||||||
|
// /// TODO: 启动slave, 监听事件
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// catch (...)
|
||||||
|
// {
|
||||||
|
// throw;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//}
|
30
src/Databases/MySQL/DatabaseMaterializeMySQL.h
Normal file
30
src/Databases/MySQL/DatabaseMaterializeMySQL.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
//#pragma once
|
||||||
|
//
|
||||||
|
//#include <DataTypes/DataTypeString.h>
|
||||||
|
//#include <DataTypes/DataTypesNumber.h>
|
||||||
|
//#include <Databases/IDatabase.h>
|
||||||
|
//#include <Parsers/ASTCreateQuery.h>
|
||||||
|
//#include <mysqlxx/Pool.h>
|
||||||
|
//
|
||||||
|
//namespace DB
|
||||||
|
//{
|
||||||
|
//
|
||||||
|
//class DatabaseMaterializeMySQL : public IDatabase
|
||||||
|
//{
|
||||||
|
//public:
|
||||||
|
// DatabaseMaterializeMySQL(
|
||||||
|
// const Context & context, const String & database_name_, const String & metadata_path_,
|
||||||
|
// const ASTStorage * database_engine_define_, const String & mysql_database_name_, mysqlxx::Pool && pool_);
|
||||||
|
//
|
||||||
|
// String getEngineName() const override { return "MySQL"; }
|
||||||
|
//
|
||||||
|
//private:
|
||||||
|
// const Context & global_context;
|
||||||
|
// String metadata_path;
|
||||||
|
// ASTPtr database_engine_define;
|
||||||
|
// String mysql_database_name;
|
||||||
|
//
|
||||||
|
// mutable mysqlxx::Pool pool;
|
||||||
|
//};
|
||||||
|
//
|
||||||
|
//}
|
@ -9,7 +9,7 @@
|
|||||||
# include <DataTypes/DataTypeString.h>
|
# include <DataTypes/DataTypeString.h>
|
||||||
# include <DataTypes/DataTypesNumber.h>
|
# include <DataTypes/DataTypesNumber.h>
|
||||||
# include <DataTypes/convertMySQLDataType.h>
|
# include <DataTypes/convertMySQLDataType.h>
|
||||||
# include <Databases/DatabaseMySQL.h>
|
# include <Databases/MySQL/DatabaseMySQL.h>
|
||||||
# include <Formats/MySQLBlockInputStream.h>
|
# include <Formats/MySQLBlockInputStream.h>
|
||||||
# include <IO/Operators.h>
|
# include <IO/Operators.h>
|
||||||
# include <Parsers/ASTCreateQuery.h>
|
# include <Parsers/ASTCreateQuery.h>
|
||||||
@ -70,6 +70,7 @@ DatabaseMySQL::DatabaseMySQL(
|
|||||||
, database_name_in_mysql(database_name_in_mysql_)
|
, database_name_in_mysql(database_name_in_mysql_)
|
||||||
, mysql_pool(std::move(pool))
|
, mysql_pool(std::move(pool))
|
||||||
{
|
{
|
||||||
|
empty(); /// test database is works fine.
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DatabaseMySQL::empty() const
|
bool DatabaseMySQL::empty() const
|
6
src/Databases/MySQL/MasterStatusInfo.cpp
Normal file
6
src/Databases/MySQL/MasterStatusInfo.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include <Databases/MySQL/MasterStatusInfo.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
27
src/Databases/MySQL/MasterStatusInfo.h
Normal file
27
src/Databases/MySQL/MasterStatusInfo.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Core/Types.h>
|
||||||
|
#include <mysqlxx/Connection.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
struct MasterStatusInfo
|
||||||
|
{
|
||||||
|
String binlog_file;
|
||||||
|
UInt64 binlog_position;
|
||||||
|
String binlog_do_db;
|
||||||
|
String binlog_ignore_db;
|
||||||
|
String executed_gtid_set;
|
||||||
|
|
||||||
|
MasterStatusInfo(
|
||||||
|
String binlog_file_, UInt64 binlog_position_, String binlog_do_db_, String binlog_ignore_db_, String executed_gtid_set_);
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::shared_ptr<MasterStatusInfo> fetchMasterStatusInfo(mysqlxx::Connection * connection);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
84
src/Databases/MySQL/createMySQLDatabase.cpp
Normal file
84
src/Databases/MySQL/createMySQLDatabase.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#include <Databases/MySQL/createMySQLDatabase.h>
|
||||||
|
|
||||||
|
#if USE_MYSQL
|
||||||
|
|
||||||
|
#include <Core/Types.h>
|
||||||
|
#include <Common/parseAddress.h>
|
||||||
|
#include <Common/SettingsChanges.h>
|
||||||
|
#include <Databases/MySQL/DatabaseMySQL.h>
|
||||||
|
#include <Databases/MySQL/DatabaseMaterializeMySQL.h>
|
||||||
|
|
||||||
|
#include <mysqlxx/Pool.h>
|
||||||
|
#include <Parsers/ASTFunction.h>
|
||||||
|
#include <Interpreters/evaluateConstantExpression.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace ErrorCodes
|
||||||
|
{
|
||||||
|
extern const int BAD_ARGUMENTS;
|
||||||
|
extern const int CANNOT_CREATE_DATABASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline String safeGetLiteralValue(const ASTPtr & ast)
|
||||||
|
{
|
||||||
|
if (!ast || !ast->as<ASTLiteral>())
|
||||||
|
throw Exception("Database engine MySQL requested literal argument.", ErrorCodes::BAD_ARGUMENTS);
|
||||||
|
|
||||||
|
return ast->as<ASTLiteral>()->value.safeGet<String>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static inline bool materializeMySQLDatabase(const ASTSetQuery * settings)
|
||||||
|
{
|
||||||
|
if (!settings || settings->changes.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (const auto & change : settings->changes)
|
||||||
|
{
|
||||||
|
if (change.name == "materialize_data")
|
||||||
|
{
|
||||||
|
if (change.value.getType() == Field::Types::String)
|
||||||
|
return change.value.safeGet<String>() == "true"; ///TODO: ignore case
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
DatabasePtr createMySQLDatabase(const String & database_name, const String & metadata_path, const ASTStorage * define, Context & context)
|
||||||
|
{
|
||||||
|
const ASTFunction * engine = define->engine;
|
||||||
|
if (!engine->arguments || engine->arguments->children.size() != 4)
|
||||||
|
throw Exception( "MySQL Database require mysql_hostname, mysql_database_name, mysql_username, mysql_password arguments.",
|
||||||
|
ErrorCodes::BAD_ARGUMENTS);
|
||||||
|
|
||||||
|
ASTs & arguments = engine->arguments->children;
|
||||||
|
arguments[1] = evaluateConstantExpressionOrIdentifierAsLiteral(arguments[1], context);
|
||||||
|
|
||||||
|
const auto & host_name_and_port = safeGetLiteralValue(arguments[0]);
|
||||||
|
const auto & mysql_database_name = safeGetLiteralValue(arguments[1]);
|
||||||
|
const auto & mysql_user_name = safeGetLiteralValue(arguments[2]);
|
||||||
|
const auto & mysql_user_password = safeGetLiteralValue(arguments[3]);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const auto & [remote_host_name, remote_port] = parseAddress(host_name_and_port, 3306);
|
||||||
|
auto mysql_pool = mysqlxx::Pool(mysql_database_name, remote_host_name, mysql_user_name, mysql_user_password, remote_port);
|
||||||
|
|
||||||
|
/*if (materializeMySQLDatabase(define->settings))
|
||||||
|
return std::make_shared<DatabaseMaterializeMySQL>(
|
||||||
|
context, database_name, metadata_path, define, mysql_database_name, std::move(mysql_pool));*/
|
||||||
|
|
||||||
|
return std::make_shared<DatabaseMySQL>(context, database_name, metadata_path, define, mysql_database_name, std::move(mysql_pool));
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
const auto & exception_message = getCurrentExceptionMessage(true);
|
||||||
|
throw Exception("Cannot create MySQL database, because " + exception_message, ErrorCodes::CANNOT_CREATE_DATABASE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
19
src/Databases/MySQL/createMySQLDatabase.h
Normal file
19
src/Databases/MySQL/createMySQLDatabase.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if !defined(ARCADIA_BUILD)
|
||||||
|
# include "config_core.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if USE_MYSQL
|
||||||
|
|
||||||
|
#include <Databases/IDatabase.h>
|
||||||
|
#include <Parsers/ASTCreateQuery.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
DatabasePtr createMySQLDatabase(const String & database_name, const String & metadata_path, const ASTStorage * define, Context & context);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -1,5 +1,6 @@
|
|||||||
include(${ClickHouse_SOURCE_DIR}/cmake/dbms_glob_sources.cmake)
|
include(${ClickHouse_SOURCE_DIR}/cmake/dbms_glob_sources.cmake)
|
||||||
add_headers_and_sources(clickhouse_parsers .)
|
add_headers_and_sources(clickhouse_parsers .)
|
||||||
|
add_headers_and_sources(clickhouse_parsers ./MySQL)
|
||||||
add_library(clickhouse_parsers ${clickhouse_parsers_headers} ${clickhouse_parsers_sources})
|
add_library(clickhouse_parsers ${clickhouse_parsers_headers} ${clickhouse_parsers_sources})
|
||||||
target_link_libraries(clickhouse_parsers PUBLIC clickhouse_common_io)
|
target_link_libraries(clickhouse_parsers PUBLIC clickhouse_common_io)
|
||||||
|
|
||||||
|
95
src/Parsers/MySQL/ASTCreateDefines.cpp
Normal file
95
src/Parsers/MySQL/ASTCreateDefines.cpp
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
#include <Parsers/CommonParsers.h>
|
||||||
|
#include <Parsers/ExpressionListParsers.h>
|
||||||
|
#include <Parsers/MySQL/ASTCreateDefines.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareIndex.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareColumn.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareConstraint.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace MySQLParser
|
||||||
|
{
|
||||||
|
|
||||||
|
class ParserCreateDefine : public IParserBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
const char * getName() const override { return "table property (column, index, constraint)"; }
|
||||||
|
|
||||||
|
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override
|
||||||
|
{
|
||||||
|
MySQLParser::ParserDeclareIndex p_declare_index;
|
||||||
|
MySQLParser::ParserDeclareColumn p_declare_column;
|
||||||
|
MySQLParser::ParserDeclareConstraint p_declare_constraint;
|
||||||
|
|
||||||
|
if (likely(!p_declare_index.parse(pos, node, expected)))
|
||||||
|
{
|
||||||
|
if (likely(!p_declare_constraint.parse(pos, node, expected)))
|
||||||
|
{
|
||||||
|
if (!p_declare_column.parse(pos, node, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ASTPtr ASTCreateDefines::clone() const
|
||||||
|
{
|
||||||
|
auto res = std::make_shared<ASTCreateDefines>(*this);
|
||||||
|
res->children.clear();
|
||||||
|
|
||||||
|
if (columns)
|
||||||
|
res->set(res->columns, columns->clone());
|
||||||
|
|
||||||
|
if (indices)
|
||||||
|
res->set(res->indices, indices->clone());
|
||||||
|
|
||||||
|
if (constraints)
|
||||||
|
res->set(res->constraints, constraints->clone());
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParserCreateDefines::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected & expected)
|
||||||
|
{
|
||||||
|
ASTPtr create_defines;
|
||||||
|
ParserList create_defines_parser(std::make_unique<ParserCreateDefine>(), std::make_unique<ParserToken>(TokenType::Comma), false);
|
||||||
|
|
||||||
|
if (!create_defines_parser.parse(pos, create_defines, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ASTPtr columns = std::make_shared<ASTExpressionList>();
|
||||||
|
ASTPtr indices = std::make_shared<ASTExpressionList>();
|
||||||
|
ASTPtr constraints = std::make_shared<ASTExpressionList>();
|
||||||
|
|
||||||
|
for (const auto & create_define : create_defines->children)
|
||||||
|
{
|
||||||
|
if (create_define->as<ASTDeclareColumn>())
|
||||||
|
columns->children.push_back(create_define);
|
||||||
|
else if (create_define->as<ASTDeclareIndex>())
|
||||||
|
indices->children.push_back(create_define);
|
||||||
|
else if (create_define->as<ASTDeclareConstraint>())
|
||||||
|
constraints->children.push_back(create_define);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto res = std::make_shared<ASTCreateDefines>();
|
||||||
|
if (!columns->children.empty())
|
||||||
|
res->set(res->columns, columns);
|
||||||
|
if (!indices->children.empty())
|
||||||
|
res->set(res->indices, indices);
|
||||||
|
if (!constraints->children.empty())
|
||||||
|
res->set(res->constraints, constraints);
|
||||||
|
|
||||||
|
node = res;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
37
src/Parsers/MySQL/ASTCreateDefines.h
Normal file
37
src/Parsers/MySQL/ASTCreateDefines.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Parsers/IAST.h>
|
||||||
|
#include <Parsers/IParserBase.h>
|
||||||
|
#include <Parsers/ASTExpressionList.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace MySQLParser
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class ASTCreateDefines : public IAST
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ASTExpressionList * columns = nullptr;
|
||||||
|
ASTExpressionList * indices = nullptr;
|
||||||
|
ASTExpressionList * constraints = nullptr;
|
||||||
|
|
||||||
|
ASTPtr clone() const override;
|
||||||
|
|
||||||
|
String getID(char) const override { return "Create definitions"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ParserCreateDefines : public IParserBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||||
|
|
||||||
|
const char * getName() const override { return "table property list (column, index, constraint)"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
128
src/Parsers/MySQL/ASTCreateQuery.cpp
Normal file
128
src/Parsers/MySQL/ASTCreateQuery.cpp
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
#include <Parsers/MySQL/ASTCreateQuery.h>
|
||||||
|
|
||||||
|
#include <Interpreters/StorageID.h>
|
||||||
|
#include <Parsers/ASTIdentifier.h>
|
||||||
|
#include <Parsers/CommonParsers.h>
|
||||||
|
#include <Parsers/ExpressionElementParsers.h>
|
||||||
|
#include <Parsers/ExpressionListParsers.h>
|
||||||
|
#include <Parsers/MySQL/ASTCreateDefines.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclarePartitionOptions.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareTableOptions.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace MySQLParser
|
||||||
|
{
|
||||||
|
|
||||||
|
ASTPtr ASTCreateQuery::clone() const
|
||||||
|
{
|
||||||
|
auto res = std::make_shared<ASTCreateQuery>(*this);
|
||||||
|
res->children.clear();
|
||||||
|
|
||||||
|
if (columns_list)
|
||||||
|
{
|
||||||
|
res->columns_list = columns_list->clone();
|
||||||
|
res->children.emplace_back(res->columns_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (table_options)
|
||||||
|
{
|
||||||
|
res->table_options = table_options->clone();
|
||||||
|
res->children.emplace_back(res->table_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (partition_options)
|
||||||
|
{
|
||||||
|
res->partition_options = partition_options->clone();
|
||||||
|
res->children.emplace_back(res->partition_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParserCreateQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||||
|
{
|
||||||
|
ASTPtr table;
|
||||||
|
ASTPtr like_table;
|
||||||
|
ASTPtr columns_list;
|
||||||
|
ASTPtr table_options;
|
||||||
|
ASTPtr partition_options;
|
||||||
|
bool is_temporary = false;
|
||||||
|
bool if_not_exists = false;
|
||||||
|
|
||||||
|
if (!ParserKeyword("CREATE").ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ParserKeyword("TEMPORARY").ignore(pos, expected))
|
||||||
|
is_temporary = true;
|
||||||
|
|
||||||
|
if (!ParserKeyword("TABLE").ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ParserKeyword("IF NOT EXISTS").ignore(pos, expected))
|
||||||
|
if_not_exists = true;
|
||||||
|
|
||||||
|
if (!ParserCompoundIdentifier(true).parse(pos, table, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ParserKeyword("LIKE").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!ParserCompoundIdentifier(true).parse(pos, like_table, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ParserToken(TokenType::OpeningRoundBracket).ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (ParserKeyword("LIKE").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!ParserCompoundIdentifier(true).parse(pos, like_table, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ParserToken(TokenType::ClosingRoundBracket).ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!ParserCreateDefines().parse(pos, columns_list, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ParserToken(TokenType::ClosingRoundBracket).ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ParserDeclareTableOptions().parse(pos, table_options, expected);
|
||||||
|
ParserDeclarePartitionOptions().parse(pos, partition_options, expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto create_query = std::make_shared<ASTCreateQuery>();
|
||||||
|
|
||||||
|
create_query->temporary = is_temporary;
|
||||||
|
create_query->if_not_exists = if_not_exists;
|
||||||
|
|
||||||
|
StorageID table_id = getTableIdentifier(table);
|
||||||
|
create_query->table = table_id.table_name;
|
||||||
|
create_query->database = table_id.database_name;
|
||||||
|
create_query->like_table = like_table;
|
||||||
|
create_query->columns_list = columns_list;
|
||||||
|
create_query->table_options = table_options;
|
||||||
|
create_query->partition_options = partition_options;
|
||||||
|
|
||||||
|
if (create_query->like_table)
|
||||||
|
create_query->children.emplace_back(create_query->like_table);
|
||||||
|
|
||||||
|
if (create_query->columns_list)
|
||||||
|
create_query->children.emplace_back(create_query->columns_list);
|
||||||
|
|
||||||
|
if (create_query->table_options)
|
||||||
|
create_query->children.emplace_back(create_query->table_options);
|
||||||
|
|
||||||
|
if (create_query->partition_options)
|
||||||
|
create_query->children.emplace_back(create_query->partition_options);
|
||||||
|
|
||||||
|
node = create_query;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
40
src/Parsers/MySQL/ASTCreateQuery.h
Normal file
40
src/Parsers/MySQL/ASTCreateQuery.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Parsers/IAST.h>
|
||||||
|
#include <Parsers/IParserBase.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace MySQLParser
|
||||||
|
{
|
||||||
|
|
||||||
|
class ASTCreateQuery : public IAST
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool temporary{false};
|
||||||
|
bool if_not_exists{false};
|
||||||
|
|
||||||
|
String table;
|
||||||
|
String database;
|
||||||
|
ASTPtr like_table;
|
||||||
|
ASTPtr columns_list;
|
||||||
|
ASTPtr table_options;
|
||||||
|
ASTPtr partition_options;
|
||||||
|
|
||||||
|
ASTPtr clone() const override;
|
||||||
|
|
||||||
|
String getID(char) const override { return "create query"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ParserCreateQuery : public IParserBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
const char * getName() const override { return "create query"; }
|
||||||
|
|
||||||
|
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
98
src/Parsers/MySQL/ASTDeclareColumn.cpp
Normal file
98
src/Parsers/MySQL/ASTDeclareColumn.cpp
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
#include <Parsers/MySQL/ASTDeclareColumn.h>
|
||||||
|
|
||||||
|
#include <Parsers/ASTIdentifier.h>
|
||||||
|
#include <Parsers/ExpressionListParsers.h>
|
||||||
|
#include <Parsers/ExpressionElementParsers.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareOption.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareReference.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareConstraint.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace MySQLParser
|
||||||
|
{
|
||||||
|
|
||||||
|
ASTPtr ASTDeclareColumn::clone() const
|
||||||
|
{
|
||||||
|
auto res = std::make_shared<ASTDeclareColumn>(*this);
|
||||||
|
res->children.clear();
|
||||||
|
|
||||||
|
if (data_type)
|
||||||
|
{
|
||||||
|
res->data_type = data_type->clone();
|
||||||
|
res->children.emplace_back(res->data_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (column_options)
|
||||||
|
{
|
||||||
|
res->column_options = column_options->clone();
|
||||||
|
res->children.emplace_back(res->column_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParserDeclareColumn::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||||
|
{
|
||||||
|
ASTPtr column_name;
|
||||||
|
ASTPtr column_data_type;
|
||||||
|
ASTPtr column_options;
|
||||||
|
|
||||||
|
ParserExpression p_expression;
|
||||||
|
ParserIdentifier p_identifier;
|
||||||
|
|
||||||
|
if (!p_identifier.parse(pos, column_name, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!p_expression.parse(pos, column_data_type, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!parseColumnDeclareOptions(pos, column_options, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto declare_column = std::make_shared<ASTDeclareColumn>();
|
||||||
|
declare_column->name = column_name->as<ASTIdentifier>()->name;
|
||||||
|
declare_column->data_type = column_data_type;
|
||||||
|
declare_column->column_options = column_options;
|
||||||
|
|
||||||
|
if (declare_column->data_type)
|
||||||
|
declare_column->children.emplace_back(declare_column->data_type);
|
||||||
|
|
||||||
|
if (declare_column->column_options)
|
||||||
|
declare_column->children.emplace_back(declare_column->column_options);
|
||||||
|
|
||||||
|
node = declare_column;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool ParserDeclareColumn::parseColumnDeclareOptions(IParser::Pos & pos, ASTPtr & node, Expected & expected)
|
||||||
|
{
|
||||||
|
ParserDeclareOption p_non_generate_options{
|
||||||
|
{
|
||||||
|
OptionDescribe("NULL", "is_null", std::make_unique<ParserAlwaysTrue>()),
|
||||||
|
OptionDescribe("NOT NULL", "is_null", std::make_unique<ParserAlwaysFalse>()),
|
||||||
|
OptionDescribe("DEFAULT", "default", std::make_unique<ParserExpression>()),
|
||||||
|
OptionDescribe("AUTO_INCREMENT", "auto_increment", std::make_unique<ParserAlwaysTrue>()),
|
||||||
|
OptionDescribe("UNIQUE", "unique_key", std::make_unique<ParserAlwaysTrue>()),
|
||||||
|
OptionDescribe("UNIQUE KEY", "unique_key", std::make_unique<ParserAlwaysTrue>()),
|
||||||
|
OptionDescribe("KEY", "primary_key", std::make_unique<ParserAlwaysTrue>()),
|
||||||
|
OptionDescribe("PRIMARY KEY", "primary_key", std::make_unique<ParserAlwaysTrue>()),
|
||||||
|
OptionDescribe("COMMENT", "comment", std::make_unique<ParserStringLiteral>()),
|
||||||
|
OptionDescribe("COLLATE", "collate", std::make_unique<ParserCharsetName>()),
|
||||||
|
OptionDescribe("COLUMN_FORMAT", "column_format", std::make_unique<ParserIdentifier>()),
|
||||||
|
OptionDescribe("STORAGE", "storage", std::make_unique<ParserIdentifier>()),
|
||||||
|
OptionDescribe("AS", "generated", std::make_unique<ParserExpression>()),
|
||||||
|
OptionDescribe("GENERATED ALWAYS AS", "generated", std::make_unique<ParserExpression>()),
|
||||||
|
OptionDescribe("STORED", "is_stored", std::make_unique<ParserAlwaysTrue>()),
|
||||||
|
OptionDescribe("VIRTUAL", "is_stored", std::make_unique<ParserAlwaysFalse>()),
|
||||||
|
OptionDescribe("", "reference", std::make_unique<ParserDeclareReference>()),
|
||||||
|
OptionDescribe("", "constraint", std::make_unique<ParserDeclareConstraint>()),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return p_non_generate_options.parse(pos, node, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
37
src/Parsers/MySQL/ASTDeclareColumn.h
Normal file
37
src/Parsers/MySQL/ASTDeclareColumn.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Parsers/IAST.h>
|
||||||
|
#include <Parsers/IParserBase.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace MySQLParser
|
||||||
|
{
|
||||||
|
|
||||||
|
class ASTDeclareColumn : public IAST
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
String name;
|
||||||
|
ASTPtr data_type;
|
||||||
|
ASTPtr column_options;
|
||||||
|
|
||||||
|
ASTPtr clone() const override;
|
||||||
|
|
||||||
|
String getID(char /*delimiter*/) const override { return "Column definition"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ParserDeclareColumn : public IParserBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
const char * getName() const override { return "index declaration"; }
|
||||||
|
|
||||||
|
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||||
|
|
||||||
|
bool parseColumnDeclareOptions(Pos & pos, ASTPtr & node, Expected & expected);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
74
src/Parsers/MySQL/ASTDeclareConstraint.cpp
Normal file
74
src/Parsers/MySQL/ASTDeclareConstraint.cpp
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#include <Parsers/MySQL/ASTDeclareConstraint.h>
|
||||||
|
|
||||||
|
#include <Parsers/ASTIdentifier.h>
|
||||||
|
#include <Parsers/CommonParsers.h>
|
||||||
|
#include <Parsers/ExpressionElementParsers.h>
|
||||||
|
#include <Parsers/ExpressionListParsers.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace MySQLParser
|
||||||
|
{
|
||||||
|
|
||||||
|
ASTPtr ASTDeclareConstraint::clone() const
|
||||||
|
{
|
||||||
|
auto res = std::make_shared<ASTDeclareConstraint>(*this);
|
||||||
|
res->children.clear();
|
||||||
|
|
||||||
|
if (check_expression)
|
||||||
|
{
|
||||||
|
res->check_expression = check_expression->clone();
|
||||||
|
res->children.emplace_back(res->check_expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParserDeclareConstraint::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected & expected)
|
||||||
|
{
|
||||||
|
bool enforced = true;
|
||||||
|
ASTPtr constraint_symbol;
|
||||||
|
ASTPtr index_check_expression;
|
||||||
|
ParserExpression p_expression;
|
||||||
|
|
||||||
|
if (ParserKeyword("CONSTRAINT").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!ParserKeyword("CHECK").checkWithoutMoving(pos, expected))
|
||||||
|
ParserIdentifier().parse(pos, constraint_symbol, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!ParserKeyword("CHECK").ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!p_expression.parse(pos, index_check_expression, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ParserKeyword("NOT").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!ParserKeyword("ENFORCED").ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
enforced = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enforced = true;
|
||||||
|
ParserKeyword("ENFORCED").ignore(pos, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto declare_constraint = std::make_shared<ASTDeclareConstraint>();
|
||||||
|
declare_constraint->enforced = enforced;
|
||||||
|
declare_constraint->check_expression = index_check_expression;
|
||||||
|
|
||||||
|
if (constraint_symbol)
|
||||||
|
declare_constraint->constraint_name = constraint_symbol->as<ASTIdentifier>()->name;
|
||||||
|
|
||||||
|
node = declare_constraint;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
35
src/Parsers/MySQL/ASTDeclareConstraint.h
Normal file
35
src/Parsers/MySQL/ASTDeclareConstraint.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Parsers/IAST.h>
|
||||||
|
#include <Parsers/IParserBase.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace MySQLParser
|
||||||
|
{
|
||||||
|
|
||||||
|
class ASTDeclareConstraint : public IAST
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool enforced{true};
|
||||||
|
String constraint_name;
|
||||||
|
ASTPtr check_expression;
|
||||||
|
|
||||||
|
ASTPtr clone() const override;
|
||||||
|
|
||||||
|
String getID(char /*delimiter*/) const override { return "constraint declaration"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ParserDeclareConstraint : public IParserBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
const char * getName() const override { return "constraint declaration"; }
|
||||||
|
|
||||||
|
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
235
src/Parsers/MySQL/ASTDeclareIndex.cpp
Normal file
235
src/Parsers/MySQL/ASTDeclareIndex.cpp
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
#include <Parsers/ASTIdentifier.h>
|
||||||
|
#include <Parsers/CommonParsers.h>
|
||||||
|
#include <Parsers/ExpressionListParsers.h>
|
||||||
|
#include <Parsers/ExpressionElementParsers.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareIndex.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareOption.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareReference.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace MySQLParser
|
||||||
|
{
|
||||||
|
|
||||||
|
struct ParserIndexColumn : public IParserBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
const char * getName() const override { return "index column"; }
|
||||||
|
|
||||||
|
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override
|
||||||
|
{
|
||||||
|
ParserExpression p_expression;
|
||||||
|
|
||||||
|
if (!p_expression.parse(pos, node, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ParserKeyword("ASC").ignore(pos, expected);
|
||||||
|
ParserKeyword("DESC").ignore(pos, expected);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ASTPtr ASTDeclareIndex::clone() const
|
||||||
|
{
|
||||||
|
auto res = std::make_shared<ASTDeclareIndex>(*this);
|
||||||
|
res->children.clear();
|
||||||
|
|
||||||
|
if (index_columns)
|
||||||
|
{
|
||||||
|
res->index_columns = index_columns->clone();
|
||||||
|
res->children.emplace_back(res->index_columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (index_options)
|
||||||
|
{
|
||||||
|
res->index_options = index_options->clone();
|
||||||
|
res->children.emplace_back(res->index_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (reference_definition)
|
||||||
|
{
|
||||||
|
res->reference_definition = reference_definition->clone();
|
||||||
|
res->children.emplace_back(res->reference_definition);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
bool ParserDeclareIndex::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected & expected)
|
||||||
|
{
|
||||||
|
String index_name;
|
||||||
|
String index_type;
|
||||||
|
ASTPtr index_columns;
|
||||||
|
ASTPtr index_options;
|
||||||
|
ASTPtr declare_reference;
|
||||||
|
ParserIndexColumn p_expression;
|
||||||
|
|
||||||
|
ParserDeclareOption p_index_options{
|
||||||
|
{
|
||||||
|
OptionDescribe("KEY_BLOCK_SIZE", "key_block_size", std::make_unique<ParserLiteral>()),
|
||||||
|
OptionDescribe("USING", "index_type", std::make_unique<ParserIdentifier>()),
|
||||||
|
OptionDescribe("WITH PARSER", "index_parser", std::make_unique<ParserIdentifier>()),
|
||||||
|
OptionDescribe("COMMENT", "comment", std::make_unique<ParserStringLiteral>()),
|
||||||
|
OptionDescribe("VISIBLE", "visible", std::make_unique<ParserAlwaysTrue>()),
|
||||||
|
OptionDescribe("INVISIBLE", "visible", std::make_unique<ParserAlwaysFalse>()),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!parseDeclareOrdinaryIndex(pos, index_name, index_type, expected))
|
||||||
|
{
|
||||||
|
if (!parseDeclareConstraintIndex(pos, index_name, index_type, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParserToken s_opening_round(TokenType::OpeningRoundBracket);
|
||||||
|
ParserToken s_closing_round(TokenType::ClosingRoundBracket);
|
||||||
|
|
||||||
|
if (!s_opening_round.ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ParserList p_index_columns(std::make_unique<ParserIndexColumn>(), std::make_unique<ParserToken>(TokenType::Comma));
|
||||||
|
|
||||||
|
if (!p_index_columns.parse(pos, index_columns, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!s_closing_round.ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (index_type != "FOREIGN")
|
||||||
|
p_index_options.parse(pos, index_options, expected);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!ParserDeclareReference().parse(pos, declare_reference, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto declare_index = std::make_shared<ASTDeclareIndex>();
|
||||||
|
declare_index->index_name = index_name;
|
||||||
|
declare_index->index_type = index_type;
|
||||||
|
declare_index->index_columns = index_columns;
|
||||||
|
declare_index->index_options = index_options;
|
||||||
|
declare_index->reference_definition = declare_reference;
|
||||||
|
|
||||||
|
if (declare_index->index_columns)
|
||||||
|
declare_index->children.emplace_back(declare_index->index_columns);
|
||||||
|
|
||||||
|
if (declare_index->index_options)
|
||||||
|
declare_index->children.emplace_back(declare_index->index_options);
|
||||||
|
|
||||||
|
if (declare_index->reference_definition)
|
||||||
|
declare_index->children.emplace_back(declare_index->reference_definition);
|
||||||
|
|
||||||
|
node = declare_index;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool ParserDeclareIndex::parseDeclareOrdinaryIndex(IParser::Pos & pos, String & index_name, String & index_type, Expected & expected)
|
||||||
|
{
|
||||||
|
ASTPtr temp_node;
|
||||||
|
ParserKeyword k_key("KEY");
|
||||||
|
ParserKeyword k_index("INDEX");
|
||||||
|
|
||||||
|
ParserExpression p_expression;
|
||||||
|
ParserIdentifier p_identifier;
|
||||||
|
|
||||||
|
if (ParserKeyword("SPATIAL").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!k_key.ignore(pos, expected))
|
||||||
|
k_index.ignore(pos, expected);
|
||||||
|
|
||||||
|
index_type = "SPATIAL";
|
||||||
|
if (p_identifier.parse(pos, temp_node, expected))
|
||||||
|
index_name = temp_node->as<ASTIdentifier>()->name;
|
||||||
|
}
|
||||||
|
else if (ParserKeyword("FULLTEXT").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!k_key.ignore(pos, expected))
|
||||||
|
k_index.ignore(pos, expected);
|
||||||
|
|
||||||
|
index_type = "FULLTEXT";
|
||||||
|
if (p_identifier.parse(pos, temp_node, expected))
|
||||||
|
index_name = temp_node->as<ASTIdentifier>()->name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!k_key.ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!k_index.ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
index_type = "BTREE"; /// default index type
|
||||||
|
if (p_identifier.parse(pos, temp_node, expected))
|
||||||
|
index_name = temp_node->as<ASTIdentifier>()->name;
|
||||||
|
|
||||||
|
if (ParserKeyword("USING").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!p_identifier.parse(pos, temp_node, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
index_type = temp_node->as<ASTIdentifier>()->name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParserDeclareIndex::parseDeclareConstraintIndex(IParser::Pos & pos, String & index_name, String & index_type, Expected & expected)
|
||||||
|
{
|
||||||
|
ASTPtr temp_node;
|
||||||
|
ParserIdentifier p_identifier;
|
||||||
|
|
||||||
|
if (ParserKeyword("CONSTRAINT").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!ParserKeyword("PRIMARY").checkWithoutMoving(pos, expected) && !ParserKeyword("UNIQUE").checkWithoutMoving(pos, expected)
|
||||||
|
&& !ParserKeyword("FOREIGN").checkWithoutMoving(pos, expected))
|
||||||
|
{
|
||||||
|
if (!p_identifier.parse(pos, temp_node, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
index_name = temp_node->as<ASTIdentifier>()->name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ParserKeyword("UNIQUE").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!ParserKeyword("KEY").ignore(pos, expected))
|
||||||
|
ParserKeyword("INDEX").ignore(pos, expected);
|
||||||
|
|
||||||
|
if (p_identifier.parse(pos, temp_node, expected))
|
||||||
|
index_name = temp_node->as<ASTIdentifier>()->name; /// reset index_name
|
||||||
|
|
||||||
|
index_type = "UNIQUE_BTREE"; /// default btree index_type
|
||||||
|
if (ParserKeyword("USING").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!p_identifier.parse(pos, temp_node, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
index_type = temp_node->as<ASTIdentifier>()->name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ParserKeyword("PRIMARY KEY").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
index_type = "PRIMARY_KEY_BTREE"; /// default btree index_type
|
||||||
|
if (ParserKeyword("USING").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!p_identifier.parse(pos, temp_node, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
index_type = temp_node->as<ASTIdentifier>()->name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ParserKeyword("FOREIGN KEY").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
index_type = "FOREIGN";
|
||||||
|
if (p_identifier.parse(pos, temp_node, expected))
|
||||||
|
index_name = temp_node->as<ASTIdentifier>()->name; /// reset index_name
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
43
src/Parsers/MySQL/ASTDeclareIndex.h
Normal file
43
src/Parsers/MySQL/ASTDeclareIndex.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Core/Field.h>
|
||||||
|
#include <Parsers/IAST.h>
|
||||||
|
#include <Parsers/IParserBase.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace MySQLParser
|
||||||
|
{
|
||||||
|
|
||||||
|
class ASTDeclareIndex: public IAST
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
String index_name;
|
||||||
|
String index_type;
|
||||||
|
ASTPtr index_columns;
|
||||||
|
ASTPtr index_options;
|
||||||
|
ASTPtr reference_definition;
|
||||||
|
|
||||||
|
ASTPtr clone() const override;
|
||||||
|
|
||||||
|
String getID(char /*delimiter*/) const override { return "index declaration"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ParserDeclareIndex : public IParserBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
const char * getName() const override { return "index declaration"; }
|
||||||
|
|
||||||
|
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||||
|
|
||||||
|
bool parseDeclareOrdinaryIndex(Pos & pos, String & index_name, String & index_type, Expected & expected);
|
||||||
|
|
||||||
|
bool parseDeclareConstraintIndex(Pos & pos, String & index_name, String & index_type, Expected & expected);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
142
src/Parsers/MySQL/ASTDeclareOption.cpp
Normal file
142
src/Parsers/MySQL/ASTDeclareOption.cpp
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
#include <Parsers/MySQL/ASTDeclareOption.h>
|
||||||
|
|
||||||
|
#include <IO/ReadBufferFromMemory.h>
|
||||||
|
#include <IO/ReadHelpers.h>
|
||||||
|
#include <Parsers/ASTIdentifier.h>
|
||||||
|
#include <Parsers/ASTLiteral.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace MySQLParser
|
||||||
|
{
|
||||||
|
|
||||||
|
bool ParserDeclareOption::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||||
|
{
|
||||||
|
std::unordered_map<String, ASTPtr> changes;
|
||||||
|
std::unordered_map<String, std::shared_ptr<IParser>> usage_parsers_cached;
|
||||||
|
usage_parsers_cached.reserve(options_collection.size());
|
||||||
|
|
||||||
|
const auto & get_parser_from_cache = [&](const char * usage_name)
|
||||||
|
{
|
||||||
|
auto iterator = usage_parsers_cached.find(usage_name);
|
||||||
|
if (iterator == usage_parsers_cached.end())
|
||||||
|
iterator = usage_parsers_cached.insert(std::make_pair(usage_name, std::make_shared<ParserKeyword>(usage_name))).first;
|
||||||
|
|
||||||
|
return iterator->second;
|
||||||
|
};
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
ASTPtr value;
|
||||||
|
bool found{false};
|
||||||
|
for (const auto & option_describe : options_collection)
|
||||||
|
{
|
||||||
|
if (strlen(option_describe.usage_name) == 0)
|
||||||
|
{
|
||||||
|
if (option_describe.value_parser->parse(pos, value, expected))
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
changes.insert(std::make_pair(option_describe.option_name, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (get_parser_from_cache(option_describe.usage_name)->ignore(pos, expected))
|
||||||
|
{
|
||||||
|
ParserToken{TokenType::Equals}.ignore(pos, expected);
|
||||||
|
|
||||||
|
if (!option_describe.value_parser->parse(pos, value, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/*const auto & changes_iterator = changes.find(option_describe.option_name);
|
||||||
|
if (changes_iterator != changes.end())
|
||||||
|
throw Exception("Duplicate options declare", ErrorCodes::)*/
|
||||||
|
found = true;
|
||||||
|
changes.insert(std::make_pair(option_describe.option_name, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ParserToken{TokenType::Comma}.ignore(pos, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!changes.empty())
|
||||||
|
{
|
||||||
|
auto options_declare = std::make_shared<ASTDeclareOptions>();
|
||||||
|
options_declare->changes = changes;
|
||||||
|
|
||||||
|
node = options_declare;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASTPtr ASTDeclareOptions::clone() const
|
||||||
|
{
|
||||||
|
auto res = std::make_shared<ASTDeclareOptions>(*this);
|
||||||
|
res->children.clear();
|
||||||
|
res->changes.clear();
|
||||||
|
|
||||||
|
for (const auto & [name, value] : this->changes)
|
||||||
|
res->changes.insert(std::make_pair(name, value->clone()));
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParserAlwaysTrue::parseImpl(IParser::Pos & /*pos*/, ASTPtr & node, Expected & /*expected*/)
|
||||||
|
{
|
||||||
|
node = std::make_shared<ASTLiteral>(Field(UInt64(1)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParserAlwaysFalse::parseImpl(IParser::Pos & /*pos*/, ASTPtr & node, Expected & /*expected*/)
|
||||||
|
{
|
||||||
|
node = std::make_shared<ASTLiteral>(Field(UInt64(0)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParserCharsetName::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected &)
|
||||||
|
{
|
||||||
|
/// Identifier in backquotes or in double quotes
|
||||||
|
if (pos->type == TokenType::QuotedIdentifier)
|
||||||
|
{
|
||||||
|
ReadBufferFromMemory buf(pos->begin, pos->size());
|
||||||
|
String s;
|
||||||
|
|
||||||
|
if (*pos->begin == '`')
|
||||||
|
readBackQuotedStringWithSQLStyle(s, buf);
|
||||||
|
else
|
||||||
|
readDoubleQuotedStringWithSQLStyle(s, buf);
|
||||||
|
|
||||||
|
if (s.empty()) /// Identifiers "empty string" are not allowed.
|
||||||
|
return false;
|
||||||
|
|
||||||
|
node = std::make_shared<ASTIdentifier>(s);
|
||||||
|
++pos;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (pos->type == TokenType::BareWord)
|
||||||
|
{
|
||||||
|
const char * begin = pos->begin;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (isWhitespaceASCII(*pos->end))
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node = std::make_shared<ASTIdentifier>(String(begin, pos->end));
|
||||||
|
++pos;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
76
src/Parsers/MySQL/ASTDeclareOption.h
Normal file
76
src/Parsers/MySQL/ASTDeclareOption.h
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Parsers/IAST.h>
|
||||||
|
#include <Parsers/IParserBase.h>
|
||||||
|
#include <Parsers/CommonParsers.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace MySQLParser
|
||||||
|
{
|
||||||
|
|
||||||
|
struct OptionDescribe
|
||||||
|
{
|
||||||
|
const char * usage_name;
|
||||||
|
String option_name;
|
||||||
|
std::shared_ptr<IParser> value_parser;
|
||||||
|
|
||||||
|
OptionDescribe(const char * usage_name_, const String & option_name_, const std::shared_ptr<IParser> & value_parser_)
|
||||||
|
:usage_name(usage_name_), option_name(option_name_), value_parser(value_parser_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ASTDeclareOptions : public IAST
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::unordered_map<String, ASTPtr> changes;
|
||||||
|
|
||||||
|
ASTPtr clone() const override;
|
||||||
|
|
||||||
|
String getID(char /*delimiter*/) const override { return "options declaration"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ParserAlwaysTrue : public IParserBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const char * getName() const override { return "always true"; }
|
||||||
|
|
||||||
|
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ParserAlwaysFalse : public IParserBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const char * getName() const override { return "always false"; }
|
||||||
|
|
||||||
|
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Copy and paste from ParserIdentifier,
|
||||||
|
/// the difference is that multiple tokens are glued if there is no whitespace ASCII between them
|
||||||
|
struct ParserCharsetName : public IParserBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
const char * getName() const override { return "charset name"; }
|
||||||
|
|
||||||
|
bool parseImpl(Pos & pos, ASTPtr & node, Expected &) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ParserDeclareOption : public IParserBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::vector<OptionDescribe> options_collection;
|
||||||
|
|
||||||
|
const char * getName() const override { return "option declaration"; }
|
||||||
|
|
||||||
|
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||||
|
public:
|
||||||
|
ParserDeclareOption(const std::vector<OptionDescribe> & options_collection_) : options_collection(options_collection_) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
127
src/Parsers/MySQL/ASTDeclarePartition.cpp
Normal file
127
src/Parsers/MySQL/ASTDeclarePartition.cpp
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
#include <Parsers/MySQL/ASTDeclarePartition.h>
|
||||||
|
|
||||||
|
#include <Parsers/ASTIdentifier.h>
|
||||||
|
#include <Parsers/ExpressionElementParsers.h>
|
||||||
|
#include <Parsers/ExpressionListParsers.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareOption.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareSubPartition.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace MySQLParser
|
||||||
|
{
|
||||||
|
|
||||||
|
ASTPtr ASTDeclarePartition::clone() const
|
||||||
|
{
|
||||||
|
auto res = std::make_shared<ASTDeclarePartition>(*this);
|
||||||
|
res->children.clear();
|
||||||
|
|
||||||
|
if (options)
|
||||||
|
{
|
||||||
|
res->options = options->clone();
|
||||||
|
res->children.emplace_back(res->options);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (less_than)
|
||||||
|
{
|
||||||
|
res->less_than = less_than->clone();
|
||||||
|
res->children.emplace_back(res->less_than);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_expression)
|
||||||
|
{
|
||||||
|
res->in_expression = in_expression->clone();
|
||||||
|
res->children.emplace_back(res->in_expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subpartitions)
|
||||||
|
{
|
||||||
|
res->subpartitions = subpartitions->clone();
|
||||||
|
res->children.emplace_back(res->subpartitions);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParserDeclarePartition::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected & expected)
|
||||||
|
{
|
||||||
|
if (!ParserKeyword{"PARTITION"}.ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ASTPtr options;
|
||||||
|
ASTPtr less_than;
|
||||||
|
ASTPtr in_expression;
|
||||||
|
ASTPtr partition_name;
|
||||||
|
|
||||||
|
ParserExpression p_expression;
|
||||||
|
ParserIdentifier p_identifier;
|
||||||
|
|
||||||
|
if (!p_identifier.parse(pos, partition_name, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ParserKeyword p_values("VALUES");
|
||||||
|
if (p_values.ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (ParserKeyword{"IN"}.ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!p_expression.parse(pos, in_expression, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (ParserKeyword{"LESS THAN"}.ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!p_expression.parse(pos, less_than, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ParserDeclareOption{
|
||||||
|
{
|
||||||
|
OptionDescribe("ENGINE", "engine", std::make_shared<ParserIdentifier>()),
|
||||||
|
OptionDescribe("STORAGE ENGINE", "engine", std::make_shared<ParserIdentifier>()),
|
||||||
|
OptionDescribe("COMMENT", "comment", std::make_shared<ParserStringLiteral>()),
|
||||||
|
OptionDescribe("DATA DIRECTORY", "data_directory", std::make_shared<ParserStringLiteral>()),
|
||||||
|
OptionDescribe("INDEX DIRECTORY", "index_directory", std::make_shared<ParserStringLiteral>()),
|
||||||
|
OptionDescribe("MAX_ROWS", "max_rows", std::make_shared<ParserLiteral>()),
|
||||||
|
OptionDescribe("MIN_ROWS", "min_rows", std::make_shared<ParserLiteral>()),
|
||||||
|
OptionDescribe("TABLESPACE", "tablespace", std::make_shared<ParserIdentifier>()),
|
||||||
|
}
|
||||||
|
}.parse(pos, options, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ASTPtr subpartitions;
|
||||||
|
if (ParserToken(TokenType::OpeningRoundBracket).ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!DB::ParserList(std::make_unique<ParserDeclareSubPartition>(), std::make_unique<ParserToken>(TokenType::Comma))
|
||||||
|
.parse(pos, subpartitions, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ParserToken(TokenType::ClosingRoundBracket).ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto partition_declare = std::make_shared<ASTDeclarePartition>();
|
||||||
|
partition_declare->options = options;
|
||||||
|
partition_declare->less_than = less_than;
|
||||||
|
partition_declare->in_expression = in_expression;
|
||||||
|
partition_declare->subpartitions = subpartitions;
|
||||||
|
partition_declare->partition_name = partition_name->as<ASTIdentifier>()->name;
|
||||||
|
|
||||||
|
if (partition_declare->options)
|
||||||
|
partition_declare->children.emplace_back(partition_declare->options);
|
||||||
|
|
||||||
|
if (partition_declare->less_than)
|
||||||
|
partition_declare->children.emplace_back(partition_declare->less_than);
|
||||||
|
|
||||||
|
if (partition_declare->in_expression)
|
||||||
|
partition_declare->children.emplace_back(partition_declare->in_expression);
|
||||||
|
|
||||||
|
if (partition_declare->subpartitions)
|
||||||
|
partition_declare->children.emplace_back(partition_declare->subpartitions);
|
||||||
|
|
||||||
|
node = partition_declare;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
35
src/Parsers/MySQL/ASTDeclarePartition.h
Normal file
35
src/Parsers/MySQL/ASTDeclarePartition.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Parsers/IAST.h>
|
||||||
|
#include <Parsers/IParserBase.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace MySQLParser
|
||||||
|
{
|
||||||
|
|
||||||
|
class ASTDeclarePartition : public IAST
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
String partition_name;
|
||||||
|
ASTPtr less_than;
|
||||||
|
ASTPtr in_expression;
|
||||||
|
ASTPtr options;
|
||||||
|
ASTPtr subpartitions;
|
||||||
|
|
||||||
|
ASTPtr clone() const override;
|
||||||
|
|
||||||
|
String getID(char /*delimiter*/) const override { return "partition declaration"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ParserDeclarePartition : public IParserBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
const char * getName() const override { return "partition declaration"; }
|
||||||
|
|
||||||
|
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
184
src/Parsers/MySQL/ASTDeclarePartitionOptions.cpp
Normal file
184
src/Parsers/MySQL/ASTDeclarePartitionOptions.cpp
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
#include <Parsers/MySQL/ASTDeclarePartitionOptions.h>
|
||||||
|
|
||||||
|
#include <Parsers/ASTLiteral.h>
|
||||||
|
#include <Parsers/CommonParsers.h>
|
||||||
|
#include <Parsers/ExpressionListParsers.h>
|
||||||
|
#include <Parsers/ExpressionElementParsers.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclarePartition.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace MySQLParser
|
||||||
|
{
|
||||||
|
|
||||||
|
ASTPtr ASTDeclarePartitionOptions::clone() const
|
||||||
|
{
|
||||||
|
auto res = std::make_shared<ASTDeclarePartitionOptions>(*this);
|
||||||
|
res->children.clear();
|
||||||
|
|
||||||
|
if (partition_numbers)
|
||||||
|
{
|
||||||
|
res->partition_numbers = partition_numbers->clone();
|
||||||
|
res->children.emplace_back(res->partition_numbers);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (partition_expression)
|
||||||
|
{
|
||||||
|
res->partition_expression = partition_expression->clone();
|
||||||
|
res->children.emplace_back(res->partition_expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subpartition_numbers)
|
||||||
|
{
|
||||||
|
res->subpartition_numbers = subpartition_numbers->clone();
|
||||||
|
res->children.emplace_back(res->subpartition_numbers);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subpartition_expression)
|
||||||
|
{
|
||||||
|
res->subpartition_expression = subpartition_expression->clone();
|
||||||
|
res->children.emplace_back(res->subpartition_expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParserDeclarePartitionOptions::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||||
|
{
|
||||||
|
String partition_type;
|
||||||
|
ASTPtr partition_numbers;
|
||||||
|
ASTPtr partition_expression;
|
||||||
|
String subpartition_type;
|
||||||
|
ASTPtr subpartition_numbers;
|
||||||
|
ASTPtr subpartition_expression;
|
||||||
|
ASTPtr declare_partitions;
|
||||||
|
|
||||||
|
if (!ParserKeyword("PARTITION BY").ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!parsePartitionExpression(pos, partition_type, partition_expression, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ParserKeyword("PARTITIONS").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
ParserLiteral p_literal;
|
||||||
|
if (!p_literal.parse(pos, partition_numbers, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ParserKeyword("SUBPARTITION BY").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!parsePartitionExpression(pos, subpartition_type, subpartition_expression, expected, true))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ParserKeyword("SUBPARTITIONS").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
ParserLiteral p_literal;
|
||||||
|
if (!p_literal.parse(pos, subpartition_numbers, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ParserToken(TokenType::OpeningRoundBracket).ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!ParserList(std::make_unique<ParserDeclarePartition>(), std::make_unique<ParserToken>(TokenType::Comma))
|
||||||
|
.parse(pos, declare_partitions, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ParserToken(TokenType::ClosingRoundBracket).ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto declare_partition_options = std::make_shared<ASTDeclarePartitionOptions>();
|
||||||
|
declare_partition_options->partition_type = partition_type;
|
||||||
|
declare_partition_options->partition_numbers = partition_numbers;
|
||||||
|
declare_partition_options->partition_expression = partition_expression;
|
||||||
|
declare_partition_options->subpartition_type = subpartition_type;
|
||||||
|
declare_partition_options->subpartition_numbers = subpartition_numbers;
|
||||||
|
declare_partition_options->subpartition_expression = subpartition_expression;
|
||||||
|
declare_partition_options->declare_partitions = declare_partitions;
|
||||||
|
|
||||||
|
if (declare_partition_options->partition_numbers)
|
||||||
|
declare_partition_options->children.emplace_back(declare_partition_options->partition_numbers);
|
||||||
|
|
||||||
|
if (declare_partition_options->partition_expression)
|
||||||
|
declare_partition_options->children.emplace_back(declare_partition_options->partition_expression);
|
||||||
|
|
||||||
|
if (declare_partition_options->subpartition_numbers)
|
||||||
|
declare_partition_options->children.emplace_back(declare_partition_options->subpartition_numbers);
|
||||||
|
|
||||||
|
if (declare_partition_options->subpartition_expression)
|
||||||
|
declare_partition_options->children.emplace_back(declare_partition_options->subpartition_expression);
|
||||||
|
|
||||||
|
if (declare_partition_options->declare_partitions)
|
||||||
|
declare_partition_options->children.emplace_back(declare_partition_options->declare_partitions);
|
||||||
|
|
||||||
|
node = declare_partition_options;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParserDeclarePartitionOptions::parsePartitionExpression(Pos & pos, std::string & type, ASTPtr & node, Expected & expected, bool subpartition)
|
||||||
|
{
|
||||||
|
ASTPtr expression;
|
||||||
|
ParserExpression p_expression;
|
||||||
|
if (!subpartition && ParserKeyword("LIST").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
type = "list";
|
||||||
|
ParserKeyword("COLUMNS").ignore(pos, expected);
|
||||||
|
if (!p_expression.parse(pos, expression, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (!subpartition && ParserKeyword("RANGE").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
type = "range";
|
||||||
|
ParserKeyword("COLUMNS").ignore(pos, expected);
|
||||||
|
if (!p_expression.parse(pos, expression, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ParserKeyword("LINEAR").ignore(pos, expected))
|
||||||
|
type = "linear_";
|
||||||
|
|
||||||
|
if (ParserKeyword("KEY").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
type += "key";
|
||||||
|
|
||||||
|
if (ParserKeyword("ALGORITHM").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!ParserToken(TokenType::Equals).ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ASTPtr algorithm;
|
||||||
|
ParserLiteral p_literal;
|
||||||
|
if (!p_literal.parse(pos, algorithm, expected) || !algorithm->as<ASTLiteral>())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
UInt64 algorithm_type = algorithm->as<ASTLiteral>()->value.safeGet<UInt64>();
|
||||||
|
|
||||||
|
if (algorithm_type != 1 && algorithm_type != 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
type += "_" + toString(algorithm_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!p_expression.parse(pos, expression, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (ParserKeyword("HASH").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
type += "hash";
|
||||||
|
if (!p_expression.parse(pos, expression, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = expression;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
40
src/Parsers/MySQL/ASTDeclarePartitionOptions.h
Normal file
40
src/Parsers/MySQL/ASTDeclarePartitionOptions.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Parsers/IAST.h>
|
||||||
|
#include <Parsers/IParserBase.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace MySQLParser
|
||||||
|
{
|
||||||
|
|
||||||
|
class ASTDeclarePartitionOptions : public IAST
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
String partition_type;
|
||||||
|
ASTPtr partition_numbers;
|
||||||
|
ASTPtr partition_expression;
|
||||||
|
String subpartition_type;
|
||||||
|
ASTPtr subpartition_numbers;
|
||||||
|
ASTPtr subpartition_expression;
|
||||||
|
ASTPtr declare_partitions;
|
||||||
|
|
||||||
|
ASTPtr clone() const override;
|
||||||
|
|
||||||
|
String getID(char /*delimiter*/) const override { return "partition options declaration"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ParserDeclarePartitionOptions : public IParserBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
const char * getName() const override { return "partition options declaration"; }
|
||||||
|
|
||||||
|
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||||
|
|
||||||
|
bool parsePartitionExpression(Pos & pos, std::string & type, ASTPtr & node, Expected & expected, bool subpartition = false);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
105
src/Parsers/MySQL/ASTDeclareReference.cpp
Normal file
105
src/Parsers/MySQL/ASTDeclareReference.cpp
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
#include <Parsers/MySQL/ASTDeclareReference.h>
|
||||||
|
|
||||||
|
#include <Parsers/ASTIdentifier.h>
|
||||||
|
#include <Parsers/CommonParsers.h>
|
||||||
|
#include <Parsers/ExpressionListParsers.h>
|
||||||
|
#include <Parsers/ExpressionElementParsers.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace MySQLParser
|
||||||
|
{
|
||||||
|
|
||||||
|
bool parseReferenceOption(IParser::Pos & pos, ASTDeclareReference::ReferenceOption & option, Expected & expected)
|
||||||
|
{
|
||||||
|
if (ParserKeyword("RESTRICT").ignore(pos, expected))
|
||||||
|
option = ASTDeclareReference::RESTRICT;
|
||||||
|
else if (ParserKeyword("CASCADE").ignore(pos, expected))
|
||||||
|
option = ASTDeclareReference::CASCADE;
|
||||||
|
else if (ParserKeyword("SET NULL").ignore(pos, expected))
|
||||||
|
option = ASTDeclareReference::SET_NULL;
|
||||||
|
else if (ParserKeyword("NO ACTION").ignore(pos, expected))
|
||||||
|
option = ASTDeclareReference::NO_ACTION;
|
||||||
|
else if (ParserKeyword("SET DEFAULT").ignore(pos, expected))
|
||||||
|
option = ASTDeclareReference::SET_DEFAULT;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASTPtr ASTDeclareReference::clone() const
|
||||||
|
{
|
||||||
|
auto res = std::make_shared<ASTDeclareReference>(*this);
|
||||||
|
res->children.clear();
|
||||||
|
|
||||||
|
if (reference_expression)
|
||||||
|
{
|
||||||
|
res->reference_expression = reference_expression->clone();
|
||||||
|
res->children.emplace_back(res->reference_expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParserDeclareReference::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected & expected)
|
||||||
|
{
|
||||||
|
ASTPtr table_name;
|
||||||
|
ASTPtr expression;
|
||||||
|
ParserExpression p_expression;
|
||||||
|
ParserIdentifier p_identifier;
|
||||||
|
ASTDeclareReference::MatchKind match_kind = ASTDeclareReference::MATCH_FULL;
|
||||||
|
ASTDeclareReference::ReferenceOption delete_option = ASTDeclareReference::RESTRICT;
|
||||||
|
ASTDeclareReference::ReferenceOption update_option = ASTDeclareReference::RESTRICT;
|
||||||
|
|
||||||
|
if (!ParserKeyword("REFERENCES").ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!p_identifier.parse(pos, table_name, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!p_expression.parse(pos, expression, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ParserKeyword("MATCH").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (ParserKeyword("FULL").ignore(pos, expected))
|
||||||
|
match_kind = ASTDeclareReference::MATCH_FULL;
|
||||||
|
else if (ParserKeyword("SIMPLE").ignore(pos, expected))
|
||||||
|
match_kind = ASTDeclareReference::MATCH_SIMPLE;
|
||||||
|
else if (ParserKeyword("PARTIAL").ignore(pos, expected))
|
||||||
|
match_kind = ASTDeclareReference::MATCH_PARTIAL;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (ParserKeyword("ON DELETE").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!parseReferenceOption(pos, delete_option, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (ParserKeyword("ON UPDATE").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!parseReferenceOption(pos, update_option, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto declare_reference = std::make_shared<ASTDeclareReference>();
|
||||||
|
declare_reference->kind = match_kind;
|
||||||
|
declare_reference->on_delete_option = delete_option;
|
||||||
|
declare_reference->on_update_option = update_option;
|
||||||
|
declare_reference->reference_expression = expression;
|
||||||
|
declare_reference->reference_table_name = table_name->as<ASTIdentifier>()->name;
|
||||||
|
|
||||||
|
node = declare_reference;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
52
src/Parsers/MySQL/ASTDeclareReference.h
Normal file
52
src/Parsers/MySQL/ASTDeclareReference.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Parsers/IAST.h>
|
||||||
|
#include <Parsers/IParserBase.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace MySQLParser
|
||||||
|
{
|
||||||
|
|
||||||
|
class ASTDeclareReference : public IAST
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum MatchKind
|
||||||
|
{
|
||||||
|
MATCH_FULL,
|
||||||
|
MATCH_PARTIAL,
|
||||||
|
MATCH_SIMPLE
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ReferenceOption
|
||||||
|
{
|
||||||
|
RESTRICT,
|
||||||
|
CASCADE,
|
||||||
|
SET_NULL,
|
||||||
|
NO_ACTION,
|
||||||
|
SET_DEFAULT
|
||||||
|
};
|
||||||
|
|
||||||
|
MatchKind kind;
|
||||||
|
String reference_table_name;
|
||||||
|
ASTPtr reference_expression;
|
||||||
|
ReferenceOption on_delete_option;
|
||||||
|
ReferenceOption on_update_option;
|
||||||
|
|
||||||
|
ASTPtr clone() const override;
|
||||||
|
|
||||||
|
String getID(char /*delimiter*/) const override { return "subpartition declaration"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ParserDeclareReference : public IParserBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
const char * getName() const override { return "reference declaration"; }
|
||||||
|
|
||||||
|
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
66
src/Parsers/MySQL/ASTDeclareSubPartition.cpp
Normal file
66
src/Parsers/MySQL/ASTDeclareSubPartition.cpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#include <Parsers/MySQL/ASTDeclareSubPartition.h>
|
||||||
|
|
||||||
|
#include <Parsers/ASTIdentifier.h>
|
||||||
|
#include <Parsers/CommonParsers.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareOption.h>
|
||||||
|
#include <Parsers/ExpressionElementParsers.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace MySQLParser
|
||||||
|
{
|
||||||
|
|
||||||
|
bool ParserDeclareSubPartition::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||||
|
{
|
||||||
|
if (!ParserKeyword{"SUBPARTITION"}.ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ASTPtr options;
|
||||||
|
ASTPtr logical_name;
|
||||||
|
ParserIdentifier p_identifier;
|
||||||
|
|
||||||
|
if (!p_identifier.parse(pos, logical_name, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ParserDeclareOption{
|
||||||
|
{
|
||||||
|
OptionDescribe("ENGINE", "engine", std::make_shared<ParserIdentifier>()),
|
||||||
|
OptionDescribe("STORAGE ENGINE", "engine", std::make_shared<ParserIdentifier>()),
|
||||||
|
OptionDescribe("COMMENT", "comment", std::make_shared<ParserStringLiteral>()),
|
||||||
|
OptionDescribe("DATA DIRECTORY", "data_directory", std::make_shared<ParserStringLiteral>()),
|
||||||
|
OptionDescribe("INDEX DIRECTORY", "index_directory", std::make_shared<ParserStringLiteral>()),
|
||||||
|
OptionDescribe("MAX_ROWS", "max_rows", std::make_shared<ParserLiteral>()),
|
||||||
|
OptionDescribe("MIN_ROWS", "min_rows", std::make_shared<ParserLiteral>()),
|
||||||
|
OptionDescribe("TABLESPACE", "tablespace", std::make_shared<ParserIdentifier>()),
|
||||||
|
}
|
||||||
|
}.parse(pos, options, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto subpartition_declare = std::make_shared<ASTDeclareSubPartition>();
|
||||||
|
subpartition_declare->options = options;
|
||||||
|
subpartition_declare->logical_name = logical_name->as<ASTIdentifier>()->name;
|
||||||
|
|
||||||
|
if (subpartition_declare->options)
|
||||||
|
subpartition_declare->children.emplace_back(subpartition_declare->options);
|
||||||
|
|
||||||
|
node = subpartition_declare;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASTPtr ASTDeclareSubPartition::clone() const
|
||||||
|
{
|
||||||
|
auto res = std::make_shared<ASTDeclareSubPartition>(*this);
|
||||||
|
res->children.clear();
|
||||||
|
|
||||||
|
if (options)
|
||||||
|
{
|
||||||
|
res->options = options->clone();
|
||||||
|
res->children.emplace_back(res->options);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
33
src/Parsers/MySQL/ASTDeclareSubPartition.h
Normal file
33
src/Parsers/MySQL/ASTDeclareSubPartition.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Parsers/IAST.h>
|
||||||
|
#include <Parsers/IParserBase.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace MySQLParser
|
||||||
|
{
|
||||||
|
|
||||||
|
class ASTDeclareSubPartition : public IAST
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ASTPtr options;
|
||||||
|
String logical_name;
|
||||||
|
|
||||||
|
ASTPtr clone() const override;
|
||||||
|
|
||||||
|
String getID(char /*delimiter*/) const override { return "subpartition declaration"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ParserDeclareSubPartition : public IParserBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
const char * getName() const override { return "subpartition declaration"; }
|
||||||
|
|
||||||
|
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
102
src/Parsers/MySQL/ASTDeclareTableOptions.cpp
Normal file
102
src/Parsers/MySQL/ASTDeclareTableOptions.cpp
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
#include <Parsers/MySQL/ASTDeclareTableOptions.h>
|
||||||
|
|
||||||
|
#include <IO/ReadBufferFromMemory.h>
|
||||||
|
#include <IO/ReadHelpers.h>
|
||||||
|
#include <Parsers/ASTIdentifier.h>
|
||||||
|
#include <Parsers/ASTLiteral.h>
|
||||||
|
#include <Parsers/ExpressionElementParsers.h>
|
||||||
|
#include <Parsers/ExpressionListParsers.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareOption.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace MySQLParser
|
||||||
|
{
|
||||||
|
|
||||||
|
template <bool allow_default = false>
|
||||||
|
struct ParserBoolOption : public IParserBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
const char * getName() const override { return "bool option with default"; }
|
||||||
|
|
||||||
|
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override
|
||||||
|
{
|
||||||
|
if constexpr(allow_default)
|
||||||
|
{
|
||||||
|
if (ParserKeyword("DEFAULT").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
node = std::make_shared<ASTIdentifier>("DEFAULT");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ParserLiteral p_literal;
|
||||||
|
if (!p_literal.parse(pos, node, expected) || !node->as<ASTLiteral>())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return !(node->as<ASTLiteral>()->value.safeGet<UInt64>() != 0 && node->as<ASTLiteral>()->value.safeGet<UInt64>() != 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ParserTablespaceName : public IParserBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
const char * getName() const override { return "table space name"; }
|
||||||
|
|
||||||
|
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override
|
||||||
|
{
|
||||||
|
ParserIdentifier p_identifier;
|
||||||
|
if (!p_identifier.parse(pos, node, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ParserKeyword("STORAGE").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!ParserKeyword("DISK").ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!ParserKeyword("MEMORY").ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool ParserDeclareTableOptions::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected & expected)
|
||||||
|
{
|
||||||
|
return ParserDeclareOption{
|
||||||
|
{
|
||||||
|
OptionDescribe("AUTO_INCREMENT", "auto_increment", std::make_shared<ParserLiteral>()),
|
||||||
|
OptionDescribe("AVG_ROW_LENGTH", "avg_row_length", std::make_shared<ParserLiteral>()),
|
||||||
|
OptionDescribe("CHARACTER SET", "character_set", std::make_shared<ParserCharsetName>()),
|
||||||
|
OptionDescribe("DEFAULT CHARACTER SET", "character_set", std::make_shared<ParserIdentifier>()),
|
||||||
|
OptionDescribe("CHECKSUM", "checksum", std::make_shared<ParserBoolOption<false>>()),
|
||||||
|
OptionDescribe("COLLATE", "collate", std::make_shared<ParserCharsetName>()),
|
||||||
|
OptionDescribe("DEFAULT COLLATE", "collate", std::make_shared<ParserIdentifier>()),
|
||||||
|
OptionDescribe("COMMENT", "comment", std::make_shared<ParserStringLiteral>()),
|
||||||
|
OptionDescribe("COMPRESSION", "compression", std::make_shared<ParserStringLiteral>()),
|
||||||
|
OptionDescribe("CONNECTION", "connection", std::make_shared<ParserStringLiteral>()),
|
||||||
|
OptionDescribe("DATA DIRECTORY", "data_directory", std::make_shared<ParserStringLiteral>()),
|
||||||
|
OptionDescribe("INDEX DIRECTORY", "index_directory", std::make_shared<ParserStringLiteral>()),
|
||||||
|
OptionDescribe("DELAY_KEY_WRITE", "delay_key_write", std::make_shared<ParserBoolOption<false>>()),
|
||||||
|
OptionDescribe("ENCRYPTION", "encryption", std::make_shared<ParserStringLiteral>()),
|
||||||
|
OptionDescribe("ENGINE", "engine", std::make_shared<ParserIdentifier>()),
|
||||||
|
OptionDescribe("INSERT_METHOD", "insert_method", std::make_shared<ParserIdentifier>()),
|
||||||
|
OptionDescribe("KEY_BLOCK_SIZE", "key_block_size", std::make_shared<ParserLiteral>()),
|
||||||
|
OptionDescribe("MAX_ROWS", "max_rows", std::make_shared<ParserLiteral>()),
|
||||||
|
OptionDescribe("MIN_ROWS", "min_rows", std::make_shared<ParserLiteral>()),
|
||||||
|
OptionDescribe("PACK_KEYS", "pack_keys", std::make_shared<ParserBoolOption<true>>()),
|
||||||
|
OptionDescribe("PASSWORD", "password", std::make_shared<ParserStringLiteral>()),
|
||||||
|
OptionDescribe("ROW_FORMAT", "row_format", std::make_shared<ParserIdentifier>()),
|
||||||
|
OptionDescribe("STATS_AUTO_RECALC", "stats_auto_recalc", std::make_shared<ParserBoolOption<true>>()),
|
||||||
|
OptionDescribe("STATS_PERSISTENT", "stats_persistent", std::make_shared<ParserBoolOption<true>>()),
|
||||||
|
OptionDescribe("STATS_SAMPLE_PAGES", "stats_sample_pages", std::make_shared<ParserLiteral>()),
|
||||||
|
OptionDescribe("TABLESPACE", "tablespace", std::make_shared<ParserTablespaceName>()),
|
||||||
|
OptionDescribe("UNION", "union", std::make_shared<ParserExpression>()),
|
||||||
|
}
|
||||||
|
}.parse(pos, node, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
21
src/Parsers/MySQL/ASTDeclareTableOptions.h
Normal file
21
src/Parsers/MySQL/ASTDeclareTableOptions.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Parsers/IParserBase.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace MySQLParser
|
||||||
|
{
|
||||||
|
|
||||||
|
class ParserDeclareTableOptions : public IParserBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
const char * getName() const override { return "table options declaration"; }
|
||||||
|
|
||||||
|
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
60
src/Parsers/MySQL/tests/gtest_column_parser.cpp
Normal file
60
src/Parsers/MySQL/tests/gtest_column_parser.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <Parsers/parseQuery.h>
|
||||||
|
#include <Parsers/ASTLiteral.h>
|
||||||
|
#include <Parsers/ASTFunction.h>
|
||||||
|
#include <Parsers/ASTIdentifier.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareColumn.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareOption.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareReference.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareConstraint.h>
|
||||||
|
|
||||||
|
using namespace DB;
|
||||||
|
using namespace DB::MySQLParser;
|
||||||
|
|
||||||
|
TEST(ParserColumn, AllNonGeneratedColumnOption)
|
||||||
|
{
|
||||||
|
ParserDeclareColumn p_column;
|
||||||
|
|
||||||
|
String input = "col_01 VARCHAR(100) NOT NULL DEFAULT NULL AUTO_INCREMENT UNIQUE KEY PRIMARY KEY COMMENT 'column comment' COLLATE utf-8 "
|
||||||
|
"COLUMN_FORMAT FIXED STORAGE MEMORY REFERENCES tbl_name (col_01) CHECK 1";
|
||||||
|
ASTPtr ast = parseQuery(p_column, input.data(), input.data() + input.size(), "", 0, 0);
|
||||||
|
EXPECT_EQ(ast->as<ASTDeclareColumn>()->name, "col_01");
|
||||||
|
EXPECT_EQ(ast->as<ASTDeclareColumn>()->data_type->as<ASTFunction>()->name, "VARCHAR");
|
||||||
|
EXPECT_EQ(ast->as<ASTDeclareColumn>()->data_type->as<ASTFunction>()->arguments->children[0]->as<ASTLiteral>()->value.safeGet<UInt64>(), 100);
|
||||||
|
|
||||||
|
ASTDeclareOptions * declare_options = ast->as<ASTDeclareColumn>()->column_options->as<ASTDeclareOptions>();
|
||||||
|
EXPECT_EQ(declare_options->changes["is_null"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 0);
|
||||||
|
EXPECT_TRUE(declare_options->changes["default"]->as<ASTLiteral>()->value.isNull());
|
||||||
|
EXPECT_EQ(declare_options->changes["auto_increment"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1);
|
||||||
|
EXPECT_EQ(declare_options->changes["unique_key"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1);
|
||||||
|
EXPECT_EQ(declare_options->changes["primary_key"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1);
|
||||||
|
EXPECT_EQ(declare_options->changes["comment"]->as<ASTLiteral>()->value.safeGet<DB::String>(), "column comment");
|
||||||
|
EXPECT_EQ(declare_options->changes["collate"]->as<ASTIdentifier>()->name, "utf-8");
|
||||||
|
EXPECT_EQ(declare_options->changes["column_format"]->as<ASTIdentifier>()->name, "FIXED");
|
||||||
|
EXPECT_EQ(declare_options->changes["storage"]->as<ASTIdentifier>()->name, "MEMORY");
|
||||||
|
EXPECT_TRUE(declare_options->changes["reference"]->as<ASTDeclareReference>());
|
||||||
|
EXPECT_TRUE(declare_options->changes["constraint"]->as<ASTDeclareConstraint>());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserColumn, AllGeneratedColumnOption)
|
||||||
|
{
|
||||||
|
ParserDeclareColumn p_column;
|
||||||
|
|
||||||
|
String input = "col_01 VARCHAR(100) NULL UNIQUE KEY PRIMARY KEY COMMENT 'column comment' COLLATE utf-8 "
|
||||||
|
"REFERENCES tbl_name (col_01) CHECK 1 GENERATED ALWAYS AS (1) STORED";
|
||||||
|
ASTPtr ast = parseQuery(p_column, input.data(), input.data() + input.size(), "", 0, 0);
|
||||||
|
EXPECT_EQ(ast->as<ASTDeclareColumn>()->name, "col_01");
|
||||||
|
EXPECT_EQ(ast->as<ASTDeclareColumn>()->data_type->as<ASTFunction>()->name, "VARCHAR");
|
||||||
|
EXPECT_EQ(ast->as<ASTDeclareColumn>()->data_type->as<ASTFunction>()->arguments->children[0]->as<ASTLiteral>()->value.safeGet<UInt64>(), 100);
|
||||||
|
|
||||||
|
ASTDeclareOptions * declare_options = ast->as<ASTDeclareColumn>()->column_options->as<ASTDeclareOptions>();
|
||||||
|
EXPECT_EQ(declare_options->changes["is_null"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1);
|
||||||
|
EXPECT_EQ(declare_options->changes["unique_key"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1);
|
||||||
|
EXPECT_EQ(declare_options->changes["primary_key"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1);
|
||||||
|
EXPECT_EQ(declare_options->changes["comment"]->as<ASTLiteral>()->value.safeGet<DB::String>(), "column comment");
|
||||||
|
EXPECT_EQ(declare_options->changes["collate"]->as<ASTIdentifier>()->name, "utf-8");
|
||||||
|
EXPECT_EQ(declare_options->changes["generated"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1);
|
||||||
|
EXPECT_EQ(declare_options->changes["is_stored"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1);
|
||||||
|
EXPECT_TRUE(declare_options->changes["reference"]->as<ASTDeclareReference>());
|
||||||
|
EXPECT_TRUE(declare_options->changes["constraint"]->as<ASTDeclareConstraint>());
|
||||||
|
}
|
57
src/Parsers/MySQL/tests/gtest_constraint_parser.cpp
Normal file
57
src/Parsers/MySQL/tests/gtest_constraint_parser.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <Parsers/parseQuery.h>
|
||||||
|
#include <Parsers/ASTLiteral.h>
|
||||||
|
#include <Parsers/ASTFunction.h>
|
||||||
|
#include <Parsers/ASTIdentifier.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareConstraint.h>
|
||||||
|
|
||||||
|
using namespace DB;
|
||||||
|
using namespace DB::MySQLParser;
|
||||||
|
|
||||||
|
TEST(ParserConstraint, CheckConstraint)
|
||||||
|
{
|
||||||
|
/// [CONSTRAINT [symbol]] CHECK (expr) [[NOT] ENFORCED]
|
||||||
|
ParserDeclareConstraint p_constraint;
|
||||||
|
|
||||||
|
String constraint_01 = "CONSTRAINT symbol_name CHECK col_01 = 1";
|
||||||
|
ASTPtr ast_constraint_01 = parseQuery(p_constraint, constraint_01.data(), constraint_01.data() + constraint_01.size(), "", 0, 0);
|
||||||
|
EXPECT_EQ(ast_constraint_01->as<ASTDeclareConstraint>()->constraint_name, "symbol_name");
|
||||||
|
auto check_expression_01 = ast_constraint_01->as<ASTDeclareConstraint>()->check_expression->as<ASTFunction>();
|
||||||
|
EXPECT_EQ(check_expression_01->name, "equals");
|
||||||
|
EXPECT_EQ(check_expression_01->arguments->children[0]->as<ASTIdentifier>()->name, "col_01");
|
||||||
|
EXPECT_EQ(check_expression_01->arguments->children[1]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1);
|
||||||
|
|
||||||
|
String constraint_02 = "CONSTRAINT CHECK col_01 = 1";
|
||||||
|
ASTPtr ast_constraint_02 = parseQuery(p_constraint, constraint_02.data(), constraint_02.data() + constraint_02.size(), "", 0, 0);
|
||||||
|
EXPECT_EQ(ast_constraint_02->as<ASTDeclareConstraint>()->constraint_name, "");
|
||||||
|
auto check_expression_02 = ast_constraint_02->as<ASTDeclareConstraint>()->check_expression->as<ASTFunction>();
|
||||||
|
EXPECT_EQ(check_expression_02->name, "equals");
|
||||||
|
EXPECT_EQ(check_expression_02->arguments->children[0]->as<ASTIdentifier>()->name, "col_01");
|
||||||
|
EXPECT_EQ(check_expression_02->arguments->children[1]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1);
|
||||||
|
|
||||||
|
String constraint_03 = "CHECK col_01 = 1";
|
||||||
|
ASTPtr ast_constraint_03 = parseQuery(p_constraint, constraint_03.data(), constraint_03.data() + constraint_03.size(), "", 0, 0);
|
||||||
|
EXPECT_EQ(ast_constraint_03->as<ASTDeclareConstraint>()->constraint_name, "");
|
||||||
|
auto check_expression_03 = ast_constraint_03->as<ASTDeclareConstraint>()->check_expression->as<ASTFunction>();
|
||||||
|
EXPECT_EQ(check_expression_03->name, "equals");
|
||||||
|
EXPECT_EQ(check_expression_03->arguments->children[0]->as<ASTIdentifier>()->name, "col_01");
|
||||||
|
EXPECT_EQ(check_expression_03->arguments->children[1]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1);
|
||||||
|
|
||||||
|
String constraint_04 = "CONSTRAINT CHECK col_01 = 1 ENFORCED";
|
||||||
|
ASTPtr ast_constraint_04 = parseQuery(p_constraint, constraint_04.data(), constraint_04.data() + constraint_04.size(), "", 0, 0);
|
||||||
|
EXPECT_TRUE(ast_constraint_04->as<ASTDeclareConstraint>()->enforced);
|
||||||
|
EXPECT_EQ(ast_constraint_04->as<ASTDeclareConstraint>()->constraint_name, "");
|
||||||
|
auto check_expression_04 = ast_constraint_04->as<ASTDeclareConstraint>()->check_expression->as<ASTFunction>();
|
||||||
|
EXPECT_EQ(check_expression_04->name, "equals");
|
||||||
|
EXPECT_EQ(check_expression_04->arguments->children[0]->as<ASTIdentifier>()->name, "col_01");
|
||||||
|
EXPECT_EQ(check_expression_04->arguments->children[1]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1);
|
||||||
|
|
||||||
|
String constraint_05 = "CONSTRAINT CHECK col_01 = 1 NOT ENFORCED";
|
||||||
|
ASTPtr ast_constraint_05 = parseQuery(p_constraint, constraint_05.data(), constraint_05.data() + constraint_05.size(), "", 0, 0);
|
||||||
|
EXPECT_FALSE(ast_constraint_05->as<ASTDeclareConstraint>()->enforced);
|
||||||
|
EXPECT_EQ(ast_constraint_05->as<ASTDeclareConstraint>()->constraint_name, "");
|
||||||
|
auto check_expression_05 = ast_constraint_05->as<ASTDeclareConstraint>()->check_expression->as<ASTFunction>();
|
||||||
|
EXPECT_EQ(check_expression_05->name, "equals");
|
||||||
|
EXPECT_EQ(check_expression_05->arguments->children[0]->as<ASTIdentifier>()->name, "col_01");
|
||||||
|
EXPECT_EQ(check_expression_05->arguments->children[1]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1);
|
||||||
|
}
|
33
src/Parsers/MySQL/tests/gtest_create_parser.cpp
Normal file
33
src/Parsers/MySQL/tests/gtest_create_parser.cpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <Parsers/parseQuery.h>
|
||||||
|
#include <Parsers/ASTFunction.h>
|
||||||
|
#include <Parsers/ASTIdentifier.h>
|
||||||
|
#include <Parsers/MySQL/ASTCreateQuery.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareOption.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclarePartitionOptions.h>
|
||||||
|
#include <Parsers/MySQL/ASTCreateDefines.h>
|
||||||
|
|
||||||
|
using namespace DB;
|
||||||
|
using namespace DB::MySQLParser;
|
||||||
|
|
||||||
|
TEST(CreateTableParser, LikeCreate)
|
||||||
|
{
|
||||||
|
ParserCreateQuery p_create_query;
|
||||||
|
String like_create_01 = "CREATE TABLE IF NOT EXISTS table_name LIKE table_name_01";
|
||||||
|
parseQuery(p_create_query, like_create_01.data(), like_create_01.data() + like_create_01.size(), "", 0, 0);
|
||||||
|
String like_create_02 = "CREATE TABLE IF NOT EXISTS table_name (LIKE table_name_01)";
|
||||||
|
parseQuery(p_create_query, like_create_02.data(), like_create_02.data() + like_create_02.size(), "", 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CreateTableParser, SimpleCreate)
|
||||||
|
{
|
||||||
|
ParserCreateQuery p_create_query;
|
||||||
|
String input = "CREATE TABLE IF NOT EXISTS table_name(col_01 VARCHAR(100), INDEX (col_01), CHECK 1) ENGINE INNODB PARTITION BY HASH(col_01)";
|
||||||
|
ASTPtr ast = parseQuery(p_create_query, input.data(), input.data() + input.size(), "", 0, 0);
|
||||||
|
EXPECT_TRUE(ast->as<ASTCreateQuery>()->if_not_exists);
|
||||||
|
EXPECT_EQ(ast->as<ASTCreateQuery>()->columns_list->as<ASTCreateDefines>()->columns->children.size(), 1);
|
||||||
|
EXPECT_EQ(ast->as<ASTCreateQuery>()->columns_list->as<ASTCreateDefines>()->indices->children.size(), 1);
|
||||||
|
EXPECT_EQ(ast->as<ASTCreateQuery>()->columns_list->as<ASTCreateDefines>()->constraints->children.size(), 1);
|
||||||
|
EXPECT_EQ(ast->as<ASTCreateQuery>()->table_options->as<ASTDeclareOptions>()->changes["engine"]->as<ASTIdentifier>()->name, "INNODB");
|
||||||
|
EXPECT_TRUE(ast->as<ASTCreateQuery>()->partition_options->as<ASTDeclarePartitionOptions>());
|
||||||
|
}
|
125
src/Parsers/MySQL/tests/gtest_index_parser.cpp
Normal file
125
src/Parsers/MySQL/tests/gtest_index_parser.cpp
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <Parsers/parseQuery.h>
|
||||||
|
#include <Parsers/ASTLiteral.h>
|
||||||
|
#include <Parsers/ASTFunction.h>
|
||||||
|
#include <Parsers/ASTIdentifier.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareIndex.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareOption.h>
|
||||||
|
|
||||||
|
using namespace DB;
|
||||||
|
using namespace DB::MySQLParser;
|
||||||
|
|
||||||
|
TEST(ParserIndex, AllIndexOptions)
|
||||||
|
{
|
||||||
|
String input = "INDEX (col_01, col_02(100), col_03 DESC) KEY_BLOCK_SIZE 3 USING HASH WITH PARSER parser_name COMMENT 'index comment' VISIBLE";
|
||||||
|
|
||||||
|
ParserDeclareIndex p_index;
|
||||||
|
ASTPtr ast = parseQuery(p_index, input.data(), input.data() + input.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclareIndex * declare_index = ast->as<ASTDeclareIndex>();
|
||||||
|
EXPECT_EQ(declare_index->index_columns->children[0]->as<ASTIdentifier>()->name, "col_01");
|
||||||
|
EXPECT_EQ(declare_index->index_columns->children[1]->as<ASTFunction>()->name, "col_02");
|
||||||
|
EXPECT_EQ(declare_index->index_columns->children[1]->as<ASTFunction>()->arguments->children[0]->as<ASTLiteral>()->value.safeGet<UInt64>(), 100);
|
||||||
|
EXPECT_EQ(declare_index->index_columns->children[2]->as<ASTIdentifier>()->name, "col_03");
|
||||||
|
ASTDeclareOptions * declare_options = declare_index->index_options->as<ASTDeclareOptions>();
|
||||||
|
EXPECT_EQ(declare_options->changes["key_block_size"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 3);
|
||||||
|
EXPECT_EQ(declare_options->changes["index_type"]->as<ASTIdentifier>()->name, "HASH");
|
||||||
|
EXPECT_EQ(declare_options->changes["comment"]->as<ASTLiteral>()->value.safeGet<String>(), "index comment");
|
||||||
|
EXPECT_EQ(declare_options->changes["visible"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserIndex, OptionalIndexOptions)
|
||||||
|
{
|
||||||
|
String input = "INDEX (col_01, col_02(100), col_03 DESC) USING HASH INVISIBLE KEY_BLOCK_SIZE 3";
|
||||||
|
|
||||||
|
ParserDeclareIndex p_index;
|
||||||
|
ASTPtr ast = parseQuery(p_index, input.data(), input.data() + input.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclareIndex * declare_index = ast->as<ASTDeclareIndex>();
|
||||||
|
EXPECT_EQ(declare_index->index_columns->children[0]->as<ASTIdentifier>()->name, "col_01");
|
||||||
|
EXPECT_EQ(declare_index->index_columns->children[1]->as<ASTFunction>()->name, "col_02");
|
||||||
|
EXPECT_EQ(declare_index->index_columns->children[1]->as<ASTFunction>()->arguments->children[0]->as<ASTLiteral>()->value.safeGet<UInt64>(), 100);
|
||||||
|
EXPECT_EQ(declare_index->index_columns->children[2]->as<ASTIdentifier>()->name, "col_03");
|
||||||
|
ASTDeclareOptions * declare_options = declare_index->index_options->as<ASTDeclareOptions>();
|
||||||
|
EXPECT_EQ(declare_options->changes["index_type"]->as<ASTIdentifier>()->name, "HASH");
|
||||||
|
EXPECT_EQ(declare_options->changes["visible"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 0);
|
||||||
|
EXPECT_EQ(declare_options->changes["key_block_size"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserIndex, OrdinaryIndex)
|
||||||
|
{
|
||||||
|
ParserDeclareIndex p_index;
|
||||||
|
String non_unique_index_01 = "KEY index_name USING HASH (col_01) INVISIBLE";
|
||||||
|
parseQuery(p_index, non_unique_index_01.data(), non_unique_index_01.data() + non_unique_index_01.size(), "", 0, 0);
|
||||||
|
|
||||||
|
String non_unique_index_02 = "INDEX index_name USING HASH (col_01) INVISIBLE";
|
||||||
|
parseQuery(p_index, non_unique_index_02.data(), non_unique_index_02.data() + non_unique_index_02.size(), "", 0, 0);
|
||||||
|
|
||||||
|
String fulltext_index_01 = "FULLTEXT index_name (col_01) INVISIBLE";
|
||||||
|
parseQuery(p_index, fulltext_index_01.data(), fulltext_index_01.data() + fulltext_index_01.size(), "", 0, 0);
|
||||||
|
|
||||||
|
String fulltext_index_02 = "FULLTEXT INDEX index_name (col_01) INVISIBLE";
|
||||||
|
parseQuery(p_index, fulltext_index_02.data(), fulltext_index_02.data() + fulltext_index_02.size(), "", 0, 0);
|
||||||
|
|
||||||
|
String fulltext_index_03 = "FULLTEXT KEY index_name (col_01) INVISIBLE";
|
||||||
|
parseQuery(p_index, fulltext_index_03.data(), fulltext_index_03.data() + fulltext_index_03.size(), "", 0, 0);
|
||||||
|
|
||||||
|
String spatial_index_01 = "SPATIAL index_name (col_01) INVISIBLE";
|
||||||
|
parseQuery(p_index, spatial_index_01.data(), spatial_index_01.data() + spatial_index_01.size(), "", 0, 0);
|
||||||
|
|
||||||
|
String spatial_index_02 = "SPATIAL INDEX index_name (col_01) INVISIBLE";
|
||||||
|
parseQuery(p_index, spatial_index_02.data(), spatial_index_02.data() + spatial_index_02.size(), "", 0, 0);
|
||||||
|
|
||||||
|
String spatial_index_03 = "SPATIAL KEY index_name (col_01) INVISIBLE";
|
||||||
|
parseQuery(p_index, spatial_index_03.data(), spatial_index_03.data() + spatial_index_03.size(), "", 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserIndex, ConstraintIndex)
|
||||||
|
{
|
||||||
|
ParserDeclareIndex p_index;
|
||||||
|
|
||||||
|
String primary_key_01 = "PRIMARY KEY (col_01) INVISIBLE";
|
||||||
|
parseQuery(p_index, primary_key_01.data(), primary_key_01.data() + primary_key_01.size(), "", 0, 0);
|
||||||
|
|
||||||
|
String primary_key_02 = "PRIMARY KEY USING BTREE (col_01) INVISIBLE";
|
||||||
|
parseQuery(p_index, primary_key_02.data(), primary_key_02.data() + primary_key_02.size(), "", 0, 0);
|
||||||
|
|
||||||
|
String primary_key_03 = "CONSTRAINT PRIMARY KEY USING BTREE (col_01) INVISIBLE";
|
||||||
|
parseQuery(p_index, primary_key_03.data(), primary_key_03.data() + primary_key_03.size(), "", 0, 0);
|
||||||
|
|
||||||
|
String primary_key_04 = "CONSTRAINT index_name PRIMARY KEY USING BTREE (col_01) INVISIBLE";
|
||||||
|
parseQuery(p_index, primary_key_04.data(), primary_key_04.data() + primary_key_04.size(), "", 0, 0);
|
||||||
|
|
||||||
|
String unique_key_01 = "UNIQUE (col_01) INVISIBLE";
|
||||||
|
parseQuery(p_index, unique_key_01.data(), unique_key_01.data() + unique_key_01.size(), "", 0, 0);
|
||||||
|
|
||||||
|
String unique_key_02 = "UNIQUE INDEX (col_01) INVISIBLE";
|
||||||
|
parseQuery(p_index, unique_key_02.data(), unique_key_02.data() + unique_key_02.size(), "", 0, 0);
|
||||||
|
|
||||||
|
String unique_key_03 = "UNIQUE KEY (col_01) INVISIBLE";
|
||||||
|
parseQuery(p_index, unique_key_03.data(), unique_key_03.data() + unique_key_03.size(), "", 0, 0);
|
||||||
|
|
||||||
|
String unique_key_04 = "UNIQUE KEY index_name (col_01) INVISIBLE";
|
||||||
|
parseQuery(p_index, unique_key_04.data(), unique_key_04.data() + unique_key_04.size(), "", 0, 0);
|
||||||
|
|
||||||
|
String unique_key_05 = "UNIQUE KEY index_name USING HASH (col_01) INVISIBLE";
|
||||||
|
parseQuery(p_index, unique_key_05.data(), unique_key_05.data() + unique_key_05.size(), "", 0, 0);
|
||||||
|
|
||||||
|
String unique_key_06 = "CONSTRAINT UNIQUE KEY index_name USING HASH (col_01) INVISIBLE";
|
||||||
|
parseQuery(p_index, unique_key_06.data(), unique_key_06.data() + unique_key_06.size(), "", 0, 0);
|
||||||
|
|
||||||
|
String unique_key_07 = "CONSTRAINT index_name UNIQUE KEY index_name_1 USING HASH (col_01) INVISIBLE";
|
||||||
|
parseQuery(p_index, unique_key_07.data(), unique_key_07.data() + unique_key_07.size(), "", 0, 0);
|
||||||
|
|
||||||
|
String foreign_key_01 = "FOREIGN KEY (col_01) REFERENCES tbl_name (col_01)";
|
||||||
|
parseQuery(p_index, foreign_key_01.data(), foreign_key_01.data() + foreign_key_01.size(), "", 0, 0);
|
||||||
|
|
||||||
|
String foreign_key_02 = "FOREIGN KEY index_name (col_01) REFERENCES tbl_name (col_01)";
|
||||||
|
parseQuery(p_index, foreign_key_02.data(), foreign_key_02.data() + foreign_key_02.size(), "", 0, 0);
|
||||||
|
|
||||||
|
String foreign_key_03 = "CONSTRAINT FOREIGN KEY index_name (col_01) REFERENCES tbl_name (col_01)";
|
||||||
|
parseQuery(p_index, foreign_key_03.data(), foreign_key_03.data() + foreign_key_03.size(), "", 0, 0);
|
||||||
|
|
||||||
|
String foreign_key_04 = "CONSTRAINT index_name FOREIGN KEY index_name_01 (col_01) REFERENCES tbl_name (col_01)";
|
||||||
|
parseQuery(p_index, foreign_key_04.data(), foreign_key_04.data() + foreign_key_04.size(), "", 0, 0);
|
||||||
|
}
|
167
src/Parsers/MySQL/tests/gtest_partition_options_parser.cpp
Normal file
167
src/Parsers/MySQL/tests/gtest_partition_options_parser.cpp
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <Parsers/parseQuery.h>
|
||||||
|
#include <Parsers/ASTLiteral.h>
|
||||||
|
#include <Parsers/ASTFunction.h>
|
||||||
|
#include <Parsers/ASTIdentifier.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclarePartition.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclarePartitionOptions.h>
|
||||||
|
|
||||||
|
using namespace DB;
|
||||||
|
using namespace DB::MySQLParser;
|
||||||
|
|
||||||
|
TEST(ParserPartitionOptions, HashPatitionOptions)
|
||||||
|
{
|
||||||
|
String hash_partition = "PARTITION BY HASH(col_01)";
|
||||||
|
|
||||||
|
ParserDeclarePartitionOptions p_partition_options;
|
||||||
|
ASTPtr ast_01 = parseQuery(p_partition_options, hash_partition.data(), hash_partition.data() + hash_partition.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclarePartitionOptions * declare_partition_options_01 = ast_01->as<ASTDeclarePartitionOptions>();
|
||||||
|
EXPECT_EQ(declare_partition_options_01->partition_type, "hash");
|
||||||
|
EXPECT_EQ(declare_partition_options_01->partition_expression->as<ASTIdentifier>()->name, "col_01");
|
||||||
|
|
||||||
|
String linear_hash_partition = "PARTITION BY LINEAR HASH(col_01)";
|
||||||
|
ASTPtr ast_02 = parseQuery(p_partition_options, linear_hash_partition.data(), linear_hash_partition.data() + linear_hash_partition.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclarePartitionOptions * declare_partition_options_02 = ast_02->as<ASTDeclarePartitionOptions>();
|
||||||
|
EXPECT_EQ(declare_partition_options_02->partition_type, "linear_hash");
|
||||||
|
EXPECT_EQ(declare_partition_options_02->partition_expression->as<ASTIdentifier>()->name, "col_01");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserPartitionOptions, KeyPatitionOptions)
|
||||||
|
{
|
||||||
|
String key_partition = "PARTITION BY KEY(col_01)";
|
||||||
|
|
||||||
|
ParserDeclarePartitionOptions p_partition_options;
|
||||||
|
ASTPtr ast_01 = parseQuery(p_partition_options, key_partition.data(), key_partition.data() + key_partition.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclarePartitionOptions * declare_partition_options_01 = ast_01->as<ASTDeclarePartitionOptions>();
|
||||||
|
EXPECT_EQ(declare_partition_options_01->partition_type, "key");
|
||||||
|
EXPECT_EQ(declare_partition_options_01->partition_expression->as<ASTIdentifier>()->name, "col_01");
|
||||||
|
|
||||||
|
String linear_key_partition = "PARTITION BY LINEAR KEY(col_01, col_02)";
|
||||||
|
ASTPtr ast_02 = parseQuery(p_partition_options, linear_key_partition.data(), linear_key_partition.data() + linear_key_partition.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclarePartitionOptions * declare_partition_options_02 = ast_02->as<ASTDeclarePartitionOptions>();
|
||||||
|
EXPECT_EQ(declare_partition_options_02->partition_type, "linear_key");
|
||||||
|
ASTPtr columns_list = declare_partition_options_02->partition_expression->as<ASTFunction>()->arguments;
|
||||||
|
EXPECT_EQ(columns_list->children[0]->as<ASTIdentifier>()->name, "col_01");
|
||||||
|
EXPECT_EQ(columns_list->children[1]->as<ASTIdentifier>()->name, "col_02");
|
||||||
|
|
||||||
|
String key_partition_with_algorithm = "PARTITION BY KEY ALGORITHM=1 (col_01)";
|
||||||
|
ASTPtr ast_03 = parseQuery(p_partition_options, key_partition_with_algorithm.data(), key_partition_with_algorithm.data() + key_partition_with_algorithm.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclarePartitionOptions * declare_partition_options_03 = ast_03->as<ASTDeclarePartitionOptions>();
|
||||||
|
EXPECT_EQ(declare_partition_options_03->partition_type, "key_1");
|
||||||
|
EXPECT_EQ(declare_partition_options_03->partition_expression->as<ASTIdentifier>()->name, "col_01");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserPartitionOptions, RangePatitionOptions)
|
||||||
|
{
|
||||||
|
String range_partition = "PARTITION BY RANGE(col_01)";
|
||||||
|
|
||||||
|
ParserDeclarePartitionOptions p_partition_options;
|
||||||
|
ASTPtr ast_01 = parseQuery(p_partition_options, range_partition.data(), range_partition.data() + range_partition.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclarePartitionOptions * declare_partition_options_01 = ast_01->as<ASTDeclarePartitionOptions>();
|
||||||
|
EXPECT_EQ(declare_partition_options_01->partition_type, "range");
|
||||||
|
EXPECT_EQ(declare_partition_options_01->partition_expression->as<ASTIdentifier>()->name, "col_01");
|
||||||
|
|
||||||
|
String range_columns_partition = "PARTITION BY RANGE COLUMNS(col_01, col_02)";
|
||||||
|
ASTPtr ast_02 = parseQuery(p_partition_options, range_columns_partition.data(), range_columns_partition.data() + range_columns_partition.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclarePartitionOptions * declare_partition_options_02 = ast_02->as<ASTDeclarePartitionOptions>();
|
||||||
|
EXPECT_EQ(declare_partition_options_02->partition_type, "range");
|
||||||
|
ASTPtr columns_list = declare_partition_options_02->partition_expression->as<ASTFunction>()->arguments;
|
||||||
|
EXPECT_EQ(columns_list->children[0]->as<ASTIdentifier>()->name, "col_01");
|
||||||
|
EXPECT_EQ(columns_list->children[1]->as<ASTIdentifier>()->name, "col_02");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserPartitionOptions, ListPatitionOptions)
|
||||||
|
{
|
||||||
|
String range_partition = "PARTITION BY LIST(col_01)";
|
||||||
|
|
||||||
|
ParserDeclarePartitionOptions p_partition_options;
|
||||||
|
ASTPtr ast_01 = parseQuery(p_partition_options, range_partition.data(), range_partition.data() + range_partition.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclarePartitionOptions * declare_partition_options_01 = ast_01->as<ASTDeclarePartitionOptions>();
|
||||||
|
EXPECT_EQ(declare_partition_options_01->partition_type, "list");
|
||||||
|
EXPECT_EQ(declare_partition_options_01->partition_expression->as<ASTIdentifier>()->name, "col_01");
|
||||||
|
|
||||||
|
String range_columns_partition = "PARTITION BY LIST COLUMNS(col_01, col_02)";
|
||||||
|
ASTPtr ast_02 = parseQuery(p_partition_options, range_columns_partition.data(), range_columns_partition.data() + range_columns_partition.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclarePartitionOptions * declare_partition_options_02 = ast_02->as<ASTDeclarePartitionOptions>();
|
||||||
|
EXPECT_EQ(declare_partition_options_02->partition_type, "list");
|
||||||
|
ASTPtr columns_list = declare_partition_options_02->partition_expression->as<ASTFunction>()->arguments;
|
||||||
|
EXPECT_EQ(columns_list->children[0]->as<ASTIdentifier>()->name, "col_01");
|
||||||
|
EXPECT_EQ(columns_list->children[1]->as<ASTIdentifier>()->name, "col_02");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserPartitionOptions, PatitionNumberOptions)
|
||||||
|
{
|
||||||
|
String numbers_partition = "PARTITION BY KEY(col_01) PARTITIONS 2";
|
||||||
|
|
||||||
|
ParserDeclarePartitionOptions p_partition_options;
|
||||||
|
ASTPtr ast = parseQuery(p_partition_options, numbers_partition.data(), numbers_partition.data() + numbers_partition.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclarePartitionOptions * declare_partition_options = ast->as<ASTDeclarePartitionOptions>();
|
||||||
|
EXPECT_EQ(declare_partition_options->partition_type, "key");
|
||||||
|
EXPECT_EQ(declare_partition_options->partition_expression->as<ASTIdentifier>()->name, "col_01");
|
||||||
|
EXPECT_EQ(declare_partition_options->partition_numbers->as<ASTLiteral>()->value.safeGet<UInt64>(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserPartitionOptions, PatitionWithSubpartitionOptions)
|
||||||
|
{
|
||||||
|
String partition_with_subpartition = "PARTITION BY KEY(col_01) PARTITIONS 3 SUBPARTITION BY HASH(col_02) SUBPARTITIONS 4";
|
||||||
|
|
||||||
|
ParserDeclarePartitionOptions p_partition_options;
|
||||||
|
ASTPtr ast = parseQuery(p_partition_options, partition_with_subpartition.data(), partition_with_subpartition.data() + partition_with_subpartition.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclarePartitionOptions * declare_partition_options = ast->as<ASTDeclarePartitionOptions>();
|
||||||
|
EXPECT_EQ(declare_partition_options->partition_type, "key");
|
||||||
|
EXPECT_EQ(declare_partition_options->partition_expression->as<ASTIdentifier>()->name, "col_01");
|
||||||
|
EXPECT_EQ(declare_partition_options->partition_numbers->as<ASTLiteral>()->value.safeGet<UInt64>(), 3);
|
||||||
|
EXPECT_EQ(declare_partition_options->subpartition_type, "hash");
|
||||||
|
EXPECT_EQ(declare_partition_options->subpartition_expression->as<ASTIdentifier>()->name, "col_02");
|
||||||
|
EXPECT_EQ(declare_partition_options->subpartition_numbers->as<ASTLiteral>()->value.safeGet<UInt64>(), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserPartitionOptions, PatitionOptionsWithDeclarePartition)
|
||||||
|
{
|
||||||
|
String partition_options_with_declare = "PARTITION BY KEY(col_01) PARTITIONS 3 SUBPARTITION BY HASH(col_02) SUBPARTITIONS 4 (PARTITION partition_name)";
|
||||||
|
|
||||||
|
ParserDeclarePartitionOptions p_partition_options;
|
||||||
|
ASTPtr ast = parseQuery(p_partition_options,
|
||||||
|
partition_options_with_declare.data(),
|
||||||
|
partition_options_with_declare.data() + partition_options_with_declare.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclarePartitionOptions * declare_partition_options = ast->as<ASTDeclarePartitionOptions>();
|
||||||
|
EXPECT_EQ(declare_partition_options->partition_type, "key");
|
||||||
|
EXPECT_EQ(declare_partition_options->partition_expression->as<ASTIdentifier>()->name, "col_01");
|
||||||
|
EXPECT_EQ(declare_partition_options->partition_numbers->as<ASTLiteral>()->value.safeGet<UInt64>(), 3);
|
||||||
|
EXPECT_EQ(declare_partition_options->subpartition_type, "hash");
|
||||||
|
EXPECT_EQ(declare_partition_options->subpartition_expression->as<ASTIdentifier>()->name, "col_02");
|
||||||
|
EXPECT_EQ(declare_partition_options->subpartition_numbers->as<ASTLiteral>()->value.safeGet<UInt64>(), 4);
|
||||||
|
EXPECT_TRUE(declare_partition_options->declare_partitions->as<ASTExpressionList>()->children[0]->as<ASTDeclarePartition>());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserPartitionOptions, PatitionOptionsWithDeclarePartitions)
|
||||||
|
{
|
||||||
|
String partition_options_with_declare = "PARTITION BY KEY(col_01) PARTITIONS 3 SUBPARTITION BY HASH(col_02) SUBPARTITIONS 4 (PARTITION partition_01, PARTITION partition_02)";
|
||||||
|
|
||||||
|
ParserDeclarePartitionOptions p_partition_options;
|
||||||
|
ASTPtr ast = parseQuery(p_partition_options,
|
||||||
|
partition_options_with_declare.data(),
|
||||||
|
partition_options_with_declare.data() + partition_options_with_declare.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclarePartitionOptions * declare_partition_options = ast->as<ASTDeclarePartitionOptions>();
|
||||||
|
EXPECT_EQ(declare_partition_options->partition_type, "key");
|
||||||
|
EXPECT_EQ(declare_partition_options->partition_expression->as<ASTIdentifier>()->name, "col_01");
|
||||||
|
EXPECT_EQ(declare_partition_options->partition_numbers->as<ASTLiteral>()->value.safeGet<UInt64>(), 3);
|
||||||
|
EXPECT_EQ(declare_partition_options->subpartition_type, "hash");
|
||||||
|
EXPECT_EQ(declare_partition_options->subpartition_expression->as<ASTIdentifier>()->name, "col_02");
|
||||||
|
EXPECT_EQ(declare_partition_options->subpartition_numbers->as<ASTLiteral>()->value.safeGet<UInt64>(), 4);
|
||||||
|
EXPECT_TRUE(declare_partition_options->declare_partitions->as<ASTExpressionList>()->children[0]->as<ASTDeclarePartition>());
|
||||||
|
EXPECT_TRUE(declare_partition_options->declare_partitions->as<ASTExpressionList>()->children[1]->as<ASTDeclarePartition>());
|
||||||
|
}
|
149
src/Parsers/MySQL/tests/gtest_partition_parser.cpp
Normal file
149
src/Parsers/MySQL/tests/gtest_partition_parser.cpp
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <Parsers/parseQuery.h>
|
||||||
|
#include <Parsers/ASTLiteral.h>
|
||||||
|
#include <Parsers/ASTFunction.h>
|
||||||
|
#include <Parsers/ASTIdentifier.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareOption.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclarePartition.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareSubPartition.h>
|
||||||
|
|
||||||
|
using namespace DB;
|
||||||
|
using namespace DB::MySQLParser;
|
||||||
|
|
||||||
|
TEST(ParserPartition, AllPatitionOptions)
|
||||||
|
{
|
||||||
|
String input = "PARTITION partition_name ENGINE = engine_name COMMENT 'partition comment'"
|
||||||
|
" INDEX DIRECTORY 'index_directory' DATA DIRECTORY 'data_directory' max_rows 1000 MIN_ROWs 0"
|
||||||
|
" TABLESPACE table_space_name";
|
||||||
|
|
||||||
|
ParserDeclarePartition p_partition;
|
||||||
|
ASTPtr ast = parseQuery(p_partition, input.data(), input.data() + input.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclarePartition * declare_partition = ast->as<ASTDeclarePartition>();
|
||||||
|
EXPECT_EQ(declare_partition->partition_name, "partition_name");
|
||||||
|
ASTDeclareOptions * declare_options = declare_partition->options->as<ASTDeclareOptions>();
|
||||||
|
EXPECT_EQ(declare_options->changes["engine"]->as<ASTIdentifier>()->name, "engine_name");
|
||||||
|
EXPECT_EQ(declare_options->changes["comment"]->as<ASTLiteral>()->value.safeGet<String>(), "partition comment");
|
||||||
|
EXPECT_EQ(declare_options->changes["data_directory"]->as<ASTLiteral>()->value.safeGet<String>(), "data_directory");
|
||||||
|
EXPECT_EQ(declare_options->changes["index_directory"]->as<ASTLiteral>()->value.safeGet<String>(), "index_directory");
|
||||||
|
EXPECT_EQ(declare_options->changes["min_rows"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 0);
|
||||||
|
EXPECT_EQ(declare_options->changes["max_rows"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1000);
|
||||||
|
EXPECT_EQ(declare_options->changes["tablespace"]->as<ASTIdentifier>()->name, "table_space_name");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserPartition, OptionalPatitionOptions)
|
||||||
|
{
|
||||||
|
String input = "PARTITION partition_name STORAGE engine = engine_name max_rows 1000 min_rows 0 tablespace table_space_name";
|
||||||
|
ParserDeclarePartition p_partition;
|
||||||
|
ASTPtr ast = parseQuery(p_partition, input.data(), input.data() + input.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclarePartition * declare_partition = ast->as<ASTDeclarePartition>();
|
||||||
|
EXPECT_EQ(declare_partition->partition_name, "partition_name");
|
||||||
|
ASTDeclareOptions * declare_options = declare_partition->options->as<ASTDeclareOptions>();
|
||||||
|
EXPECT_EQ(declare_options->changes["engine"]->as<ASTIdentifier>()->name, "engine_name");
|
||||||
|
EXPECT_EQ(declare_options->changes["min_rows"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 0);
|
||||||
|
EXPECT_EQ(declare_options->changes["max_rows"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1000);
|
||||||
|
EXPECT_EQ(declare_options->changes["tablespace"]->as<ASTIdentifier>()->name, "table_space_name");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserPartition, PatitionOptionsWithLessThan)
|
||||||
|
{
|
||||||
|
ParserDeclarePartition p_partition;
|
||||||
|
String partition_01 = "PARTITION partition_01 VALUES LESS THAN (1991) STORAGE engine = engine_name";
|
||||||
|
ASTPtr ast_partition_01 = parseQuery(p_partition, partition_01.data(), partition_01.data() + partition_01.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclarePartition * declare_partition_01 = ast_partition_01->as<ASTDeclarePartition>();
|
||||||
|
EXPECT_EQ(declare_partition_01->partition_name, "partition_01");
|
||||||
|
EXPECT_EQ(declare_partition_01->less_than->as<ASTLiteral>()->value.safeGet<UInt64>(), 1991);
|
||||||
|
ASTDeclareOptions * declare_options_01 = declare_partition_01->options->as<ASTDeclareOptions>();
|
||||||
|
EXPECT_EQ(declare_options_01->changes["engine"]->as<ASTIdentifier>()->name, "engine_name");
|
||||||
|
|
||||||
|
String partition_02 = "PARTITION partition_02 VALUES LESS THAN MAXVALUE STORAGE engine = engine_name";
|
||||||
|
ASTPtr ast_partition_02 = parseQuery(p_partition, partition_02.data(), partition_02.data() + partition_02.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclarePartition * declare_partition_02 = ast_partition_02->as<ASTDeclarePartition>();
|
||||||
|
EXPECT_EQ(declare_partition_02->partition_name, "partition_02");
|
||||||
|
EXPECT_EQ(declare_partition_02->less_than->as<ASTIdentifier>()->name, "MAXVALUE");
|
||||||
|
ASTDeclareOptions * declare_options_02 = declare_partition_02->options->as<ASTDeclareOptions>();
|
||||||
|
EXPECT_EQ(declare_options_02->changes["engine"]->as<ASTIdentifier>()->name, "engine_name");
|
||||||
|
|
||||||
|
String partition_03 = "PARTITION partition_03 VALUES LESS THAN (50, MAXVALUE) STORAGE engine = engine_name";
|
||||||
|
ASTPtr ast_partition_03 = parseQuery(p_partition, partition_03.data(), partition_03.data() + partition_03.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclarePartition * declare_partition_03 = ast_partition_03->as<ASTDeclarePartition>();
|
||||||
|
EXPECT_EQ(declare_partition_03->partition_name, "partition_03");
|
||||||
|
ASTPtr declare_partition_03_argument = declare_partition_03->less_than->as<ASTFunction>()->arguments;
|
||||||
|
EXPECT_EQ(declare_partition_03_argument->children[0]->as<ASTLiteral>()->value.safeGet<UInt64>(), 50);
|
||||||
|
EXPECT_EQ(declare_partition_03_argument->children[1]->as<ASTIdentifier>()->name, "MAXVALUE");
|
||||||
|
ASTDeclareOptions * declare_options_03 = declare_partition_03->options->as<ASTDeclareOptions>();
|
||||||
|
EXPECT_EQ(declare_options_03->changes["engine"]->as<ASTIdentifier>()->name, "engine_name");
|
||||||
|
|
||||||
|
String partition_04 = "PARTITION partition_04 VALUES LESS THAN (MAXVALUE, MAXVALUE) STORAGE engine = engine_name";
|
||||||
|
ASTPtr ast_partition_04 = parseQuery(p_partition, partition_04.data(), partition_04.data() + partition_04.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclarePartition * declare_partition_04 = ast_partition_04->as<ASTDeclarePartition>();
|
||||||
|
EXPECT_EQ(declare_partition_04->partition_name, "partition_04");
|
||||||
|
ASTPtr declare_partition_04_argument = declare_partition_04->less_than->as<ASTFunction>()->arguments;
|
||||||
|
EXPECT_EQ(declare_partition_04_argument->children[0]->as<ASTIdentifier>()->name, "MAXVALUE");
|
||||||
|
EXPECT_EQ(declare_partition_04_argument->children[1]->as<ASTIdentifier>()->name, "MAXVALUE");
|
||||||
|
ASTDeclareOptions * declare_options_04 = declare_partition_04->options->as<ASTDeclareOptions>();
|
||||||
|
EXPECT_EQ(declare_options_04->changes["engine"]->as<ASTIdentifier>()->name, "engine_name");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserPartition, PatitionOptionsWithInExpression)
|
||||||
|
{
|
||||||
|
ParserDeclarePartition p_partition;
|
||||||
|
String partition_01 = "PARTITION partition_01 VALUES IN (NULL, 1991, MAXVALUE) STORAGE engine = engine_name";
|
||||||
|
ASTPtr ast_partition_01 = parseQuery(p_partition, partition_01.data(), partition_01.data() + partition_01.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclarePartition * declare_partition_01 = ast_partition_01->as<ASTDeclarePartition>();
|
||||||
|
EXPECT_EQ(declare_partition_01->partition_name, "partition_01");
|
||||||
|
ASTPtr declare_partition_01_argument = declare_partition_01->in_expression->as<ASTFunction>()->arguments;
|
||||||
|
EXPECT_TRUE(declare_partition_01_argument->children[0]->as<ASTLiteral>()->value.isNull());
|
||||||
|
EXPECT_EQ(declare_partition_01_argument->children[1]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1991);
|
||||||
|
EXPECT_EQ(declare_partition_01_argument->children[2]->as<ASTIdentifier>()->name, "MAXVALUE");
|
||||||
|
ASTDeclareOptions * declare_options_01 = declare_partition_01->options->as<ASTDeclareOptions>();
|
||||||
|
EXPECT_EQ(declare_options_01->changes["engine"]->as<ASTIdentifier>()->name, "engine_name");
|
||||||
|
|
||||||
|
String partition_02 = "PARTITION partition_02 VALUES IN ((NULL, 1991), (1991, NULL), (MAXVALUE, MAXVALUE)) STORAGE engine = engine_name";
|
||||||
|
ASTPtr ast_partition_02 = parseQuery(p_partition, partition_02.data(), partition_02.data() + partition_02.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclarePartition * declare_partition_02 = ast_partition_02->as<ASTDeclarePartition>();
|
||||||
|
EXPECT_EQ(declare_partition_02->partition_name, "partition_02");
|
||||||
|
ASTPtr declare_partition_02_argument = declare_partition_02->in_expression->as<ASTFunction>()->arguments;
|
||||||
|
|
||||||
|
ASTPtr argument_01 = declare_partition_02_argument->children[0];
|
||||||
|
EXPECT_TRUE(argument_01->as<ASTLiteral>()->value.safeGet<Tuple>()[0].isNull());
|
||||||
|
EXPECT_EQ(argument_01->as<ASTLiteral>()->value.safeGet<Tuple>()[1].safeGet<UInt64>(), 1991);
|
||||||
|
|
||||||
|
ASTPtr argument_02 = declare_partition_02_argument->children[1];
|
||||||
|
EXPECT_EQ(argument_02->as<ASTLiteral>()->value.safeGet<Tuple>()[0].safeGet<UInt64>(), 1991);
|
||||||
|
EXPECT_TRUE(argument_02->as<ASTLiteral>()->value.safeGet<Tuple>()[1].isNull());
|
||||||
|
|
||||||
|
ASTPtr argument_03 = declare_partition_02_argument->children[2]->as<ASTFunction>()->arguments;
|
||||||
|
EXPECT_EQ(argument_03->as<ASTExpressionList>()->children[0]->as<ASTIdentifier>()->name, "MAXVALUE");
|
||||||
|
EXPECT_EQ(argument_03->as<ASTExpressionList>()->children[1]->as<ASTIdentifier>()->name, "MAXVALUE");
|
||||||
|
|
||||||
|
ASTDeclareOptions * declare_options_02 = declare_partition_02->options->as<ASTDeclareOptions>();
|
||||||
|
EXPECT_EQ(declare_options_02->changes["engine"]->as<ASTIdentifier>()->name, "engine_name");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserPartition, PatitionOptionsWithSubpartitions)
|
||||||
|
{
|
||||||
|
ParserDeclarePartition p_partition;
|
||||||
|
String partition_01 = "PARTITION partition_01 VALUES IN (NULL, 1991, MAXVALUE) STORAGE engine = engine_name (SUBPARTITION s_p01)";
|
||||||
|
ASTPtr ast_partition_01 = parseQuery(p_partition, partition_01.data(), partition_01.data() + partition_01.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclarePartition * declare_partition_01 = ast_partition_01->as<ASTDeclarePartition>();
|
||||||
|
EXPECT_EQ(declare_partition_01->partition_name, "partition_01");
|
||||||
|
EXPECT_TRUE(declare_partition_01->subpartitions->as<ASTExpressionList>()->children[0]->as<ASTDeclareSubPartition>());
|
||||||
|
|
||||||
|
String partition_02 = "PARTITION partition_02 VALUES IN (NULL, 1991, MAXVALUE) STORAGE engine = engine_name (SUBPARTITION s_p01, SUBPARTITION s_p02)";
|
||||||
|
ASTPtr ast_partition_02 = parseQuery(p_partition, partition_02.data(), partition_02.data() + partition_02.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclarePartition * declare_partition_02 = ast_partition_02->as<ASTDeclarePartition>();
|
||||||
|
EXPECT_EQ(declare_partition_02->partition_name, "partition_02");
|
||||||
|
EXPECT_TRUE(declare_partition_02->subpartitions->as<ASTExpressionList>()->children[0]->as<ASTDeclareSubPartition>());
|
||||||
|
EXPECT_TRUE(declare_partition_02->subpartitions->as<ASTExpressionList>()->children[1]->as<ASTDeclareSubPartition>());
|
||||||
|
}
|
||||||
|
|
92
src/Parsers/MySQL/tests/gtest_reference_parser.cpp
Normal file
92
src/Parsers/MySQL/tests/gtest_reference_parser.cpp
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <Parsers/parseQuery.h>
|
||||||
|
#include <Parsers/ASTFunction.h>
|
||||||
|
#include <Parsers/ASTIdentifier.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareReference.h>
|
||||||
|
|
||||||
|
using namespace DB;
|
||||||
|
using namespace DB::MySQLParser;
|
||||||
|
|
||||||
|
TEST(ParserReference, SimpleReference)
|
||||||
|
{
|
||||||
|
ParserDeclareReference p_reference;
|
||||||
|
|
||||||
|
String reference_01 = "REFERENCES table_name (ref_col_01)";
|
||||||
|
ASTPtr ast_reference_01 = parseQuery(p_reference, reference_01.data(), reference_01.data() + reference_01.size(), "", 0, 0);
|
||||||
|
EXPECT_EQ(ast_reference_01->as<ASTDeclareReference>()->reference_table_name, "table_name");
|
||||||
|
EXPECT_EQ(ast_reference_01->as<ASTDeclareReference>()->reference_expression->as<ASTIdentifier>()->name, "ref_col_01");
|
||||||
|
|
||||||
|
String reference_02 = "REFERENCES table_name (ref_col_01, ref_col_02)";
|
||||||
|
ASTPtr ast_reference_02 = parseQuery(p_reference, reference_02.data(), reference_02.data() + reference_02.size(), "", 0, 0);
|
||||||
|
EXPECT_EQ(ast_reference_02->as<ASTDeclareReference>()->reference_table_name, "table_name");
|
||||||
|
ASTPtr arguments = ast_reference_02->as<ASTDeclareReference>()->reference_expression->as<ASTFunction>()->arguments;
|
||||||
|
EXPECT_EQ(arguments->children[0]->as<ASTIdentifier>()->name, "ref_col_01");
|
||||||
|
EXPECT_EQ(arguments->children[1]->as<ASTIdentifier>()->name, "ref_col_02");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserReference, ReferenceDifferenceKind)
|
||||||
|
{
|
||||||
|
ParserDeclareReference p_reference;
|
||||||
|
String reference_01 = "REFERENCES table_name (ref_col_01) MATCH FULL";
|
||||||
|
ASTPtr ast_reference_01 = parseQuery(p_reference, reference_01.data(), reference_01.data() + reference_01.size(), "", 0, 0);
|
||||||
|
EXPECT_EQ(ast_reference_01->as<ASTDeclareReference>()->reference_table_name, "table_name");
|
||||||
|
EXPECT_EQ(ast_reference_01->as<ASTDeclareReference>()->reference_expression->as<ASTIdentifier>()->name, "ref_col_01");
|
||||||
|
EXPECT_EQ(ast_reference_01->as<ASTDeclareReference>()->kind, ASTDeclareReference::MATCH_FULL);
|
||||||
|
|
||||||
|
String reference_02 = "REFERENCES table_name (ref_col_01) MATCH PARTIAL";
|
||||||
|
ASTPtr ast_reference_02 = parseQuery(p_reference, reference_02.data(), reference_02.data() + reference_02.size(), "", 0, 0);
|
||||||
|
EXPECT_EQ(ast_reference_02->as<ASTDeclareReference>()->reference_table_name, "table_name");
|
||||||
|
EXPECT_EQ(ast_reference_02->as<ASTDeclareReference>()->reference_expression->as<ASTIdentifier>()->name, "ref_col_01");
|
||||||
|
EXPECT_EQ(ast_reference_02->as<ASTDeclareReference>()->kind, ASTDeclareReference::MATCH_PARTIAL);
|
||||||
|
|
||||||
|
String reference_03 = "REFERENCES table_name (ref_col_01) MATCH SIMPLE";
|
||||||
|
ASTPtr ast_reference_03 = parseQuery(p_reference, reference_03.data(), reference_03.data() + reference_03.size(), "", 0, 0);
|
||||||
|
EXPECT_EQ(ast_reference_03->as<ASTDeclareReference>()->reference_table_name, "table_name");
|
||||||
|
EXPECT_EQ(ast_reference_03->as<ASTDeclareReference>()->reference_expression->as<ASTIdentifier>()->name, "ref_col_01");
|
||||||
|
EXPECT_EQ(ast_reference_03->as<ASTDeclareReference>()->kind, ASTDeclareReference::MATCH_SIMPLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserReference, ReferenceDifferenceOption)
|
||||||
|
{
|
||||||
|
ParserDeclareReference p_reference;
|
||||||
|
String reference_01 = "REFERENCES table_name (ref_col_01) MATCH FULL ON DELETE RESTRICT ON UPDATE RESTRICT";
|
||||||
|
ASTPtr ast_reference_01 = parseQuery(p_reference, reference_01.data(), reference_01.data() + reference_01.size(), "", 0, 0);
|
||||||
|
EXPECT_EQ(ast_reference_01->as<ASTDeclareReference>()->reference_table_name, "table_name");
|
||||||
|
EXPECT_EQ(ast_reference_01->as<ASTDeclareReference>()->reference_expression->as<ASTIdentifier>()->name, "ref_col_01");
|
||||||
|
EXPECT_EQ(ast_reference_01->as<ASTDeclareReference>()->kind, ASTDeclareReference::MATCH_FULL);
|
||||||
|
EXPECT_EQ(ast_reference_01->as<ASTDeclareReference>()->on_delete_option, ASTDeclareReference::RESTRICT);
|
||||||
|
EXPECT_EQ(ast_reference_01->as<ASTDeclareReference>()->on_update_option, ASTDeclareReference::RESTRICT);
|
||||||
|
|
||||||
|
String reference_02 = "REFERENCES table_name (ref_col_01) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE";
|
||||||
|
ASTPtr ast_reference_02 = parseQuery(p_reference, reference_02.data(), reference_02.data() + reference_02.size(), "", 0, 0);
|
||||||
|
EXPECT_EQ(ast_reference_02->as<ASTDeclareReference>()->reference_table_name, "table_name");
|
||||||
|
EXPECT_EQ(ast_reference_02->as<ASTDeclareReference>()->reference_expression->as<ASTIdentifier>()->name, "ref_col_01");
|
||||||
|
EXPECT_EQ(ast_reference_02->as<ASTDeclareReference>()->kind, ASTDeclareReference::MATCH_FULL);
|
||||||
|
EXPECT_EQ(ast_reference_02->as<ASTDeclareReference>()->on_delete_option, ASTDeclareReference::CASCADE);
|
||||||
|
EXPECT_EQ(ast_reference_02->as<ASTDeclareReference>()->on_update_option, ASTDeclareReference::CASCADE);
|
||||||
|
|
||||||
|
String reference_03 = "REFERENCES table_name (ref_col_01) MATCH FULL ON DELETE SET NULL ON UPDATE SET NULL";
|
||||||
|
ASTPtr ast_reference_03 = parseQuery(p_reference, reference_03.data(), reference_03.data() + reference_03.size(), "", 0, 0);
|
||||||
|
EXPECT_EQ(ast_reference_03->as<ASTDeclareReference>()->reference_table_name, "table_name");
|
||||||
|
EXPECT_EQ(ast_reference_03->as<ASTDeclareReference>()->reference_expression->as<ASTIdentifier>()->name, "ref_col_01");
|
||||||
|
EXPECT_EQ(ast_reference_03->as<ASTDeclareReference>()->kind, ASTDeclareReference::MATCH_FULL);
|
||||||
|
EXPECT_EQ(ast_reference_03->as<ASTDeclareReference>()->on_delete_option, ASTDeclareReference::SET_NULL);
|
||||||
|
EXPECT_EQ(ast_reference_03->as<ASTDeclareReference>()->on_update_option, ASTDeclareReference::SET_NULL);
|
||||||
|
|
||||||
|
String reference_04 = "REFERENCES table_name (ref_col_01) MATCH FULL ON UPDATE NO ACTION ON DELETE NO ACTION";
|
||||||
|
ASTPtr ast_reference_04 = parseQuery(p_reference, reference_04.data(), reference_04.data() + reference_04.size(), "", 0, 0);
|
||||||
|
EXPECT_EQ(ast_reference_04->as<ASTDeclareReference>()->reference_table_name, "table_name");
|
||||||
|
EXPECT_EQ(ast_reference_04->as<ASTDeclareReference>()->reference_expression->as<ASTIdentifier>()->name, "ref_col_01");
|
||||||
|
EXPECT_EQ(ast_reference_04->as<ASTDeclareReference>()->kind, ASTDeclareReference::MATCH_FULL);
|
||||||
|
EXPECT_EQ(ast_reference_04->as<ASTDeclareReference>()->on_delete_option, ASTDeclareReference::NO_ACTION);
|
||||||
|
EXPECT_EQ(ast_reference_04->as<ASTDeclareReference>()->on_update_option, ASTDeclareReference::NO_ACTION);
|
||||||
|
|
||||||
|
String reference_05 = "REFERENCES table_name (ref_col_01) MATCH FULL ON UPDATE SET DEFAULT ON DELETE SET DEFAULT";
|
||||||
|
ASTPtr ast_reference_05 = parseQuery(p_reference, reference_05.data(), reference_05.data() + reference_05.size(), "", 0, 0);
|
||||||
|
EXPECT_EQ(ast_reference_05->as<ASTDeclareReference>()->reference_table_name, "table_name");
|
||||||
|
EXPECT_EQ(ast_reference_05->as<ASTDeclareReference>()->reference_expression->as<ASTIdentifier>()->name, "ref_col_01");
|
||||||
|
EXPECT_EQ(ast_reference_05->as<ASTDeclareReference>()->kind, ASTDeclareReference::MATCH_FULL);
|
||||||
|
EXPECT_EQ(ast_reference_05->as<ASTDeclareReference>()->on_delete_option, ASTDeclareReference::SET_DEFAULT);
|
||||||
|
EXPECT_EQ(ast_reference_05->as<ASTDeclareReference>()->on_update_option, ASTDeclareReference::SET_DEFAULT);
|
||||||
|
}
|
||||||
|
|
45
src/Parsers/MySQL/tests/gtest_subpartition_parser.cpp
Normal file
45
src/Parsers/MySQL/tests/gtest_subpartition_parser.cpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <Parsers/parseQuery.h>
|
||||||
|
#include <Parsers/ASTLiteral.h>
|
||||||
|
#include <Parsers/ASTIdentifier.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareOption.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareSubPartition.h>
|
||||||
|
|
||||||
|
using namespace DB;
|
||||||
|
using namespace DB::MySQLParser;
|
||||||
|
|
||||||
|
TEST(ParserSubpartition, AllSubpatitionOptions)
|
||||||
|
{
|
||||||
|
String input = "SUBPARTITION subpartition_name ENGINE = engine_name COMMENT 'subpartition comment'"
|
||||||
|
" DATA DIRECTORY 'data_directory' INDEX DIRECTORY 'index_directory' max_rows 1000 MIN_ROWs 0"
|
||||||
|
" TABLESPACE table_space_name";
|
||||||
|
MySQLParser::ParserDeclareSubPartition p_subpartition;
|
||||||
|
ASTPtr ast = parseQuery(p_subpartition, input.data(), input.data() + input.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclareSubPartition * declare_subpartition = ast->as<ASTDeclareSubPartition>();
|
||||||
|
EXPECT_EQ(declare_subpartition->logical_name, "subpartition_name");
|
||||||
|
ASTDeclareOptions * declare_options = declare_subpartition->options->as<ASTDeclareOptions>();
|
||||||
|
EXPECT_EQ(declare_options->changes["engine"]->as<ASTIdentifier>()->name, "engine_name");
|
||||||
|
EXPECT_EQ(declare_options->changes["comment"]->as<ASTLiteral>()->value.safeGet<String>(), "subpartition comment");
|
||||||
|
EXPECT_EQ(declare_options->changes["data_directory"]->as<ASTLiteral>()->value.safeGet<String>(), "data_directory");
|
||||||
|
EXPECT_EQ(declare_options->changes["index_directory"]->as<ASTLiteral>()->value.safeGet<String>(), "index_directory");
|
||||||
|
EXPECT_EQ(declare_options->changes["min_rows"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 0);
|
||||||
|
EXPECT_EQ(declare_options->changes["max_rows"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1000);
|
||||||
|
EXPECT_EQ(declare_options->changes["tablespace"]->as<ASTIdentifier>()->name, "table_space_name");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserSubpartition, OptionalSubpatitionOptions)
|
||||||
|
{
|
||||||
|
String input = "SUBPARTITION subpartition_name STORAGE engine = engine_name max_rows 1000 min_rows 0 tablespace table_space_name";
|
||||||
|
MySQLParser::ParserDeclareSubPartition p_subpartition;
|
||||||
|
ASTPtr ast = parseQuery(p_subpartition, input.data(), input.data() + input.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclareSubPartition * declare_subpartition = ast->as<ASTDeclareSubPartition>();
|
||||||
|
EXPECT_EQ(declare_subpartition->logical_name, "subpartition_name");
|
||||||
|
ASTDeclareOptions * declare_options = declare_subpartition->options->as<ASTDeclareOptions>();
|
||||||
|
EXPECT_EQ(declare_options->changes["engine"]->as<ASTIdentifier>()->name, "engine_name");
|
||||||
|
EXPECT_EQ(declare_options->changes["min_rows"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 0);
|
||||||
|
EXPECT_EQ(declare_options->changes["max_rows"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1000);
|
||||||
|
EXPECT_EQ(declare_options->changes["tablespace"]->as<ASTIdentifier>()->name, "table_space_name");
|
||||||
|
}
|
||||||
|
|
64
src/Parsers/MySQL/tests/gtest_table_options_parser.cpp
Normal file
64
src/Parsers/MySQL/tests/gtest_table_options_parser.cpp
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <Parsers/parseQuery.h>
|
||||||
|
#include <Parsers/ASTLiteral.h>
|
||||||
|
#include <Parsers/ASTFunction.h>
|
||||||
|
#include <Parsers/ASTIdentifier.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareOption.h>
|
||||||
|
#include <Parsers/MySQL/ASTDeclareTableOptions.h>
|
||||||
|
|
||||||
|
using namespace DB;
|
||||||
|
using namespace DB::MySQLParser;
|
||||||
|
|
||||||
|
TEST(ParserTableOptions, AllSubpatitionOptions)
|
||||||
|
{
|
||||||
|
String input = "AUTO_INCREMENt = 1 AVG_ROW_LENGTh 3 CHARACTER SET utf-8 CHECKSUM 1 COLLATE utf8_bin"
|
||||||
|
" COMMENT 'table option comment' COMPRESSION 'LZ4' CONNECTION 'connect_string' DATA DIRECTORY 'data_directory'"
|
||||||
|
" INDEX DIRECTORY 'index_directory' DELAY_KEY_WRITE 0 ENCRYPTION 'Y' ENGINE INNODB INSERT_METHOD NO KEY_BLOCK_SIZE 3"
|
||||||
|
" MAX_ROWS 1000 MIN_ROWS 0 PACK_KEYS DEFAULT PASSWORD 'password' ROW_FORMAT DYNAMIC STATS_AUTO_RECALC DEFAULT "
|
||||||
|
" STATS_PERSISTENT DEFAULT STATS_SAMPLE_PAGES 3 TABLESPACE tablespace_name STORAGE MEMORY UNION (table_01, table_02)";
|
||||||
|
|
||||||
|
ParserDeclareTableOptions p_table_options;
|
||||||
|
ASTPtr ast = parseQuery(p_table_options, input.data(), input.data() + input.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclareOptions * declare_options = ast->as<ASTDeclareOptions>();
|
||||||
|
EXPECT_EQ(declare_options->changes["auto_increment"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1);
|
||||||
|
EXPECT_EQ(declare_options->changes["avg_row_length"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 3);
|
||||||
|
EXPECT_EQ(declare_options->changes["character_set"]->as<ASTIdentifier>()->name, "utf-8");
|
||||||
|
EXPECT_EQ(declare_options->changes["checksum"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1);
|
||||||
|
EXPECT_EQ(declare_options->changes["collate"]->as<ASTIdentifier>()->name, "utf8_bin");
|
||||||
|
EXPECT_EQ(declare_options->changes["comment"]->as<ASTLiteral>()->value.safeGet<String>(), "table option comment");
|
||||||
|
EXPECT_EQ(declare_options->changes["compression"]->as<ASTLiteral>()->value.safeGet<String>(), "LZ4");
|
||||||
|
EXPECT_EQ(declare_options->changes["connection"]->as<ASTLiteral>()->value.safeGet<String>(), "connect_string");
|
||||||
|
EXPECT_EQ(declare_options->changes["data_directory"]->as<ASTLiteral>()->value.safeGet<String>(), "data_directory");
|
||||||
|
EXPECT_EQ(declare_options->changes["index_directory"]->as<ASTLiteral>()->value.safeGet<String>(), "index_directory");
|
||||||
|
EXPECT_EQ(declare_options->changes["delay_key_write"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 0);
|
||||||
|
EXPECT_EQ(declare_options->changes["encryption"]->as<ASTLiteral>()->value.safeGet<String>(), "Y");
|
||||||
|
EXPECT_EQ(declare_options->changes["engine"]->as<ASTIdentifier>()->name, "INNODB");
|
||||||
|
EXPECT_EQ(declare_options->changes["insert_method"]->as<ASTIdentifier>()->name, "NO");
|
||||||
|
EXPECT_EQ(declare_options->changes["key_block_size"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 3);
|
||||||
|
|
||||||
|
EXPECT_EQ(declare_options->changes["max_rows"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1000);
|
||||||
|
EXPECT_EQ(declare_options->changes["min_rows"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 0);
|
||||||
|
EXPECT_EQ(declare_options->changes["pack_keys"]->as<ASTIdentifier>()->name, "DEFAULT");
|
||||||
|
EXPECT_EQ(declare_options->changes["password"]->as<ASTLiteral>()->value.safeGet<String>(), "password");
|
||||||
|
EXPECT_EQ(declare_options->changes["row_format"]->as<ASTIdentifier>()->name, "DYNAMIC");
|
||||||
|
EXPECT_EQ(declare_options->changes["stats_auto_recalc"]->as<ASTIdentifier>()->name, "DEFAULT");
|
||||||
|
EXPECT_EQ(declare_options->changes["stats_persistent"]->as<ASTIdentifier>()->name, "DEFAULT");
|
||||||
|
EXPECT_EQ(declare_options->changes["stats_sample_pages"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 3);
|
||||||
|
EXPECT_EQ(declare_options->changes["tablespace"]->as<ASTIdentifier>()->name, "tablespace_name");
|
||||||
|
|
||||||
|
ASTPtr arguments = declare_options->changes["union"]->as<ASTFunction>()->arguments;
|
||||||
|
EXPECT_EQ(arguments->children[0]->as<ASTIdentifier>()->name, "table_01");
|
||||||
|
EXPECT_EQ(arguments->children[1]->as<ASTIdentifier>()->name, "table_02");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParserTableOptions, OptionalTableOptions)
|
||||||
|
{
|
||||||
|
String input = "STATS_AUTO_RECALC DEFAULT AUTO_INCREMENt = 1 ";
|
||||||
|
ParserDeclareTableOptions p_table_options;
|
||||||
|
ASTPtr ast = parseQuery(p_table_options, input.data(), input.data() + input.size(), "", 0, 0);
|
||||||
|
|
||||||
|
ASTDeclareOptions * declare_options = ast->as<ASTDeclareOptions>();
|
||||||
|
EXPECT_EQ(declare_options->changes["auto_increment"]->as<ASTLiteral>()->value.safeGet<UInt64>(), 1);
|
||||||
|
EXPECT_EQ(declare_options->changes["stats_auto_recalc"]->as<ASTIdentifier>()->name, "DEFAULT");
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user