save TO table of a materialized view to the ATTACH query [#CLICKHOUSE-2]

This commit is contained in:
Alexey Zatelepin 2017-10-30 20:53:01 +03:00
parent b0f1227e90
commit f2ebffb7f0
8 changed files with 59 additions and 32 deletions

View File

@ -27,6 +27,8 @@ String getTableDefinitionFromCreateQuery(const ASTPtr & query)
/// We remove everything that is not needed for ATTACH from the query.
create.attach = true;
create.database.clear();
create.as_database.clear();
create.as_table.clear();
create.if_not_exists = false;
create.is_populate = false;
@ -34,13 +36,6 @@ String getTableDefinitionFromCreateQuery(const ASTPtr & query)
if (!create.is_view && !create.is_materialized_view)
create.select = nullptr;
/// For "MATERIALIZED VIEW x TO y" it's necessary to save destination table
if (!create.is_materialized_view || create.storage)
{
create.as_database.clear();
create.as_table.clear();
}
std::ostringstream statement_stream;
formatAST(create, statement_stream, 0, false);
statement_stream << '\n';

View File

@ -480,12 +480,15 @@ BlockIO InterpreterCreateQuery::createTable(ASTCreateQuery & create)
create.attach = true;
}
if (create.to_database.empty())
create.to_database = current_database;
std::unique_ptr<InterpreterSelectQuery> interpreter_select;
Block as_select_sample;
/// For `view` type tables, you may need `sample_block` to get the columns.
if (create.select && (!create.attach || (!create.columns && (create.is_view || create.is_materialized_view))))
{
create.select->setDatabaseIfNeeded(database_name);
create.select->setDatabaseIfNeeded(current_database);
interpreter_select = std::make_unique<InterpreterSelectQuery>(create.select->ptr(), context);
as_select_sample = interpreter_select->getSampleBlock();
}

View File

@ -88,6 +88,8 @@ public:
String database;
String table;
ASTExpressionList * columns = nullptr;
String to_database; /// For CREATE MATERIALIZED VIEW mv TO table.
String to_table;
ASTStorage * storage = nullptr;
String as_database;
String as_table;
@ -166,11 +168,18 @@ protected:
formatOnCluster(settings);
}
if (!to_table.empty())
{
settings.ostr
<< (settings.hilite ? hilite_keyword : "") << " TO " << (settings.hilite ? hilite_none : "")
<< (!to_database.empty() ? backQuoteIfNeed(to_database) + "." : "") << backQuoteIfNeed(to_table);
}
if (!as_table.empty())
{
std::string what = (!is_materialized_view ? " AS " : " TO ");
settings.ostr << (settings.hilite ? hilite_keyword : "") << what << (settings.hilite ? hilite_none : "")
<< (!as_database.empty() ? backQuoteIfNeed(as_database) + "." : "") << backQuoteIfNeed(as_table);
settings.ostr
<< (settings.hilite ? hilite_keyword : "") << " AS " << (settings.hilite ? hilite_none : "")
<< (!as_database.empty() ? backQuoteIfNeed(as_database) + "." : "") << backQuoteIfNeed(as_table);
}
if (columns)

View File

@ -208,6 +208,8 @@ bool ParserCreateQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
ASTPtr database;
ASTPtr table;
ASTPtr columns;
ASTPtr to_database;
ASTPtr to_table;
ASTPtr storage;
ASTPtr as_database;
ASTPtr as_table;
@ -219,7 +221,6 @@ bool ParserCreateQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
bool is_materialized_view = false;
bool is_populate = false;
bool is_temporary = false;
bool to_table = false;
if (!s_create.ignore(pos, expected))
{
@ -362,17 +363,13 @@ bool ParserCreateQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
// TO [db.]table
if (ParserKeyword{"TO"}.ignore(pos, expected))
{
to_table = true;
/// FIXME: as_table is ambiguous, it is set in AS clause also
if (!name_p.parse(pos, as_table, expected))
if (!name_p.parse(pos, to_table, expected))
return false;
if (s_dot.ignore(pos, expected))
{
as_database = as_table;
if (!name_p.parse(pos, as_table, expected))
to_database = to_table;
if (!name_p.parse(pos, to_table, expected))
return false;
}
}
@ -422,6 +419,11 @@ bool ParserCreateQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
query->table = typeid_cast<ASTIdentifier &>(*table).name;
query->cluster = cluster_str;
if (to_database)
query->to_database = typeid_cast<ASTIdentifier &>(*to_database).name;
if (to_table)
query->to_table = typeid_cast<ASTIdentifier &>(*to_table).name;
query->set(query->columns, columns);
query->set(query->storage, storage);
if (as_database)

View File

@ -388,9 +388,6 @@ StoragePtr StorageFactory::get(
checkAllTypesAreAllowedInTable(materialized_columns);
checkAllTypesAreAllowedInTable(alias_columns);
if (!query.storage)
throw Exception("Incorrect CREATE query: ENGINE required", ErrorCodes::ENGINE_REQUIRED);
if (query.is_materialized_view)
{
/// Pass local_context here to convey setting for inner table
@ -400,6 +397,9 @@ StoragePtr StorageFactory::get(
attach);
}
if (!query.storage)
throw Exception("Incorrect CREATE query: ENGINE required", ErrorCodes::ENGINE_REQUIRED);
ASTStorage & storage_def = *query.storage;
const ASTFunction & engine_def = *storage_def.engine;
@ -423,7 +423,7 @@ StoragePtr StorageFactory::get(
auto check_arguments_empty = [&]
{
if (args_ptr)
if (args_ptr && !args_ptr->empty())
throw Exception(
"Engine " + name + " doesn't support any arguments (" + toString(args_ptr->size()) + " given)",
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);

View File

@ -70,8 +70,10 @@ StorageMaterializedView::StorageMaterializedView(
if (!query.select)
throw Exception("SELECT query is not specified for " + getName(), ErrorCodes::INCORRECT_QUERY);
if (!query.storage && query.as_table.empty())
throw Exception("ENGINE of MaterializedView should be specified explicitly", ErrorCodes::INCORRECT_QUERY);
if (!query.storage && query.to_table.empty())
throw Exception(
"You must specify where to save results of a MaterializedView query: either ENGINE or an existing table in a TO clause",
ErrorCodes::INCORRECT_QUERY);
extractDependentTable(*query.select, select_database_name, select_table_name);
@ -81,10 +83,10 @@ StorageMaterializedView::StorageMaterializedView(
DatabaseAndTableName(database_name, table_name));
// If the destination table is not set, use inner table
if (!query.as_table.empty())
if (!query.to_table.empty())
{
target_database_name = query.as_database;
target_table_name = query.as_table;
target_database_name = query.to_database;
target_table_name = query.to_table;
}
else
{

View File

@ -2,3 +2,9 @@
2
1
2
1
2
3
1
2
3

View File

@ -5,16 +5,26 @@ DROP TABLE IF EXISTS test.mv;
CREATE TABLE test.src (x UInt8) ENGINE = Null;
CREATE TABLE test.dst (x UInt8) ENGINE = Memory;
CREATE MATERIALIZED VIEW test.mv TO test.dst AS SELECT * FROM test.src;
INSERT INTO test.src VALUES (1), (2);
USE test;
CREATE MATERIALIZED VIEW mv TO dst AS SELECT * FROM src;
INSERT INTO src VALUES (1), (2);
SELECT * FROM mv;
-- Detach MV and see if the data is still readable
DETACH TABLE test.mv;
SELECT * FROM test.dst;
DETACH TABLE mv;
SELECT * FROM dst;
USE default;
-- Reattach MV (shortcut)
ATTACH TABLE test.mv;
INSERT INTO test.src VALUES (3);
SELECT * FROM test.mv;
-- Drop the MV and see if the data is still readable
DROP TABLE test.mv;
SELECT * FROM test.dst;